]> git.proxmox.com Git - rustc.git/blob - src/llvm/utils/TableGen/CodeGenSchedule.h
Imported Upstream version 0.6
[rustc.git] / src / llvm / 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