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 14 #include "CodeGenTarget.h" 15 #include "CodeGenSchedule.h" 16 #include "PredicateExpander.h" 17 #include "llvm/ADT/SmallPtrSet.h" 18 #include "llvm/ADT/STLExtras.h" 19 #include "llvm/ADT/StringExtras.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/MC/MCInstrItineraries.h" 22 #include "llvm/MC/MCSchedule.h" 23 #include "llvm/MC/SubtargetFeature.h" 24 #include "llvm/Support/Debug.h" 25 #include "llvm/Support/Format.h" 26 #include "llvm/Support/raw_ostream.h" 27 #include "llvm/TableGen/Error.h" 28 #include "llvm/TableGen/Record.h" 29 #include "llvm/TableGen/TableGenBackend.h" 30 #include <algorithm> 31 #include <cassert> 32 #include <cstdint> 33 #include <iterator> 34 #include <map> 35 #include <string> 36 #include <vector> 37 38 using namespace llvm; 39 40 #define DEBUG_TYPE "subtarget-emitter" 41 42 namespace { 43 44 class SubtargetEmitter { 45 // Each processor has a SchedClassDesc table with an entry for each SchedClass. 46 // The SchedClassDesc table indexes into a global write resource table, write 47 // latency table, and read advance table. 48 struct SchedClassTables { 49 std::vector<std::vector<MCSchedClassDesc>> ProcSchedClasses; 50 std::vector<MCWriteProcResEntry> WriteProcResources; 51 std::vector<MCWriteLatencyEntry> WriteLatencies; 52 std::vector<std::string> WriterNames; 53 std::vector<MCReadAdvanceEntry> ReadAdvanceEntries; 54 55 // Reserve an invalid entry at index 0 56 SchedClassTables() { 57 ProcSchedClasses.resize(1); 58 WriteProcResources.resize(1); 59 WriteLatencies.resize(1); 60 WriterNames.push_back("InvalidWrite"); 61 ReadAdvanceEntries.resize(1); 62 } 63 }; 64 65 struct LessWriteProcResources { 66 bool operator()(const MCWriteProcResEntry &LHS, 67 const MCWriteProcResEntry &RHS) { 68 return LHS.ProcResourceIdx < RHS.ProcResourceIdx; 69 } 70 }; 71 72 const CodeGenTarget &TGT; 73 RecordKeeper &Records; 74 CodeGenSchedModels &SchedModels; 75 std::string Target; 76 77 void Enumeration(raw_ostream &OS); 78 unsigned FeatureKeyValues(raw_ostream &OS); 79 unsigned CPUKeyValues(raw_ostream &OS); 80 void FormItineraryStageString(const std::string &Names, 81 Record *ItinData, std::string &ItinString, 82 unsigned &NStages); 83 void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString, 84 unsigned &NOperandCycles); 85 void FormItineraryBypassString(const std::string &Names, 86 Record *ItinData, 87 std::string &ItinString, unsigned NOperandCycles); 88 void EmitStageAndOperandCycleData(raw_ostream &OS, 89 std::vector<std::vector<InstrItinerary>> 90 &ProcItinLists); 91 void EmitItineraries(raw_ostream &OS, 92 std::vector<std::vector<InstrItinerary>> 93 &ProcItinLists); 94 unsigned EmitRegisterFileTables(const CodeGenProcModel &ProcModel, 95 raw_ostream &OS); 96 void EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel, 97 raw_ostream &OS); 98 void EmitProcessorProp(raw_ostream &OS, const Record *R, StringRef Name, 99 char Separator); 100 void EmitProcessorResourceSubUnits(const CodeGenProcModel &ProcModel, 101 raw_ostream &OS); 102 void EmitProcessorResources(const CodeGenProcModel &ProcModel, 103 raw_ostream &OS); 104 Record *FindWriteResources(const CodeGenSchedRW &SchedWrite, 105 const CodeGenProcModel &ProcModel); 106 Record *FindReadAdvance(const CodeGenSchedRW &SchedRead, 107 const CodeGenProcModel &ProcModel); 108 void ExpandProcResources(RecVec &PRVec, std::vector<int64_t> &Cycles, 109 const CodeGenProcModel &ProcModel); 110 void GenSchedClassTables(const CodeGenProcModel &ProcModel, 111 SchedClassTables &SchedTables); 112 void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS); 113 void EmitProcessorModels(raw_ostream &OS); 114 void EmitProcessorLookup(raw_ostream &OS); 115 void EmitSchedModelHelpers(const std::string &ClassName, raw_ostream &OS); 116 void emitSchedModelHelpersImpl(raw_ostream &OS, 117 bool OnlyExpandMCInstPredicates = false); 118 void emitGenMCSubtargetInfo(raw_ostream &OS); 119 void EmitMCInstrAnalysisPredicateFunctions(raw_ostream &OS); 120 121 void EmitSchedModel(raw_ostream &OS); 122 void EmitHwModeCheck(const std::string &ClassName, raw_ostream &OS); 123 void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures, 124 unsigned NumProcs); 125 126 public: 127 SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT) 128 : TGT(TGT), Records(R), SchedModels(TGT.getSchedModels()), 129 Target(TGT.getName()) {} 130 131 void run(raw_ostream &o); 132 }; 133 134 } // end anonymous namespace 135 136 // 137 // Enumeration - Emit the specified class as an enumeration. 138 // 139 void SubtargetEmitter::Enumeration(raw_ostream &OS) { 140 // Get all records of class and sort 141 std::vector<Record*> DefList = 142 Records.getAllDerivedDefinitions("SubtargetFeature"); 143 llvm::sort(DefList, LessRecord()); 144 145 unsigned N = DefList.size(); 146 if (N == 0) 147 return; 148 if (N > MAX_SUBTARGET_FEATURES) 149 PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES."); 150 151 OS << "namespace " << Target << " {\n"; 152 153 // Open enumeration. 154 OS << "enum {\n"; 155 156 // For each record 157 for (unsigned i = 0; i < N; ++i) { 158 // Next record 159 Record *Def = DefList[i]; 160 161 // Get and emit name 162 OS << " " << Def->getName() << " = " << i << ",\n"; 163 } 164 165 // Close enumeration and namespace 166 OS << "};\n"; 167 OS << "} // end namespace " << Target << "\n"; 168 } 169 170 // 171 // FeatureKeyValues - Emit data of all the subtarget features. Used by the 172 // command line. 173 // 174 unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { 175 // Gather and sort all the features 176 std::vector<Record*> FeatureList = 177 Records.getAllDerivedDefinitions("SubtargetFeature"); 178 179 if (FeatureList.empty()) 180 return 0; 181 182 llvm::sort(FeatureList, LessRecordFieldName()); 183 184 // Begin feature table 185 OS << "// Sorted (by key) array of values for CPU features.\n" 186 << "extern const llvm::SubtargetFeatureKV " << Target 187 << "FeatureKV[] = {\n"; 188 189 // For each feature 190 unsigned NumFeatures = 0; 191 for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) { 192 // Next feature 193 Record *Feature = FeatureList[i]; 194 195 StringRef Name = Feature->getName(); 196 StringRef CommandLineName = Feature->getValueAsString("Name"); 197 StringRef Desc = Feature->getValueAsString("Desc"); 198 199 if (CommandLineName.empty()) continue; 200 201 // Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in } } 202 OS << " { " 203 << "\"" << CommandLineName << "\", " 204 << "\"" << Desc << "\", " 205 << "{ " << Target << "::" << Name << " }, "; 206 207 RecVec ImpliesList = Feature->getValueAsListOfDefs("Implies"); 208 209 OS << "{"; 210 for (unsigned j = 0, M = ImpliesList.size(); j < M;) { 211 OS << " " << Target << "::" << ImpliesList[j]->getName(); 212 if (++j < M) OS << ","; 213 } 214 OS << " } },\n"; 215 ++NumFeatures; 216 } 217 218 // End feature table 219 OS << "};\n"; 220 221 return NumFeatures; 222 } 223 224 // 225 // CPUKeyValues - Emit data of all the subtarget processors. Used by command 226 // line. 227 // 228 unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { 229 // Gather and sort processor information 230 std::vector<Record*> ProcessorList = 231 Records.getAllDerivedDefinitions("Processor"); 232 llvm::sort(ProcessorList, LessRecordFieldName()); 233 234 // Begin processor table 235 OS << "// Sorted (by key) array of values for CPU subtype.\n" 236 << "extern const llvm::SubtargetFeatureKV " << Target 237 << "SubTypeKV[] = {\n"; 238 239 // For each processor 240 for (Record *Processor : ProcessorList) { 241 StringRef Name = Processor->getValueAsString("Name"); 242 RecVec FeatureList = Processor->getValueAsListOfDefs("Features"); 243 244 // Emit as { "cpu", "description", { f1 , f2 , ... fn } }, 245 OS << " { " 246 << "\"" << Name << "\", " 247 << "\"Select the " << Name << " processor\", "; 248 249 OS << "{"; 250 for (unsigned j = 0, M = FeatureList.size(); j < M;) { 251 OS << " " << Target << "::" << FeatureList[j]->getName(); 252 if (++j < M) OS << ","; 253 } 254 // The { } is for the "implies" section of this data structure. 255 OS << " }, { } },\n"; 256 } 257 258 // End processor table 259 OS << "};\n"; 260 261 return ProcessorList.size(); 262 } 263 264 // 265 // FormItineraryStageString - Compose a string containing the stage 266 // data initialization for the specified itinerary. N is the number 267 // of stages. 268 // 269 void SubtargetEmitter::FormItineraryStageString(const std::string &Name, 270 Record *ItinData, 271 std::string &ItinString, 272 unsigned &NStages) { 273 // Get states list 274 RecVec StageList = ItinData->getValueAsListOfDefs("Stages"); 275 276 // For each stage 277 unsigned N = NStages = StageList.size(); 278 for (unsigned i = 0; i < N;) { 279 // Next stage 280 const Record *Stage = StageList[i]; 281 282 // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind } 283 int Cycles = Stage->getValueAsInt("Cycles"); 284 ItinString += " { " + itostr(Cycles) + ", "; 285 286 // Get unit list 287 RecVec UnitList = Stage->getValueAsListOfDefs("Units"); 288 289 // For each unit 290 for (unsigned j = 0, M = UnitList.size(); j < M;) { 291 // Add name and bitwise or 292 ItinString += Name + "FU::" + UnitList[j]->getName().str(); 293 if (++j < M) ItinString += " | "; 294 } 295 296 int TimeInc = Stage->getValueAsInt("TimeInc"); 297 ItinString += ", " + itostr(TimeInc); 298 299 int Kind = Stage->getValueAsInt("Kind"); 300 ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind); 301 302 // Close off stage 303 ItinString += " }"; 304 if (++i < N) ItinString += ", "; 305 } 306 } 307 308 // 309 // FormItineraryOperandCycleString - Compose a string containing the 310 // operand cycle initialization for the specified itinerary. N is the 311 // number of operands that has cycles specified. 312 // 313 void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData, 314 std::string &ItinString, unsigned &NOperandCycles) { 315 // Get operand cycle list 316 std::vector<int64_t> OperandCycleList = 317 ItinData->getValueAsListOfInts("OperandCycles"); 318 319 // For each operand cycle 320 unsigned N = NOperandCycles = OperandCycleList.size(); 321 for (unsigned i = 0; i < N;) { 322 // Next operand cycle 323 const int OCycle = OperandCycleList[i]; 324 325 ItinString += " " + itostr(OCycle); 326 if (++i < N) ItinString += ", "; 327 } 328 } 329 330 void SubtargetEmitter::FormItineraryBypassString(const std::string &Name, 331 Record *ItinData, 332 std::string &ItinString, 333 unsigned NOperandCycles) { 334 RecVec BypassList = ItinData->getValueAsListOfDefs("Bypasses"); 335 unsigned N = BypassList.size(); 336 unsigned i = 0; 337 for (; i < N;) { 338 ItinString += Name + "Bypass::" + BypassList[i]->getName().str(); 339 if (++i < NOperandCycles) ItinString += ", "; 340 } 341 for (; i < NOperandCycles;) { 342 ItinString += " 0"; 343 if (++i < NOperandCycles) ItinString += ", "; 344 } 345 } 346 347 // 348 // EmitStageAndOperandCycleData - Generate unique itinerary stages and operand 349 // cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed 350 // by CodeGenSchedClass::Index. 351 // 352 void SubtargetEmitter:: 353 EmitStageAndOperandCycleData(raw_ostream &OS, 354 std::vector<std::vector<InstrItinerary>> 355 &ProcItinLists) { 356 // Multiple processor models may share an itinerary record. Emit it once. 357 SmallPtrSet<Record*, 8> ItinsDefSet; 358 359 // Emit functional units for all the itineraries. 360 for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) { 361 362 if (!ItinsDefSet.insert(ProcModel.ItinsDef).second) 363 continue; 364 365 RecVec FUs = ProcModel.ItinsDef->getValueAsListOfDefs("FU"); 366 if (FUs.empty()) 367 continue; 368 369 StringRef Name = ProcModel.ItinsDef->getName(); 370 OS << "\n// Functional units for \"" << Name << "\"\n" 371 << "namespace " << Name << "FU {\n"; 372 373 for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j) 374 OS << " const unsigned " << FUs[j]->getName() 375 << " = 1 << " << j << ";\n"; 376 377 OS << "} // end namespace " << Name << "FU\n"; 378 379 RecVec BPs = ProcModel.ItinsDef->getValueAsListOfDefs("BP"); 380 if (!BPs.empty()) { 381 OS << "\n// Pipeline forwarding paths for itineraries \"" << Name 382 << "\"\n" << "namespace " << Name << "Bypass {\n"; 383 384 OS << " const unsigned NoBypass = 0;\n"; 385 for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j) 386 OS << " const unsigned " << BPs[j]->getName() 387 << " = 1 << " << j << ";\n"; 388 389 OS << "} // end namespace " << Name << "Bypass\n"; 390 } 391 } 392 393 // Begin stages table 394 std::string StageTable = "\nextern const llvm::InstrStage " + Target + 395 "Stages[] = {\n"; 396 StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n"; 397 398 // Begin operand cycle table 399 std::string OperandCycleTable = "extern const unsigned " + Target + 400 "OperandCycles[] = {\n"; 401 OperandCycleTable += " 0, // No itinerary\n"; 402 403 // Begin pipeline bypass table 404 std::string BypassTable = "extern const unsigned " + Target + 405 "ForwardingPaths[] = {\n"; 406 BypassTable += " 0, // No itinerary\n"; 407 408 // For each Itinerary across all processors, add a unique entry to the stages, 409 // operand cycles, and pipeline bypass tables. Then add the new Itinerary 410 // object with computed offsets to the ProcItinLists result. 411 unsigned StageCount = 1, OperandCycleCount = 1; 412 std::map<std::string, unsigned> ItinStageMap, ItinOperandMap; 413 for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) { 414 // Add process itinerary to the list. 415 ProcItinLists.resize(ProcItinLists.size()+1); 416 417 // If this processor defines no itineraries, then leave the itinerary list 418 // empty. 419 std::vector<InstrItinerary> &ItinList = ProcItinLists.back(); 420 if (!ProcModel.hasItineraries()) 421 continue; 422 423 StringRef Name = ProcModel.ItinsDef->getName(); 424 425 ItinList.resize(SchedModels.numInstrSchedClasses()); 426 assert(ProcModel.ItinDefList.size() == ItinList.size() && "bad Itins"); 427 428 for (unsigned SchedClassIdx = 0, SchedClassEnd = ItinList.size(); 429 SchedClassIdx < SchedClassEnd; ++SchedClassIdx) { 430 431 // Next itinerary data 432 Record *ItinData = ProcModel.ItinDefList[SchedClassIdx]; 433 434 // Get string and stage count 435 std::string ItinStageString; 436 unsigned NStages = 0; 437 if (ItinData) 438 FormItineraryStageString(Name, ItinData, ItinStageString, NStages); 439 440 // Get string and operand cycle count 441 std::string ItinOperandCycleString; 442 unsigned NOperandCycles = 0; 443 std::string ItinBypassString; 444 if (ItinData) { 445 FormItineraryOperandCycleString(ItinData, ItinOperandCycleString, 446 NOperandCycles); 447 448 FormItineraryBypassString(Name, ItinData, ItinBypassString, 449 NOperandCycles); 450 } 451 452 // Check to see if stage already exists and create if it doesn't 453 uint16_t FindStage = 0; 454 if (NStages > 0) { 455 FindStage = ItinStageMap[ItinStageString]; 456 if (FindStage == 0) { 457 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices 458 StageTable += ItinStageString + ", // " + itostr(StageCount); 459 if (NStages > 1) 460 StageTable += "-" + itostr(StageCount + NStages - 1); 461 StageTable += "\n"; 462 // Record Itin class number. 463 ItinStageMap[ItinStageString] = FindStage = StageCount; 464 StageCount += NStages; 465 } 466 } 467 468 // Check to see if operand cycle already exists and create if it doesn't 469 uint16_t FindOperandCycle = 0; 470 if (NOperandCycles > 0) { 471 std::string ItinOperandString = ItinOperandCycleString+ItinBypassString; 472 FindOperandCycle = ItinOperandMap[ItinOperandString]; 473 if (FindOperandCycle == 0) { 474 // Emit as cycle, // index 475 OperandCycleTable += ItinOperandCycleString + ", // "; 476 std::string OperandIdxComment = itostr(OperandCycleCount); 477 if (NOperandCycles > 1) 478 OperandIdxComment += "-" 479 + itostr(OperandCycleCount + NOperandCycles - 1); 480 OperandCycleTable += OperandIdxComment + "\n"; 481 // Record Itin class number. 482 ItinOperandMap[ItinOperandCycleString] = 483 FindOperandCycle = OperandCycleCount; 484 // Emit as bypass, // index 485 BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n"; 486 OperandCycleCount += NOperandCycles; 487 } 488 } 489 490 // Set up itinerary as location and location + stage count 491 int16_t NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0; 492 InstrItinerary Intinerary = { 493 NumUOps, 494 FindStage, 495 uint16_t(FindStage + NStages), 496 FindOperandCycle, 497 uint16_t(FindOperandCycle + NOperandCycles), 498 }; 499 500 // Inject - empty slots will be 0, 0 501 ItinList[SchedClassIdx] = Intinerary; 502 } 503 } 504 505 // Closing stage 506 StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End stages\n"; 507 StageTable += "};\n"; 508 509 // Closing operand cycles 510 OperandCycleTable += " 0 // End operand cycles\n"; 511 OperandCycleTable += "};\n"; 512 513 BypassTable += " 0 // End bypass tables\n"; 514 BypassTable += "};\n"; 515 516 // Emit tables. 517 OS << StageTable; 518 OS << OperandCycleTable; 519 OS << BypassTable; 520 } 521 522 // 523 // EmitProcessorData - Generate data for processor itineraries that were 524 // computed during EmitStageAndOperandCycleData(). ProcItinLists lists all 525 // Itineraries for each processor. The Itinerary lists are indexed on 526 // CodeGenSchedClass::Index. 527 // 528 void SubtargetEmitter:: 529 EmitItineraries(raw_ostream &OS, 530 std::vector<std::vector<InstrItinerary>> &ProcItinLists) { 531 // Multiple processor models may share an itinerary record. Emit it once. 532 SmallPtrSet<Record*, 8> ItinsDefSet; 533 534 // For each processor's machine model 535 std::vector<std::vector<InstrItinerary>>::iterator 536 ProcItinListsIter = ProcItinLists.begin(); 537 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), 538 PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) { 539 540 Record *ItinsDef = PI->ItinsDef; 541 if (!ItinsDefSet.insert(ItinsDef).second) 542 continue; 543 544 // Get the itinerary list for the processor. 545 assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator"); 546 std::vector<InstrItinerary> &ItinList = *ProcItinListsIter; 547 548 // Empty itineraries aren't referenced anywhere in the tablegen output 549 // so don't emit them. 550 if (ItinList.empty()) 551 continue; 552 553 OS << "\n"; 554 OS << "static const llvm::InstrItinerary "; 555 556 // Begin processor itinerary table 557 OS << ItinsDef->getName() << "[] = {\n"; 558 559 // For each itinerary class in CodeGenSchedClass::Index order. 560 for (unsigned j = 0, M = ItinList.size(); j < M; ++j) { 561 InstrItinerary &Intinerary = ItinList[j]; 562 563 // Emit Itinerary in the form of 564 // { firstStage, lastStage, firstCycle, lastCycle } // index 565 OS << " { " << 566 Intinerary.NumMicroOps << ", " << 567 Intinerary.FirstStage << ", " << 568 Intinerary.LastStage << ", " << 569 Intinerary.FirstOperandCycle << ", " << 570 Intinerary.LastOperandCycle << " }" << 571 ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n"; 572 } 573 // End processor itinerary table 574 OS << " { 0, uint16_t(~0U), uint16_t(~0U), uint16_t(~0U), uint16_t(~0U) }" 575 "// end marker\n"; 576 OS << "};\n"; 577 } 578 } 579 580 // Emit either the value defined in the TableGen Record, or the default 581 // value defined in the C++ header. The Record is null if the processor does not 582 // define a model. 583 void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R, 584 StringRef Name, char Separator) { 585 OS << " "; 586 int V = R ? R->getValueAsInt(Name) : -1; 587 if (V >= 0) 588 OS << V << Separator << " // " << Name; 589 else 590 OS << "MCSchedModel::Default" << Name << Separator; 591 OS << '\n'; 592 } 593 594 void SubtargetEmitter::EmitProcessorResourceSubUnits( 595 const CodeGenProcModel &ProcModel, raw_ostream &OS) { 596 OS << "\nstatic const unsigned " << ProcModel.ModelName 597 << "ProcResourceSubUnits[] = {\n" 598 << " 0, // Invalid\n"; 599 600 for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) { 601 Record *PRDef = ProcModel.ProcResourceDefs[i]; 602 if (!PRDef->isSubClassOf("ProcResGroup")) 603 continue; 604 RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources"); 605 for (Record *RUDef : ResUnits) { 606 Record *const RU = 607 SchedModels.findProcResUnits(RUDef, ProcModel, PRDef->getLoc()); 608 for (unsigned J = 0; J < RU->getValueAsInt("NumUnits"); ++J) { 609 OS << " " << ProcModel.getProcResourceIdx(RU) << ", "; 610 } 611 } 612 OS << " // " << PRDef->getName() << "\n"; 613 } 614 OS << "};\n"; 615 } 616 617 static void EmitRetireControlUnitInfo(const CodeGenProcModel &ProcModel, 618 raw_ostream &OS) { 619 int64_t ReorderBufferSize = 0, MaxRetirePerCycle = 0; 620 if (Record *RCU = ProcModel.RetireControlUnit) { 621 ReorderBufferSize = 622 std::max(ReorderBufferSize, RCU->getValueAsInt("ReorderBufferSize")); 623 MaxRetirePerCycle = 624 std::max(MaxRetirePerCycle, RCU->getValueAsInt("MaxRetirePerCycle")); 625 } 626 627 OS << ReorderBufferSize << ", // ReorderBufferSize\n "; 628 OS << MaxRetirePerCycle << ", // MaxRetirePerCycle\n "; 629 } 630 631 static void EmitRegisterFileInfo(const CodeGenProcModel &ProcModel, 632 unsigned NumRegisterFiles, 633 unsigned NumCostEntries, raw_ostream &OS) { 634 if (NumRegisterFiles) 635 OS << ProcModel.ModelName << "RegisterFiles,\n " << (1 + NumRegisterFiles); 636 else 637 OS << "nullptr,\n 0"; 638 639 OS << ", // Number of register files.\n "; 640 if (NumCostEntries) 641 OS << ProcModel.ModelName << "RegisterCosts,\n "; 642 else 643 OS << "nullptr,\n "; 644 OS << NumCostEntries << ", // Number of register cost entries.\n"; 645 } 646 647 unsigned 648 SubtargetEmitter::EmitRegisterFileTables(const CodeGenProcModel &ProcModel, 649 raw_ostream &OS) { 650 if (llvm::all_of(ProcModel.RegisterFiles, [](const CodeGenRegisterFile &RF) { 651 return RF.hasDefaultCosts(); 652 })) 653 return 0; 654 655 // Print the RegisterCost table first. 656 OS << "\n// {RegisterClassID, Register Cost, AllowMoveElimination }\n"; 657 OS << "static const llvm::MCRegisterCostEntry " << ProcModel.ModelName 658 << "RegisterCosts" 659 << "[] = {\n"; 660 661 for (const CodeGenRegisterFile &RF : ProcModel.RegisterFiles) { 662 // Skip register files with a default cost table. 663 if (RF.hasDefaultCosts()) 664 continue; 665 // Add entries to the cost table. 666 for (const CodeGenRegisterCost &RC : RF.Costs) { 667 OS << " { "; 668 Record *Rec = RC.RCDef; 669 if (Rec->getValue("Namespace")) 670 OS << Rec->getValueAsString("Namespace") << "::"; 671 OS << Rec->getName() << "RegClassID, " << RC.Cost << ", " 672 << RC.AllowMoveElimination << "},\n"; 673 } 674 } 675 OS << "};\n"; 676 677 // Now generate a table with register file info. 678 OS << "\n // {Name, #PhysRegs, #CostEntries, IndexToCostTbl, " 679 << "MaxMovesEliminatedPerCycle, AllowZeroMoveEliminationOnly }\n"; 680 OS << "static const llvm::MCRegisterFileDesc " << ProcModel.ModelName 681 << "RegisterFiles" 682 << "[] = {\n" 683 << " { \"InvalidRegisterFile\", 0, 0, 0, 0, 0 },\n"; 684 unsigned CostTblIndex = 0; 685 686 for (const CodeGenRegisterFile &RD : ProcModel.RegisterFiles) { 687 OS << " { "; 688 OS << '"' << RD.Name << '"' << ", " << RD.NumPhysRegs << ", "; 689 unsigned NumCostEntries = RD.Costs.size(); 690 OS << NumCostEntries << ", " << CostTblIndex << ", " 691 << RD.MaxMovesEliminatedPerCycle << ", " 692 << RD.AllowZeroMoveEliminationOnly << "},\n"; 693 CostTblIndex += NumCostEntries; 694 } 695 OS << "};\n"; 696 697 return CostTblIndex; 698 } 699 700 void SubtargetEmitter::EmitExtraProcessorInfo(const CodeGenProcModel &ProcModel, 701 raw_ostream &OS) { 702 // Generate a table of register file descriptors (one entry per each user 703 // defined register file), and a table of register costs. 704 unsigned NumCostEntries = EmitRegisterFileTables(ProcModel, OS); 705 706 // Now generate a table for the extra processor info. 707 OS << "\nstatic const llvm::MCExtraProcessorInfo " << ProcModel.ModelName 708 << "ExtraInfo = {\n "; 709 710 // Add information related to the retire control unit. 711 EmitRetireControlUnitInfo(ProcModel, OS); 712 713 // Add information related to the register files (i.e. where to find register 714 // file descriptors and register costs). 715 EmitRegisterFileInfo(ProcModel, ProcModel.RegisterFiles.size(), 716 NumCostEntries, OS); 717 718 OS << "};\n"; 719 } 720 721 void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel, 722 raw_ostream &OS) { 723 EmitProcessorResourceSubUnits(ProcModel, OS); 724 725 OS << "\n// {Name, NumUnits, SuperIdx, BufferSize, SubUnitsIdxBegin}\n"; 726 OS << "static const llvm::MCProcResourceDesc " << ProcModel.ModelName 727 << "ProcResources" 728 << "[] = {\n" 729 << " {\"InvalidUnit\", 0, 0, 0, 0},\n"; 730 731 unsigned SubUnitsOffset = 1; 732 for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) { 733 Record *PRDef = ProcModel.ProcResourceDefs[i]; 734 735 Record *SuperDef = nullptr; 736 unsigned SuperIdx = 0; 737 unsigned NumUnits = 0; 738 const unsigned SubUnitsBeginOffset = SubUnitsOffset; 739 int BufferSize = PRDef->getValueAsInt("BufferSize"); 740 if (PRDef->isSubClassOf("ProcResGroup")) { 741 RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources"); 742 for (Record *RU : ResUnits) { 743 NumUnits += RU->getValueAsInt("NumUnits"); 744 SubUnitsOffset += RU->getValueAsInt("NumUnits"); 745 } 746 } 747 else { 748 // Find the SuperIdx 749 if (PRDef->getValueInit("Super")->isComplete()) { 750 SuperDef = 751 SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), 752 ProcModel, PRDef->getLoc()); 753 SuperIdx = ProcModel.getProcResourceIdx(SuperDef); 754 } 755 NumUnits = PRDef->getValueAsInt("NumUnits"); 756 } 757 // Emit the ProcResourceDesc 758 OS << " {\"" << PRDef->getName() << "\", "; 759 if (PRDef->getName().size() < 15) 760 OS.indent(15 - PRDef->getName().size()); 761 OS << NumUnits << ", " << SuperIdx << ", " << BufferSize << ", "; 762 if (SubUnitsBeginOffset != SubUnitsOffset) { 763 OS << ProcModel.ModelName << "ProcResourceSubUnits + " 764 << SubUnitsBeginOffset; 765 } else { 766 OS << "nullptr"; 767 } 768 OS << "}, // #" << i+1; 769 if (SuperDef) 770 OS << ", Super=" << SuperDef->getName(); 771 OS << "\n"; 772 } 773 OS << "};\n"; 774 } 775 776 // Find the WriteRes Record that defines processor resources for this 777 // SchedWrite. 778 Record *SubtargetEmitter::FindWriteResources( 779 const CodeGenSchedRW &SchedWrite, const CodeGenProcModel &ProcModel) { 780 781 // Check if the SchedWrite is already subtarget-specific and directly 782 // specifies a set of processor resources. 783 if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes")) 784 return SchedWrite.TheDef; 785 786 Record *AliasDef = nullptr; 787 for (Record *A : SchedWrite.Aliases) { 788 const CodeGenSchedRW &AliasRW = 789 SchedModels.getSchedRW(A->getValueAsDef("AliasRW")); 790 if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) { 791 Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel"); 792 if (&SchedModels.getProcModel(ModelDef) != &ProcModel) 793 continue; 794 } 795 if (AliasDef) 796 PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases " 797 "defined for processor " + ProcModel.ModelName + 798 " Ensure only one SchedAlias exists per RW."); 799 AliasDef = AliasRW.TheDef; 800 } 801 if (AliasDef && AliasDef->isSubClassOf("SchedWriteRes")) 802 return AliasDef; 803 804 // Check this processor's list of write resources. 805 Record *ResDef = nullptr; 806 for (Record *WR : ProcModel.WriteResDefs) { 807 if (!WR->isSubClassOf("WriteRes")) 808 continue; 809 if (AliasDef == WR->getValueAsDef("WriteType") 810 || SchedWrite.TheDef == WR->getValueAsDef("WriteType")) { 811 if (ResDef) { 812 PrintFatalError(WR->getLoc(), "Resources are defined for both " 813 "SchedWrite and its alias on processor " + 814 ProcModel.ModelName); 815 } 816 ResDef = WR; 817 } 818 } 819 // TODO: If ProcModel has a base model (previous generation processor), 820 // then call FindWriteResources recursively with that model here. 821 if (!ResDef) { 822 PrintFatalError(ProcModel.ModelDef->getLoc(), 823 Twine("Processor does not define resources for ") + 824 SchedWrite.TheDef->getName()); 825 } 826 return ResDef; 827 } 828 829 /// Find the ReadAdvance record for the given SchedRead on this processor or 830 /// return NULL. 831 Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, 832 const CodeGenProcModel &ProcModel) { 833 // Check for SchedReads that directly specify a ReadAdvance. 834 if (SchedRead.TheDef->isSubClassOf("SchedReadAdvance")) 835 return SchedRead.TheDef; 836 837 // Check this processor's list of aliases for SchedRead. 838 Record *AliasDef = nullptr; 839 for (Record *A : SchedRead.Aliases) { 840 const CodeGenSchedRW &AliasRW = 841 SchedModels.getSchedRW(A->getValueAsDef("AliasRW")); 842 if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) { 843 Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel"); 844 if (&SchedModels.getProcModel(ModelDef) != &ProcModel) 845 continue; 846 } 847 if (AliasDef) 848 PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases " 849 "defined for processor " + ProcModel.ModelName + 850 " Ensure only one SchedAlias exists per RW."); 851 AliasDef = AliasRW.TheDef; 852 } 853 if (AliasDef && AliasDef->isSubClassOf("SchedReadAdvance")) 854 return AliasDef; 855 856 // Check this processor's ReadAdvanceList. 857 Record *ResDef = nullptr; 858 for (Record *RA : ProcModel.ReadAdvanceDefs) { 859 if (!RA->isSubClassOf("ReadAdvance")) 860 continue; 861 if (AliasDef == RA->getValueAsDef("ReadType") 862 || SchedRead.TheDef == RA->getValueAsDef("ReadType")) { 863 if (ResDef) { 864 PrintFatalError(RA->getLoc(), "Resources are defined for both " 865 "SchedRead and its alias on processor " + 866 ProcModel.ModelName); 867 } 868 ResDef = RA; 869 } 870 } 871 // TODO: If ProcModel has a base model (previous generation processor), 872 // then call FindReadAdvance recursively with that model here. 873 if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") { 874 PrintFatalError(ProcModel.ModelDef->getLoc(), 875 Twine("Processor does not define resources for ") + 876 SchedRead.TheDef->getName()); 877 } 878 return ResDef; 879 } 880 881 // Expand an explicit list of processor resources into a full list of implied 882 // resource groups and super resources that cover them. 883 void SubtargetEmitter::ExpandProcResources(RecVec &PRVec, 884 std::vector<int64_t> &Cycles, 885 const CodeGenProcModel &PM) { 886 assert(PRVec.size() == Cycles.size() && "failed precondition"); 887 for (unsigned i = 0, e = PRVec.size(); i != e; ++i) { 888 Record *PRDef = PRVec[i]; 889 RecVec SubResources; 890 if (PRDef->isSubClassOf("ProcResGroup")) 891 SubResources = PRDef->getValueAsListOfDefs("Resources"); 892 else { 893 SubResources.push_back(PRDef); 894 PRDef = SchedModels.findProcResUnits(PRDef, PM, PRDef->getLoc()); 895 for (Record *SubDef = PRDef; 896 SubDef->getValueInit("Super")->isComplete();) { 897 if (SubDef->isSubClassOf("ProcResGroup")) { 898 // Disallow this for simplicitly. 899 PrintFatalError(SubDef->getLoc(), "Processor resource group " 900 " cannot be a super resources."); 901 } 902 Record *SuperDef = 903 SchedModels.findProcResUnits(SubDef->getValueAsDef("Super"), PM, 904 SubDef->getLoc()); 905 PRVec.push_back(SuperDef); 906 Cycles.push_back(Cycles[i]); 907 SubDef = SuperDef; 908 } 909 } 910 for (Record *PR : PM.ProcResourceDefs) { 911 if (PR == PRDef || !PR->isSubClassOf("ProcResGroup")) 912 continue; 913 RecVec SuperResources = PR->getValueAsListOfDefs("Resources"); 914 RecIter SubI = SubResources.begin(), SubE = SubResources.end(); 915 for( ; SubI != SubE; ++SubI) { 916 if (!is_contained(SuperResources, *SubI)) { 917 break; 918 } 919 } 920 if (SubI == SubE) { 921 PRVec.push_back(PR); 922 Cycles.push_back(Cycles[i]); 923 } 924 } 925 } 926 } 927 928 // Generate the SchedClass table for this processor and update global 929 // tables. Must be called for each processor in order. 930 void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, 931 SchedClassTables &SchedTables) { 932 SchedTables.ProcSchedClasses.resize(SchedTables.ProcSchedClasses.size() + 1); 933 if (!ProcModel.hasInstrSchedModel()) 934 return; 935 936 std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back(); 937 LLVM_DEBUG(dbgs() << "\n+++ SCHED CLASSES (GenSchedClassTables) +++\n"); 938 for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) { 939 LLVM_DEBUG(SC.dump(&SchedModels)); 940 941 SCTab.resize(SCTab.size() + 1); 942 MCSchedClassDesc &SCDesc = SCTab.back(); 943 // SCDesc.Name is guarded by NDEBUG 944 SCDesc.NumMicroOps = 0; 945 SCDesc.BeginGroup = false; 946 SCDesc.EndGroup = false; 947 SCDesc.WriteProcResIdx = 0; 948 SCDesc.WriteLatencyIdx = 0; 949 SCDesc.ReadAdvanceIdx = 0; 950 951 // A Variant SchedClass has no resources of its own. 952 bool HasVariants = false; 953 for (const CodeGenSchedTransition &CGT : 954 make_range(SC.Transitions.begin(), SC.Transitions.end())) { 955 if (CGT.ProcIndices[0] == 0 || 956 is_contained(CGT.ProcIndices, ProcModel.Index)) { 957 HasVariants = true; 958 break; 959 } 960 } 961 if (HasVariants) { 962 SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps; 963 continue; 964 } 965 966 // Determine if the SchedClass is actually reachable on this processor. If 967 // not don't try to locate the processor resources, it will fail. 968 // If ProcIndices contains 0, this class applies to all processors. 969 assert(!SC.ProcIndices.empty() && "expect at least one procidx"); 970 if (SC.ProcIndices[0] != 0) { 971 if (!is_contained(SC.ProcIndices, ProcModel.Index)) 972 continue; 973 } 974 IdxVec Writes = SC.Writes; 975 IdxVec Reads = SC.Reads; 976 if (!SC.InstRWs.empty()) { 977 // This class has a default ReadWrite list which can be overridden by 978 // InstRW definitions. 979 Record *RWDef = nullptr; 980 for (Record *RW : SC.InstRWs) { 981 Record *RWModelDef = RW->getValueAsDef("SchedModel"); 982 if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) { 983 RWDef = RW; 984 break; 985 } 986 } 987 if (RWDef) { 988 Writes.clear(); 989 Reads.clear(); 990 SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"), 991 Writes, Reads); 992 } 993 } 994 if (Writes.empty()) { 995 // Check this processor's itinerary class resources. 996 for (Record *I : ProcModel.ItinRWDefs) { 997 RecVec Matched = I->getValueAsListOfDefs("MatchedItinClasses"); 998 if (is_contained(Matched, SC.ItinClassDef)) { 999 SchedModels.findRWs(I->getValueAsListOfDefs("OperandReadWrites"), 1000 Writes, Reads); 1001 break; 1002 } 1003 } 1004 if (Writes.empty()) { 1005 LLVM_DEBUG(dbgs() << ProcModel.ModelName 1006 << " does not have resources for class " << SC.Name 1007 << '\n'); 1008 } 1009 } 1010 // Sum resources across all operand writes. 1011 std::vector<MCWriteProcResEntry> WriteProcResources; 1012 std::vector<MCWriteLatencyEntry> WriteLatencies; 1013 std::vector<std::string> WriterNames; 1014 std::vector<MCReadAdvanceEntry> ReadAdvanceEntries; 1015 for (unsigned W : Writes) { 1016 IdxVec WriteSeq; 1017 SchedModels.expandRWSeqForProc(W, WriteSeq, /*IsRead=*/false, 1018 ProcModel); 1019 1020 // For each operand, create a latency entry. 1021 MCWriteLatencyEntry WLEntry; 1022 WLEntry.Cycles = 0; 1023 unsigned WriteID = WriteSeq.back(); 1024 WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name); 1025 // If this Write is not referenced by a ReadAdvance, don't distinguish it 1026 // from other WriteLatency entries. 1027 if (!SchedModels.hasReadOfWrite( 1028 SchedModels.getSchedWrite(WriteID).TheDef)) { 1029 WriteID = 0; 1030 } 1031 WLEntry.WriteResourceID = WriteID; 1032 1033 for (unsigned WS : WriteSeq) { 1034 1035 Record *WriteRes = 1036 FindWriteResources(SchedModels.getSchedWrite(WS), ProcModel); 1037 1038 // Mark the parent class as invalid for unsupported write types. 1039 if (WriteRes->getValueAsBit("Unsupported")) { 1040 SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps; 1041 break; 1042 } 1043 WLEntry.Cycles += WriteRes->getValueAsInt("Latency"); 1044 SCDesc.NumMicroOps += WriteRes->getValueAsInt("NumMicroOps"); 1045 SCDesc.BeginGroup |= WriteRes->getValueAsBit("BeginGroup"); 1046 SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup"); 1047 SCDesc.BeginGroup |= WriteRes->getValueAsBit("SingleIssue"); 1048 SCDesc.EndGroup |= WriteRes->getValueAsBit("SingleIssue"); 1049 1050 // Create an entry for each ProcResource listed in WriteRes. 1051 RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources"); 1052 std::vector<int64_t> Cycles = 1053 WriteRes->getValueAsListOfInts("ResourceCycles"); 1054 1055 if (Cycles.empty()) { 1056 // If ResourceCycles is not provided, default to one cycle per 1057 // resource. 1058 Cycles.resize(PRVec.size(), 1); 1059 } else if (Cycles.size() != PRVec.size()) { 1060 // If ResourceCycles is provided, check consistency. 1061 PrintFatalError( 1062 WriteRes->getLoc(), 1063 Twine("Inconsistent resource cycles: !size(ResourceCycles) != " 1064 "!size(ProcResources): ") 1065 .concat(Twine(PRVec.size())) 1066 .concat(" vs ") 1067 .concat(Twine(Cycles.size()))); 1068 } 1069 1070 ExpandProcResources(PRVec, Cycles, ProcModel); 1071 1072 for (unsigned PRIdx = 0, PREnd = PRVec.size(); 1073 PRIdx != PREnd; ++PRIdx) { 1074 MCWriteProcResEntry WPREntry; 1075 WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]); 1076 assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx"); 1077 WPREntry.Cycles = Cycles[PRIdx]; 1078 // If this resource is already used in this sequence, add the current 1079 // entry's cycles so that the same resource appears to be used 1080 // serially, rather than multiple parallel uses. This is important for 1081 // in-order machine where the resource consumption is a hazard. 1082 unsigned WPRIdx = 0, WPREnd = WriteProcResources.size(); 1083 for( ; WPRIdx != WPREnd; ++WPRIdx) { 1084 if (WriteProcResources[WPRIdx].ProcResourceIdx 1085 == WPREntry.ProcResourceIdx) { 1086 WriteProcResources[WPRIdx].Cycles += WPREntry.Cycles; 1087 break; 1088 } 1089 } 1090 if (WPRIdx == WPREnd) 1091 WriteProcResources.push_back(WPREntry); 1092 } 1093 } 1094 WriteLatencies.push_back(WLEntry); 1095 } 1096 // Create an entry for each operand Read in this SchedClass. 1097 // Entries must be sorted first by UseIdx then by WriteResourceID. 1098 for (unsigned UseIdx = 0, EndIdx = Reads.size(); 1099 UseIdx != EndIdx; ++UseIdx) { 1100 Record *ReadAdvance = 1101 FindReadAdvance(SchedModels.getSchedRead(Reads[UseIdx]), ProcModel); 1102 if (!ReadAdvance) 1103 continue; 1104 1105 // Mark the parent class as invalid for unsupported write types. 1106 if (ReadAdvance->getValueAsBit("Unsupported")) { 1107 SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps; 1108 break; 1109 } 1110 RecVec ValidWrites = ReadAdvance->getValueAsListOfDefs("ValidWrites"); 1111 IdxVec WriteIDs; 1112 if (ValidWrites.empty()) 1113 WriteIDs.push_back(0); 1114 else { 1115 for (Record *VW : ValidWrites) { 1116 WriteIDs.push_back(SchedModels.getSchedRWIdx(VW, /*IsRead=*/false)); 1117 } 1118 } 1119 llvm::sort(WriteIDs); 1120 for(unsigned W : WriteIDs) { 1121 MCReadAdvanceEntry RAEntry; 1122 RAEntry.UseIdx = UseIdx; 1123 RAEntry.WriteResourceID = W; 1124 RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles"); 1125 ReadAdvanceEntries.push_back(RAEntry); 1126 } 1127 } 1128 if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) { 1129 WriteProcResources.clear(); 1130 WriteLatencies.clear(); 1131 ReadAdvanceEntries.clear(); 1132 } 1133 // Add the information for this SchedClass to the global tables using basic 1134 // compression. 1135 // 1136 // WritePrecRes entries are sorted by ProcResIdx. 1137 llvm::sort(WriteProcResources, LessWriteProcResources()); 1138 1139 SCDesc.NumWriteProcResEntries = WriteProcResources.size(); 1140 std::vector<MCWriteProcResEntry>::iterator WPRPos = 1141 std::search(SchedTables.WriteProcResources.begin(), 1142 SchedTables.WriteProcResources.end(), 1143 WriteProcResources.begin(), WriteProcResources.end()); 1144 if (WPRPos != SchedTables.WriteProcResources.end()) 1145 SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin(); 1146 else { 1147 SCDesc.WriteProcResIdx = SchedTables.WriteProcResources.size(); 1148 SchedTables.WriteProcResources.insert(WPRPos, WriteProcResources.begin(), 1149 WriteProcResources.end()); 1150 } 1151 // Latency entries must remain in operand order. 1152 SCDesc.NumWriteLatencyEntries = WriteLatencies.size(); 1153 std::vector<MCWriteLatencyEntry>::iterator WLPos = 1154 std::search(SchedTables.WriteLatencies.begin(), 1155 SchedTables.WriteLatencies.end(), 1156 WriteLatencies.begin(), WriteLatencies.end()); 1157 if (WLPos != SchedTables.WriteLatencies.end()) { 1158 unsigned idx = WLPos - SchedTables.WriteLatencies.begin(); 1159 SCDesc.WriteLatencyIdx = idx; 1160 for (unsigned i = 0, e = WriteLatencies.size(); i < e; ++i) 1161 if (SchedTables.WriterNames[idx + i].find(WriterNames[i]) == 1162 std::string::npos) { 1163 SchedTables.WriterNames[idx + i] += std::string("_") + WriterNames[i]; 1164 } 1165 } 1166 else { 1167 SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size(); 1168 SchedTables.WriteLatencies.insert(SchedTables.WriteLatencies.end(), 1169 WriteLatencies.begin(), 1170 WriteLatencies.end()); 1171 SchedTables.WriterNames.insert(SchedTables.WriterNames.end(), 1172 WriterNames.begin(), WriterNames.end()); 1173 } 1174 // ReadAdvanceEntries must remain in operand order. 1175 SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size(); 1176 std::vector<MCReadAdvanceEntry>::iterator RAPos = 1177 std::search(SchedTables.ReadAdvanceEntries.begin(), 1178 SchedTables.ReadAdvanceEntries.end(), 1179 ReadAdvanceEntries.begin(), ReadAdvanceEntries.end()); 1180 if (RAPos != SchedTables.ReadAdvanceEntries.end()) 1181 SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin(); 1182 else { 1183 SCDesc.ReadAdvanceIdx = SchedTables.ReadAdvanceEntries.size(); 1184 SchedTables.ReadAdvanceEntries.insert(RAPos, ReadAdvanceEntries.begin(), 1185 ReadAdvanceEntries.end()); 1186 } 1187 } 1188 } 1189 1190 // Emit SchedClass tables for all processors and associated global tables. 1191 void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables, 1192 raw_ostream &OS) { 1193 // Emit global WriteProcResTable. 1194 OS << "\n// {ProcResourceIdx, Cycles}\n" 1195 << "extern const llvm::MCWriteProcResEntry " 1196 << Target << "WriteProcResTable[] = {\n" 1197 << " { 0, 0}, // Invalid\n"; 1198 for (unsigned WPRIdx = 1, WPREnd = SchedTables.WriteProcResources.size(); 1199 WPRIdx != WPREnd; ++WPRIdx) { 1200 MCWriteProcResEntry &WPREntry = SchedTables.WriteProcResources[WPRIdx]; 1201 OS << " {" << format("%2d", WPREntry.ProcResourceIdx) << ", " 1202 << format("%2d", WPREntry.Cycles) << "}"; 1203 if (WPRIdx + 1 < WPREnd) 1204 OS << ','; 1205 OS << " // #" << WPRIdx << '\n'; 1206 } 1207 OS << "}; // " << Target << "WriteProcResTable\n"; 1208 1209 // Emit global WriteLatencyTable. 1210 OS << "\n// {Cycles, WriteResourceID}\n" 1211 << "extern const llvm::MCWriteLatencyEntry " 1212 << Target << "WriteLatencyTable[] = {\n" 1213 << " { 0, 0}, // Invalid\n"; 1214 for (unsigned WLIdx = 1, WLEnd = SchedTables.WriteLatencies.size(); 1215 WLIdx != WLEnd; ++WLIdx) { 1216 MCWriteLatencyEntry &WLEntry = SchedTables.WriteLatencies[WLIdx]; 1217 OS << " {" << format("%2d", WLEntry.Cycles) << ", " 1218 << format("%2d", WLEntry.WriteResourceID) << "}"; 1219 if (WLIdx + 1 < WLEnd) 1220 OS << ','; 1221 OS << " // #" << WLIdx << " " << SchedTables.WriterNames[WLIdx] << '\n'; 1222 } 1223 OS << "}; // " << Target << "WriteLatencyTable\n"; 1224 1225 // Emit global ReadAdvanceTable. 1226 OS << "\n// {UseIdx, WriteResourceID, Cycles}\n" 1227 << "extern const llvm::MCReadAdvanceEntry " 1228 << Target << "ReadAdvanceTable[] = {\n" 1229 << " {0, 0, 0}, // Invalid\n"; 1230 for (unsigned RAIdx = 1, RAEnd = SchedTables.ReadAdvanceEntries.size(); 1231 RAIdx != RAEnd; ++RAIdx) { 1232 MCReadAdvanceEntry &RAEntry = SchedTables.ReadAdvanceEntries[RAIdx]; 1233 OS << " {" << RAEntry.UseIdx << ", " 1234 << format("%2d", RAEntry.WriteResourceID) << ", " 1235 << format("%2d", RAEntry.Cycles) << "}"; 1236 if (RAIdx + 1 < RAEnd) 1237 OS << ','; 1238 OS << " // #" << RAIdx << '\n'; 1239 } 1240 OS << "}; // " << Target << "ReadAdvanceTable\n"; 1241 1242 // Emit a SchedClass table for each processor. 1243 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), 1244 PE = SchedModels.procModelEnd(); PI != PE; ++PI) { 1245 if (!PI->hasInstrSchedModel()) 1246 continue; 1247 1248 std::vector<MCSchedClassDesc> &SCTab = 1249 SchedTables.ProcSchedClasses[1 + (PI - SchedModels.procModelBegin())]; 1250 1251 OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup," 1252 << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n"; 1253 OS << "static const llvm::MCSchedClassDesc " 1254 << PI->ModelName << "SchedClasses[] = {\n"; 1255 1256 // The first class is always invalid. We no way to distinguish it except by 1257 // name and position. 1258 assert(SchedModels.getSchedClass(0).Name == "NoInstrModel" 1259 && "invalid class not first"); 1260 OS << " {DBGFIELD(\"InvalidSchedClass\") " 1261 << MCSchedClassDesc::InvalidNumMicroOps 1262 << ", false, false, 0, 0, 0, 0, 0, 0},\n"; 1263 1264 for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) { 1265 MCSchedClassDesc &MCDesc = SCTab[SCIdx]; 1266 const CodeGenSchedClass &SchedClass = SchedModels.getSchedClass(SCIdx); 1267 OS << " {DBGFIELD(\"" << SchedClass.Name << "\") "; 1268 if (SchedClass.Name.size() < 18) 1269 OS.indent(18 - SchedClass.Name.size()); 1270 OS << MCDesc.NumMicroOps 1271 << ", " << ( MCDesc.BeginGroup ? "true" : "false" ) 1272 << ", " << ( MCDesc.EndGroup ? "true" : "false" ) 1273 << ", " << format("%2d", MCDesc.WriteProcResIdx) 1274 << ", " << MCDesc.NumWriteProcResEntries 1275 << ", " << format("%2d", MCDesc.WriteLatencyIdx) 1276 << ", " << MCDesc.NumWriteLatencyEntries 1277 << ", " << format("%2d", MCDesc.ReadAdvanceIdx) 1278 << ", " << MCDesc.NumReadAdvanceEntries 1279 << "}, // #" << SCIdx << '\n'; 1280 } 1281 OS << "}; // " << PI->ModelName << "SchedClasses\n"; 1282 } 1283 } 1284 1285 void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { 1286 // For each processor model. 1287 for (const CodeGenProcModel &PM : SchedModels.procModels()) { 1288 // Emit extra processor info if available. 1289 if (PM.hasExtraProcessorInfo()) 1290 EmitExtraProcessorInfo(PM, OS); 1291 // Emit processor resource table. 1292 if (PM.hasInstrSchedModel()) 1293 EmitProcessorResources(PM, OS); 1294 else if(!PM.ProcResourceDefs.empty()) 1295 PrintFatalError(PM.ModelDef->getLoc(), "SchedMachineModel defines " 1296 "ProcResources without defining WriteRes SchedWriteRes"); 1297 1298 // Begin processor itinerary properties 1299 OS << "\n"; 1300 OS << "static const llvm::MCSchedModel " << PM.ModelName << " = {\n"; 1301 EmitProcessorProp(OS, PM.ModelDef, "IssueWidth", ','); 1302 EmitProcessorProp(OS, PM.ModelDef, "MicroOpBufferSize", ','); 1303 EmitProcessorProp(OS, PM.ModelDef, "LoopMicroOpBufferSize", ','); 1304 EmitProcessorProp(OS, PM.ModelDef, "LoadLatency", ','); 1305 EmitProcessorProp(OS, PM.ModelDef, "HighLatency", ','); 1306 EmitProcessorProp(OS, PM.ModelDef, "MispredictPenalty", ','); 1307 1308 bool PostRAScheduler = 1309 (PM.ModelDef ? PM.ModelDef->getValueAsBit("PostRAScheduler") : false); 1310 1311 OS << " " << (PostRAScheduler ? "true" : "false") << ", // " 1312 << "PostRAScheduler\n"; 1313 1314 bool CompleteModel = 1315 (PM.ModelDef ? PM.ModelDef->getValueAsBit("CompleteModel") : false); 1316 1317 OS << " " << (CompleteModel ? "true" : "false") << ", // " 1318 << "CompleteModel\n"; 1319 1320 OS << " " << PM.Index << ", // Processor ID\n"; 1321 if (PM.hasInstrSchedModel()) 1322 OS << " " << PM.ModelName << "ProcResources" << ",\n" 1323 << " " << PM.ModelName << "SchedClasses" << ",\n" 1324 << " " << PM.ProcResourceDefs.size()+1 << ",\n" 1325 << " " << (SchedModels.schedClassEnd() 1326 - SchedModels.schedClassBegin()) << ",\n"; 1327 else 1328 OS << " nullptr, nullptr, 0, 0," 1329 << " // No instruction-level machine model.\n"; 1330 if (PM.hasItineraries()) 1331 OS << " " << PM.ItinsDef->getName() << ",\n"; 1332 else 1333 OS << " nullptr, // No Itinerary\n"; 1334 if (PM.hasExtraProcessorInfo()) 1335 OS << " &" << PM.ModelName << "ExtraInfo,\n"; 1336 else 1337 OS << " nullptr // No extra processor descriptor\n"; 1338 OS << "};\n"; 1339 } 1340 } 1341 1342 // 1343 // EmitProcessorLookup - generate cpu name to sched model lookup tables. 1344 // 1345 void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { 1346 // Gather and sort processor information 1347 std::vector<Record*> ProcessorList = 1348 Records.getAllDerivedDefinitions("Processor"); 1349 llvm::sort(ProcessorList, LessRecordFieldName()); 1350 1351 // Begin processor->sched model table 1352 OS << "\n"; 1353 OS << "// Sorted (by key) array of sched model for CPU subtype.\n" 1354 << "extern const llvm::SubtargetInfoKV " << Target 1355 << "ProcSchedKV[] = {\n"; 1356 // For each processor 1357 for (Record *Processor : ProcessorList) { 1358 StringRef Name = Processor->getValueAsString("Name"); 1359 const std::string &ProcModelName = 1360 SchedModels.getModelForProc(Processor).ModelName; 1361 1362 // Emit as { "cpu", procinit }, 1363 OS << " { \"" << Name << "\", (const void *)&" << ProcModelName << " },\n"; 1364 } 1365 // End processor->sched model table 1366 OS << "};\n"; 1367 } 1368 1369 // 1370 // EmitSchedModel - Emits all scheduling model tables, folding common patterns. 1371 // 1372 void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) { 1373 OS << "#ifdef DBGFIELD\n" 1374 << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n" 1375 << "#endif\n" 1376 << "#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)\n" 1377 << "#define DBGFIELD(x) x,\n" 1378 << "#else\n" 1379 << "#define DBGFIELD(x)\n" 1380 << "#endif\n"; 1381 1382 if (SchedModels.hasItineraries()) { 1383 std::vector<std::vector<InstrItinerary>> ProcItinLists; 1384 // Emit the stage data 1385 EmitStageAndOperandCycleData(OS, ProcItinLists); 1386 EmitItineraries(OS, ProcItinLists); 1387 } 1388 OS << "\n// ===============================================================\n" 1389 << "// Data tables for the new per-operand machine model.\n"; 1390 1391 SchedClassTables SchedTables; 1392 for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) { 1393 GenSchedClassTables(ProcModel, SchedTables); 1394 } 1395 EmitSchedClassTables(SchedTables, OS); 1396 1397 // Emit the processor machine model 1398 EmitProcessorModels(OS); 1399 // Emit the processor lookup data 1400 EmitProcessorLookup(OS); 1401 1402 OS << "\n#undef DBGFIELD"; 1403 } 1404 1405 static void emitPredicateProlog(const RecordKeeper &Records, raw_ostream &OS) { 1406 std::string Buffer; 1407 raw_string_ostream Stream(Buffer); 1408 1409 // Collect all the PredicateProlog records and print them to the output 1410 // stream. 1411 std::vector<Record *> Prologs = 1412 Records.getAllDerivedDefinitions("PredicateProlog"); 1413 llvm::sort(Prologs, LessRecord()); 1414 for (Record *P : Prologs) 1415 Stream << P->getValueAsString("Code") << '\n'; 1416 1417 Stream.flush(); 1418 OS << Buffer; 1419 } 1420 1421 static void emitPredicates(const CodeGenSchedTransition &T, 1422 const CodeGenSchedClass &SC, PredicateExpander &PE, 1423 raw_ostream &OS) { 1424 std::string Buffer; 1425 raw_string_ostream SS(Buffer); 1426 1427 auto IsTruePredicate = [](const Record *Rec) { 1428 return Rec->isSubClassOf("MCSchedPredicate") && 1429 Rec->getValueAsDef("Pred")->isSubClassOf("MCTrue"); 1430 }; 1431 1432 // If not all predicates are MCTrue, then we need an if-stmt. 1433 unsigned NumNonTruePreds = 1434 T.PredTerm.size() - count_if(T.PredTerm, IsTruePredicate); 1435 1436 SS.indent(PE.getIndentLevel() * 2); 1437 1438 if (NumNonTruePreds) { 1439 bool FirstNonTruePredicate = true; 1440 SS << "if ("; 1441 1442 PE.setIndentLevel(PE.getIndentLevel() + 2); 1443 1444 for (const Record *Rec : T.PredTerm) { 1445 // Skip predicates that evaluate to "true". 1446 if (IsTruePredicate(Rec)) 1447 continue; 1448 1449 if (FirstNonTruePredicate) { 1450 FirstNonTruePredicate = false; 1451 } else { 1452 SS << "\n"; 1453 SS.indent(PE.getIndentLevel() * 2); 1454 SS << "&& "; 1455 } 1456 1457 if (Rec->isSubClassOf("MCSchedPredicate")) { 1458 PE.expandPredicate(SS, Rec->getValueAsDef("Pred")); 1459 continue; 1460 } 1461 1462 // Expand this legacy predicate and wrap it around braces if there is more 1463 // than one predicate to expand. 1464 SS << ((NumNonTruePreds > 1) ? "(" : "") 1465 << Rec->getValueAsString("Predicate") 1466 << ((NumNonTruePreds > 1) ? ")" : ""); 1467 } 1468 1469 SS << ")\n"; // end of if-stmt 1470 PE.decreaseIndentLevel(); 1471 SS.indent(PE.getIndentLevel() * 2); 1472 PE.decreaseIndentLevel(); 1473 } 1474 1475 SS << "return " << T.ToClassIdx << "; // " << SC.Name << '\n'; 1476 SS.flush(); 1477 OS << Buffer; 1478 } 1479 1480 // Used by method `SubtargetEmitter::emitSchedModelHelpersImpl()` to generate 1481 // epilogue code for the auto-generated helper. 1482 void emitSchedModelHelperEpilogue(raw_ostream &OS, bool ShouldReturnZero) { 1483 if (ShouldReturnZero) { 1484 OS << " // Don't know how to resolve this scheduling class.\n" 1485 << " return 0;\n"; 1486 return; 1487 } 1488 1489 OS << " report_fatal_error(\"Expected a variant SchedClass\");\n"; 1490 } 1491 1492 bool hasMCSchedPredicates(const CodeGenSchedTransition &T) { 1493 return all_of(T.PredTerm, [](const Record *Rec) { 1494 return Rec->isSubClassOf("MCSchedPredicate"); 1495 }); 1496 } 1497 1498 void collectVariantClasses(const CodeGenSchedModels &SchedModels, 1499 IdxVec &VariantClasses, 1500 bool OnlyExpandMCInstPredicates) { 1501 for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) { 1502 // Ignore non-variant scheduling classes. 1503 if (SC.Transitions.empty()) 1504 continue; 1505 1506 if (OnlyExpandMCInstPredicates) { 1507 // Ignore this variant scheduling class if transitions don't uses any 1508 // MCSchedPredicate definitions. 1509 if (!all_of(SC.Transitions, [](const CodeGenSchedTransition &T) { 1510 return hasMCSchedPredicates(T); 1511 })) 1512 continue; 1513 } 1514 1515 VariantClasses.push_back(SC.Index); 1516 } 1517 } 1518 1519 void collectProcessorIndices(const CodeGenSchedClass &SC, IdxVec &ProcIndices) { 1520 // A variant scheduling class may define transitions for multiple 1521 // processors. This function identifies wich processors are associated with 1522 // transition rules specified by variant class `SC`. 1523 for (const CodeGenSchedTransition &T : SC.Transitions) { 1524 IdxVec PI; 1525 std::set_union(T.ProcIndices.begin(), T.ProcIndices.end(), 1526 ProcIndices.begin(), ProcIndices.end(), 1527 std::back_inserter(PI)); 1528 ProcIndices.swap(PI); 1529 } 1530 } 1531 1532 void SubtargetEmitter::emitSchedModelHelpersImpl( 1533 raw_ostream &OS, bool OnlyExpandMCInstPredicates) { 1534 IdxVec VariantClasses; 1535 collectVariantClasses(SchedModels, VariantClasses, 1536 OnlyExpandMCInstPredicates); 1537 1538 if (VariantClasses.empty()) { 1539 emitSchedModelHelperEpilogue(OS, OnlyExpandMCInstPredicates); 1540 return; 1541 } 1542 1543 // Construct a switch statement where the condition is a check on the 1544 // scheduling class identifier. There is a `case` for every variant class 1545 // defined by the processor models of this target. 1546 // Each `case` implements a number of rules to resolve (i.e. to transition from) 1547 // a variant scheduling class to another scheduling class. Rules are 1548 // described by instances of CodeGenSchedTransition. Note that transitions may 1549 // not be valid for all processors. 1550 OS << " switch (SchedClass) {\n"; 1551 for (unsigned VC : VariantClasses) { 1552 IdxVec ProcIndices; 1553 const CodeGenSchedClass &SC = SchedModels.getSchedClass(VC); 1554 collectProcessorIndices(SC, ProcIndices); 1555 1556 OS << " case " << VC << ": // " << SC.Name << '\n'; 1557 1558 PredicateExpander PE(Target); 1559 PE.setByRef(false); 1560 PE.setExpandForMC(OnlyExpandMCInstPredicates); 1561 for (unsigned PI : ProcIndices) { 1562 OS << " "; 1563 // Emit a guard on the processor ID. 1564 if (PI != 0) { 1565 OS << (OnlyExpandMCInstPredicates 1566 ? "if (CPUID == " 1567 : "if (SchedModel->getProcessorID() == "); 1568 OS << PI << ") "; 1569 OS << "{ // " << (SchedModels.procModelBegin() + PI)->ModelName << '\n'; 1570 } 1571 1572 // Now emit transitions associated with processor PI. 1573 for (const CodeGenSchedTransition &T : SC.Transitions) { 1574 if (PI != 0 && !count(T.ProcIndices, PI)) 1575 continue; 1576 PE.setIndentLevel(3); 1577 emitPredicates(T, SchedModels.getSchedClass(T.ToClassIdx), PE, OS); 1578 } 1579 1580 OS << " }\n"; 1581 if (PI == 0) 1582 break; 1583 } 1584 1585 if (SC.isInferred()) 1586 OS << " return " << SC.Index << ";\n"; 1587 OS << " break;\n"; 1588 } 1589 1590 OS << " };\n"; 1591 1592 emitSchedModelHelperEpilogue(OS, OnlyExpandMCInstPredicates); 1593 } 1594 1595 void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName, 1596 raw_ostream &OS) { 1597 OS << "unsigned " << ClassName 1598 << "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI," 1599 << " const TargetSchedModel *SchedModel) const {\n"; 1600 1601 // Emit the predicate prolog code. 1602 emitPredicateProlog(Records, OS); 1603 1604 // Emit target predicates. 1605 emitSchedModelHelpersImpl(OS); 1606 1607 OS << "} // " << ClassName << "::resolveSchedClass\n\n"; 1608 1609 OS << "unsigned " << ClassName 1610 << "\n::resolveVariantSchedClass(unsigned SchedClass, const MCInst *MI," 1611 << " unsigned CPUID) const {\n" 1612 << " return " << Target << "_MC" 1613 << "::resolveVariantSchedClassImpl(SchedClass, MI, CPUID);\n" 1614 << "} // " << ClassName << "::resolveVariantSchedClass\n\n"; 1615 1616 STIPredicateExpander PE(Target); 1617 PE.setClassPrefix(ClassName); 1618 PE.setExpandDefinition(true); 1619 PE.setByRef(false); 1620 PE.setIndentLevel(0); 1621 1622 for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates()) 1623 PE.expandSTIPredicate(OS, Fn); 1624 } 1625 1626 void SubtargetEmitter::EmitHwModeCheck(const std::string &ClassName, 1627 raw_ostream &OS) { 1628 const CodeGenHwModes &CGH = TGT.getHwModes(); 1629 assert(CGH.getNumModeIds() > 0); 1630 if (CGH.getNumModeIds() == 1) 1631 return; 1632 1633 OS << "unsigned " << ClassName << "::getHwMode() const {\n"; 1634 for (unsigned M = 1, NumModes = CGH.getNumModeIds(); M != NumModes; ++M) { 1635 const HwMode &HM = CGH.getMode(M); 1636 OS << " if (checkFeatures(\"" << HM.Features 1637 << "\")) return " << M << ";\n"; 1638 } 1639 OS << " return 0;\n}\n"; 1640 } 1641 1642 // 1643 // ParseFeaturesFunction - Produces a subtarget specific function for parsing 1644 // the subtarget features string. 1645 // 1646 void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, 1647 unsigned NumFeatures, 1648 unsigned NumProcs) { 1649 std::vector<Record*> Features = 1650 Records.getAllDerivedDefinitions("SubtargetFeature"); 1651 llvm::sort(Features, LessRecord()); 1652 1653 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" 1654 << "// subtarget options.\n" 1655 << "void llvm::"; 1656 OS << Target; 1657 OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n" 1658 << " LLVM_DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n" 1659 << " LLVM_DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n"; 1660 1661 if (Features.empty()) { 1662 OS << "}\n"; 1663 return; 1664 } 1665 1666 OS << " InitMCProcessorInfo(CPU, FS);\n" 1667 << " const FeatureBitset& Bits = getFeatureBits();\n"; 1668 1669 for (Record *R : Features) { 1670 // Next record 1671 StringRef Instance = R->getName(); 1672 StringRef Value = R->getValueAsString("Value"); 1673 StringRef Attribute = R->getValueAsString("Attribute"); 1674 1675 if (Value=="true" || Value=="false") 1676 OS << " if (Bits[" << Target << "::" 1677 << Instance << "]) " 1678 << Attribute << " = " << Value << ";\n"; 1679 else 1680 OS << " if (Bits[" << Target << "::" 1681 << Instance << "] && " 1682 << Attribute << " < " << Value << ") " 1683 << Attribute << " = " << Value << ";\n"; 1684 } 1685 1686 OS << "}\n"; 1687 } 1688 1689 void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) { 1690 OS << "namespace " << Target << "_MC {\n" 1691 << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,\n" 1692 << " const MCInst *MI, unsigned CPUID) {\n"; 1693 emitSchedModelHelpersImpl(OS, /* OnlyExpandMCPredicates */ true); 1694 OS << "}\n"; 1695 OS << "} // end of namespace " << Target << "_MC\n\n"; 1696 1697 OS << "struct " << Target 1698 << "GenMCSubtargetInfo : public MCSubtargetInfo {\n"; 1699 OS << " " << Target << "GenMCSubtargetInfo(const Triple &TT, \n" 1700 << " StringRef CPU, StringRef FS, ArrayRef<SubtargetFeatureKV> PF,\n" 1701 << " ArrayRef<SubtargetFeatureKV> PD,\n" 1702 << " const SubtargetInfoKV *ProcSched,\n" 1703 << " const MCWriteProcResEntry *WPR,\n" 1704 << " const MCWriteLatencyEntry *WL,\n" 1705 << " const MCReadAdvanceEntry *RA, const InstrStage *IS,\n" 1706 << " const unsigned *OC, const unsigned *FP) :\n" 1707 << " MCSubtargetInfo(TT, CPU, FS, PF, PD, ProcSched,\n" 1708 << " WPR, WL, RA, IS, OC, FP) { }\n\n" 1709 << " unsigned resolveVariantSchedClass(unsigned SchedClass,\n" 1710 << " const MCInst *MI, unsigned CPUID) const override {\n" 1711 << " return " << Target << "_MC" 1712 << "::resolveVariantSchedClassImpl(SchedClass, MI, CPUID); \n"; 1713 OS << " }\n"; 1714 OS << "};\n"; 1715 } 1716 1717 void SubtargetEmitter::EmitMCInstrAnalysisPredicateFunctions(raw_ostream &OS) { 1718 OS << "\n#ifdef GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n"; 1719 OS << "#undef GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n\n"; 1720 1721 STIPredicateExpander PE(Target); 1722 PE.setExpandForMC(true); 1723 PE.setByRef(true); 1724 for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates()) 1725 PE.expandSTIPredicate(OS, Fn); 1726 1727 OS << "#endif // GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n\n"; 1728 1729 OS << "\n#ifdef GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n"; 1730 OS << "#undef GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n\n"; 1731 1732 std::string ClassPrefix = Target + "MCInstrAnalysis"; 1733 PE.setExpandDefinition(true); 1734 PE.setClassPrefix(ClassPrefix); 1735 PE.setIndentLevel(0); 1736 for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates()) 1737 PE.expandSTIPredicate(OS, Fn); 1738 1739 OS << "#endif // GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n\n"; 1740 } 1741 1742 // 1743 // SubtargetEmitter::run - Main subtarget enumeration emitter. 1744 // 1745 void SubtargetEmitter::run(raw_ostream &OS) { 1746 emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); 1747 1748 OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n"; 1749 OS << "#undef GET_SUBTARGETINFO_ENUM\n\n"; 1750 1751 OS << "namespace llvm {\n"; 1752 Enumeration(OS); 1753 OS << "} // end namespace llvm\n\n"; 1754 OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; 1755 1756 OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n"; 1757 OS << "#undef GET_SUBTARGETINFO_MC_DESC\n\n"; 1758 1759 OS << "namespace llvm {\n"; 1760 #if 0 1761 OS << "namespace {\n"; 1762 #endif 1763 unsigned NumFeatures = FeatureKeyValues(OS); 1764 OS << "\n"; 1765 unsigned NumProcs = CPUKeyValues(OS); 1766 OS << "\n"; 1767 EmitSchedModel(OS); 1768 OS << "\n"; 1769 #if 0 1770 OS << "} // end anonymous namespace\n\n"; 1771 #endif 1772 1773 // MCInstrInfo initialization routine. 1774 emitGenMCSubtargetInfo(OS); 1775 1776 OS << "\nstatic inline MCSubtargetInfo *create" << Target 1777 << "MCSubtargetInfoImpl(" 1778 << "const Triple &TT, StringRef CPU, StringRef FS) {\n"; 1779 OS << " return new " << Target << "GenMCSubtargetInfo(TT, CPU, FS, "; 1780 if (NumFeatures) 1781 OS << Target << "FeatureKV, "; 1782 else 1783 OS << "None, "; 1784 if (NumProcs) 1785 OS << Target << "SubTypeKV, "; 1786 else 1787 OS << "None, "; 1788 OS << '\n'; OS.indent(22); 1789 OS << Target << "ProcSchedKV, " 1790 << Target << "WriteProcResTable, " 1791 << Target << "WriteLatencyTable, " 1792 << Target << "ReadAdvanceTable, "; 1793 OS << '\n'; OS.indent(22); 1794 if (SchedModels.hasItineraries()) { 1795 OS << Target << "Stages, " 1796 << Target << "OperandCycles, " 1797 << Target << "ForwardingPaths"; 1798 } else 1799 OS << "nullptr, nullptr, nullptr"; 1800 OS << ");\n}\n\n"; 1801 1802 OS << "} // end namespace llvm\n\n"; 1803 1804 OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n"; 1805 1806 OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n"; 1807 OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n\n"; 1808 1809 OS << "#include \"llvm/Support/Debug.h\"\n"; 1810 OS << "#include \"llvm/Support/raw_ostream.h\"\n\n"; 1811 ParseFeaturesFunction(OS, NumFeatures, NumProcs); 1812 1813 OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n"; 1814 1815 // Create a TargetSubtargetInfo subclass to hide the MC layer initialization. 1816 OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n"; 1817 OS << "#undef GET_SUBTARGETINFO_HEADER\n\n"; 1818 1819 std::string ClassName = Target + "GenSubtargetInfo"; 1820 OS << "namespace llvm {\n"; 1821 OS << "class DFAPacketizer;\n"; 1822 OS << "namespace " << Target << "_MC {\n" 1823 << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass," 1824 << " const MCInst *MI, unsigned CPUID);\n" 1825 << "}\n\n"; 1826 OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" 1827 << " explicit " << ClassName << "(const Triple &TT, StringRef CPU, " 1828 << "StringRef FS);\n" 1829 << "public:\n" 1830 << " unsigned resolveSchedClass(unsigned SchedClass, " 1831 << " const MachineInstr *DefMI," 1832 << " const TargetSchedModel *SchedModel) const override;\n" 1833 << " unsigned resolveVariantSchedClass(unsigned SchedClass," 1834 << " const MCInst *MI, unsigned CPUID) const override;\n" 1835 << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" 1836 << " const;\n"; 1837 if (TGT.getHwModes().getNumModeIds() > 1) 1838 OS << " unsigned getHwMode() const override;\n"; 1839 1840 STIPredicateExpander PE(Target); 1841 PE.setByRef(false); 1842 for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates()) 1843 PE.expandSTIPredicate(OS, Fn); 1844 1845 OS << "};\n" 1846 << "} // end namespace llvm\n\n"; 1847 1848 OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n"; 1849 1850 OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n"; 1851 OS << "#undef GET_SUBTARGETINFO_CTOR\n\n"; 1852 1853 OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n\n"; 1854 OS << "namespace llvm {\n"; 1855 OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; 1856 OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n"; 1857 OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n"; 1858 OS << "extern const llvm::MCWriteProcResEntry " 1859 << Target << "WriteProcResTable[];\n"; 1860 OS << "extern const llvm::MCWriteLatencyEntry " 1861 << Target << "WriteLatencyTable[];\n"; 1862 OS << "extern const llvm::MCReadAdvanceEntry " 1863 << Target << "ReadAdvanceTable[];\n"; 1864 1865 if (SchedModels.hasItineraries()) { 1866 OS << "extern const llvm::InstrStage " << Target << "Stages[];\n"; 1867 OS << "extern const unsigned " << Target << "OperandCycles[];\n"; 1868 OS << "extern const unsigned " << Target << "ForwardingPaths[];\n"; 1869 } 1870 1871 OS << ClassName << "::" << ClassName << "(const Triple &TT, StringRef CPU, " 1872 << "StringRef FS)\n" 1873 << " : TargetSubtargetInfo(TT, CPU, FS, "; 1874 if (NumFeatures) 1875 OS << "makeArrayRef(" << Target << "FeatureKV, " << NumFeatures << "), "; 1876 else 1877 OS << "None, "; 1878 if (NumProcs) 1879 OS << "makeArrayRef(" << Target << "SubTypeKV, " << NumProcs << "), "; 1880 else 1881 OS << "None, "; 1882 OS << '\n'; OS.indent(24); 1883 OS << Target << "ProcSchedKV, " 1884 << Target << "WriteProcResTable, " 1885 << Target << "WriteLatencyTable, " 1886 << Target << "ReadAdvanceTable, "; 1887 OS << '\n'; OS.indent(24); 1888 if (SchedModels.hasItineraries()) { 1889 OS << Target << "Stages, " 1890 << Target << "OperandCycles, " 1891 << Target << "ForwardingPaths"; 1892 } else 1893 OS << "nullptr, nullptr, nullptr"; 1894 OS << ") {}\n\n"; 1895 1896 EmitSchedModelHelpers(ClassName, OS); 1897 EmitHwModeCheck(ClassName, OS); 1898 1899 OS << "} // end namespace llvm\n\n"; 1900 1901 OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n"; 1902 1903 EmitMCInstrAnalysisPredicateFunctions(OS); 1904 } 1905 1906 namespace llvm { 1907 1908 void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) { 1909 CodeGenTarget CGTarget(RK); 1910 SubtargetEmitter(RK, CGTarget).run(OS); 1911 } 1912 1913 } // end namespace llvm 1914