SubtargetEmitter.cpp 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558
  1. //===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This tablegen backend emits subtarget enumerations.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "CodeGenTarget.h"
  14. #include "CodeGenSchedule.h"
  15. #include "llvm/ADT/STLExtras.h"
  16. #include "llvm/ADT/StringExtras.h"
  17. #include "llvm/MC/MCInstrItineraries.h"
  18. #include "llvm/MC/SubtargetFeature.h"
  19. #include "llvm/Support/Debug.h"
  20. #include "llvm/Support/Format.h"
  21. #include "llvm/TableGen/Error.h"
  22. #include "llvm/TableGen/Record.h"
  23. #include "llvm/TableGen/TableGenBackend.h"
  24. #include <algorithm>
  25. #include <map>
  26. #include <string>
  27. #include <vector>
  28. using namespace llvm;
  29. #define DEBUG_TYPE "subtarget-emitter"
  30. namespace {
  31. class SubtargetEmitter {
  32. // Each processor has a SchedClassDesc table with an entry for each SchedClass.
  33. // The SchedClassDesc table indexes into a global write resource table, write
  34. // latency table, and read advance table.
  35. struct SchedClassTables {
  36. std::vector<std::vector<MCSchedClassDesc> > ProcSchedClasses;
  37. std::vector<MCWriteProcResEntry> WriteProcResources;
  38. std::vector<MCWriteLatencyEntry> WriteLatencies;
  39. std::vector<std::string> WriterNames;
  40. std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
  41. // Reserve an invalid entry at index 0
  42. SchedClassTables() {
  43. ProcSchedClasses.resize(1);
  44. WriteProcResources.resize(1);
  45. WriteLatencies.resize(1);
  46. WriterNames.push_back("InvalidWrite");
  47. ReadAdvanceEntries.resize(1);
  48. }
  49. };
  50. struct LessWriteProcResources {
  51. bool operator()(const MCWriteProcResEntry &LHS,
  52. const MCWriteProcResEntry &RHS) {
  53. return LHS.ProcResourceIdx < RHS.ProcResourceIdx;
  54. }
  55. };
  56. RecordKeeper &Records;
  57. CodeGenSchedModels &SchedModels;
  58. std::string Target;
  59. void Enumeration(raw_ostream &OS, const char *ClassName);
  60. unsigned FeatureKeyValues(raw_ostream &OS);
  61. unsigned CPUKeyValues(raw_ostream &OS);
  62. void FormItineraryStageString(const std::string &Names,
  63. Record *ItinData, std::string &ItinString,
  64. unsigned &NStages);
  65. void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
  66. unsigned &NOperandCycles);
  67. void FormItineraryBypassString(const std::string &Names,
  68. Record *ItinData,
  69. std::string &ItinString, unsigned NOperandCycles);
  70. void EmitStageAndOperandCycleData(raw_ostream &OS,
  71. std::vector<std::vector<InstrItinerary> >
  72. &ProcItinLists);
  73. void EmitItineraries(raw_ostream &OS,
  74. std::vector<std::vector<InstrItinerary> >
  75. &ProcItinLists);
  76. void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name,
  77. char Separator);
  78. void EmitProcessorResources(const CodeGenProcModel &ProcModel,
  79. raw_ostream &OS);
  80. Record *FindWriteResources(const CodeGenSchedRW &SchedWrite,
  81. const CodeGenProcModel &ProcModel);
  82. Record *FindReadAdvance(const CodeGenSchedRW &SchedRead,
  83. const CodeGenProcModel &ProcModel);
  84. void ExpandProcResources(RecVec &PRVec, std::vector<int64_t> &Cycles,
  85. const CodeGenProcModel &ProcModel);
  86. void GenSchedClassTables(const CodeGenProcModel &ProcModel,
  87. SchedClassTables &SchedTables);
  88. void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
  89. void EmitProcessorModels(raw_ostream &OS);
  90. void EmitProcessorLookup(raw_ostream &OS);
  91. void EmitSchedModelHelpers(std::string ClassName, raw_ostream &OS);
  92. void EmitSchedModel(raw_ostream &OS);
  93. void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
  94. unsigned NumProcs);
  95. public:
  96. SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
  97. Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
  98. void run(raw_ostream &o);
  99. };
  100. } // End anonymous namespace
  101. //
  102. // Enumeration - Emit the specified class as an enumeration.
  103. //
  104. void SubtargetEmitter::Enumeration(raw_ostream &OS,
  105. const char *ClassName) {
  106. // Get all records of class and sort
  107. std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
  108. std::sort(DefList.begin(), DefList.end(), LessRecord());
  109. unsigned N = DefList.size();
  110. if (N == 0)
  111. return;
  112. if (N > MAX_SUBTARGET_FEATURES)
  113. PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
  114. OS << "namespace " << Target << " {\n";
  115. // Open enumeration. Use a 64-bit underlying type.
  116. OS << "enum : uint64_t {\n";
  117. // For each record
  118. for (unsigned i = 0; i < N;) {
  119. // Next record
  120. Record *Def = DefList[i];
  121. // Get and emit name
  122. OS << " " << Def->getName() << " = " << i;
  123. if (++i < N) OS << ",";
  124. OS << "\n";
  125. }
  126. // Close enumeration and namespace
  127. OS << "};\n}\n";
  128. }
  129. //
  130. // FeatureKeyValues - Emit data of all the subtarget features. Used by the
  131. // command line.
  132. //
  133. unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
  134. // Gather and sort all the features
  135. std::vector<Record*> FeatureList =
  136. Records.getAllDerivedDefinitions("SubtargetFeature");
  137. if (FeatureList.empty())
  138. return 0;
  139. std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
  140. // Begin feature table
  141. OS << "// Sorted (by key) array of values for CPU features.\n"
  142. << "extern const llvm::SubtargetFeatureKV " << Target
  143. << "FeatureKV[] = {\n";
  144. // For each feature
  145. unsigned NumFeatures = 0;
  146. for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
  147. // Next feature
  148. Record *Feature = FeatureList[i];
  149. const std::string &Name = Feature->getName();
  150. const std::string &CommandLineName = Feature->getValueAsString("Name");
  151. const std::string &Desc = Feature->getValueAsString("Desc");
  152. if (CommandLineName.empty()) continue;
  153. // Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in } }
  154. OS << " { "
  155. << "\"" << CommandLineName << "\", "
  156. << "\"" << Desc << "\", "
  157. << "{ " << Target << "::" << Name << " }, ";
  158. const std::vector<Record*> &ImpliesList =
  159. Feature->getValueAsListOfDefs("Implies");
  160. if (ImpliesList.empty()) {
  161. OS << "{ }";
  162. } else {
  163. OS << "{ ";
  164. for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
  165. OS << Target << "::" << ImpliesList[j]->getName();
  166. if (++j < M) OS << ", ";
  167. }
  168. OS << " }";
  169. }
  170. OS << " }";
  171. ++NumFeatures;
  172. // Depending on 'if more in the list' emit comma
  173. if ((i + 1) < N) OS << ",";
  174. OS << "\n";
  175. }
  176. // End feature table
  177. OS << "};\n";
  178. return NumFeatures;
  179. }
  180. //
  181. // CPUKeyValues - Emit data of all the subtarget processors. Used by command
  182. // line.
  183. //
  184. unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
  185. // Gather and sort processor information
  186. std::vector<Record*> ProcessorList =
  187. Records.getAllDerivedDefinitions("Processor");
  188. std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
  189. // Begin processor table
  190. OS << "// Sorted (by key) array of values for CPU subtype.\n"
  191. << "extern const llvm::SubtargetFeatureKV " << Target
  192. << "SubTypeKV[] = {\n";
  193. // For each processor
  194. for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
  195. // Next processor
  196. Record *Processor = ProcessorList[i];
  197. const std::string &Name = Processor->getValueAsString("Name");
  198. const std::vector<Record*> &FeatureList =
  199. Processor->getValueAsListOfDefs("Features");
  200. // Emit as { "cpu", "description", { f1 , f2 , ... fn } },
  201. OS << " { "
  202. << "\"" << Name << "\", "
  203. << "\"Select the " << Name << " processor\", ";
  204. if (FeatureList.empty()) {
  205. OS << "{ }";
  206. } else {
  207. OS << "{ ";
  208. for (unsigned j = 0, M = FeatureList.size(); j < M;) {
  209. OS << Target << "::" << FeatureList[j]->getName();
  210. if (++j < M) OS << ", ";
  211. }
  212. OS << " }";
  213. }
  214. // The { } is for the "implies" section of this data structure.
  215. OS << ", { } }";
  216. // Depending on 'if more in the list' emit comma
  217. if (++i < N) OS << ",";
  218. OS << "\n";
  219. }
  220. // End processor table
  221. OS << "};\n";
  222. return ProcessorList.size();
  223. }
  224. //
  225. // FormItineraryStageString - Compose a string containing the stage
  226. // data initialization for the specified itinerary. N is the number
  227. // of stages.
  228. //
  229. void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
  230. Record *ItinData,
  231. std::string &ItinString,
  232. unsigned &NStages) {
  233. // Get states list
  234. const std::vector<Record*> &StageList =
  235. ItinData->getValueAsListOfDefs("Stages");
  236. // For each stage
  237. unsigned N = NStages = StageList.size();
  238. for (unsigned i = 0; i < N;) {
  239. // Next stage
  240. const Record *Stage = StageList[i];
  241. // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
  242. int Cycles = Stage->getValueAsInt("Cycles");
  243. ItinString += " { " + itostr(Cycles) + ", ";
  244. // Get unit list
  245. const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
  246. // For each unit
  247. for (unsigned j = 0, M = UnitList.size(); j < M;) {
  248. // Add name and bitwise or
  249. ItinString += Name + "FU::" + UnitList[j]->getName();
  250. if (++j < M) ItinString += " | ";
  251. }
  252. int TimeInc = Stage->getValueAsInt("TimeInc");
  253. ItinString += ", " + itostr(TimeInc);
  254. int Kind = Stage->getValueAsInt("Kind");
  255. ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
  256. // Close off stage
  257. ItinString += " }";
  258. if (++i < N) ItinString += ", ";
  259. }
  260. }
  261. //
  262. // FormItineraryOperandCycleString - Compose a string containing the
  263. // operand cycle initialization for the specified itinerary. N is the
  264. // number of operands that has cycles specified.
  265. //
  266. void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
  267. std::string &ItinString, unsigned &NOperandCycles) {
  268. // Get operand cycle list
  269. const std::vector<int64_t> &OperandCycleList =
  270. ItinData->getValueAsListOfInts("OperandCycles");
  271. // For each operand cycle
  272. unsigned N = NOperandCycles = OperandCycleList.size();
  273. for (unsigned i = 0; i < N;) {
  274. // Next operand cycle
  275. const int OCycle = OperandCycleList[i];
  276. ItinString += " " + itostr(OCycle);
  277. if (++i < N) ItinString += ", ";
  278. }
  279. }
  280. void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
  281. Record *ItinData,
  282. std::string &ItinString,
  283. unsigned NOperandCycles) {
  284. const std::vector<Record*> &BypassList =
  285. ItinData->getValueAsListOfDefs("Bypasses");
  286. unsigned N = BypassList.size();
  287. unsigned i = 0;
  288. for (; i < N;) {
  289. ItinString += Name + "Bypass::" + BypassList[i]->getName();
  290. if (++i < NOperandCycles) ItinString += ", ";
  291. }
  292. for (; i < NOperandCycles;) {
  293. ItinString += " 0";
  294. if (++i < NOperandCycles) ItinString += ", ";
  295. }
  296. }
  297. //
  298. // EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
  299. // cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
  300. // by CodeGenSchedClass::Index.
  301. //
  302. void SubtargetEmitter::
  303. EmitStageAndOperandCycleData(raw_ostream &OS,
  304. std::vector<std::vector<InstrItinerary> >
  305. &ProcItinLists) {
  306. // Multiple processor models may share an itinerary record. Emit it once.
  307. SmallPtrSet<Record*, 8> ItinsDefSet;
  308. // Emit functional units for all the itineraries.
  309. for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
  310. PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
  311. if (!ItinsDefSet.insert(PI->ItinsDef).second)
  312. continue;
  313. std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
  314. if (FUs.empty())
  315. continue;
  316. const std::string &Name = PI->ItinsDef->getName();
  317. OS << "\n// Functional units for \"" << Name << "\"\n"
  318. << "namespace " << Name << "FU {\n";
  319. for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
  320. OS << " const unsigned " << FUs[j]->getName()
  321. << " = 1 << " << j << ";\n";
  322. OS << "}\n";
  323. std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
  324. if (!BPs.empty()) {
  325. OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
  326. << "\"\n" << "namespace " << Name << "Bypass {\n";
  327. OS << " const unsigned NoBypass = 0;\n";
  328. for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
  329. OS << " const unsigned " << BPs[j]->getName()
  330. << " = 1 << " << j << ";\n";
  331. OS << "}\n";
  332. }
  333. }
  334. // Begin stages table
  335. std::string StageTable = "\nextern const llvm::InstrStage " + Target +
  336. "Stages[] = {\n";
  337. StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
  338. // Begin operand cycle table
  339. std::string OperandCycleTable = "extern const unsigned " + Target +
  340. "OperandCycles[] = {\n";
  341. OperandCycleTable += " 0, // No itinerary\n";
  342. // Begin pipeline bypass table
  343. std::string BypassTable = "extern const unsigned " + Target +
  344. "ForwardingPaths[] = {\n";
  345. BypassTable += " 0, // No itinerary\n";
  346. // For each Itinerary across all processors, add a unique entry to the stages,
  347. // operand cycles, and pipepine bypess tables. Then add the new Itinerary
  348. // object with computed offsets to the ProcItinLists result.
  349. unsigned StageCount = 1, OperandCycleCount = 1;
  350. std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
  351. for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
  352. PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
  353. const CodeGenProcModel &ProcModel = *PI;
  354. // Add process itinerary to the list.
  355. ProcItinLists.resize(ProcItinLists.size()+1);
  356. // If this processor defines no itineraries, then leave the itinerary list
  357. // empty.
  358. std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
  359. if (!ProcModel.hasItineraries())
  360. continue;
  361. const std::string &Name = ProcModel.ItinsDef->getName();
  362. ItinList.resize(SchedModels.numInstrSchedClasses());
  363. assert(ProcModel.ItinDefList.size() == ItinList.size() && "bad Itins");
  364. for (unsigned SchedClassIdx = 0, SchedClassEnd = ItinList.size();
  365. SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
  366. // Next itinerary data
  367. Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
  368. // Get string and stage count
  369. std::string ItinStageString;
  370. unsigned NStages = 0;
  371. if (ItinData)
  372. FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
  373. // Get string and operand cycle count
  374. std::string ItinOperandCycleString;
  375. unsigned NOperandCycles = 0;
  376. std::string ItinBypassString;
  377. if (ItinData) {
  378. FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
  379. NOperandCycles);
  380. FormItineraryBypassString(Name, ItinData, ItinBypassString,
  381. NOperandCycles);
  382. }
  383. // Check to see if stage already exists and create if it doesn't
  384. unsigned FindStage = 0;
  385. if (NStages > 0) {
  386. FindStage = ItinStageMap[ItinStageString];
  387. if (FindStage == 0) {
  388. // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
  389. StageTable += ItinStageString + ", // " + itostr(StageCount);
  390. if (NStages > 1)
  391. StageTable += "-" + itostr(StageCount + NStages - 1);
  392. StageTable += "\n";
  393. // Record Itin class number.
  394. ItinStageMap[ItinStageString] = FindStage = StageCount;
  395. StageCount += NStages;
  396. }
  397. }
  398. // Check to see if operand cycle already exists and create if it doesn't
  399. unsigned FindOperandCycle = 0;
  400. if (NOperandCycles > 0) {
  401. std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
  402. FindOperandCycle = ItinOperandMap[ItinOperandString];
  403. if (FindOperandCycle == 0) {
  404. // Emit as cycle, // index
  405. OperandCycleTable += ItinOperandCycleString + ", // ";
  406. std::string OperandIdxComment = itostr(OperandCycleCount);
  407. if (NOperandCycles > 1)
  408. OperandIdxComment += "-"
  409. + itostr(OperandCycleCount + NOperandCycles - 1);
  410. OperandCycleTable += OperandIdxComment + "\n";
  411. // Record Itin class number.
  412. ItinOperandMap[ItinOperandCycleString] =
  413. FindOperandCycle = OperandCycleCount;
  414. // Emit as bypass, // index
  415. BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
  416. OperandCycleCount += NOperandCycles;
  417. }
  418. }
  419. // Set up itinerary as location and location + stage count
  420. int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
  421. InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
  422. FindOperandCycle,
  423. FindOperandCycle + NOperandCycles};
  424. // Inject - empty slots will be 0, 0
  425. ItinList[SchedClassIdx] = Intinerary;
  426. }
  427. }
  428. // Closing stage
  429. StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
  430. StageTable += "};\n";
  431. // Closing operand cycles
  432. OperandCycleTable += " 0 // End operand cycles\n";
  433. OperandCycleTable += "};\n";
  434. BypassTable += " 0 // End bypass tables\n";
  435. BypassTable += "};\n";
  436. // Emit tables.
  437. OS << StageTable;
  438. OS << OperandCycleTable;
  439. OS << BypassTable;
  440. }
  441. //
  442. // EmitProcessorData - Generate data for processor itineraries that were
  443. // computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
  444. // Itineraries for each processor. The Itinerary lists are indexed on
  445. // CodeGenSchedClass::Index.
  446. //
  447. void SubtargetEmitter::
  448. EmitItineraries(raw_ostream &OS,
  449. std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
  450. // Multiple processor models may share an itinerary record. Emit it once.
  451. SmallPtrSet<Record*, 8> ItinsDefSet;
  452. // For each processor's machine model
  453. std::vector<std::vector<InstrItinerary> >::iterator
  454. ProcItinListsIter = ProcItinLists.begin();
  455. for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
  456. PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
  457. Record *ItinsDef = PI->ItinsDef;
  458. if (!ItinsDefSet.insert(ItinsDef).second)
  459. continue;
  460. // Get processor itinerary name
  461. const std::string &Name = ItinsDef->getName();
  462. // Get the itinerary list for the processor.
  463. assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
  464. std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
  465. // Empty itineraries aren't referenced anywhere in the tablegen output
  466. // so don't emit them.
  467. if (ItinList.empty())
  468. continue;
  469. OS << "\n";
  470. OS << "static const llvm::InstrItinerary ";
  471. // Begin processor itinerary table
  472. OS << Name << "[] = {\n";
  473. // For each itinerary class in CodeGenSchedClass::Index order.
  474. for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
  475. InstrItinerary &Intinerary = ItinList[j];
  476. // Emit Itinerary in the form of
  477. // { firstStage, lastStage, firstCycle, lastCycle } // index
  478. OS << " { " <<
  479. Intinerary.NumMicroOps << ", " <<
  480. Intinerary.FirstStage << ", " <<
  481. Intinerary.LastStage << ", " <<
  482. Intinerary.FirstOperandCycle << ", " <<
  483. Intinerary.LastOperandCycle << " }" <<
  484. ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
  485. }
  486. // End processor itinerary table
  487. OS << " { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
  488. OS << "};\n";
  489. }
  490. }
  491. // Emit either the value defined in the TableGen Record, or the default
  492. // value defined in the C++ header. The Record is null if the processor does not
  493. // define a model.
  494. void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
  495. const char *Name, char Separator) {
  496. OS << " ";
  497. int V = R ? R->getValueAsInt(Name) : -1;
  498. if (V >= 0)
  499. OS << V << Separator << " // " << Name;
  500. else
  501. OS << "MCSchedModel::Default" << Name << Separator;
  502. OS << '\n';
  503. }
  504. void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
  505. raw_ostream &OS) {
  506. char Sep = ProcModel.ProcResourceDefs.empty() ? ' ' : ',';
  507. OS << "\n// {Name, NumUnits, SuperIdx, IsBuffered}\n";
  508. OS << "static const llvm::MCProcResourceDesc "
  509. << ProcModel.ModelName << "ProcResources" << "[] = {\n"
  510. << " {DBGFIELD(\"InvalidUnit\") 0, 0, 0}" << Sep << "\n";
  511. for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
  512. Record *PRDef = ProcModel.ProcResourceDefs[i];
  513. Record *SuperDef = nullptr;
  514. unsigned SuperIdx = 0;
  515. unsigned NumUnits = 0;
  516. int BufferSize = PRDef->getValueAsInt("BufferSize");
  517. if (PRDef->isSubClassOf("ProcResGroup")) {
  518. RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources");
  519. for (RecIter RUI = ResUnits.begin(), RUE = ResUnits.end();
  520. RUI != RUE; ++RUI) {
  521. NumUnits += (*RUI)->getValueAsInt("NumUnits");
  522. }
  523. }
  524. else {
  525. // Find the SuperIdx
  526. if (PRDef->getValueInit("Super")->isComplete()) {
  527. SuperDef = SchedModels.findProcResUnits(
  528. PRDef->getValueAsDef("Super"), ProcModel);
  529. SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
  530. }
  531. NumUnits = PRDef->getValueAsInt("NumUnits");
  532. }
  533. // Emit the ProcResourceDesc
  534. if (i+1 == e)
  535. Sep = ' ';
  536. OS << " {DBGFIELD(\"" << PRDef->getName() << "\") ";
  537. if (PRDef->getName().size() < 15)
  538. OS.indent(15 - PRDef->getName().size());
  539. OS << NumUnits << ", " << SuperIdx << ", "
  540. << BufferSize << "}" << Sep << " // #" << i+1;
  541. if (SuperDef)
  542. OS << ", Super=" << SuperDef->getName();
  543. OS << "\n";
  544. }
  545. OS << "};\n";
  546. }
  547. // Find the WriteRes Record that defines processor resources for this
  548. // SchedWrite.
  549. Record *SubtargetEmitter::FindWriteResources(
  550. const CodeGenSchedRW &SchedWrite, const CodeGenProcModel &ProcModel) {
  551. // Check if the SchedWrite is already subtarget-specific and directly
  552. // specifies a set of processor resources.
  553. if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes"))
  554. return SchedWrite.TheDef;
  555. Record *AliasDef = nullptr;
  556. for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
  557. AI != AE; ++AI) {
  558. const CodeGenSchedRW &AliasRW =
  559. SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
  560. if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
  561. Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
  562. if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
  563. continue;
  564. }
  565. if (AliasDef)
  566. PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
  567. "defined for processor " + ProcModel.ModelName +
  568. " Ensure only one SchedAlias exists per RW.");
  569. AliasDef = AliasRW.TheDef;
  570. }
  571. if (AliasDef && AliasDef->isSubClassOf("SchedWriteRes"))
  572. return AliasDef;
  573. // Check this processor's list of write resources.
  574. Record *ResDef = nullptr;
  575. for (RecIter WRI = ProcModel.WriteResDefs.begin(),
  576. WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
  577. if (!(*WRI)->isSubClassOf("WriteRes"))
  578. continue;
  579. if (AliasDef == (*WRI)->getValueAsDef("WriteType")
  580. || SchedWrite.TheDef == (*WRI)->getValueAsDef("WriteType")) {
  581. if (ResDef) {
  582. PrintFatalError((*WRI)->getLoc(), "Resources are defined for both "
  583. "SchedWrite and its alias on processor " +
  584. ProcModel.ModelName);
  585. }
  586. ResDef = *WRI;
  587. }
  588. }
  589. // TODO: If ProcModel has a base model (previous generation processor),
  590. // then call FindWriteResources recursively with that model here.
  591. if (!ResDef) {
  592. PrintFatalError(ProcModel.ModelDef->getLoc(),
  593. std::string("Processor does not define resources for ")
  594. + SchedWrite.TheDef->getName());
  595. }
  596. return ResDef;
  597. }
  598. /// Find the ReadAdvance record for the given SchedRead on this processor or
  599. /// return NULL.
  600. Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
  601. const CodeGenProcModel &ProcModel) {
  602. // Check for SchedReads that directly specify a ReadAdvance.
  603. if (SchedRead.TheDef->isSubClassOf("SchedReadAdvance"))
  604. return SchedRead.TheDef;
  605. // Check this processor's list of aliases for SchedRead.
  606. Record *AliasDef = nullptr;
  607. for (RecIter AI = SchedRead.Aliases.begin(), AE = SchedRead.Aliases.end();
  608. AI != AE; ++AI) {
  609. const CodeGenSchedRW &AliasRW =
  610. SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
  611. if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
  612. Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
  613. if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
  614. continue;
  615. }
  616. if (AliasDef)
  617. PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
  618. "defined for processor " + ProcModel.ModelName +
  619. " Ensure only one SchedAlias exists per RW.");
  620. AliasDef = AliasRW.TheDef;
  621. }
  622. if (AliasDef && AliasDef->isSubClassOf("SchedReadAdvance"))
  623. return AliasDef;
  624. // Check this processor's ReadAdvanceList.
  625. Record *ResDef = nullptr;
  626. for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
  627. RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
  628. if (!(*RAI)->isSubClassOf("ReadAdvance"))
  629. continue;
  630. if (AliasDef == (*RAI)->getValueAsDef("ReadType")
  631. || SchedRead.TheDef == (*RAI)->getValueAsDef("ReadType")) {
  632. if (ResDef) {
  633. PrintFatalError((*RAI)->getLoc(), "Resources are defined for both "
  634. "SchedRead and its alias on processor " +
  635. ProcModel.ModelName);
  636. }
  637. ResDef = *RAI;
  638. }
  639. }
  640. // TODO: If ProcModel has a base model (previous generation processor),
  641. // then call FindReadAdvance recursively with that model here.
  642. if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") {
  643. PrintFatalError(ProcModel.ModelDef->getLoc(),
  644. std::string("Processor does not define resources for ")
  645. + SchedRead.TheDef->getName());
  646. }
  647. return ResDef;
  648. }
  649. // Expand an explicit list of processor resources into a full list of implied
  650. // resource groups and super resources that cover them.
  651. void SubtargetEmitter::ExpandProcResources(RecVec &PRVec,
  652. std::vector<int64_t> &Cycles,
  653. const CodeGenProcModel &PM) {
  654. // Default to 1 resource cycle.
  655. Cycles.resize(PRVec.size(), 1);
  656. for (unsigned i = 0, e = PRVec.size(); i != e; ++i) {
  657. Record *PRDef = PRVec[i];
  658. RecVec SubResources;
  659. if (PRDef->isSubClassOf("ProcResGroup"))
  660. SubResources = PRDef->getValueAsListOfDefs("Resources");
  661. else {
  662. SubResources.push_back(PRDef);
  663. PRDef = SchedModels.findProcResUnits(PRVec[i], PM);
  664. for (Record *SubDef = PRDef;
  665. SubDef->getValueInit("Super")->isComplete();) {
  666. if (SubDef->isSubClassOf("ProcResGroup")) {
  667. // Disallow this for simplicitly.
  668. PrintFatalError(SubDef->getLoc(), "Processor resource group "
  669. " cannot be a super resources.");
  670. }
  671. Record *SuperDef =
  672. SchedModels.findProcResUnits(SubDef->getValueAsDef("Super"), PM);
  673. PRVec.push_back(SuperDef);
  674. Cycles.push_back(Cycles[i]);
  675. SubDef = SuperDef;
  676. }
  677. }
  678. for (RecIter PRI = PM.ProcResourceDefs.begin(),
  679. PRE = PM.ProcResourceDefs.end();
  680. PRI != PRE; ++PRI) {
  681. if (*PRI == PRDef || !(*PRI)->isSubClassOf("ProcResGroup"))
  682. continue;
  683. RecVec SuperResources = (*PRI)->getValueAsListOfDefs("Resources");
  684. RecIter SubI = SubResources.begin(), SubE = SubResources.end();
  685. for( ; SubI != SubE; ++SubI) {
  686. if (std::find(SuperResources.begin(), SuperResources.end(), *SubI)
  687. == SuperResources.end()) {
  688. break;
  689. }
  690. }
  691. if (SubI == SubE) {
  692. PRVec.push_back(*PRI);
  693. Cycles.push_back(Cycles[i]);
  694. }
  695. }
  696. }
  697. }
  698. // Generate the SchedClass table for this processor and update global
  699. // tables. Must be called for each processor in order.
  700. void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
  701. SchedClassTables &SchedTables) {
  702. SchedTables.ProcSchedClasses.resize(SchedTables.ProcSchedClasses.size() + 1);
  703. if (!ProcModel.hasInstrSchedModel())
  704. return;
  705. std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back();
  706. for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
  707. SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
  708. DEBUG(SCI->dump(&SchedModels));
  709. SCTab.resize(SCTab.size() + 1);
  710. MCSchedClassDesc &SCDesc = SCTab.back();
  711. // SCDesc.Name is guarded by NDEBUG
  712. SCDesc.NumMicroOps = 0;
  713. SCDesc.BeginGroup = false;
  714. SCDesc.EndGroup = false;
  715. SCDesc.WriteProcResIdx = 0;
  716. SCDesc.WriteLatencyIdx = 0;
  717. SCDesc.ReadAdvanceIdx = 0;
  718. // A Variant SchedClass has no resources of its own.
  719. bool HasVariants = false;
  720. for (std::vector<CodeGenSchedTransition>::const_iterator
  721. TI = SCI->Transitions.begin(), TE = SCI->Transitions.end();
  722. TI != TE; ++TI) {
  723. if (TI->ProcIndices[0] == 0) {
  724. HasVariants = true;
  725. break;
  726. }
  727. IdxIter PIPos = std::find(TI->ProcIndices.begin(),
  728. TI->ProcIndices.end(), ProcModel.Index);
  729. if (PIPos != TI->ProcIndices.end()) {
  730. HasVariants = true;
  731. break;
  732. }
  733. }
  734. if (HasVariants) {
  735. SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps;
  736. continue;
  737. }
  738. // Determine if the SchedClass is actually reachable on this processor. If
  739. // not don't try to locate the processor resources, it will fail.
  740. // If ProcIndices contains 0, this class applies to all processors.
  741. assert(!SCI->ProcIndices.empty() && "expect at least one procidx");
  742. if (SCI->ProcIndices[0] != 0) {
  743. IdxIter PIPos = std::find(SCI->ProcIndices.begin(),
  744. SCI->ProcIndices.end(), ProcModel.Index);
  745. if (PIPos == SCI->ProcIndices.end())
  746. continue;
  747. }
  748. IdxVec Writes = SCI->Writes;
  749. IdxVec Reads = SCI->Reads;
  750. if (!SCI->InstRWs.empty()) {
  751. // This class has a default ReadWrite list which can be overriden by
  752. // InstRW definitions.
  753. Record *RWDef = nullptr;
  754. for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
  755. RWI != RWE; ++RWI) {
  756. Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
  757. if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) {
  758. RWDef = *RWI;
  759. break;
  760. }
  761. }
  762. if (RWDef) {
  763. Writes.clear();
  764. Reads.clear();
  765. SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
  766. Writes, Reads);
  767. }
  768. }
  769. if (Writes.empty()) {
  770. // Check this processor's itinerary class resources.
  771. for (RecIter II = ProcModel.ItinRWDefs.begin(),
  772. IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) {
  773. RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
  774. if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef)
  775. != Matched.end()) {
  776. SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"),
  777. Writes, Reads);
  778. break;
  779. }
  780. }
  781. if (Writes.empty()) {
  782. DEBUG(dbgs() << ProcModel.ModelName
  783. << " does not have resources for class " << SCI->Name << '\n');
  784. }
  785. }
  786. // Sum resources across all operand writes.
  787. std::vector<MCWriteProcResEntry> WriteProcResources;
  788. std::vector<MCWriteLatencyEntry> WriteLatencies;
  789. std::vector<std::string> WriterNames;
  790. std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
  791. for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
  792. IdxVec WriteSeq;
  793. SchedModels.expandRWSeqForProc(*WI, WriteSeq, /*IsRead=*/false,
  794. ProcModel);
  795. // For each operand, create a latency entry.
  796. MCWriteLatencyEntry WLEntry;
  797. WLEntry.Cycles = 0;
  798. unsigned WriteID = WriteSeq.back();
  799. WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name);
  800. // If this Write is not referenced by a ReadAdvance, don't distinguish it
  801. // from other WriteLatency entries.
  802. if (!SchedModels.hasReadOfWrite(
  803. SchedModels.getSchedWrite(WriteID).TheDef)) {
  804. WriteID = 0;
  805. }
  806. WLEntry.WriteResourceID = WriteID;
  807. for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end();
  808. WSI != WSE; ++WSI) {
  809. Record *WriteRes =
  810. FindWriteResources(SchedModels.getSchedWrite(*WSI), ProcModel);
  811. // Mark the parent class as invalid for unsupported write types.
  812. if (WriteRes->getValueAsBit("Unsupported")) {
  813. SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
  814. break;
  815. }
  816. WLEntry.Cycles += WriteRes->getValueAsInt("Latency");
  817. SCDesc.NumMicroOps += WriteRes->getValueAsInt("NumMicroOps");
  818. SCDesc.BeginGroup |= WriteRes->getValueAsBit("BeginGroup");
  819. SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup");
  820. // Create an entry for each ProcResource listed in WriteRes.
  821. RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources");
  822. std::vector<int64_t> Cycles =
  823. WriteRes->getValueAsListOfInts("ResourceCycles");
  824. ExpandProcResources(PRVec, Cycles, ProcModel);
  825. for (unsigned PRIdx = 0, PREnd = PRVec.size();
  826. PRIdx != PREnd; ++PRIdx) {
  827. MCWriteProcResEntry WPREntry;
  828. WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]);
  829. assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx");
  830. WPREntry.Cycles = Cycles[PRIdx];
  831. // If this resource is already used in this sequence, add the current
  832. // entry's cycles so that the same resource appears to be used
  833. // serially, rather than multiple parallel uses. This is important for
  834. // in-order machine where the resource consumption is a hazard.
  835. unsigned WPRIdx = 0, WPREnd = WriteProcResources.size();
  836. for( ; WPRIdx != WPREnd; ++WPRIdx) {
  837. if (WriteProcResources[WPRIdx].ProcResourceIdx
  838. == WPREntry.ProcResourceIdx) {
  839. WriteProcResources[WPRIdx].Cycles += WPREntry.Cycles;
  840. break;
  841. }
  842. }
  843. if (WPRIdx == WPREnd)
  844. WriteProcResources.push_back(WPREntry);
  845. }
  846. }
  847. WriteLatencies.push_back(WLEntry);
  848. }
  849. // Create an entry for each operand Read in this SchedClass.
  850. // Entries must be sorted first by UseIdx then by WriteResourceID.
  851. for (unsigned UseIdx = 0, EndIdx = Reads.size();
  852. UseIdx != EndIdx; ++UseIdx) {
  853. Record *ReadAdvance =
  854. FindReadAdvance(SchedModels.getSchedRead(Reads[UseIdx]), ProcModel);
  855. if (!ReadAdvance)
  856. continue;
  857. // Mark the parent class as invalid for unsupported write types.
  858. if (ReadAdvance->getValueAsBit("Unsupported")) {
  859. SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
  860. break;
  861. }
  862. RecVec ValidWrites = ReadAdvance->getValueAsListOfDefs("ValidWrites");
  863. IdxVec WriteIDs;
  864. if (ValidWrites.empty())
  865. WriteIDs.push_back(0);
  866. else {
  867. for (RecIter VWI = ValidWrites.begin(), VWE = ValidWrites.end();
  868. VWI != VWE; ++VWI) {
  869. WriteIDs.push_back(SchedModels.getSchedRWIdx(*VWI, /*IsRead=*/false));
  870. }
  871. }
  872. std::sort(WriteIDs.begin(), WriteIDs.end());
  873. for(IdxIter WI = WriteIDs.begin(), WE = WriteIDs.end(); WI != WE; ++WI) {
  874. MCReadAdvanceEntry RAEntry;
  875. RAEntry.UseIdx = UseIdx;
  876. RAEntry.WriteResourceID = *WI;
  877. RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
  878. ReadAdvanceEntries.push_back(RAEntry);
  879. }
  880. }
  881. if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
  882. WriteProcResources.clear();
  883. WriteLatencies.clear();
  884. ReadAdvanceEntries.clear();
  885. }
  886. // Add the information for this SchedClass to the global tables using basic
  887. // compression.
  888. //
  889. // WritePrecRes entries are sorted by ProcResIdx.
  890. std::sort(WriteProcResources.begin(), WriteProcResources.end(),
  891. LessWriteProcResources());
  892. SCDesc.NumWriteProcResEntries = WriteProcResources.size();
  893. std::vector<MCWriteProcResEntry>::iterator WPRPos =
  894. std::search(SchedTables.WriteProcResources.begin(),
  895. SchedTables.WriteProcResources.end(),
  896. WriteProcResources.begin(), WriteProcResources.end());
  897. if (WPRPos != SchedTables.WriteProcResources.end())
  898. SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin();
  899. else {
  900. SCDesc.WriteProcResIdx = SchedTables.WriteProcResources.size();
  901. SchedTables.WriteProcResources.insert(WPRPos, WriteProcResources.begin(),
  902. WriteProcResources.end());
  903. }
  904. // Latency entries must remain in operand order.
  905. SCDesc.NumWriteLatencyEntries = WriteLatencies.size();
  906. std::vector<MCWriteLatencyEntry>::iterator WLPos =
  907. std::search(SchedTables.WriteLatencies.begin(),
  908. SchedTables.WriteLatencies.end(),
  909. WriteLatencies.begin(), WriteLatencies.end());
  910. if (WLPos != SchedTables.WriteLatencies.end()) {
  911. unsigned idx = WLPos - SchedTables.WriteLatencies.begin();
  912. SCDesc.WriteLatencyIdx = idx;
  913. for (unsigned i = 0, e = WriteLatencies.size(); i < e; ++i)
  914. if (SchedTables.WriterNames[idx + i].find(WriterNames[i]) ==
  915. std::string::npos) {
  916. SchedTables.WriterNames[idx + i] += std::string("_") + WriterNames[i];
  917. }
  918. }
  919. else {
  920. SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size();
  921. SchedTables.WriteLatencies.insert(SchedTables.WriteLatencies.end(),
  922. WriteLatencies.begin(),
  923. WriteLatencies.end());
  924. SchedTables.WriterNames.insert(SchedTables.WriterNames.end(),
  925. WriterNames.begin(), WriterNames.end());
  926. }
  927. // ReadAdvanceEntries must remain in operand order.
  928. SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size();
  929. std::vector<MCReadAdvanceEntry>::iterator RAPos =
  930. std::search(SchedTables.ReadAdvanceEntries.begin(),
  931. SchedTables.ReadAdvanceEntries.end(),
  932. ReadAdvanceEntries.begin(), ReadAdvanceEntries.end());
  933. if (RAPos != SchedTables.ReadAdvanceEntries.end())
  934. SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin();
  935. else {
  936. SCDesc.ReadAdvanceIdx = SchedTables.ReadAdvanceEntries.size();
  937. SchedTables.ReadAdvanceEntries.insert(RAPos, ReadAdvanceEntries.begin(),
  938. ReadAdvanceEntries.end());
  939. }
  940. }
  941. }
  942. // Emit SchedClass tables for all processors and associated global tables.
  943. void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
  944. raw_ostream &OS) {
  945. // Emit global WriteProcResTable.
  946. OS << "\n// {ProcResourceIdx, Cycles}\n"
  947. << "extern const llvm::MCWriteProcResEntry "
  948. << Target << "WriteProcResTable[] = {\n"
  949. << " { 0, 0}, // Invalid\n";
  950. for (unsigned WPRIdx = 1, WPREnd = SchedTables.WriteProcResources.size();
  951. WPRIdx != WPREnd; ++WPRIdx) {
  952. MCWriteProcResEntry &WPREntry = SchedTables.WriteProcResources[WPRIdx];
  953. OS << " {" << format("%2d", WPREntry.ProcResourceIdx) << ", "
  954. << format("%2d", WPREntry.Cycles) << "}";
  955. if (WPRIdx + 1 < WPREnd)
  956. OS << ',';
  957. OS << " // #" << WPRIdx << '\n';
  958. }
  959. OS << "}; // " << Target << "WriteProcResTable\n";
  960. // Emit global WriteLatencyTable.
  961. OS << "\n// {Cycles, WriteResourceID}\n"
  962. << "extern const llvm::MCWriteLatencyEntry "
  963. << Target << "WriteLatencyTable[] = {\n"
  964. << " { 0, 0}, // Invalid\n";
  965. for (unsigned WLIdx = 1, WLEnd = SchedTables.WriteLatencies.size();
  966. WLIdx != WLEnd; ++WLIdx) {
  967. MCWriteLatencyEntry &WLEntry = SchedTables.WriteLatencies[WLIdx];
  968. OS << " {" << format("%2d", WLEntry.Cycles) << ", "
  969. << format("%2d", WLEntry.WriteResourceID) << "}";
  970. if (WLIdx + 1 < WLEnd)
  971. OS << ',';
  972. OS << " // #" << WLIdx << " " << SchedTables.WriterNames[WLIdx] << '\n';
  973. }
  974. OS << "}; // " << Target << "WriteLatencyTable\n";
  975. // Emit global ReadAdvanceTable.
  976. OS << "\n// {UseIdx, WriteResourceID, Cycles}\n"
  977. << "extern const llvm::MCReadAdvanceEntry "
  978. << Target << "ReadAdvanceTable[] = {\n"
  979. << " {0, 0, 0}, // Invalid\n";
  980. for (unsigned RAIdx = 1, RAEnd = SchedTables.ReadAdvanceEntries.size();
  981. RAIdx != RAEnd; ++RAIdx) {
  982. MCReadAdvanceEntry &RAEntry = SchedTables.ReadAdvanceEntries[RAIdx];
  983. OS << " {" << RAEntry.UseIdx << ", "
  984. << format("%2d", RAEntry.WriteResourceID) << ", "
  985. << format("%2d", RAEntry.Cycles) << "}";
  986. if (RAIdx + 1 < RAEnd)
  987. OS << ',';
  988. OS << " // #" << RAIdx << '\n';
  989. }
  990. OS << "}; // " << Target << "ReadAdvanceTable\n";
  991. // Emit a SchedClass table for each processor.
  992. for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
  993. PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
  994. if (!PI->hasInstrSchedModel())
  995. continue;
  996. std::vector<MCSchedClassDesc> &SCTab =
  997. SchedTables.ProcSchedClasses[1 + (PI - SchedModels.procModelBegin())];
  998. OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup,"
  999. << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n";
  1000. OS << "static const llvm::MCSchedClassDesc "
  1001. << PI->ModelName << "SchedClasses[] = {\n";
  1002. // The first class is always invalid. We no way to distinguish it except by
  1003. // name and position.
  1004. assert(SchedModels.getSchedClass(0).Name == "NoInstrModel"
  1005. && "invalid class not first");
  1006. OS << " {DBGFIELD(\"InvalidSchedClass\") "
  1007. << MCSchedClassDesc::InvalidNumMicroOps
  1008. << ", 0, 0, 0, 0, 0, 0, 0, 0},\n";
  1009. for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
  1010. MCSchedClassDesc &MCDesc = SCTab[SCIdx];
  1011. const CodeGenSchedClass &SchedClass = SchedModels.getSchedClass(SCIdx);
  1012. OS << " {DBGFIELD(\"" << SchedClass.Name << "\") ";
  1013. if (SchedClass.Name.size() < 18)
  1014. OS.indent(18 - SchedClass.Name.size());
  1015. OS << MCDesc.NumMicroOps
  1016. << ", " << MCDesc.BeginGroup << ", " << MCDesc.EndGroup
  1017. << ", " << format("%2d", MCDesc.WriteProcResIdx)
  1018. << ", " << MCDesc.NumWriteProcResEntries
  1019. << ", " << format("%2d", MCDesc.WriteLatencyIdx)
  1020. << ", " << MCDesc.NumWriteLatencyEntries
  1021. << ", " << format("%2d", MCDesc.ReadAdvanceIdx)
  1022. << ", " << MCDesc.NumReadAdvanceEntries << "}";
  1023. if (SCIdx + 1 < SCEnd)
  1024. OS << ',';
  1025. OS << " // #" << SCIdx << '\n';
  1026. }
  1027. OS << "}; // " << PI->ModelName << "SchedClasses\n";
  1028. }
  1029. }
  1030. void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
  1031. // For each processor model.
  1032. for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
  1033. PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
  1034. // Emit processor resource table.
  1035. if (PI->hasInstrSchedModel())
  1036. EmitProcessorResources(*PI, OS);
  1037. else if(!PI->ProcResourceDefs.empty())
  1038. PrintFatalError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
  1039. "ProcResources without defining WriteRes SchedWriteRes");
  1040. // Begin processor itinerary properties
  1041. OS << "\n";
  1042. OS << "static const llvm::MCSchedModel " << PI->ModelName << " = {\n";
  1043. EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
  1044. EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ',');
  1045. EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ',');
  1046. EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
  1047. EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
  1048. EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
  1049. OS << " " << (bool)(PI->ModelDef ?
  1050. PI->ModelDef->getValueAsBit("PostRAScheduler") : 0)
  1051. << ", // " << "PostRAScheduler\n";
  1052. OS << " " << (bool)(PI->ModelDef ?
  1053. PI->ModelDef->getValueAsBit("CompleteModel") : 0)
  1054. << ", // " << "CompleteModel\n";
  1055. OS << " " << PI->Index << ", // Processor ID\n";
  1056. if (PI->hasInstrSchedModel())
  1057. OS << " " << PI->ModelName << "ProcResources" << ",\n"
  1058. << " " << PI->ModelName << "SchedClasses" << ",\n"
  1059. << " " << PI->ProcResourceDefs.size()+1 << ",\n"
  1060. << " " << (SchedModels.schedClassEnd()
  1061. - SchedModels.schedClassBegin()) << ",\n";
  1062. else
  1063. OS << " 0, 0, 0, 0, // No instruction-level machine model.\n";
  1064. if (PI->hasItineraries())
  1065. OS << " " << PI->ItinsDef->getName() << "};\n";
  1066. else
  1067. OS << " nullptr}; // No Itinerary\n";
  1068. }
  1069. }
  1070. //
  1071. // EmitProcessorLookup - generate cpu name to itinerary lookup table.
  1072. //
  1073. void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
  1074. // Gather and sort processor information
  1075. std::vector<Record*> ProcessorList =
  1076. Records.getAllDerivedDefinitions("Processor");
  1077. std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
  1078. // Begin processor table
  1079. OS << "\n";
  1080. OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
  1081. << "extern const llvm::SubtargetInfoKV "
  1082. << Target << "ProcSchedKV[] = {\n";
  1083. // For each processor
  1084. for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
  1085. // Next processor
  1086. Record *Processor = ProcessorList[i];
  1087. const std::string &Name = Processor->getValueAsString("Name");
  1088. const std::string &ProcModelName =
  1089. SchedModels.getModelForProc(Processor).ModelName;
  1090. // Emit as { "cpu", procinit },
  1091. OS << " { \"" << Name << "\", (const void *)&" << ProcModelName << " }";
  1092. // Depending on ''if more in the list'' emit comma
  1093. if (++i < N) OS << ",";
  1094. OS << "\n";
  1095. }
  1096. // End processor table
  1097. OS << "};\n";
  1098. }
  1099. //
  1100. // EmitSchedModel - Emits all scheduling model tables, folding common patterns.
  1101. //
  1102. void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
  1103. OS << "#ifdef DBGFIELD\n"
  1104. << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n"
  1105. << "#endif\n"
  1106. << "#ifndef NDEBUG\n"
  1107. << "#define DBGFIELD(x) x,\n"
  1108. << "#else\n"
  1109. << "#define DBGFIELD(x)\n"
  1110. << "#endif\n";
  1111. if (SchedModels.hasItineraries()) {
  1112. std::vector<std::vector<InstrItinerary> > ProcItinLists;
  1113. // Emit the stage data
  1114. EmitStageAndOperandCycleData(OS, ProcItinLists);
  1115. EmitItineraries(OS, ProcItinLists);
  1116. }
  1117. OS << "\n// ===============================================================\n"
  1118. << "// Data tables for the new per-operand machine model.\n";
  1119. SchedClassTables SchedTables;
  1120. for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
  1121. PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
  1122. GenSchedClassTables(*PI, SchedTables);
  1123. }
  1124. EmitSchedClassTables(SchedTables, OS);
  1125. // Emit the processor machine model
  1126. EmitProcessorModels(OS);
  1127. // Emit the processor lookup data
  1128. EmitProcessorLookup(OS);
  1129. OS << "#undef DBGFIELD";
  1130. }
  1131. void SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName,
  1132. raw_ostream &OS) {
  1133. OS << "unsigned " << ClassName
  1134. << "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,"
  1135. << " const TargetSchedModel *SchedModel) const {\n";
  1136. std::vector<Record*> Prologs = Records.getAllDerivedDefinitions("PredicateProlog");
  1137. std::sort(Prologs.begin(), Prologs.end(), LessRecord());
  1138. for (std::vector<Record*>::const_iterator
  1139. PI = Prologs.begin(), PE = Prologs.end(); PI != PE; ++PI) {
  1140. OS << (*PI)->getValueAsString("Code") << '\n';
  1141. }
  1142. IdxVec VariantClasses;
  1143. for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
  1144. SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
  1145. if (SCI->Transitions.empty())
  1146. continue;
  1147. VariantClasses.push_back(SCI->Index);
  1148. }
  1149. if (!VariantClasses.empty()) {
  1150. OS << " switch (SchedClass) {\n";
  1151. for (IdxIter VCI = VariantClasses.begin(), VCE = VariantClasses.end();
  1152. VCI != VCE; ++VCI) {
  1153. const CodeGenSchedClass &SC = SchedModels.getSchedClass(*VCI);
  1154. OS << " case " << *VCI << ": // " << SC.Name << '\n';
  1155. IdxVec ProcIndices;
  1156. for (std::vector<CodeGenSchedTransition>::const_iterator
  1157. TI = SC.Transitions.begin(), TE = SC.Transitions.end();
  1158. TI != TE; ++TI) {
  1159. IdxVec PI;
  1160. std::set_union(TI->ProcIndices.begin(), TI->ProcIndices.end(),
  1161. ProcIndices.begin(), ProcIndices.end(),
  1162. std::back_inserter(PI));
  1163. ProcIndices.swap(PI);
  1164. }
  1165. for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
  1166. PI != PE; ++PI) {
  1167. OS << " ";
  1168. if (*PI != 0)
  1169. OS << "if (SchedModel->getProcessorID() == " << *PI << ") ";
  1170. OS << "{ // " << (SchedModels.procModelBegin() + *PI)->ModelName
  1171. << '\n';
  1172. for (std::vector<CodeGenSchedTransition>::const_iterator
  1173. TI = SC.Transitions.begin(), TE = SC.Transitions.end();
  1174. TI != TE; ++TI) {
  1175. if (*PI != 0 && !std::count(TI->ProcIndices.begin(),
  1176. TI->ProcIndices.end(), *PI)) {
  1177. continue;
  1178. }
  1179. OS << " if (";
  1180. for (RecIter RI = TI->PredTerm.begin(), RE = TI->PredTerm.end();
  1181. RI != RE; ++RI) {
  1182. if (RI != TI->PredTerm.begin())
  1183. OS << "\n && ";
  1184. OS << "(" << (*RI)->getValueAsString("Predicate") << ")";
  1185. }
  1186. OS << ")\n"
  1187. << " return " << TI->ToClassIdx << "; // "
  1188. << SchedModels.getSchedClass(TI->ToClassIdx).Name << '\n';
  1189. }
  1190. OS << " }\n";
  1191. if (*PI == 0)
  1192. break;
  1193. }
  1194. if (SC.isInferred())
  1195. OS << " return " << SC.Index << ";\n";
  1196. OS << " break;\n";
  1197. }
  1198. OS << " };\n";
  1199. }
  1200. OS << " report_fatal_error(\"Expected a variant SchedClass\");\n"
  1201. << "} // " << ClassName << "::resolveSchedClass\n";
  1202. }
  1203. //
  1204. // ParseFeaturesFunction - Produces a subtarget specific function for parsing
  1205. // the subtarget features string.
  1206. //
  1207. void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
  1208. unsigned NumFeatures,
  1209. unsigned NumProcs) {
  1210. std::vector<Record*> Features =
  1211. Records.getAllDerivedDefinitions("SubtargetFeature");
  1212. std::sort(Features.begin(), Features.end(), LessRecord());
  1213. OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
  1214. << "// subtarget options.\n"
  1215. << "void llvm::";
  1216. OS << Target;
  1217. OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
  1218. << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
  1219. << " DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
  1220. if (Features.empty()) {
  1221. OS << "}\n";
  1222. return;
  1223. }
  1224. OS << " InitMCProcessorInfo(CPU, FS);\n"
  1225. << " const FeatureBitset& Bits = getFeatureBits();\n";
  1226. for (unsigned i = 0; i < Features.size(); i++) {
  1227. // Next record
  1228. Record *R = Features[i];
  1229. const std::string &Instance = R->getName();
  1230. const std::string &Value = R->getValueAsString("Value");
  1231. const std::string &Attribute = R->getValueAsString("Attribute");
  1232. if (Value=="true" || Value=="false")
  1233. OS << " if (Bits[" << Target << "::"
  1234. << Instance << "]) "
  1235. << Attribute << " = " << Value << ";\n";
  1236. else
  1237. OS << " if (Bits[" << Target << "::"
  1238. << Instance << "] && "
  1239. << Attribute << " < " << Value << ") "
  1240. << Attribute << " = " << Value << ";\n";
  1241. }
  1242. OS << "}\n";
  1243. }
  1244. //
  1245. // SubtargetEmitter::run - Main subtarget enumeration emitter.
  1246. //
  1247. void SubtargetEmitter::run(raw_ostream &OS) {
  1248. emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
  1249. OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
  1250. OS << "#undef GET_SUBTARGETINFO_ENUM\n";
  1251. OS << "namespace llvm {\n";
  1252. Enumeration(OS, "SubtargetFeature");
  1253. OS << "} // End llvm namespace \n";
  1254. OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
  1255. OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
  1256. OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
  1257. OS << "namespace llvm {\n";
  1258. #if 0
  1259. OS << "namespace {\n";
  1260. #endif
  1261. unsigned NumFeatures = FeatureKeyValues(OS);
  1262. OS << "\n";
  1263. unsigned NumProcs = CPUKeyValues(OS);
  1264. OS << "\n";
  1265. EmitSchedModel(OS);
  1266. OS << "\n";
  1267. #if 0
  1268. OS << "}\n";
  1269. #endif
  1270. // MCInstrInfo initialization routine.
  1271. OS << "static inline MCSubtargetInfo *create" << Target
  1272. << "MCSubtargetInfoImpl("
  1273. << "const Triple &TT, StringRef CPU, StringRef FS) {\n";
  1274. OS << " return new MCSubtargetInfo(TT, CPU, FS, ";
  1275. if (NumFeatures)
  1276. OS << Target << "FeatureKV, ";
  1277. else
  1278. OS << "None, ";
  1279. if (NumProcs)
  1280. OS << Target << "SubTypeKV, ";
  1281. else
  1282. OS << "None, ";
  1283. OS << '\n'; OS.indent(22);
  1284. OS << Target << "ProcSchedKV, "
  1285. << Target << "WriteProcResTable, "
  1286. << Target << "WriteLatencyTable, "
  1287. << Target << "ReadAdvanceTable, ";
  1288. if (SchedModels.hasItineraries()) {
  1289. OS << '\n'; OS.indent(22);
  1290. OS << Target << "Stages, "
  1291. << Target << "OperandCycles, "
  1292. << Target << "ForwardingPaths";
  1293. } else
  1294. OS << "0, 0, 0";
  1295. OS << ");\n}\n\n";
  1296. OS << "} // End llvm namespace \n";
  1297. OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
  1298. OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
  1299. OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
  1300. OS << "#include \"llvm/Support/Debug.h\"\n";
  1301. OS << "#include \"llvm/Support/raw_ostream.h\"\n";
  1302. ParseFeaturesFunction(OS, NumFeatures, NumProcs);
  1303. OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
  1304. // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
  1305. OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
  1306. OS << "#undef GET_SUBTARGETINFO_HEADER\n";
  1307. std::string ClassName = Target + "GenSubtargetInfo";
  1308. OS << "namespace llvm {\n";
  1309. OS << "class DFAPacketizer;\n";
  1310. OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
  1311. << " explicit " << ClassName << "(const Triple &TT, StringRef CPU, "
  1312. << "StringRef FS);\n"
  1313. << "public:\n"
  1314. << " unsigned resolveSchedClass(unsigned SchedClass, "
  1315. << " const MachineInstr *DefMI,"
  1316. << " const TargetSchedModel *SchedModel) const override;\n"
  1317. << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
  1318. << " const;\n"
  1319. << "};\n";
  1320. OS << "} // End llvm namespace \n";
  1321. OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
  1322. OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
  1323. OS << "#undef GET_SUBTARGETINFO_CTOR\n";
  1324. OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n";
  1325. OS << "namespace llvm {\n";
  1326. OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
  1327. OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
  1328. OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
  1329. OS << "extern const llvm::MCWriteProcResEntry "
  1330. << Target << "WriteProcResTable[];\n";
  1331. OS << "extern const llvm::MCWriteLatencyEntry "
  1332. << Target << "WriteLatencyTable[];\n";
  1333. OS << "extern const llvm::MCReadAdvanceEntry "
  1334. << Target << "ReadAdvanceTable[];\n";
  1335. if (SchedModels.hasItineraries()) {
  1336. OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
  1337. OS << "extern const unsigned " << Target << "OperandCycles[];\n";
  1338. OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
  1339. }
  1340. OS << ClassName << "::" << ClassName << "(const Triple &TT, StringRef CPU, "
  1341. << "StringRef FS)\n"
  1342. << " : TargetSubtargetInfo(TT, CPU, FS, ";
  1343. if (NumFeatures)
  1344. OS << "makeArrayRef(" << Target << "FeatureKV, " << NumFeatures << "), ";
  1345. else
  1346. OS << "None, ";
  1347. if (NumProcs)
  1348. OS << "makeArrayRef(" << Target << "SubTypeKV, " << NumProcs << "), ";
  1349. else
  1350. OS << "None, ";
  1351. OS << '\n'; OS.indent(24);
  1352. OS << Target << "ProcSchedKV, "
  1353. << Target << "WriteProcResTable, "
  1354. << Target << "WriteLatencyTable, "
  1355. << Target << "ReadAdvanceTable, ";
  1356. OS << '\n'; OS.indent(24);
  1357. if (SchedModels.hasItineraries()) {
  1358. OS << Target << "Stages, "
  1359. << Target << "OperandCycles, "
  1360. << Target << "ForwardingPaths";
  1361. } else
  1362. OS << "0, 0, 0";
  1363. OS << ") {}\n\n";
  1364. EmitSchedModelHelpers(ClassName, OS);
  1365. OS << "} // End llvm namespace \n";
  1366. OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
  1367. }
  1368. namespace llvm {
  1369. void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
  1370. CodeGenTarget CGTarget(RK);
  1371. SubtargetEmitter(RK, CGTarget).run(OS);
  1372. }
  1373. } // End llvm namespace