CodeGenSchedule.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. //===- CodeGenSchedule.cpp - Scheduling MachineModels ---------------------===//
  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 file defines structures to encapsulate the machine model as decribed in
  11. // the target description.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #define DEBUG_TYPE "subtarget-emitter"
  15. #include "CodeGenSchedule.h"
  16. #include "CodeGenTarget.h"
  17. #include "llvm/Support/Debug.h"
  18. using namespace llvm;
  19. // CodeGenModels ctor interprets machine model records and populates maps.
  20. CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
  21. const CodeGenTarget &TGT):
  22. Records(RK), Target(TGT), NumItineraryClasses(0), HasProcItineraries(false) {
  23. // Populate SchedClassIdxMap and set NumItineraryClasses.
  24. CollectSchedClasses();
  25. // Populate ProcModelMap.
  26. CollectProcModels();
  27. }
  28. // Visit all the instruction definitions for this target to gather and enumerate
  29. // the itinerary classes. These are the explicitly specified SchedClasses. More
  30. // SchedClasses may be inferred.
  31. void CodeGenSchedModels::CollectSchedClasses() {
  32. // NoItinerary is always the first class at Index=0
  33. SchedClasses.resize(1);
  34. SchedClasses.back().Name = "NoItinerary";
  35. SchedClassIdxMap[SchedClasses.back().Name] = 0;
  36. // Gather and sort all itinerary classes used by instruction descriptions.
  37. std::vector<Record*> ItinClassList;
  38. for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
  39. E = Target.inst_end(); I != E; ++I) {
  40. Record *SchedDef = (*I)->TheDef->getValueAsDef("Itinerary");
  41. // Map a new SchedClass with no index.
  42. if (!SchedClassIdxMap.count(SchedDef->getName())) {
  43. SchedClassIdxMap[SchedDef->getName()] = 0;
  44. ItinClassList.push_back(SchedDef);
  45. }
  46. }
  47. // Assign each itinerary class unique number, skipping NoItinerary==0
  48. NumItineraryClasses = ItinClassList.size();
  49. std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord());
  50. for (unsigned i = 0, N = NumItineraryClasses; i < N; i++) {
  51. Record *ItinDef = ItinClassList[i];
  52. SchedClassIdxMap[ItinDef->getName()] = SchedClasses.size();
  53. SchedClasses.push_back(CodeGenSchedClass(ItinDef));
  54. }
  55. // TODO: Infer classes from non-itinerary scheduler resources.
  56. }
  57. // Gather all processor models.
  58. void CodeGenSchedModels::CollectProcModels() {
  59. std::vector<Record*> ProcRecords =
  60. Records.getAllDerivedDefinitions("Processor");
  61. std::sort(ProcRecords.begin(), ProcRecords.end(), LessRecordFieldName());
  62. // Reserve space because we can. Reallocation would be ok.
  63. ProcModels.reserve(ProcRecords.size());
  64. // For each processor, find a unique machine model.
  65. for (unsigned i = 0, N = ProcRecords.size(); i < N; ++i)
  66. addProcModel(ProcRecords[i]);
  67. }
  68. // Get a unique processor model based on the defined MachineModel and
  69. // ProcessorItineraries.
  70. void CodeGenSchedModels::addProcModel(Record *ProcDef) {
  71. unsigned Idx = getProcModelIdx(ProcDef);
  72. if (Idx < ProcModels.size())
  73. return;
  74. Record *ModelDef = ProcDef->getValueAsDef("SchedModel");
  75. Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");
  76. std::string ModelName = ModelDef->getName();
  77. const std::string &ItinName = ItinsDef->getName();
  78. bool NoModel = ModelDef->getValueAsBit("NoModel");
  79. bool hasTopLevelItin = !ItinsDef->getValueAsListOfDefs("IID").empty();
  80. if (NoModel) {
  81. // If an itinerary is defined without a machine model, infer a new model.
  82. if (NoModel && hasTopLevelItin) {
  83. ModelName = ItinName + "Model";
  84. ModelDef = NULL;
  85. }
  86. }
  87. else {
  88. // If a machine model is defined, the itinerary must be defined within it
  89. // rather than in the Processor definition itself.
  90. assert(!hasTopLevelItin && "Itinerary must be defined in SchedModel");
  91. ItinsDef = ModelDef->getValueAsDef("Itineraries");
  92. }
  93. ProcModelMap[getProcModelKey(ProcDef)]= ProcModels.size();
  94. ProcModels.push_back(CodeGenProcModel(ModelName, ModelDef, ItinsDef));
  95. std::vector<Record*> ItinRecords = ItinsDef->getValueAsListOfDefs("IID");
  96. CollectProcItin(ProcModels.back(), ItinRecords);
  97. }
  98. // Gather the processor itineraries.
  99. void CodeGenSchedModels::CollectProcItin(CodeGenProcModel &ProcModel,
  100. std::vector<Record*> ItinRecords) {
  101. // Skip empty itinerary.
  102. if (ItinRecords.empty())
  103. return;
  104. HasProcItineraries = true;
  105. ProcModel.ItinDefList.resize(NumItineraryClasses+1);
  106. // Insert each itinerary data record in the correct position within
  107. // the processor model's ItinDefList.
  108. for (unsigned i = 0, N = ItinRecords.size(); i < N; i++) {
  109. Record *ItinData = ItinRecords[i];
  110. Record *ItinDef = ItinData->getValueAsDef("TheClass");
  111. if (!SchedClassIdxMap.count(ItinDef->getName())) {
  112. DEBUG(dbgs() << ProcModel.ItinsDef->getName()
  113. << " has unused itinerary class " << ItinDef->getName() << '\n');
  114. continue;
  115. }
  116. ProcModel.ItinDefList[getItinClassIdx(ItinDef)] = ItinData;
  117. }
  118. #ifndef NDEBUG
  119. // Check for missing itinerary entries.
  120. assert(!ProcModel.ItinDefList[0] && "NoItinerary class can't have rec");
  121. for (unsigned i = 1, N = ProcModel.ItinDefList.size(); i < N; ++i) {
  122. if (!ProcModel.ItinDefList[i])
  123. DEBUG(dbgs() << ProcModel.ItinsDef->getName()
  124. << " missing itinerary for class " << SchedClasses[i].Name << '\n');
  125. }
  126. #endif
  127. }