Andrew Trick | 2661b41 | 2012-07-07 04:00:00 +0000 | [diff] [blame] | 1 | //===- CodeGenSchedule.h - Scheduling Machine Models ------------*- C++ -*-===// |
| 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 | #ifndef CODEGEN_SCHEDULE_H |
| 16 | #define CODEGEN_SCHEDULE_H |
| 17 | |
| 18 | #include "llvm/TableGen/Record.h" |
| 19 | #include "llvm/Support/ErrorHandling.h" |
| 20 | #include "llvm/ADT/DenseMap.h" |
| 21 | #include "llvm/ADT/StringMap.h" |
| 22 | |
| 23 | namespace llvm { |
| 24 | |
| 25 | class CodeGenTarget; |
| 26 | |
| 27 | // Scheduling class. |
| 28 | // |
| 29 | // Each instruction description will be mapped to a scheduling class. It may be |
| 30 | // an explicitly defined itinerary class, or an inferred class in which case |
| 31 | // ItinClassDef == NULL. |
| 32 | struct CodeGenSchedClass { |
| 33 | std::string Name; |
| 34 | unsigned Index; |
| 35 | Record *ItinClassDef; |
| 36 | |
| 37 | CodeGenSchedClass(): Index(0), ItinClassDef(0) {} |
| 38 | CodeGenSchedClass(Record *rec): Index(0), ItinClassDef(rec) { |
| 39 | Name = rec->getName(); |
| 40 | } |
| 41 | }; |
| 42 | |
| 43 | // Processor model. |
| 44 | // |
| 45 | // ModelName is a unique name used to name an instantiation of MCSchedModel. |
| 46 | // |
| 47 | // ModelDef is NULL for inferred Models. This happens when a processor defines |
| 48 | // an itinerary but no machine model. If the processer defines neither a machine |
| 49 | // model nor itinerary, then ModelDef remains pointing to NoModel. NoModel has |
| 50 | // the special "NoModel" field set to true. |
| 51 | // |
| 52 | // ItinsDef always points to a valid record definition, but may point to the |
| 53 | // default NoItineraries. NoItineraries has an empty list of InstrItinData |
| 54 | // records. |
| 55 | // |
| 56 | // ItinDefList orders this processor's InstrItinData records by SchedClass idx. |
| 57 | struct CodeGenProcModel { |
| 58 | std::string ModelName; |
| 59 | Record *ModelDef; |
| 60 | Record *ItinsDef; |
| 61 | |
| 62 | // Array of InstrItinData records indexed by CodeGenSchedClass::Index. |
| 63 | // The list is empty if the subtarget has no itineraries. |
| 64 | std::vector<Record *> ItinDefList; |
| 65 | |
| 66 | CodeGenProcModel(const std::string &Name, Record *MDef, Record *IDef): |
| 67 | ModelName(Name), ModelDef(MDef), ItinsDef(IDef) {} |
| 68 | }; |
| 69 | |
| 70 | // Top level container for machine model data. |
| 71 | class CodeGenSchedModels { |
| 72 | RecordKeeper &Records; |
| 73 | const CodeGenTarget &Target; |
| 74 | |
| 75 | // List of unique SchedClasses. |
| 76 | std::vector<CodeGenSchedClass> SchedClasses; |
| 77 | |
| 78 | // Map SchedClass name to itinerary index. |
| 79 | // These are either explicit itinerary classes or inferred classes. |
| 80 | StringMap<unsigned> SchedClassIdxMap; |
| 81 | |
| 82 | // SchedClass indices 1 up to and including NumItineraryClasses identify |
| 83 | // itinerary classes that are explicitly used for this target's instruction |
| 84 | // definitions. NoItinerary always has index 0 regardless of whether it is |
| 85 | // explicitly referenced. |
| 86 | // |
| 87 | // Any inferred SchedClass have a index greater than NumItineraryClasses. |
| 88 | unsigned NumItineraryClasses; |
| 89 | |
| 90 | // List of unique processor models. |
| 91 | std::vector<CodeGenProcModel> ProcModels; |
| 92 | |
| 93 | // Map Processor's MachineModel + ProcItin fields to a CodeGenProcModel index. |
| 94 | typedef DenseMap<std::pair<Record*, Record*>, unsigned> ProcModelMapTy; |
| 95 | ProcModelMapTy ProcModelMap; |
| 96 | |
| 97 | // True if any processors have nonempty itineraries. |
| 98 | bool HasProcItineraries; |
| 99 | |
| 100 | public: |
| 101 | CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT); |
| 102 | |
| 103 | // Check if any instructions are assigned to an explicit itinerary class other |
| 104 | // than NoItinerary. |
| 105 | bool hasItineraryClasses() const { return NumItineraryClasses > 0; } |
| 106 | |
| 107 | // Return the number of itinerary classes in use by this target's instruction |
| 108 | // descriptions, not including "NoItinerary". |
| 109 | unsigned numItineraryClasses() const { |
| 110 | return NumItineraryClasses; |
| 111 | } |
| 112 | |
| 113 | // Get a SchedClass from its index. |
| 114 | const CodeGenSchedClass &getSchedClass(unsigned Idx) { |
| 115 | assert(Idx < SchedClasses.size() && "bad SchedClass index"); |
| 116 | return SchedClasses[Idx]; |
| 117 | } |
| 118 | |
| 119 | // Get an itinerary class's index. Value indices are '0' for NoItinerary up to |
| 120 | // and including numItineraryClasses(). |
| 121 | unsigned getItinClassIdx(Record *ItinDef) const { |
| 122 | assert(SchedClassIdxMap.count(ItinDef->getName()) && "missing ItinClass"); |
| 123 | unsigned Idx = SchedClassIdxMap.lookup(ItinDef->getName()); |
| 124 | assert(Idx <= NumItineraryClasses && "bad ItinClass index"); |
| 125 | return Idx; |
| 126 | } |
| 127 | |
| 128 | bool hasProcessorItineraries() const { |
| 129 | return HasProcItineraries; |
| 130 | } |
| 131 | |
| 132 | // Get an existing machine model for a processor definition. |
| 133 | const CodeGenProcModel &getProcModel(Record *ProcDef) const { |
| 134 | unsigned idx = getProcModelIdx(ProcDef); |
| 135 | assert(idx < ProcModels.size() && "missing machine model"); |
| 136 | return ProcModels[idx]; |
| 137 | } |
| 138 | |
| 139 | // Iterate over the unique processor models. |
| 140 | typedef std::vector<CodeGenProcModel>::const_iterator ProcIter; |
| 141 | ProcIter procModelBegin() const { return ProcModels.begin(); } |
| 142 | ProcIter procModelEnd() const { return ProcModels.end(); } |
| 143 | |
| 144 | private: |
| 145 | // Get a key that can uniquely identify a machine model. |
| 146 | ProcModelMapTy::key_type getProcModelKey(Record *ProcDef) const { |
| 147 | Record *ModelDef = ProcDef->getValueAsDef("SchedModel"); |
| 148 | Record *ItinsDef = ProcDef->getValueAsDef("ProcItin"); |
| 149 | return std::make_pair(ModelDef, ItinsDef); |
| 150 | } |
| 151 | |
| 152 | // Get the unique index of a machine model. |
| 153 | unsigned getProcModelIdx(Record *ProcDef) const { |
| 154 | ProcModelMapTy::const_iterator I = |
| 155 | ProcModelMap.find(getProcModelKey(ProcDef)); |
| 156 | if (I == ProcModelMap.end()) |
| 157 | return ProcModels.size(); |
| 158 | return I->second; |
| 159 | } |
| 160 | |
| 161 | // Initialize a new processor model if it is unique. |
| 162 | void addProcModel(Record *ProcDef); |
| 163 | |
| 164 | void CollectSchedClasses(); |
| 165 | void CollectProcModels(); |
| 166 | void CollectProcItin(CodeGenProcModel &ProcModel, |
| 167 | std::vector<Record*> ItinRecords); |
| 168 | }; |
| 169 | |
| 170 | } // namespace llvm |
| 171 | |
| 172 | #endif |