//===- CodeGenSchedule.cpp - Scheduling MachineModels ---------------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines structures to encapsulate the machine model as decribed in // the target description. // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "subtarget-emitter" #include "CodeGenSchedule.h" #include "CodeGenTarget.h" #include "llvm/Support/Debug.h" using namespace llvm; // CodeGenModels ctor interprets machine model records and populates maps. CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK, const CodeGenTarget &TGT): Records(RK), Target(TGT), NumItineraryClasses(0), HasProcItineraries(false) { // Populate SchedClassIdxMap and set NumItineraryClasses. CollectSchedClasses(); // Populate ProcModelMap. CollectProcModels(); } // Visit all the instruction definitions for this target to gather and enumerate // the itinerary classes. These are the explicitly specified SchedClasses. More // SchedClasses may be inferred. void CodeGenSchedModels::CollectSchedClasses() { // NoItinerary is always the first class at Index=0 SchedClasses.resize(1); SchedClasses.back().Name = "NoItinerary"; SchedClassIdxMap[SchedClasses.back().Name] = 0; // Gather and sort all itinerary classes used by instruction descriptions. std::vector ItinClassList; for (CodeGenTarget::inst_iterator I = Target.inst_begin(), E = Target.inst_end(); I != E; ++I) { Record *SchedDef = (*I)->TheDef->getValueAsDef("Itinerary"); // Map a new SchedClass with no index. if (!SchedClassIdxMap.count(SchedDef->getName())) { SchedClassIdxMap[SchedDef->getName()] = 0; ItinClassList.push_back(SchedDef); } } // Assign each itinerary class unique number, skipping NoItinerary==0 NumItineraryClasses = ItinClassList.size(); std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord()); for (unsigned i = 0, N = NumItineraryClasses; i < N; i++) { Record *ItinDef = ItinClassList[i]; SchedClassIdxMap[ItinDef->getName()] = SchedClasses.size(); SchedClasses.push_back(CodeGenSchedClass(ItinDef)); } // TODO: Infer classes from non-itinerary scheduler resources. } // Gather all processor models. void CodeGenSchedModels::CollectProcModels() { std::vector ProcRecords = Records.getAllDerivedDefinitions("Processor"); std::sort(ProcRecords.begin(), ProcRecords.end(), LessRecordFieldName()); // Reserve space because we can. Reallocation would be ok. ProcModels.reserve(ProcRecords.size()); // For each processor, find a unique machine model. for (unsigned i = 0, N = ProcRecords.size(); i < N; ++i) addProcModel(ProcRecords[i]); } // Get a unique processor model based on the defined MachineModel and // ProcessorItineraries. void CodeGenSchedModels::addProcModel(Record *ProcDef) { unsigned Idx = getProcModelIdx(ProcDef); if (Idx < ProcModels.size()) return; Record *ModelDef = ProcDef->getValueAsDef("SchedModel"); Record *ItinsDef = ProcDef->getValueAsDef("ProcItin"); std::string ModelName = ModelDef->getName(); const std::string &ItinName = ItinsDef->getName(); bool NoModel = ModelDef->getValueAsBit("NoModel"); bool hasTopLevelItin = !ItinsDef->getValueAsListOfDefs("IID").empty(); if (NoModel) { // If an itinerary is defined without a machine model, infer a new model. if (NoModel && hasTopLevelItin) { ModelName = ItinName + "Model"; ModelDef = NULL; } } else { // If a machine model is defined, the itinerary must be defined within it // rather than in the Processor definition itself. assert(!hasTopLevelItin && "Itinerary must be defined in SchedModel"); ItinsDef = ModelDef->getValueAsDef("Itineraries"); } ProcModelMap[getProcModelKey(ProcDef)]= ProcModels.size(); ProcModels.push_back(CodeGenProcModel(ModelName, ModelDef, ItinsDef)); std::vector ItinRecords = ItinsDef->getValueAsListOfDefs("IID"); CollectProcItin(ProcModels.back(), ItinRecords); } // Gather the processor itineraries. void CodeGenSchedModels::CollectProcItin(CodeGenProcModel &ProcModel, std::vector ItinRecords) { // Skip empty itinerary. if (ItinRecords.empty()) return; HasProcItineraries = true; ProcModel.ItinDefList.resize(NumItineraryClasses+1); // Insert each itinerary data record in the correct position within // the processor model's ItinDefList. for (unsigned i = 0, N = ItinRecords.size(); i < N; i++) { Record *ItinData = ItinRecords[i]; Record *ItinDef = ItinData->getValueAsDef("TheClass"); if (!SchedClassIdxMap.count(ItinDef->getName())) { DEBUG(dbgs() << ProcModel.ItinsDef->getName() << " has unused itinerary class " << ItinDef->getName() << '\n'); continue; } ProcModel.ItinDefList[getItinClassIdx(ItinDef)] = ItinData; } #ifndef NDEBUG // Check for missing itinerary entries. assert(!ProcModel.ItinDefList[0] && "NoItinerary class can't have rec"); for (unsigned i = 1, N = ProcModel.ItinDefList.size(); i < N; ++i) { if (!ProcModel.ItinDefList[i]) DEBUG(dbgs() << ProcModel.ItinsDef->getName() << " missing itinerary for class " << SchedClasses[i].Name << '\n'); } #endif }