I'm introducing a new machine model to simultaneously allow simple
[oota-llvm.git] / utils / TableGen / CodeGenSchedule.h
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