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