SubtargetEmitter.cpp revision 3b8fb648c6e1c519b7e0f487f4fb511744869d35
14bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===// 24bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey// 34bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey// The LLVM Compiler Infrastructure 44bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey// 53060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// This file is distributed under the University of Illinois Open Source 63060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// License. See LICENSE.TXT for details. 74bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey// 84bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//===----------------------------------------------------------------------===// 94bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey// 103d87811ce0381c3364ce10aed77de8231a03bc48Chris Lattner// This tablegen backend emits subtarget enumerations. 114bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey// 124bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//===----------------------------------------------------------------------===// 134bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey 144bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey#include "CodeGenTarget.h" 152661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick#include "CodeGenSchedule.h" 164bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey#include "llvm/ADT/StringExtras.h" 1740096d26937cd47c865464bef7b28550bc20c631Andrew Trick#include "llvm/ADT/STLExtras.h" 186f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/MC/MCInstrItineraries.h" 1940096d26937cd47c865464bef7b28550bc20c631Andrew Trick#include "llvm/TableGen/Error.h" 206f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/TableGen/Record.h" 216f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.h" 2240096d26937cd47c865464bef7b28550bc20c631Andrew Trick#include "llvm/Support/Debug.h" 23544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick#include "llvm/Support/Format.h" 249489c04efc47a68af65e226e50f03d488094ffceJeff Cohen#include <algorithm> 256f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include <map> 266f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include <string> 276f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include <vector> 284bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskeyusing namespace llvm; 294bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey 306f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesennamespace { 316f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenclass SubtargetEmitter { 3252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Each processor has a SchedClassDesc table with an entry for each SchedClass. 3352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // The SchedClassDesc table indexes into a global write resource table, write 3452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // latency table, and read advance table. 3552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick struct SchedClassTables { 3652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<std::vector<MCSchedClassDesc> > ProcSchedClasses; 3752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<MCWriteProcResEntry> WriteProcResources; 3852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<MCWriteLatencyEntry> WriteLatencies; 393b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick std::vector<std::string> WriterNames; 4052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<MCReadAdvanceEntry> ReadAdvanceEntries; 4152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 4252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Reserve an invalid entry at index 0 4352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedClassTables() { 4452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick ProcSchedClasses.resize(1); 4552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteProcResources.resize(1); 4652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteLatencies.resize(1); 473b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick WriterNames.push_back("InvalidWrite"); 4852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick ReadAdvanceEntries.resize(1); 4952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 5052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick }; 5152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 5252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick struct LessWriteProcResources { 5352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick bool operator()(const MCWriteProcResEntry &LHS, 5452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick const MCWriteProcResEntry &RHS) { 5552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick return LHS.ProcResourceIdx < RHS.ProcResourceIdx; 5652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 5752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick }; 586f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 596f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen RecordKeeper &Records; 602661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick CodeGenSchedModels &SchedModels; 616f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen std::string Target; 626f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 636f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits); 646f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen unsigned FeatureKeyValues(raw_ostream &OS); 656f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen unsigned CPUKeyValues(raw_ostream &OS); 666f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen void FormItineraryStageString(const std::string &Names, 676f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen Record *ItinData, std::string &ItinString, 686f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen unsigned &NStages); 696f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString, 706f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen unsigned &NOperandCycles); 716f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen void FormItineraryBypassString(const std::string &Names, 726f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen Record *ItinData, 736f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen std::string &ItinString, unsigned NOperandCycles); 742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick void EmitStageAndOperandCycleData(raw_ostream &OS, 752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick std::vector<std::vector<InstrItinerary> > 762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick &ProcItinLists); 772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick void EmitItineraries(raw_ostream &OS, 782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick std::vector<std::vector<InstrItinerary> > 792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick &ProcItinLists); 802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name, 816f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen char Separator); 8240096d26937cd47c865464bef7b28550bc20c631Andrew Trick void EmitProcessorResources(const CodeGenProcModel &ProcModel, 8340096d26937cd47c865464bef7b28550bc20c631Andrew Trick raw_ostream &OS); 8452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick Record *FindWriteResources(Record *WriteDef, 8552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick const CodeGenProcModel &ProcModel); 8652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick Record *FindReadAdvance(Record *ReadDef, const CodeGenProcModel &ProcModel); 8752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick void GenSchedClassTables(const CodeGenProcModel &ProcModel, 8852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedClassTables &SchedTables); 89544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS); 902661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick void EmitProcessorModels(raw_ostream &OS); 916f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen void EmitProcessorLookup(raw_ostream &OS); 924d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick void EmitSchedModelHelpers(std::string ClassName, raw_ostream &OS); 932661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick void EmitSchedModel(raw_ostream &OS); 946f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures, 956f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen unsigned NumProcs); 966f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 976f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenpublic: 982661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT): 992661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {} 1006f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 1016f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen void run(raw_ostream &o); 1026f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 1036f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen}; 1046f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} // End anonymous namespace 1056f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 1067dc02047fbb4b014e914458f54ea539c8ae58316Jim Laskey// 107581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// Enumeration - Emit the specified class as an enumeration. 108b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// 1091a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::Enumeration(raw_ostream &OS, 110581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey const char *ClassName, 111581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey bool isBits) { 112908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // Get all records of class and sort 113f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName); 11442d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina std::sort(DefList.begin(), DefList.end(), LessRecord()); 1154bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey 116b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng unsigned N = DefList.size(); 11794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng if (N == 0) 11894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng return; 119b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng if (N > 64) { 120b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng errs() << "Too many (> 64) subtarget features!\n"; 121b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng exit(1); 122b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng } 123b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng 12494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "namespace " << Target << " {\n"; 12594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 126ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // For bit flag enumerations with more than 32 items, emit constants. 127ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // Emit an enum for everything else. 128ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen if (isBits && N > 32) { 129ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // For each record 130ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen for (unsigned i = 0; i < N; i++) { 131ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // Next record 132ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen Record *Def = DefList[i]; 13394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 134ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // Get and emit name and expression (1 << i) 135ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen OS << " const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n"; 136ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen } 137ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen } else { 138ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // Open enumeration 139ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen OS << "enum {\n"; 140da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 141ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // For each record 142ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen for (unsigned i = 0; i < N;) { 143ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // Next record 144ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen Record *Def = DefList[i]; 145da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 146ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // Get and emit name 147ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen OS << " " << Def->getName(); 148908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey 149ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // If bit flags then emit expression (1 << i) 150ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen if (isBits) OS << " = " << " 1ULL << " << i; 151da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 152ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // Depending on 'if more in the list' emit comma 153ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen if (++i < N) OS << ","; 154ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen 155ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen OS << "\n"; 156ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen } 157da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 158ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen // Close enumeration 159ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen OS << "};\n"; 160ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen } 16194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 16294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "}\n"; 163b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey} 164b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey 165b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// 1664222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling// FeatureKeyValues - Emit data of all the subtarget features. Used by the 1674222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling// command line. 168b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// 16994214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengunsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { 170908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // Gather and sort all the features 171f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey std::vector<Record*> FeatureList = 172f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey Records.getAllDerivedDefinitions("SubtargetFeature"); 17394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 17494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng if (FeatureList.empty()) 17594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng return 0; 17694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 1777c9a7728d9dd248ebee8f2dd969d303711d487a9Jim Grosbach std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName()); 178b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey 179908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // Begin feature table 180581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey OS << "// Sorted (by key) array of values for CPU features.\n" 1811a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer << "extern const llvm::SubtargetFeatureKV " << Target 1821a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer << "FeatureKV[] = {\n"; 183da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 184908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // For each feature 18594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng unsigned NumFeatures = 0; 186dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) { 187f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey // Next feature 188f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey Record *Feature = FeatureList[i]; 189f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey 1904222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling const std::string &Name = Feature->getName(); 1914222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling const std::string &CommandLineName = Feature->getValueAsString("Name"); 1924222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling const std::string &Desc = Feature->getValueAsString("Desc"); 193da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 194dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey if (CommandLineName.empty()) continue; 195da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 196da4231f134989af7dc6bd3408821ba573def27b2Jim Grosbach // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in } 197b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey OS << " { " 198f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey << "\"" << CommandLineName << "\", " 199b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey << "\"" << Desc << "\", " 20094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng << Target << "::" << Name << ", "; 2014222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling 202da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick const std::vector<Record*> &ImpliesList = 2034222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling Feature->getValueAsListOfDefs("Implies"); 204da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 2054222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling if (ImpliesList.empty()) { 206b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng OS << "0ULL"; 2074222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling } else { 2084222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling for (unsigned j = 0, M = ImpliesList.size(); j < M;) { 20994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << Target << "::" << ImpliesList[j]->getName(); 2104222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling if (++j < M) OS << " | "; 2114222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling } 2124222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling } 2134222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling 2144222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling OS << " }"; 21594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng ++NumFeatures; 216da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 21710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey // Depending on 'if more in the list' emit comma 218dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey if ((i + 1) < N) OS << ","; 219da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 220f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey OS << "\n"; 221b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey } 222da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 223908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // End feature table 224b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey OS << "};\n"; 225b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey 22694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng return NumFeatures; 227b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey} 228b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey 229b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// 230b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// CPUKeyValues - Emit data of all the subtarget processors. Used by command 231b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// line. 232b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// 23394214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengunsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { 234908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // Gather and sort processor information 235f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey std::vector<Record*> ProcessorList = 236f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey Records.getAllDerivedDefinitions("Processor"); 23742d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName()); 238b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey 239908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // Begin processor table 240581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey OS << "// Sorted (by key) array of values for CPU subtype.\n" 2411a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer << "extern const llvm::SubtargetFeatureKV " << Target 2421a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer << "SubTypeKV[] = {\n"; 243da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 244908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // For each processor 245f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey for (unsigned i = 0, N = ProcessorList.size(); i < N;) { 246f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey // Next processor 247f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey Record *Processor = ProcessorList[i]; 248f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey 2494222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling const std::string &Name = Processor->getValueAsString("Name"); 250da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick const std::vector<Record*> &FeatureList = 251b0e103d46bf8799ac5523157a6ed4a78d1751a89Chris Lattner Processor->getValueAsListOfDefs("Features"); 252da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 253908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // Emit as { "cpu", "description", f1 | f2 | ... fn }, 254b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey OS << " { " 255b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey << "\"" << Name << "\", " 256b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey << "\"Select the " << Name << " processor\", "; 257da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 258f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey if (FeatureList.empty()) { 259b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng OS << "0ULL"; 260b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey } else { 261f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey for (unsigned j = 0, M = FeatureList.size(); j < M;) { 26294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << Target << "::" << FeatureList[j]->getName(); 263f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey if (++j < M) OS << " | "; 2644bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey } 2654bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey } 266da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 2674222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling // The "0" is for the "implies" section of this data structure. 268b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng OS << ", 0ULL }"; 269da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 27010b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey // Depending on 'if more in the list' emit comma 271f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey if (++i < N) OS << ","; 272da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 273f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey OS << "\n"; 2744bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey } 275da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 276908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // End processor table 277b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey OS << "};\n"; 278b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey 27994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng return ProcessorList.size(); 2804bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey} 281b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey 282581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// 283fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// FormItineraryStageString - Compose a string containing the stage 284fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// data initialization for the specified itinerary. N is the number 285fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// of stages. 2860d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey// 287928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikovvoid SubtargetEmitter::FormItineraryStageString(const std::string &Name, 288928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov Record *ItinData, 289fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin std::string &ItinString, 290fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin unsigned &NStages) { 291f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey // Get states list 2924222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling const std::vector<Record*> &StageList = 2934222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling ItinData->getValueAsListOfDefs("Stages"); 294908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey 295908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // For each stage 296f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey unsigned N = NStages = StageList.size(); 2978dadf6b13a7cdd5b5b30c3b7af310c9756e4c68eChristopher Lamb for (unsigned i = 0; i < N;) { 298f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey // Next stage 2994222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling const Record *Stage = StageList[i]; 300da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 30196085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind } 3020d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey int Cycles = Stage->getValueAsInt("Cycles"); 3037f39c14f52262a154285df9180f5edcdabe2d7dfJim Laskey ItinString += " { " + itostr(Cycles) + ", "; 304da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 305f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey // Get unit list 3064222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units"); 307da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 308908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // For each unit 309f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey for (unsigned j = 0, M = UnitList.size(); j < M;) { 310f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey // Add name and bitwise or 311928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov ItinString += Name + "FU::" + UnitList[j]->getName(); 312f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey if (++j < M) ItinString += " | "; 3130d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey } 314da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 3151a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin int TimeInc = Stage->getValueAsInt("TimeInc"); 3161a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin ItinString += ", " + itostr(TimeInc); 3171a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin 31896085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov int Kind = Stage->getValueAsInt("Kind"); 31996085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind); 32096085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov 321908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // Close off stage 322908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey ItinString += " }"; 3238dadf6b13a7cdd5b5b30c3b7af310c9756e4c68eChristopher Lamb if (++i < N) ItinString += ", "; 3240d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey } 3250d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey} 3260d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey 3270d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey// 328fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// FormItineraryOperandCycleString - Compose a string containing the 329fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// operand cycle initialization for the specified itinerary. N is the 330fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// number of operands that has cycles specified. 3310d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey// 332fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwinvoid SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData, 333fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin std::string &ItinString, unsigned &NOperandCycles) { 334fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // Get operand cycle list 335fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin const std::vector<int64_t> &OperandCycleList = 336fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin ItinData->getValueAsListOfInts("OperandCycles"); 337fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin 338fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // For each operand cycle 339fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin unsigned N = NOperandCycles = OperandCycleList.size(); 340fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin for (unsigned i = 0; i < N;) { 341fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // Next operand cycle 342fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin const int OCycle = OperandCycleList[i]; 343da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 344fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin ItinString += " " + itostr(OCycle); 345fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin if (++i < N) ItinString += ", "; 346fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin } 347fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin} 348fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin 34963d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Chengvoid SubtargetEmitter::FormItineraryBypassString(const std::string &Name, 35063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng Record *ItinData, 35163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng std::string &ItinString, 35263d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng unsigned NOperandCycles) { 35363d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng const std::vector<Record*> &BypassList = 35463d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng ItinData->getValueAsListOfDefs("Bypasses"); 35563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng unsigned N = BypassList.size(); 3563881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng unsigned i = 0; 3573881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng for (; i < N;) { 35863d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng ItinString += Name + "Bypass::" + BypassList[i]->getName(); 3593881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng if (++i < NOperandCycles) ItinString += ", "; 36063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng } 3613881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng for (; i < NOperandCycles;) { 36263d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng ItinString += " 0"; 3633881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng if (++i < NOperandCycles) ItinString += ", "; 36463d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng } 36563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng} 36663d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng 367fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// 3682661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitStageAndOperandCycleData - Generate unique itinerary stages and operand 3692661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed 3702661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// by CodeGenSchedClass::Index. 371fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// 3722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter:: 3732661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew TrickEmitStageAndOperandCycleData(raw_ostream &OS, 3742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick std::vector<std::vector<InstrItinerary> > 3752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick &ProcItinLists) { 376908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey 377cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick // Multiple processor models may share an itinerary record. Emit it once. 378cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick SmallPtrSet<Record*, 8> ItinsDefSet; 379cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick 380928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov // Emit functional units for all the itineraries. 3812661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), 3822661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick PE = SchedModels.procModelEnd(); PI != PE; ++PI) { 383928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov 384cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick if (!ItinsDefSet.insert(PI->ItinsDef)) 385cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick continue; 386cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick 3872661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU"); 388928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov if (FUs.empty()) 389928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov continue; 390928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov 3912661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick const std::string &Name = PI->ItinsDef->getName(); 3922661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << "\n// Functional units for \"" << Name << "\"\n" 393928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov << "namespace " << Name << "FU {\n"; 394928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov 395928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j) 396b460a3382961c5be9952a75d46228f624edbd39fHal Finkel OS << " const unsigned " << FUs[j]->getName() 397b460a3382961c5be9952a75d46228f624edbd39fHal Finkel << " = 1 << " << j << ";\n"; 398928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov 399928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov OS << "}\n"; 40063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng 4012661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP"); 4023881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng if (BPs.size()) { 4033881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name 4043881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng << "\"\n" << "namespace " << Name << "Bypass {\n"; 40563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng 4061a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer OS << " const unsigned NoBypass = 0;\n"; 4073881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j) 4081a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer OS << " const unsigned " << BPs[j]->getName() 4093881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng << " = 1 << " << j << ";\n"; 41063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng 4113881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng OS << "}\n"; 4123881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng } 413928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov } 414928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov 415908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // Begin stages table 4161a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer std::string StageTable = "\nextern const llvm::InstrStage " + Target + 4171a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer "Stages[] = {\n"; 41896085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n"; 419da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 420fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // Begin operand cycle table 4211a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer std::string OperandCycleTable = "extern const unsigned " + Target + 42294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng "OperandCycles[] = {\n"; 423fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin OperandCycleTable += " 0, // No itinerary\n"; 42463d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng 42563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng // Begin pipeline bypass table 4261a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer std::string BypassTable = "extern const unsigned " + Target + 427a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick "ForwardingPaths[] = {\n"; 4282661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick BypassTable += " 0, // No itinerary\n"; 429da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 4302661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // For each Itinerary across all processors, add a unique entry to the stages, 4312661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // operand cycles, and pipepine bypess tables. Then add the new Itinerary 4322661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // object with computed offsets to the ProcItinLists result. 433fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin unsigned StageCount = 1, OperandCycleCount = 1; 4343881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng std::map<std::string, unsigned> ItinStageMap, ItinOperandMap; 4352661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), 4362661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick PE = SchedModels.procModelEnd(); PI != PE; ++PI) { 4372661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick const CodeGenProcModel &ProcModel = *PI; 438da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 4392661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // Add process itinerary to the list. 4402661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick ProcItinLists.resize(ProcItinLists.size()+1); 441d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick 4422661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // If this processor defines no itineraries, then leave the itinerary list 4432661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // empty. 4442661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick std::vector<InstrItinerary> &ItinList = ProcItinLists.back(); 4452661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick if (ProcModel.ItinDefList.empty()) 446d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick continue; 447d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick 4482661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // Reserve index==0 for NoItinerary. 4492661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick ItinList.resize(SchedModels.numItineraryClasses()+1); 4502661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick 4512661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick const std::string &Name = ProcModel.ItinsDef->getName(); 452da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 453f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey // For each itinerary data 4542661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick for (unsigned SchedClassIdx = 0, 4552661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick SchedClassEnd = ProcModel.ItinDefList.size(); 4562661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick SchedClassIdx < SchedClassEnd; ++SchedClassIdx) { 4572661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick 458f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey // Next itinerary data 4592661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick Record *ItinData = ProcModel.ItinDefList[SchedClassIdx]; 460da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 461908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // Get string and stage count 462fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin std::string ItinStageString; 4632661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick unsigned NStages = 0; 4642661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick if (ItinData) 4652661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick FormItineraryStageString(Name, ItinData, ItinStageString, NStages); 466fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin 467fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // Get string and operand cycle count 468fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin std::string ItinOperandCycleString; 4692661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick unsigned NOperandCycles = 0; 47063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng std::string ItinBypassString; 4712661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick if (ItinData) { 4722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick FormItineraryOperandCycleString(ItinData, ItinOperandCycleString, 4732661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick NOperandCycles); 4742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick 4752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick FormItineraryBypassString(Name, ItinData, ItinBypassString, 4762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick NOperandCycles); 4772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick } 47863d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng 479fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // Check to see if stage already exists and create if it doesn't 480fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin unsigned FindStage = 0; 481fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin if (NStages > 0) { 482fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin FindStage = ItinStageMap[ItinStageString]; 483fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin if (FindStage == 0) { 484234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices 485234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick StageTable += ItinStageString + ", // " + itostr(StageCount); 486234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick if (NStages > 1) 487234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick StageTable += "-" + itostr(StageCount + NStages - 1); 488234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick StageTable += "\n"; 489fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // Record Itin class number. 490fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin ItinStageMap[ItinStageString] = FindStage = StageCount; 491fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin StageCount += NStages; 492fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin } 493fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin } 494da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 495fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // Check to see if operand cycle already exists and create if it doesn't 496fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin unsigned FindOperandCycle = 0; 497fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin if (NOperandCycles > 0) { 4983881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng std::string ItinOperandString = ItinOperandCycleString+ItinBypassString; 4993881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng FindOperandCycle = ItinOperandMap[ItinOperandString]; 500fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin if (FindOperandCycle == 0) { 501fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // Emit as cycle, // index 502234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick OperandCycleTable += ItinOperandCycleString + ", // "; 503234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick std::string OperandIdxComment = itostr(OperandCycleCount); 504234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick if (NOperandCycles > 1) 505234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick OperandIdxComment += "-" 506234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick + itostr(OperandCycleCount + NOperandCycles - 1); 507234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick OperandCycleTable += OperandIdxComment + "\n"; 508fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // Record Itin class number. 509da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick ItinOperandMap[ItinOperandCycleString] = 510fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin FindOperandCycle = OperandCycleCount; 51163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng // Emit as bypass, // index 512234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n"; 513fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin OperandCycleCount += NOperandCycles; 514fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin } 5150d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey } 516da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 5175f54ce347368105260be2cec497b6a4199dc5789Evan Cheng // Set up itinerary as location and location + stage count 5182661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0; 5195f54ce347368105260be2cec497b6a4199dc5789Evan Cheng InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages, 5205f54ce347368105260be2cec497b6a4199dc5789Evan Cheng FindOperandCycle, 5215f54ce347368105260be2cec497b6a4199dc5789Evan Cheng FindOperandCycle + NOperandCycles}; 5225f54ce347368105260be2cec497b6a4199dc5789Evan Cheng 523908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // Inject - empty slots will be 0, 0 5242661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick ItinList[SchedClassIdx] = Intinerary; 5250d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey } 5260d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey } 52763d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng 5287f39c14f52262a154285df9180f5edcdabe2d7dfJim Laskey // Closing stage 5292661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End stages\n"; 530fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin StageTable += "};\n"; 531fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin 532fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // Closing operand cycles 5332661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OperandCycleTable += " 0 // End operand cycles\n"; 534fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin OperandCycleTable += "};\n"; 535fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin 5362661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick BypassTable += " 0 // End bypass tables\n"; 53763d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng BypassTable += "};\n"; 53863d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng 539fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin // Emit tables. 540fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin OS << StageTable; 541fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin OS << OperandCycleTable; 54263d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng OS << BypassTable; 5430d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey} 5440d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey 5450d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey// 5462661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitProcessorData - Generate data for processor itineraries that were 5472661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// computed during EmitStageAndOperandCycleData(). ProcItinLists lists all 5482661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// Itineraries for each processor. The Itinerary lists are indexed on 5492661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// CodeGenSchedClass::Index. 5500d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey// 551234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trickvoid SubtargetEmitter:: 5522661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew TrickEmitItineraries(raw_ostream &OS, 5532661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick std::vector<std::vector<InstrItinerary> > &ProcItinLists) { 554fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick 555cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick // Multiple processor models may share an itinerary record. Emit it once. 556cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick SmallPtrSet<Record*, 8> ItinsDefSet; 557cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick 5582661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // For each processor's machine model 559f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey std::vector<std::vector<InstrItinerary> >::iterator 5602661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick ProcItinListsIter = ProcItinLists.begin(); 5612661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), 56248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) { 563cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick 5642661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick Record *ItinsDef = PI->ItinsDef; 565cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick if (!ItinsDefSet.insert(ItinsDef)) 566cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick continue; 567f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey 568908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey // Get processor itinerary name 5692661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick const std::string &Name = ItinsDef->getName(); 570da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 5712661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // Get the itinerary list for the processor. 5722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator"); 57348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick std::vector<InstrItinerary> &ItinList = *ProcItinListsIter; 574fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick 5752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << "\n"; 5762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << "static const llvm::InstrItinerary "; 5772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick if (ItinList.empty()) { 5782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << '*' << Name << " = 0;\n"; 5792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick continue; 5802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick } 581da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 5822661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // Begin processor itinerary table 5832661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << Name << "[] = {\n"; 5842661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick 5852661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // For each itinerary class in CodeGenSchedClass::Index order. 5862661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick for (unsigned j = 0, M = ItinList.size(); j < M; ++j) { 5872661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick InstrItinerary &Intinerary = ItinList[j]; 5882661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick 5892661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // Emit Itinerary in the form of 5902661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // { firstStage, lastStage, firstCycle, lastCycle } // index 5912661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << " { " << 5922661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick Intinerary.NumMicroOps << ", " << 5932661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick Intinerary.FirstStage << ", " << 5942661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick Intinerary.LastStage << ", " << 5952661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick Intinerary.FirstOperandCycle << ", " << 5962661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick Intinerary.LastOperandCycle << " }" << 5972661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n"; 5980d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey } 5992661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // End processor itinerary table 6002661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << " { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n"; 601fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick OS << "};\n"; 6020d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey } 60310b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey} 60410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey 605c8e41c591741b3da1077f7000274ad040bef8002Sylvestre Ledru// Emit either the value defined in the TableGen Record, or the default 6062661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// value defined in the C++ header. The Record is null if the processor does not 6072661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// define a model. 6082661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R, 6092661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick const char *Name, char Separator) { 6102661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << " "; 6112661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick int V = R ? R->getValueAsInt(Name) : -1; 6122661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick if (V >= 0) 6132661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << V << Separator << " // " << Name; 6142661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick else 6152661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << "MCSchedModel::Default" << Name << Separator; 6162661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << '\n'; 6172661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick} 6182661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick 61940096d26937cd47c865464bef7b28550bc20c631Andrew Trickvoid SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel, 62040096d26937cd47c865464bef7b28550bc20c631Andrew Trick raw_ostream &OS) { 62140096d26937cd47c865464bef7b28550bc20c631Andrew Trick char Sep = ProcModel.ProcResourceDefs.empty() ? ' ' : ','; 62240096d26937cd47c865464bef7b28550bc20c631Andrew Trick 62340096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << "\n// {Name, NumUnits, SuperIdx}\n"; 62440096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << "static const llvm::MCProcResourceDesc " 62540096d26937cd47c865464bef7b28550bc20c631Andrew Trick << ProcModel.ModelName << "ProcResources" << "[] = {\n" 62640096d26937cd47c865464bef7b28550bc20c631Andrew Trick << " {DBGFIELD(\"InvalidUnit\") 0, 0}" << Sep << "\n"; 62740096d26937cd47c865464bef7b28550bc20c631Andrew Trick 62840096d26937cd47c865464bef7b28550bc20c631Andrew Trick for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) { 62940096d26937cd47c865464bef7b28550bc20c631Andrew Trick Record *PRDef = ProcModel.ProcResourceDefs[i]; 63040096d26937cd47c865464bef7b28550bc20c631Andrew Trick 63140096d26937cd47c865464bef7b28550bc20c631Andrew Trick // Find the SuperIdx 63240096d26937cd47c865464bef7b28550bc20c631Andrew Trick unsigned SuperIdx = 0; 63340096d26937cd47c865464bef7b28550bc20c631Andrew Trick Record *SuperDef = 0; 63440096d26937cd47c865464bef7b28550bc20c631Andrew Trick if (PRDef->getValueInit("Super")->isComplete()) { 63540096d26937cd47c865464bef7b28550bc20c631Andrew Trick SuperDef = 63640096d26937cd47c865464bef7b28550bc20c631Andrew Trick SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), ProcModel); 63740096d26937cd47c865464bef7b28550bc20c631Andrew Trick SuperIdx = ProcModel.getProcResourceIdx(SuperDef); 63840096d26937cd47c865464bef7b28550bc20c631Andrew Trick } 63940096d26937cd47c865464bef7b28550bc20c631Andrew Trick // Emit the ProcResourceDesc 64040096d26937cd47c865464bef7b28550bc20c631Andrew Trick if (i+1 == e) 64140096d26937cd47c865464bef7b28550bc20c631Andrew Trick Sep = ' '; 64240096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << " {DBGFIELD(\"" << PRDef->getName() << "\") "; 64340096d26937cd47c865464bef7b28550bc20c631Andrew Trick if (PRDef->getName().size() < 15) 64440096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS.indent(15 - PRDef->getName().size()); 64540096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << PRDef->getValueAsInt("NumUnits") << ", " << SuperIdx 64640096d26937cd47c865464bef7b28550bc20c631Andrew Trick << "}" << Sep << " // #" << i+1; 64740096d26937cd47c865464bef7b28550bc20c631Andrew Trick if (SuperDef) 64840096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << ", Super=" << SuperDef->getName(); 64940096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << "\n"; 65040096d26937cd47c865464bef7b28550bc20c631Andrew Trick } 65140096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << "};\n"; 65240096d26937cd47c865464bef7b28550bc20c631Andrew Trick} 65340096d26937cd47c865464bef7b28550bc20c631Andrew Trick 65452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// Find the WriteRes Record that defines processor resources for this 65552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// SchedWrite. 65652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew TrickRecord *SubtargetEmitter::FindWriteResources( 65752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick Record *WriteDef, const CodeGenProcModel &ProcModel) { 65852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 65952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Check if the SchedWrite is already subtarget-specific and directly 66052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // specifies a set of processor resources. 66152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (WriteDef->isSubClassOf("SchedWriteRes")) 66252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick return WriteDef; 66352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 66452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Check this processor's list of write resources. 66552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for (RecIter WRI = ProcModel.WriteResDefs.begin(), 66652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) { 66752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (!(*WRI)->isSubClassOf("WriteRes")) 66852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick continue; 66952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (WriteDef == (*WRI)->getValueAsDef("WriteType")) 67052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick return *WRI; 67152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 67252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick throw TGError(ProcModel.ModelDef->getLoc(), 67352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::string("Processor does not define resources for ") 67452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick + WriteDef->getName()); 67552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick} 67652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 67752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick/// Find the ReadAdvance record for the given SchedRead on this processor or 67852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick/// return NULL. 67952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew TrickRecord *SubtargetEmitter::FindReadAdvance(Record *ReadDef, 68052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick const CodeGenProcModel &ProcModel) { 68152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Check for SchedReads that directly specify a ReadAdvance. 68252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (ReadDef->isSubClassOf("SchedReadAdvance")) 68352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick return ReadDef; 68452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 68552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Check this processor's ReadAdvanceList. 68652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(), 68752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) { 68852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (!(*RAI)->isSubClassOf("ReadAdvance")) 68952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick continue; 69052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (ReadDef == (*RAI)->getValueAsDef("ReadType")) 69152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick return *RAI; 69252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 69352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (ReadDef->getName() != "ReadDefault") { 69452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick throw TGError(ProcModel.ModelDef->getLoc(), 69552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::string("Processor does not define resources for ") 69652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick + ReadDef->getName()); 69752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 69852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick return NULL; 69952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick} 70052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 70152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// Generate the SchedClass table for this processor and update global 70252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// tables. Must be called for each processor in order. 70352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trickvoid SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, 70452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedClassTables &SchedTables) { 70552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedTables.ProcSchedClasses.resize(SchedTables.ProcSchedClasses.size() + 1); 70652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (!ProcModel.hasInstrSchedModel()) 70752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick return; 70852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 70952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back(); 71052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(), 71152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) { 71252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCTab.resize(SCTab.size() + 1); 71352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick MCSchedClassDesc &SCDesc = SCTab.back(); 714e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick // SCDesc.Name is guarded by NDEBUG 71552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.NumMicroOps = 0; 71652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.BeginGroup = false; 71752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.EndGroup = false; 71852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.WriteProcResIdx = 0; 71952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.WriteLatencyIdx = 0; 72052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.ReadAdvanceIdx = 0; 72152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 72252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // A Variant SchedClass has no resources of its own. 72352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (!SCI->Transitions.empty()) { 72452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps; 72552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick continue; 72652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 72752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 72852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Determine if the SchedClass is actually reachable on this processor. If 72952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // not don't try to locate the processor resources, it will fail. 73052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // If ProcIndices contains 0, this class applies to all processors. 73152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick assert(!SCI->ProcIndices.empty() && "expect at least one procidx"); 73252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (SCI->ProcIndices[0] != 0) { 73352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick IdxIter PIPos = std::find(SCI->ProcIndices.begin(), 73452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCI->ProcIndices.end(), ProcModel.Index); 73552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (PIPos == SCI->ProcIndices.end()) 73652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick continue; 73752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 73852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick IdxVec Writes = SCI->Writes; 73952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick IdxVec Reads = SCI->Reads; 74052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (SCI->ItinClassDef) { 74152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick assert(SCI->InstRWs.empty() && "ItinClass should not have InstRWs"); 74252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Check this processor's itinerary class resources. 74352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for (RecIter II = ProcModel.ItinRWDefs.begin(), 74452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) { 74552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses"); 74652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef) 74752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick != Matched.end()) { 74852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), 74952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick Writes, Reads); 75052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick break; 75152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 75252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 75352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (Writes.empty()) { 75452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick DEBUG(dbgs() << ProcModel.ItinsDef->getName() 75552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick << " does not have resources for itinerary class " 75652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick << SCI->ItinClassDef->getName() << '\n'); 75752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 75852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 75952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick else if (!SCI->InstRWs.empty()) { 76052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick assert(SCI->Writes.empty() && SCI->Reads.empty() && 76152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick "InstRW class should not have its own ReadWrites"); 76252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick Record *RWDef = 0; 76352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end(); 76452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick RWI != RWE; ++RWI) { 76552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel"); 76652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) { 76752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick RWDef = *RWI; 76852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick break; 76952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 77052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 77152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (RWDef) { 77252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"), 77352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick Writes, Reads); 77452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 77552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 77652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Sum resources across all operand writes. 77752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<MCWriteProcResEntry> WriteProcResources; 77852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<MCWriteLatencyEntry> WriteLatencies; 7793b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick std::vector<std::string> WriterNames; 78052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<MCReadAdvanceEntry> ReadAdvanceEntries; 78152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) { 78252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick IdxVec WriteSeq; 78352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedModels.expandRWSequence(*WI, WriteSeq, /*IsRead=*/false); 78452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 78552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // For each operand, create a latency entry. 78652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick MCWriteLatencyEntry WLEntry; 78752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WLEntry.Cycles = 0; 7883b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick unsigned WriteID = WriteSeq.back(); 7893b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name); 7903b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick // If this Write is not referenced by a ReadAdvance, don't distinguish it 7913b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick // from other WriteLatency entries. 7923b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick if (!SchedModels.hasReadOfWrite(SchedModels.getSchedWrite(WriteID).TheDef)) { 7933b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick WriteID = 0; 7943b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick } 7953b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick WLEntry.WriteResourceID = WriteID; 79652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 79752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end(); 79852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WSI != WSE; ++WSI) { 79952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 80052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick Record *WriteDef = SchedModels.getSchedWrite(*WSI).TheDef; 80152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick Record *WriteRes = FindWriteResources(WriteDef, ProcModel); 80252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 80352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Mark the parent class as invalid for unsupported write types. 80452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (WriteRes->getValueAsBit("Unsupported")) { 80552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps; 80652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick break; 80752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 80852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WLEntry.Cycles += WriteRes->getValueAsInt("Latency"); 80952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.NumMicroOps += WriteRes->getValueAsInt("NumMicroOps"); 81052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.BeginGroup |= WriteRes->getValueAsBit("BeginGroup"); 81152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup"); 81252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 81352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Create an entry for each ProcResource listed in WriteRes. 81452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources"); 81552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<int64_t> Cycles = 81652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteRes->getValueAsListOfInts("ResourceCycles"); 81752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for (unsigned PRIdx = 0, PREnd = PRVec.size(); 81852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick PRIdx != PREnd; ++PRIdx) { 81952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick MCWriteProcResEntry WPREntry; 82052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]); 82152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx"); 82252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (Cycles.size() > PRIdx) 82352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WPREntry.Cycles = Cycles[PRIdx]; 82452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick else 82552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WPREntry.Cycles = 1; 82652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteProcResources.push_back(WPREntry); 82752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 82852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 82952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteLatencies.push_back(WLEntry); 83052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 83152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Create an entry for each operand Read in this SchedClass. 83252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Entries must be sorted first by UseIdx then by WriteResourceID. 83352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for (unsigned UseIdx = 0, EndIdx = Reads.size(); 83452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick UseIdx != EndIdx; ++UseIdx) { 83552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick Record *ReadDef = SchedModels.getSchedRead(Reads[UseIdx]).TheDef; 83652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick Record *ReadAdvance = FindReadAdvance(ReadDef, ProcModel); 83752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (!ReadAdvance) 83852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick continue; 83952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 84052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Mark the parent class as invalid for unsupported write types. 84152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (ReadAdvance->getValueAsBit("Unsupported")) { 84252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps; 84352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick break; 84452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 84552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick RecVec ValidWrites = ReadAdvance->getValueAsListOfDefs("ValidWrites"); 84652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick IdxVec WriteIDs; 84752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (ValidWrites.empty()) 84852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteIDs.push_back(0); 84952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick else { 85052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for (RecIter VWI = ValidWrites.begin(), VWE = ValidWrites.end(); 85152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick VWI != VWE; ++VWI) { 85252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteIDs.push_back(SchedModels.getSchedRWIdx(*VWI, /*IsRead=*/false)); 85352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 85452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 85552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::sort(WriteIDs.begin(), WriteIDs.end()); 85652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for(IdxIter WI = WriteIDs.begin(), WE = WriteIDs.end(); WI != WE; ++WI) { 85752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick MCReadAdvanceEntry RAEntry; 85852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick RAEntry.UseIdx = UseIdx; 85952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick RAEntry.WriteResourceID = *WI; 86052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles"); 86152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick ReadAdvanceEntries.push_back(RAEntry); 86252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 86352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 86452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) { 86552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteProcResources.clear(); 86652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteLatencies.clear(); 86752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick ReadAdvanceEntries.clear(); 86852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 86952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Add the information for this SchedClass to the global tables using basic 87052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // compression. 87152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // 87252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // WritePrecRes entries are sorted by ProcResIdx. 87352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::sort(WriteProcResources.begin(), WriteProcResources.end(), 87452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick LessWriteProcResources()); 87552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 87652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.NumWriteProcResEntries = WriteProcResources.size(); 87752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<MCWriteProcResEntry>::iterator WPRPos = 87852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::search(SchedTables.WriteProcResources.begin(), 87952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedTables.WriteProcResources.end(), 88052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteProcResources.begin(), WriteProcResources.end()); 88152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (WPRPos != SchedTables.WriteProcResources.end()) 88252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin(); 88352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick else { 88452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.WriteProcResIdx = SchedTables.WriteProcResources.size(); 88552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedTables.WriteProcResources.insert(WPRPos, WriteProcResources.begin(), 88652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteProcResources.end()); 88752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 88852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // Latency entries must remain in operand order. 88952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.NumWriteLatencyEntries = WriteLatencies.size(); 89052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<MCWriteLatencyEntry>::iterator WLPos = 89152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::search(SchedTables.WriteLatencies.begin(), 89252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedTables.WriteLatencies.end(), 89352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick WriteLatencies.begin(), WriteLatencies.end()); 8943b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick if (WLPos != SchedTables.WriteLatencies.end()) { 8953b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick unsigned idx = WLPos - SchedTables.WriteLatencies.begin(); 8963b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick SCDesc.WriteLatencyIdx = idx; 8973b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick for (unsigned i = 0, e = WriteLatencies.size(); i < e; ++i) 8983b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick if (SchedTables.WriterNames[idx + i].find(WriterNames[i]) == 8993b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick std::string::npos) { 9003b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick SchedTables.WriterNames[idx + i] += std::string("_") + WriterNames[i]; 9013b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick } 9023b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick } 90352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick else { 90452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size(); 9053b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick SchedTables.WriteLatencies.insert(SchedTables.WriteLatencies.end(), 9063b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick WriteLatencies.begin(), 9073b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick WriteLatencies.end()); 9083b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick SchedTables.WriterNames.insert(SchedTables.WriterNames.end(), 9093b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick WriterNames.begin(), WriterNames.end()); 91052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 91152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick // ReadAdvanceEntries must remain in operand order. 91252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size(); 91352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::vector<MCReadAdvanceEntry>::iterator RAPos = 91452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick std::search(SchedTables.ReadAdvanceEntries.begin(), 91552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedTables.ReadAdvanceEntries.end(), 91652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick ReadAdvanceEntries.begin(), ReadAdvanceEntries.end()); 91752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick if (RAPos != SchedTables.ReadAdvanceEntries.end()) 91852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin(); 91952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick else { 92052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SCDesc.ReadAdvanceIdx = SchedTables.ReadAdvanceEntries.size(); 92152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedTables.ReadAdvanceEntries.insert(RAPos, ReadAdvanceEntries.begin(), 92252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick ReadAdvanceEntries.end()); 92352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 92452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 92552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick} 92652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 927544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick// Emit SchedClass tables for all processors and associated global tables. 928544c88039f16706d6764c65fda276a11f2c586d6Andrew Trickvoid SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables, 929544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick raw_ostream &OS) { 930544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick // Emit global WriteProcResTable. 931544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "\n// {ProcResourceIdx, Cycles}\n" 932544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << "extern const llvm::MCWriteProcResEntry " 933544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << Target << "WriteProcResTable[] = {\n" 934544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << " { 0, 0}, // Invalid\n"; 935544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick for (unsigned WPRIdx = 1, WPREnd = SchedTables.WriteProcResources.size(); 936544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick WPRIdx != WPREnd; ++WPRIdx) { 937544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick MCWriteProcResEntry &WPREntry = SchedTables.WriteProcResources[WPRIdx]; 938544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << " {" << format("%2d", WPREntry.ProcResourceIdx) << ", " 939544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << format("%2d", WPREntry.Cycles) << "}"; 940544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick if (WPRIdx + 1 < WPREnd) 941544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << ','; 942544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << " // #" << WPRIdx << '\n'; 943544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick } 944544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "}; // " << Target << "WriteProcResTable\n"; 945544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick 946544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick // Emit global WriteLatencyTable. 947544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "\n// {Cycles, WriteResourceID}\n" 948544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << "extern const llvm::MCWriteLatencyEntry " 949544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << Target << "WriteLatencyTable[] = {\n" 950544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << " { 0, 0}, // Invalid\n"; 951544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick for (unsigned WLIdx = 1, WLEnd = SchedTables.WriteLatencies.size(); 952544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick WLIdx != WLEnd; ++WLIdx) { 953544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick MCWriteLatencyEntry &WLEntry = SchedTables.WriteLatencies[WLIdx]; 954544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << " {" << format("%2d", WLEntry.Cycles) << ", " 955544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << format("%2d", WLEntry.WriteResourceID) << "}"; 956544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick if (WLIdx + 1 < WLEnd) 957544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << ','; 9583b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick OS << " // #" << WLIdx << " " << SchedTables.WriterNames[WLIdx] << '\n'; 959544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick } 960544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "}; // " << Target << "WriteLatencyTable\n"; 961544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick 962544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick // Emit global ReadAdvanceTable. 963544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "\n// {UseIdx, WriteResourceID, Cycles}\n" 964544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << "extern const llvm::MCReadAdvanceEntry " 965544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << Target << "ReadAdvanceTable[] = {\n" 966544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << " {0, 0, 0}, // Invalid\n"; 967544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick for (unsigned RAIdx = 1, RAEnd = SchedTables.ReadAdvanceEntries.size(); 968544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick RAIdx != RAEnd; ++RAIdx) { 969544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick MCReadAdvanceEntry &RAEntry = SchedTables.ReadAdvanceEntries[RAIdx]; 970544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << " {" << RAEntry.UseIdx << ", " 971544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << format("%2d", RAEntry.WriteResourceID) << ", " 972544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << format("%2d", RAEntry.Cycles) << "}"; 973544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick if (RAIdx + 1 < RAEnd) 974544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << ','; 975544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << " // #" << RAIdx << '\n'; 976544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick } 977544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "}; // " << Target << "ReadAdvanceTable\n"; 978544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick 979544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick // Emit a SchedClass table for each processor. 980544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), 981544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick PE = SchedModels.procModelEnd(); PI != PE; ++PI) { 982544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick if (!PI->hasInstrSchedModel()) 983544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick continue; 984544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick 985544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick std::vector<MCSchedClassDesc> &SCTab = 986544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick SchedTables.ProcSchedClasses[1 + PI - SchedModels.procModelBegin()]; 987544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick 988544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup," 989544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n"; 990544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "static const llvm::MCSchedClassDesc " 991544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << PI->ModelName << "SchedClasses[] = {\n"; 992544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick 993544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick // The first class is always invalid. We no way to distinguish it except by 994544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick // name and position. 995e4095f95ac2480aabbe289f41723b53ac1c82a98Andrew Trick assert(SchedModels.getSchedClass(0).Name == "NoItinerary" 996544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick && "invalid class not first"); 997544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << " {DBGFIELD(\"InvalidSchedClass\") " 998544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << MCSchedClassDesc::InvalidNumMicroOps 999544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << ", 0, 0, 0, 0, 0, 0, 0, 0},\n"; 1000544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick 1001544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) { 1002544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick MCSchedClassDesc &MCDesc = SCTab[SCIdx]; 1003544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick const CodeGenSchedClass &SchedClass = SchedModels.getSchedClass(SCIdx); 1004544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << " {DBGFIELD(\"" << SchedClass.Name << "\") "; 1005544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick if (SchedClass.Name.size() < 18) 1006544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS.indent(18 - SchedClass.Name.size()); 1007544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << MCDesc.NumMicroOps 1008544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << ", " << MCDesc.BeginGroup << ", " << MCDesc.EndGroup 1009544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << ", " << format("%2d", MCDesc.WriteProcResIdx) 1010544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << ", " << MCDesc.NumWriteProcResEntries 1011544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << ", " << format("%2d", MCDesc.WriteLatencyIdx) 1012544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << ", " << MCDesc.NumWriteLatencyEntries 1013544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << ", " << format("%2d", MCDesc.ReadAdvanceIdx) 1014544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << ", " << MCDesc.NumReadAdvanceEntries << "}"; 1015544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick if (SCIdx + 1 < SCEnd) 1016544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << ','; 1017544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << " // #" << SCIdx << '\n'; 1018544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick } 1019544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "}; // " << PI->ModelName << "SchedClasses\n"; 1020544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick } 1021544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick} 1022544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick 10232661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { 10242661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // For each processor model. 10252661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), 10262661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick PE = SchedModels.procModelEnd(); PI != PE; ++PI) { 102740096d26937cd47c865464bef7b28550bc20c631Andrew Trick // Emit processor resource table. 102840096d26937cd47c865464bef7b28550bc20c631Andrew Trick if (PI->hasInstrSchedModel()) 102940096d26937cd47c865464bef7b28550bc20c631Andrew Trick EmitProcessorResources(*PI, OS); 103040096d26937cd47c865464bef7b28550bc20c631Andrew Trick else if(!PI->ProcResourceDefs.empty()) 103140096d26937cd47c865464bef7b28550bc20c631Andrew Trick throw TGError(PI->ModelDef->getLoc(), "SchedMachineModel defines " 103252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick "ProcResources without defining WriteRes SchedWriteRes"); 103340096d26937cd47c865464bef7b28550bc20c631Andrew Trick 10342661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick // Begin processor itinerary properties 10352661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << "\n"; 10362661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n"; 10372661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ','); 10382661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ','); 10392661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ','); 10402661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ','); 1041d43b5c97cff06d7840b974ca84fa0639d2567968Andrew Trick EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ','); 1042e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << " " << PI->Index << ", // Processor ID\n"; 1043e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick if (PI->hasInstrSchedModel()) 1044e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << " " << PI->ModelName << "ProcResources" << ",\n" 1045e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick << " " << PI->ModelName << "SchedClasses" << ",\n" 1046e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick << " " << PI->ProcResourceDefs.size()+1 << ",\n" 1047e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick << " " << (SchedModels.schedClassEnd() 1048e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick - SchedModels.schedClassBegin()) << ",\n"; 1049e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick else 1050e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << " 0, 0, 0, 0, // No instruction-level machine model.\n"; 10512661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick if (SchedModels.hasItineraryClasses()) 105240096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << " " << PI->ItinsDef->getName() << ");\n"; 10532661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick else 105440096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << " 0); // No Itinerary\n"; 10552661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick } 10562661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick} 10572661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick 105810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey// 105910b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey// EmitProcessorLookup - generate cpu name to itinerary lookup table. 106010b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey// 10611a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { 106210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey // Gather and sort processor information 106310b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey std::vector<Record*> ProcessorList = 106410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey Records.getAllDerivedDefinitions("Processor"); 106542d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName()); 106610b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey 106710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey // Begin processor table 106810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey OS << "\n"; 106910b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey OS << "// Sorted (by key) array of itineraries for CPU subtype.\n" 10701a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer << "extern const llvm::SubtargetInfoKV " 10712661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick << Target << "ProcSchedKV[] = {\n"; 1072da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 107310b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey // For each processor 107410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey for (unsigned i = 0, N = ProcessorList.size(); i < N;) { 107510b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey // Next processor 107610b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey Record *Processor = ProcessorList[i]; 107710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey 10784222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling const std::string &Name = Processor->getValueAsString("Name"); 10792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick const std::string &ProcModelName = 108048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick SchedModels.getModelForProc(Processor).ModelName; 1081da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 108210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey // Emit as { "cpu", procinit }, 108340096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << " { \"" << Name << "\", (const void *)&" << ProcModelName << " }"; 1084da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 108510b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey // Depending on ''if more in the list'' emit comma 108610b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey if (++i < N) OS << ","; 1087da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 108810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey OS << "\n"; 108910b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey } 1090da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick 109110b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey // End processor table 109210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey OS << "};\n"; 10930d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey} 10940d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey 10950d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey// 10962661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitSchedModel - Emits all scheduling model tables, folding common patterns. 10970d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey// 10982661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitSchedModel(raw_ostream &OS) { 109940096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << "#ifdef DBGFIELD\n" 110040096d26937cd47c865464bef7b28550bc20c631Andrew Trick << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n" 110140096d26937cd47c865464bef7b28550bc20c631Andrew Trick << "#endif\n" 110240096d26937cd47c865464bef7b28550bc20c631Andrew Trick << "#ifndef NDEBUG\n" 110340096d26937cd47c865464bef7b28550bc20c631Andrew Trick << "#define DBGFIELD(x) x,\n" 110440096d26937cd47c865464bef7b28550bc20c631Andrew Trick << "#else\n" 110540096d26937cd47c865464bef7b28550bc20c631Andrew Trick << "#define DBGFIELD(x)\n" 110640096d26937cd47c865464bef7b28550bc20c631Andrew Trick << "#endif\n"; 110740096d26937cd47c865464bef7b28550bc20c631Andrew Trick 11082661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick if (SchedModels.hasItineraryClasses()) { 11092661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick std::vector<std::vector<InstrItinerary> > ProcItinLists; 11106cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey // Emit the stage data 11112661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick EmitStageAndOperandCycleData(OS, ProcItinLists); 11122661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick EmitItineraries(OS, ProcItinLists); 11136cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey } 1114544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "\n// ===============================================================\n" 1115544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << "// Data tables for the new per-operand machine model.\n"; 111640096d26937cd47c865464bef7b28550bc20c631Andrew Trick 111752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick SchedClassTables SchedTables; 111852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), 111952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick PE = SchedModels.procModelEnd(); PI != PE; ++PI) { 112052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick GenSchedClassTables(*PI, SchedTables); 112152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick } 1122544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick EmitSchedClassTables(SchedTables, OS); 1123544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick 1124544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick // Emit the processor machine model 1125544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick EmitProcessorModels(OS); 1126544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick // Emit the processor lookup data 1127544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick EmitProcessorLookup(OS); 112852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick 112940096d26937cd47c865464bef7b28550bc20c631Andrew Trick OS << "#undef DBGFIELD"; 11300d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey} 11310d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey 11324d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trickvoid SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName, 11334d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick raw_ostream &OS) { 11344d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << "unsigned " << ClassName 11354d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick << "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI," 11364d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick << " const TargetSchedModel *SchedModel) const {\n"; 11374d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick 11384d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick std::vector<Record*> Prologs = Records.getAllDerivedDefinitions("PredicateProlog"); 11394d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick std::sort(Prologs.begin(), Prologs.end(), LessRecord()); 11404d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick for (std::vector<Record*>::const_iterator 11414d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick PI = Prologs.begin(), PE = Prologs.end(); PI != PE; ++PI) { 11424d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << (*PI)->getValueAsString("Code") << '\n'; 11434d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick } 11444d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick IdxVec VariantClasses; 11454d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(), 11464d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) { 11474d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick if (SCI->Transitions.empty()) 11484d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick continue; 11494d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick VariantClasses.push_back(SCI - SchedModels.schedClassBegin()); 11504d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick } 11514d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick if (!VariantClasses.empty()) { 11524d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << " switch (SchedClass) {\n"; 11534d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick for (IdxIter VCI = VariantClasses.begin(), VCE = VariantClasses.end(); 11544d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick VCI != VCE; ++VCI) { 11554d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick const CodeGenSchedClass &SC = SchedModels.getSchedClass(*VCI); 11564d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << " case " << *VCI << ": // " << SC.Name << '\n'; 11574d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick IdxVec ProcIndices; 11584d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick for (std::vector<CodeGenSchedTransition>::const_iterator 11594d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick TI = SC.Transitions.begin(), TE = SC.Transitions.end(); 11604d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick TI != TE; ++TI) { 11614d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick IdxVec PI; 11624d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick std::set_union(TI->ProcIndices.begin(), TI->ProcIndices.end(), 11634d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick ProcIndices.begin(), ProcIndices.end(), 11644d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick std::back_inserter(PI)); 11654d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick ProcIndices.swap(PI); 11664d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick } 11674d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end(); 11684d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick PI != PE; ++PI) { 11694d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << " "; 11704d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick if (*PI != 0) 11714d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << "if (SchedModel->getProcessorID() == " << *PI << ") "; 11724d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << "{ // " << (SchedModels.procModelBegin() + *PI)->ModelName 11734d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick << '\n'; 11744d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick for (std::vector<CodeGenSchedTransition>::const_iterator 11754d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick TI = SC.Transitions.begin(), TE = SC.Transitions.end(); 11764d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick TI != TE; ++TI) { 11774d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << " if ("; 11784d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick if (*PI != 0 && !std::count(TI->ProcIndices.begin(), 11794d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick TI->ProcIndices.end(), *PI)) { 11804d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick continue; 11814d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick } 11824d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick for (RecIter RI = TI->PredTerm.begin(), RE = TI->PredTerm.end(); 11834d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick RI != RE; ++RI) { 11844d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick if (RI != TI->PredTerm.begin()) 11854d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << "\n && "; 11864d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << "(" << (*RI)->getValueAsString("Predicate") << ")"; 11874d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick } 11884d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << ")\n" 11894d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick << " return " << TI->ToClassIdx << "; // " 11904d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick << SchedModels.getSchedClass(TI->ToClassIdx).Name << '\n'; 11914d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick } 11924d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << " }\n"; 11934d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick if (*PI == 0) 11944d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick break; 11954d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick } 11964d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick unsigned SCIdx = 0; 11974d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick if (SC.ItinClassDef) 11984d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick SCIdx = SchedModels.getSchedClassIdxForItin(SC.ItinClassDef); 11994d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick else 12004d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick SCIdx = SchedModels.findSchedClassIdx(SC.Writes, SC.Reads); 12014d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick if (SCIdx != *VCI) 12024d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << " return " << SCIdx << ";\n"; 12034d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << " break;\n"; 12044d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick } 12054d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << " };\n"; 12064d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick } 12074d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick OS << " report_fatal_error(\"Expected a variant SchedClass\");\n" 12084d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick << "} // " << ClassName << "::resolveSchedClass\n"; 12094d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick} 12104d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick 12110d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey// 1212581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// ParseFeaturesFunction - Produces a subtarget specific function for parsing 1213581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// the subtarget features string. 1214581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// 121594214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengvoid SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, 121694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng unsigned NumFeatures, 121794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng unsigned NumProcs) { 1218f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey std::vector<Record*> Features = 1219f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey Records.getAllDerivedDefinitions("SubtargetFeature"); 122042d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina std::sort(Features.begin(), Features.end(), LessRecord()); 1221581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey 1222da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" 1223da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick << "// subtarget options.\n" 1224276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng << "void llvm::"; 1225581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey OS << Target; 12260ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n" 1227f0fd3afeffcb41202147f755bf770061f189a42bDavid Greene << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n" 12283f696e568bae8afa5986e7af48156c2bac041ba7Hal Finkel << " DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n"; 122994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 123094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng if (Features.empty()) { 123194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "}\n"; 123294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng return; 123394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng } 123494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 123534aadd63346b5f9b98749a306b71fcb00ee6996fAndrew Trick OS << " InitMCProcessorInfo(CPU, FS);\n" 123634aadd63346b5f9b98749a306b71fcb00ee6996fAndrew Trick << " uint64_t Bits = getFeatureBits();\n"; 12374222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling 1238f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey for (unsigned i = 0; i < Features.size(); i++) { 1239f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey // Next record 1240f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey Record *R = Features[i]; 12414222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling const std::string &Instance = R->getName(); 12424222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling const std::string &Value = R->getValueAsString("Value"); 12434222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling const std::string &Attribute = R->getValueAsString("Attribute"); 124419c95507443ebd4f1cee80917d540c8bd27f8fe1Evan Cheng 1245db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen if (Value=="true" || Value=="false") 12460ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng OS << " if ((Bits & " << Target << "::" 12470ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng << Instance << ") != 0) " 1248db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen << Attribute << " = " << Value << ";\n"; 1249db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen else 12500ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng OS << " if ((Bits & " << Target << "::" 12510ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng << Instance << ") != 0 && " 125294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng << Attribute << " < " << Value << ") " 125394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng << Attribute << " = " << Value << ";\n"; 12546cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey } 125541a024385f1220eadc48b48cb4c044a5fbc1b361Anton Korobeynikov 1256276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng OS << "}\n"; 1257581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey} 1258581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey 125941a024385f1220eadc48b48cb4c044a5fbc1b361Anton Korobeynikov// 1260b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// SubtargetEmitter::run - Main subtarget enumeration emitter. 1261b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// 12621a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::run(raw_ostream &OS) { 12636f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); 1264b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey 1265ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n"; 1266ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng OS << "#undef GET_SUBTARGETINFO_ENUM\n"; 1267ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng 1268ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng OS << "namespace llvm {\n"; 1269ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng Enumeration(OS, "SubtargetFeature", true); 1270ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng OS << "} // End llvm namespace \n"; 1271ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; 1272ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng 127394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n"; 127494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "#undef GET_SUBTARGETINFO_MC_DESC\n"; 1275928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov 127694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "namespace llvm {\n"; 1277c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#if 0 1278c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng OS << "namespace {\n"; 1279c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#endif 128094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng unsigned NumFeatures = FeatureKeyValues(OS); 1281c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng OS << "\n"; 128294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng unsigned NumProcs = CPUKeyValues(OS); 1283c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng OS << "\n"; 12842661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick EmitSchedModel(OS); 1285c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng OS << "\n"; 1286c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#if 0 1287c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng OS << "}\n"; 1288c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#endif 128994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 129094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng // MCInstrInfo initialization routine. 129194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "static inline void Init" << Target 129259ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng << "MCSubtargetInfo(MCSubtargetInfo *II, " 129359ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng << "StringRef TT, StringRef CPU, StringRef FS) {\n"; 129459ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng OS << " II->InitMCSubtargetInfo(TT, CPU, FS, "; 129594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng if (NumFeatures) 129694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << Target << "FeatureKV, "; 129794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng else 129894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "0, "; 129994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng if (NumProcs) 130094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << Target << "SubTypeKV, "; 130194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng else 130294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "0, "; 1303544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << '\n'; OS.indent(22); 1304e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << Target << "ProcSchedKV, " 1305e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick << Target << "WriteProcResTable, " 1306e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick << Target << "WriteLatencyTable, " 1307e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick << Target << "ReadAdvanceTable, "; 13082661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick if (SchedModels.hasItineraryClasses()) { 1309e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << '\n'; OS.indent(22); 1310e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << Target << "Stages, " 131194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng << Target << "OperandCycles, " 1312a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick << Target << "ForwardingPaths, "; 131394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng } else 1314e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << "0, 0, 0, "; 131594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; 131694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 131794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "} // End llvm namespace \n"; 131894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 131994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n"; 132094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 132194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n"; 132294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n"; 132394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 132494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "#include \"llvm/Support/Debug.h\"\n"; 132594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "#include \"llvm/Support/raw_ostream.h\"\n"; 132694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng ParseFeaturesFunction(OS, NumFeatures, NumProcs); 132794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 132894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n"; 132994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 13305b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng // Create a TargetSubtargetInfo subclass to hide the MC layer initialization. 133194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n"; 133294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "#undef GET_SUBTARGETINFO_HEADER\n"; 133394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 133494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng std::string ClassName = Target + "GenSubtargetInfo"; 133594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "namespace llvm {\n"; 1336dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta OS << "class DFAPacketizer;\n"; 13375b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" 13380ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng << " explicit " << ClassName << "(StringRef TT, StringRef CPU, " 13390ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng << "StringRef FS);\n" 1340dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta << "public:\n" 13414d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick << " unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *DefMI," 13424d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick << " const TargetSchedModel *SchedModel) const;\n" 1343464f3a332f81364ee09794f9502f0b25671149c6Sebastian Pop << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" 1344dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta << " const;\n" 134594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng << "};\n"; 134694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "} // End llvm namespace \n"; 134794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 134894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n"; 134994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 135094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n"; 135194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "#undef GET_SUBTARGETINFO_CTOR\n"; 135294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 1353ee290ba35af88393ba18dd19e6e39d50c7872534Andrew Trick OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n"; 135494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "namespace llvm {\n"; 13551a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; 13561a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n"; 1357544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n"; 1358544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "extern const llvm::MCWriteProcResEntry " 1359544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << Target << "WriteProcResTable[];\n"; 1360544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "extern const llvm::MCWriteLatencyEntry " 1361544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << Target << "WriteLatencyTable[];\n"; 1362544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick OS << "extern const llvm::MCReadAdvanceEntry " 1363544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick << Target << "ReadAdvanceTable[];\n"; 1364544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick 13652661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick if (SchedModels.hasItineraryClasses()) { 13661a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer OS << "extern const llvm::InstrStage " << Target << "Stages[];\n"; 13671a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer OS << "extern const unsigned " << Target << "OperandCycles[];\n"; 1368a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick OS << "extern const unsigned " << Target << "ForwardingPaths[];\n"; 1369c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng } 1370c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng 13710ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, " 13720ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng << "StringRef FS)\n" 13735b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng << " : TargetSubtargetInfo() {\n" 137459ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng << " InitMCSubtargetInfo(TT, CPU, FS, "; 137594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng if (NumFeatures) 137694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << Target << "FeatureKV, "; 137794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng else 137894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "0, "; 137994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng if (NumProcs) 138094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << Target << "SubTypeKV, "; 138194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng else 138294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "0, "; 1383e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << '\n'; OS.indent(22); 1384e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << Target << "ProcSchedKV, " 1385e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick << Target << "WriteProcResTable, " 1386e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick << Target << "WriteLatencyTable, " 1387e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick << Target << "ReadAdvanceTable, "; 1388e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << '\n'; OS.indent(22); 13892661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick if (SchedModels.hasItineraryClasses()) { 1390e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << Target << "Stages, " 139194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng << Target << "OperandCycles, " 1392a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick << Target << "ForwardingPaths, "; 139394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng } else 1394e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick OS << "0, 0, 0, "; 139594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; 1396544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick 13974d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick EmitSchedModelHelpers(ClassName, OS); 13984d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick 139994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "} // End llvm namespace \n"; 140094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng 140194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n"; 1402b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey} 14036f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 14046f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesennamespace llvm { 14056f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 14066f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenvoid EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) { 14072661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick CodeGenTarget CGTarget(RK); 14082661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick SubtargetEmitter(RK, CGTarget).run(OS); 14096f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} 14106f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen 14116f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} // End llvm namespace 1412