Typos.
[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 class CodeGenSchedModels;
27 class CodeGenInstruction;
28
29 typedef std::vector<Record*> RecVec;
30 typedef std::vector<Record*>::const_iterator RecIter;
31
32 typedef std::vector<unsigned> IdxVec;
33 typedef std::vector<unsigned>::const_iterator IdxIter;
34
35 void splitSchedReadWrites(const RecVec &RWDefs,
36                           RecVec &WriteDefs, RecVec &ReadDefs);
37
38 /// We have two kinds of SchedReadWrites. Explicitly defined and inferred
39 /// sequences.  TheDef is nonnull for explicit SchedWrites, but Sequence may or
40 /// may not be empty. TheDef is null for inferred sequences, and Sequence must
41 /// be nonempty.
42 ///
43 /// IsVariadic controls whether the variants are expanded into multiple operands
44 /// or a sequence of writes on one operand.
45 struct CodeGenSchedRW {
46   std::string Name;
47   Record *TheDef;
48   bool IsAlias;
49   bool HasVariants;
50   bool IsVariadic;
51   bool IsSequence;
52   IdxVec Sequence;
53   RecVec Aliases;
54
55   CodeGenSchedRW(): TheDef(0), IsAlias(false), HasVariants(false),
56                     IsVariadic(false), IsSequence(false) {}
57   CodeGenSchedRW(Record *Def): TheDef(Def), IsAlias(false), IsVariadic(false) {
58     Name = Def->getName();
59     HasVariants = Def->isSubClassOf("SchedVariant");
60     if (HasVariants)
61       IsVariadic = Def->getValueAsBit("Variadic");
62
63     // Read records don't currently have sequences, but it can be easily
64     // added. Note that implicit Reads (from ReadVariant) may have a Sequence
65     // (but no record).
66     IsSequence = Def->isSubClassOf("WriteSequence");
67   }
68
69   CodeGenSchedRW(const IdxVec &Seq, const std::string &Name):
70     Name(Name), TheDef(0), IsAlias(false), HasVariants(false),
71     IsVariadic(false), IsSequence(true), Sequence(Seq) {
72     assert(Sequence.size() > 1 && "implied sequence needs >1 RWs");
73   }
74
75   bool isValid() const {
76     assert((!HasVariants || TheDef) && "Variant write needs record def");
77     assert((!IsVariadic || HasVariants) && "Variadic write needs variants");
78     assert((!IsSequence || !HasVariants) && "Sequence can't have variant");
79     assert((!IsSequence || !Sequence.empty()) && "Sequence should be nonempty");
80     assert((!IsAlias || Aliases.empty()) && "Alias cannot have aliases");
81     return TheDef || !Sequence.empty();
82   }
83
84 #ifndef NDEBUG
85   void dump() const;
86 #endif
87 };
88
89 /// Represent a transition between SchedClasses induced by SchedVariant.
90 struct CodeGenSchedTransition {
91   unsigned ToClassIdx;
92   IdxVec ProcIndices;
93   RecVec PredTerm;
94 };
95
96 /// Scheduling class.
97 ///
98 /// Each instruction description will be mapped to a scheduling class. There are
99 /// four types of classes:
100 ///
101 /// 1) An explicitly defined itinerary class with ItinClassDef set.
102 /// Writes and ReadDefs are empty. ProcIndices contains 0 for any processor.
103 ///
104 /// 2) An implied class with a list of SchedWrites and SchedReads that are
105 /// defined in an instruction definition and which are common across all
106 /// subtargets. ProcIndices contains 0 for any processor.
107 ///
108 /// 3) An implied class with a list of InstRW records that map instructions to
109 /// SchedWrites and SchedReads per-processor. InstrClassMap should map the same
110 /// instructions to this class. ProcIndices contains all the processors that
111 /// provided InstrRW records for this class. ItinClassDef or Writes/Reads may
112 /// still be defined for processors with no InstRW entry.
113 ///
114 /// 4) An inferred class represents a variant of another class that may be
115 /// resolved at runtime. ProcIndices contains the set of processors that may
116 /// require the class. ProcIndices are propagated through SchedClasses as
117 /// variants are expanded. Multiple SchedClasses may be inferred from an
118 /// itinerary class. Each inherits the processor index from the ItinRW record
119 /// that mapped the itinerary class to the variant Writes or Reads.
120 struct CodeGenSchedClass {
121   std::string Name;
122   Record *ItinClassDef;
123
124   IdxVec Writes;
125   IdxVec Reads;
126   // Sorted list of ProcIdx, where ProcIdx==0 implies any processor.
127   IdxVec ProcIndices;
128
129   std::vector<CodeGenSchedTransition> Transitions;
130
131   // InstRW records associated with this class. These records may refer to an
132   // Instruction no longer mapped to this class by InstrClassMap. These
133   // Instructions should be ignored by this class because they have been split
134   // off to join another inferred class.
135   RecVec InstRWs;
136
137   CodeGenSchedClass(): ItinClassDef(0) {}
138   CodeGenSchedClass(Record *rec): ItinClassDef(rec) {
139     Name = rec->getName();
140     ProcIndices.push_back(0);
141   }
142
143 #ifndef NDEBUG
144   void dump(const CodeGenSchedModels *SchedModels) const;
145 #endif
146 };
147
148 // Processor model.
149 //
150 // ModelName is a unique name used to name an instantiation of MCSchedModel.
151 //
152 // ModelDef is NULL for inferred Models. This happens when a processor defines
153 // an itinerary but no machine model. If the processer defines neither a machine
154 // model nor itinerary, then ModelDef remains pointing to NoModel. NoModel has
155 // the special "NoModel" field set to true.
156 //
157 // ItinsDef always points to a valid record definition, but may point to the
158 // default NoItineraries. NoItineraries has an empty list of InstrItinData
159 // records.
160 //
161 // ItinDefList orders this processor's InstrItinData records by SchedClass idx.
162 struct CodeGenProcModel {
163   unsigned Index;
164   std::string ModelName;
165   Record *ModelDef;
166   Record *ItinsDef;
167
168   // Derived members...
169
170   // Array of InstrItinData records indexed by a CodeGenSchedClass index.
171   // This list is empty if the Processor has no value for Itineraries.
172   // Initialized by collectProcItins().
173   RecVec ItinDefList;
174
175   // Map itinerary classes to per-operand resources.
176   // This list is empty if no ItinRW refers to this Processor.
177   RecVec ItinRWDefs;
178
179   // All read/write resources associated with this processor.
180   RecVec WriteResDefs;
181   RecVec ReadAdvanceDefs;
182
183   // Per-operand machine model resources associated with this processor.
184   RecVec ProcResourceDefs;
185
186   CodeGenProcModel(unsigned Idx, const std::string &Name, Record *MDef,
187                    Record *IDef) :
188     Index(Idx), ModelName(Name), ModelDef(MDef), ItinsDef(IDef) {}
189
190   bool hasInstrSchedModel() const {
191     return !WriteResDefs.empty() || !ItinRWDefs.empty();
192   }
193
194   unsigned getProcResourceIdx(Record *PRDef) const;
195
196 #ifndef NDEBUG
197   void dump() const;
198 #endif
199 };
200
201 /// Top level container for machine model data.
202 class CodeGenSchedModels {
203   RecordKeeper &Records;
204   const CodeGenTarget &Target;
205
206   // List of unique processor models.
207   std::vector<CodeGenProcModel> ProcModels;
208
209   // Map Processor's MachineModel or ProcItin to a CodeGenProcModel index.
210   typedef DenseMap<Record*, unsigned> ProcModelMapTy;
211   ProcModelMapTy ProcModelMap;
212
213   // Per-operand SchedReadWrite types.
214   std::vector<CodeGenSchedRW> SchedWrites;
215   std::vector<CodeGenSchedRW> SchedReads;
216
217   // List of unique SchedClasses.
218   std::vector<CodeGenSchedClass> SchedClasses;
219
220   // Map SchedClass name to itinerary index.
221   // These are either explicit itinerary classes or classes implied by
222   // instruction definitions with SchedReadWrite lists.
223   StringMap<unsigned> SchedClassIdxMap;
224
225   // SchedClass indices 1 up to and including NumItineraryClasses identify
226   // itinerary classes that are explicitly used for this target's instruction
227   // definitions. NoItinerary always has index 0 regardless of whether it is
228   // explicitly referenced.
229   //
230   // Any implied SchedClass has an index greater than NumItineraryClasses.
231   unsigned NumItineraryClasses;
232
233   // Any inferred SchedClass has an index greater than NumInstrSchedClassses.
234   unsigned NumInstrSchedClasses;
235
236   // Map Instruction to SchedClass index. Only for Instructions mentioned in
237   // InstRW records.
238   typedef DenseMap<Record*, unsigned> InstClassMapTy;
239   InstClassMapTy InstrClassMap;
240
241 public:
242   CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT);
243
244   Record *getModelOrItinDef(Record *ProcDef) const {
245     Record *ModelDef = ProcDef->getValueAsDef("SchedModel");
246     Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");
247     if (!ItinsDef->getValueAsListOfDefs("IID").empty()) {
248       assert(ModelDef->getValueAsBit("NoModel")
249              && "Itineraries must be defined within SchedMachineModel");
250       return ItinsDef;
251     }
252     return ModelDef;
253   }
254
255   const CodeGenProcModel &getModelForProc(Record *ProcDef) const {
256     Record *ModelDef = getModelOrItinDef(ProcDef);
257     ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
258     assert(I != ProcModelMap.end() && "missing machine model");
259     return ProcModels[I->second];
260   }
261
262   const CodeGenProcModel &getProcModel(Record *ModelDef) const {
263     ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
264     assert(I != ProcModelMap.end() && "missing machine model");
265     return ProcModels[I->second];
266   }
267
268   // Iterate over the unique processor models.
269   typedef std::vector<CodeGenProcModel>::const_iterator ProcIter;
270   ProcIter procModelBegin() const { return ProcModels.begin(); }
271   ProcIter procModelEnd() const { return ProcModels.end(); }
272
273   // Get a SchedWrite from its index.
274   const CodeGenSchedRW &getSchedWrite(unsigned Idx) const {
275     assert(Idx < SchedWrites.size() && "bad SchedWrite index");
276     assert(SchedWrites[Idx].isValid() && "invalid SchedWrite");
277     return SchedWrites[Idx];
278   }
279   // Get a SchedWrite from its index.
280   const CodeGenSchedRW &getSchedRead(unsigned Idx) const {
281     assert(Idx < SchedReads.size() && "bad SchedRead index");
282     assert(SchedReads[Idx].isValid() && "invalid SchedRead");
283     return SchedReads[Idx];
284   }
285
286   const CodeGenSchedRW &getSchedRW(unsigned Idx, bool IsRead) const {
287     return IsRead ? getSchedRead(Idx) : getSchedWrite(Idx);
288   }
289   CodeGenSchedRW &getSchedRW(Record *Def, unsigned &Idx) {
290     bool IsRead = Def->isSubClassOf("SchedRead");
291     Idx = getSchedRWIdx(Def, IsRead);
292     return const_cast<CodeGenSchedRW&>(
293       IsRead ? getSchedRead(Idx) : getSchedWrite(Idx));
294   }
295   CodeGenSchedRW &getSchedRW(Record *Def) {
296     unsigned Idx;
297     return getSchedRW(Def, Idx);
298   }
299
300   unsigned getSchedRWIdx(Record *Def, bool IsRead, unsigned After = 0) const;
301
302   // Return true if the given write record is referenced by a ReadAdvance.
303   bool hasReadOfWrite(Record *WriteDef) const;
304
305   // Check if any instructions are assigned to an explicit itinerary class other
306   // than NoItinerary.
307   bool hasItineraryClasses() const { return NumItineraryClasses > 0; }
308
309   // Return the number of itinerary classes in use by this target's instruction
310   // descriptions, not including "NoItinerary".
311   unsigned numItineraryClasses() const {
312     return NumItineraryClasses;
313   }
314
315   // Get a SchedClass from its index.
316   CodeGenSchedClass &getSchedClass(unsigned Idx) {
317     assert(Idx < SchedClasses.size() && "bad SchedClass index");
318     return SchedClasses[Idx];
319   }
320   const CodeGenSchedClass &getSchedClass(unsigned Idx) const {
321     assert(Idx < SchedClasses.size() && "bad SchedClass index");
322     return SchedClasses[Idx];
323   }
324
325   // Get the SchedClass index for an instruction. Instructions with no
326   // itinerary, no SchedReadWrites, and no InstrReadWrites references return 0
327   // for NoItinerary.
328   unsigned getSchedClassIdx(const CodeGenInstruction &Inst) const;
329
330   unsigned getSchedClassIdx(const RecVec &RWDefs) const;
331
332   unsigned getSchedClassIdxForItin(const Record *ItinDef) {
333     return SchedClassIdxMap[ItinDef->getName()];
334   }
335
336   typedef std::vector<CodeGenSchedClass>::const_iterator SchedClassIter;
337   SchedClassIter schedClassBegin() const { return SchedClasses.begin(); }
338   SchedClassIter schedClassEnd() const { return SchedClasses.end(); }
339
340   void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const;
341   void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const;
342   void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const;
343
344   unsigned addSchedClass(const IdxVec &OperWrites, const IdxVec &OperReads,
345                          const IdxVec &ProcIndices);
346
347   unsigned findOrInsertRW(ArrayRef<unsigned> Seq, bool IsRead);
348
349   unsigned findSchedClassIdx(const IdxVec &Writes, const IdxVec &Reads) const;
350
351   Record *findProcResUnits(Record *ProcResKind,
352                            const CodeGenProcModel &PM) const;
353
354 private:
355   void collectProcModels();
356
357   // Initialize a new processor model if it is unique.
358   void addProcModel(Record *ProcDef);
359
360   void collectSchedRW();
361
362   std::string genRWName(const IdxVec& Seq, bool IsRead);
363   unsigned findRWForSequence(const IdxVec &Seq, bool IsRead);
364
365   void collectSchedClasses();
366
367   std::string createSchedClassName(const IdxVec &OperWrites,
368                                    const IdxVec &OperReads);
369   std::string createSchedClassName(const RecVec &InstDefs);
370   void createInstRWClass(Record *InstRWDef);
371
372   void collectProcItins();
373
374   void collectProcItinRW();
375
376   void inferSchedClasses();
377
378   void inferFromRW(const IdxVec &OperWrites, const IdxVec &OperReads,
379                    unsigned FromClassIdx, const IdxVec &ProcIndices);
380   void inferFromItinClass(Record *ItinClassDef, unsigned FromClassIdx);
381   void inferFromInstRWs(unsigned SCIdx);
382
383   void collectProcResources();
384
385   void collectItinProcResources(Record *ItinClassDef);
386
387   void collectRWResources(const IdxVec &Writes, const IdxVec &Reads,
388                           const IdxVec &ProcIndices);
389
390   void addProcResource(Record *ProcResourceKind, CodeGenProcModel &PM);
391
392   void addWriteRes(Record *ProcWriteResDef, unsigned PIdx);
393
394   void addReadAdvance(Record *ProcReadAdvanceDef, unsigned PIdx);
395 };
396
397 } // namespace llvm
398
399 #endif