blob: e9c8359410c26409e39c728e0befef1188aae6b8 [file] [log] [blame]
Andrew Trick2661b412012-07-07 04:00:00 +00001//===- 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
23namespace llvm {
24
25class CodeGenTarget;
Andrew Trick48605c32012-09-15 00:19:57 +000026class CodeGenSchedModels;
27class CodeGenInstruction;
Andrew Trick2661b412012-07-07 04:00:00 +000028
Andrew Trick48605c32012-09-15 00:19:57 +000029typedef std::vector<Record*> RecVec;
30typedef std::vector<Record*>::const_iterator RecIter;
31
32typedef std::vector<unsigned> IdxVec;
33typedef std::vector<unsigned>::const_iterator IdxIter;
34
35void 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.
45struct CodeGenSchedRW {
46 std::string Name;
47 Record *TheDef;
48 bool HasVariants;
49 bool IsVariadic;
50 bool IsSequence;
51 IdxVec Sequence;
52
53 CodeGenSchedRW(): TheDef(0), HasVariants(false), IsVariadic(false),
54 IsSequence(false) {}
55 CodeGenSchedRW(Record *Def): TheDef(Def), IsVariadic(false) {
56 Name = Def->getName();
57 HasVariants = Def->isSubClassOf("SchedVariant");
58 if (HasVariants)
59 IsVariadic = Def->getValueAsBit("Variadic");
60
61 // Read records don't currently have sequences, but it can be easily
62 // added. Note that implicit Reads (from ReadVariant) may have a Sequence
63 // (but no record).
64 IsSequence = Def->isSubClassOf("WriteSequence");
65 }
66
67 CodeGenSchedRW(const IdxVec &Seq, const std::string &Name):
68 Name(Name), TheDef(0), HasVariants(false), IsVariadic(false),
69 IsSequence(true), Sequence(Seq) {
70 assert(Sequence.size() > 1 && "implied sequence needs >1 RWs");
71 }
72
73 bool isValid() const {
74 assert((!HasVariants || TheDef) && "Variant write needs record def");
75 assert((!IsVariadic || HasVariants) && "Variadic write needs variants");
76 assert((!IsSequence || !HasVariants) && "Sequence can't have variant");
77 assert((!IsSequence || !Sequence.empty()) && "Sequence should be nonempty");
78 return TheDef || !Sequence.empty();
79 }
80
81#ifndef NDEBUG
82 void dump() const;
83#endif
84};
85
Andrew Trick5e613c22012-09-15 00:19:59 +000086/// Represent a transition between SchedClasses induced by SchedWriteVariant.
87struct CodeGenSchedTransition {
88 unsigned ToClassIdx;
89 IdxVec ProcIndices;
90 RecVec PredTerm;
91};
92
Andrew Trick48605c32012-09-15 00:19:57 +000093/// Scheduling class.
94///
95/// Each instruction description will be mapped to a scheduling class. There are
96/// four types of classes:
97///
98/// 1) An explicitly defined itinerary class with ItinClassDef set.
99/// Writes and ReadDefs are empty. ProcIndices contains 0 for any processor.
100///
101/// 2) An implied class with a list of SchedWrites and SchedReads that are
102/// defined in an instruction definition and which are common across all
103/// subtargets. ProcIndices contains 0 for any processor.
104///
105/// 3) An implied class with a list of InstRW records that map instructions to
106/// SchedWrites and SchedReads per-processor. InstrClassMap should map the same
107/// instructions to this class. ProcIndices contains all the processors that
108/// provided InstrRW records for this class. ItinClassDef or Writes/Reads may
109/// still be defined for processors with no InstRW entry.
110///
111/// 4) An inferred class represents a variant of another class that may be
112/// resolved at runtime. ProcIndices contains the set of processors that may
113/// require the class. ProcIndices are propagated through SchedClasses as
114/// variants are expanded. Multiple SchedClasses may be inferred from an
115/// itinerary class. Each inherits the processor index from the ItinRW record
116/// that mapped the itinerary class to the variant Writes or Reads.
Andrew Trick2661b412012-07-07 04:00:00 +0000117struct CodeGenSchedClass {
118 std::string Name;
Andrew Trick2661b412012-07-07 04:00:00 +0000119 Record *ItinClassDef;
120
Andrew Trick48605c32012-09-15 00:19:57 +0000121 IdxVec Writes;
122 IdxVec Reads;
123 // Sorted list of ProcIdx, where ProcIdx==0 implies any processor.
124 IdxVec ProcIndices;
125
Andrew Trick5e613c22012-09-15 00:19:59 +0000126 std::vector<CodeGenSchedTransition> Transitions;
127
Andrew Trick48605c32012-09-15 00:19:57 +0000128 // InstReadWrite records associated with this class. Any Instrs that the
129 // definitions refer to that are not mapped to this class should be ignored.
130 RecVec InstRWs;
131
132 CodeGenSchedClass(): ItinClassDef(0) {}
133 CodeGenSchedClass(Record *rec): ItinClassDef(rec) {
Andrew Trick2661b412012-07-07 04:00:00 +0000134 Name = rec->getName();
Andrew Trick48605c32012-09-15 00:19:57 +0000135 ProcIndices.push_back(0);
Andrew Trick2661b412012-07-07 04:00:00 +0000136 }
Andrew Trick48605c32012-09-15 00:19:57 +0000137
138#ifndef NDEBUG
139 void dump(const CodeGenSchedModels *SchedModels) const;
140#endif
Andrew Trick2661b412012-07-07 04:00:00 +0000141};
142
143// Processor model.
144//
145// ModelName is a unique name used to name an instantiation of MCSchedModel.
146//
147// ModelDef is NULL for inferred Models. This happens when a processor defines
148// an itinerary but no machine model. If the processer defines neither a machine
149// model nor itinerary, then ModelDef remains pointing to NoModel. NoModel has
150// the special "NoModel" field set to true.
151//
152// ItinsDef always points to a valid record definition, but may point to the
153// default NoItineraries. NoItineraries has an empty list of InstrItinData
154// records.
155//
156// ItinDefList orders this processor's InstrItinData records by SchedClass idx.
157struct CodeGenProcModel {
Andrew Trick48605c32012-09-15 00:19:57 +0000158 unsigned Index;
Andrew Trick2661b412012-07-07 04:00:00 +0000159 std::string ModelName;
160 Record *ModelDef;
161 Record *ItinsDef;
162
Andrew Trick48605c32012-09-15 00:19:57 +0000163 // Derived members...
Andrew Trick2661b412012-07-07 04:00:00 +0000164
Andrew Trick48605c32012-09-15 00:19:57 +0000165 // Array of InstrItinData records indexed by a CodeGenSchedClass index.
166 // This list is empty if the Processor has no value for Itineraries.
167 // Initialized by collectProcItins().
168 RecVec ItinDefList;
169
170 // Map itinerary classes to per-operand resources.
171 // This list is empty if no ItinRW refers to this Processor.
172 RecVec ItinRWDefs;
173
174 CodeGenProcModel(unsigned Idx, const std::string &Name, Record *MDef,
175 Record *IDef) :
176 Index(Idx), ModelName(Name), ModelDef(MDef), ItinsDef(IDef) {}
177
178#ifndef NDEBUG
179 void dump() const;
180#endif
Andrew Trick2661b412012-07-07 04:00:00 +0000181};
182
Andrew Trick48605c32012-09-15 00:19:57 +0000183/// Top level container for machine model data.
Andrew Trick2661b412012-07-07 04:00:00 +0000184class CodeGenSchedModels {
185 RecordKeeper &Records;
186 const CodeGenTarget &Target;
187
Andrew Trick48605c32012-09-15 00:19:57 +0000188 // List of unique processor models.
189 std::vector<CodeGenProcModel> ProcModels;
190
191 // Map Processor's MachineModel or ProcItin to a CodeGenProcModel index.
192 typedef DenseMap<Record*, unsigned> ProcModelMapTy;
193 ProcModelMapTy ProcModelMap;
194
195 // Per-operand SchedReadWrite types.
196 std::vector<CodeGenSchedRW> SchedWrites;
197 std::vector<CodeGenSchedRW> SchedReads;
198
Andrew Trick2661b412012-07-07 04:00:00 +0000199 // List of unique SchedClasses.
200 std::vector<CodeGenSchedClass> SchedClasses;
201
202 // Map SchedClass name to itinerary index.
Andrew Trick48605c32012-09-15 00:19:57 +0000203 // These are either explicit itinerary classes or classes implied by
204 // instruction definitions with SchedReadWrite lists.
Andrew Trick2661b412012-07-07 04:00:00 +0000205 StringMap<unsigned> SchedClassIdxMap;
206
207 // SchedClass indices 1 up to and including NumItineraryClasses identify
208 // itinerary classes that are explicitly used for this target's instruction
209 // definitions. NoItinerary always has index 0 regardless of whether it is
210 // explicitly referenced.
211 //
Andrew Trick48605c32012-09-15 00:19:57 +0000212 // Any implied SchedClass has an index greater than NumItineraryClasses.
Andrew Trick2661b412012-07-07 04:00:00 +0000213 unsigned NumItineraryClasses;
214
Andrew Trick48605c32012-09-15 00:19:57 +0000215 // Any inferred SchedClass has an index greater than NumInstrSchedClassses.
216 unsigned NumInstrSchedClasses;
Andrew Trick2661b412012-07-07 04:00:00 +0000217
Andrew Trick48605c32012-09-15 00:19:57 +0000218 // Map Instruction to SchedClass index. Only for Instructions mentioned in
219 // OpReadWrites.
220 typedef DenseMap<Record*, unsigned> InstClassMapTy;
221 InstClassMapTy InstrClassMap;
Andrew Trick2661b412012-07-07 04:00:00 +0000222
223public:
224 CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT);
225
Andrew Trick48605c32012-09-15 00:19:57 +0000226 Record *getModelOrItinDef(Record *ProcDef) const {
227 Record *ModelDef = ProcDef->getValueAsDef("SchedModel");
228 Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");
229 if (!ItinsDef->getValueAsListOfDefs("IID").empty()) {
230 assert(ModelDef->getValueAsBit("NoModel")
231 && "Itineraries must be defined within SchedMachineModel");
232 return ItinsDef;
233 }
234 return ModelDef;
235 }
236
237 const CodeGenProcModel &getModelForProc(Record *ProcDef) const {
238 Record *ModelDef = getModelOrItinDef(ProcDef);
239 ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
240 assert(I != ProcModelMap.end() && "missing machine model");
241 return ProcModels[I->second];
242 }
243
244 const CodeGenProcModel &getProcModel(Record *ModelDef) const {
245 ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
246 assert(I != ProcModelMap.end() && "missing machine model");
247 return ProcModels[I->second];
248 }
249
250 // Iterate over the unique processor models.
251 typedef std::vector<CodeGenProcModel>::const_iterator ProcIter;
252 ProcIter procModelBegin() const { return ProcModels.begin(); }
253 ProcIter procModelEnd() const { return ProcModels.end(); }
254
255 // Get a SchedWrite from its index.
256 const CodeGenSchedRW &getSchedWrite(unsigned Idx) const {
257 assert(Idx < SchedWrites.size() && "bad SchedWrite index");
258 assert(SchedWrites[Idx].isValid() && "invalid SchedWrite");
259 return SchedWrites[Idx];
260 }
261 // Get a SchedWrite from its index.
262 const CodeGenSchedRW &getSchedRead(unsigned Idx) const {
263 assert(Idx < SchedReads.size() && "bad SchedRead index");
264 assert(SchedReads[Idx].isValid() && "invalid SchedRead");
265 return SchedReads[Idx];
266 }
267
268 const CodeGenSchedRW &getSchedRW(unsigned Idx, bool IsRead) const {
269 return IsRead ? getSchedRead(Idx) : getSchedWrite(Idx);
270 }
271
272 unsigned getSchedRWIdx(Record *Def, bool IsRead, unsigned After = 0) const;
273
Andrew Trick2661b412012-07-07 04:00:00 +0000274 // Check if any instructions are assigned to an explicit itinerary class other
275 // than NoItinerary.
276 bool hasItineraryClasses() const { return NumItineraryClasses > 0; }
277
278 // Return the number of itinerary classes in use by this target's instruction
279 // descriptions, not including "NoItinerary".
280 unsigned numItineraryClasses() const {
281 return NumItineraryClasses;
282 }
283
284 // Get a SchedClass from its index.
Andrew Trick48605c32012-09-15 00:19:57 +0000285 CodeGenSchedClass &getSchedClass(unsigned Idx) {
286 assert(Idx < SchedClasses.size() && "bad SchedClass index");
287 return SchedClasses[Idx];
288 }
289 const CodeGenSchedClass &getSchedClass(unsigned Idx) const {
Andrew Trick2661b412012-07-07 04:00:00 +0000290 assert(Idx < SchedClasses.size() && "bad SchedClass index");
291 return SchedClasses[Idx];
292 }
293
294 // Get an itinerary class's index. Value indices are '0' for NoItinerary up to
295 // and including numItineraryClasses().
296 unsigned getItinClassIdx(Record *ItinDef) const {
297 assert(SchedClassIdxMap.count(ItinDef->getName()) && "missing ItinClass");
298 unsigned Idx = SchedClassIdxMap.lookup(ItinDef->getName());
299 assert(Idx <= NumItineraryClasses && "bad ItinClass index");
300 return Idx;
301 }
302
Andrew Trick48605c32012-09-15 00:19:57 +0000303 // Get the SchedClass index for an instruction. Instructions with no
304 // itinerary, no SchedReadWrites, and no InstrReadWrites references return 0
305 // for NoItinerary.
306 unsigned getSchedClassIdx(const CodeGenInstruction &Inst) const;
307
308 unsigned getSchedClassIdx(const RecVec &RWDefs) const;
309
310 unsigned getSchedClassIdxForItin(const Record *ItinDef) {
311 return SchedClassIdxMap[ItinDef->getName()];
Andrew Trick2661b412012-07-07 04:00:00 +0000312 }
313
Andrew Trick48605c32012-09-15 00:19:57 +0000314 typedef std::vector<CodeGenSchedClass>::const_iterator SchedClassIter;
315 SchedClassIter schedClassBegin() const { return SchedClasses.begin(); }
316 SchedClassIter schedClassEnd() const { return SchedClasses.end(); }
Andrew Trick2661b412012-07-07 04:00:00 +0000317
Andrew Trick48605c32012-09-15 00:19:57 +0000318 void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const;
319 void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const;
Andrew Trick5e613c22012-09-15 00:19:59 +0000320 void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const;
Andrew Trick48605c32012-09-15 00:19:57 +0000321
322 unsigned addSchedClass(const IdxVec &OperWrites, const IdxVec &OperReads,
323 const IdxVec &ProcIndices);
324
325 unsigned findOrInsertRW(ArrayRef<unsigned> Seq, bool IsRead);
326
327 unsigned findSchedClassIdx(const IdxVec &Writes, const IdxVec &Reads) const;
Andrew Trick2661b412012-07-07 04:00:00 +0000328
329private:
Andrew Trick48605c32012-09-15 00:19:57 +0000330 void collectProcModels();
Andrew Trick2661b412012-07-07 04:00:00 +0000331
332 // Initialize a new processor model if it is unique.
333 void addProcModel(Record *ProcDef);
334
Andrew Trick48605c32012-09-15 00:19:57 +0000335 void collectSchedRW();
336
337 std::string genRWName(const IdxVec& Seq, bool IsRead);
338 unsigned findRWForSequence(const IdxVec &Seq, bool IsRead);
339
340 void collectSchedClasses();
341
342 std::string createSchedClassName(const IdxVec &OperWrites,
343 const IdxVec &OperReads);
344 std::string createSchedClassName(const RecVec &InstDefs);
345 void createInstRWClass(Record *InstRWDef);
346
347 void collectProcItins();
348
349 void collectProcItinRW();
Andrew Trick5e613c22012-09-15 00:19:59 +0000350
351 void inferSchedClasses();
352
353 void inferFromRW(const IdxVec &OperWrites, const IdxVec &OperReads,
354 unsigned FromClassIdx, const IdxVec &ProcIndices);
355 void inferFromItinClass(Record *ItinClassDef, unsigned FromClassIdx);
356 void inferFromInstRWs(unsigned SCIdx);
Andrew Trick2661b412012-07-07 04:00:00 +0000357};
358
359} // namespace llvm
360
361#endif