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