blob: 211c05c8c64d8ef94e13591bc7f964f36fc4a07e [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 {
Andrew Trick2062b122012-10-03 23:06:28 +000046 unsigned Index;
Andrew Trick48605c32012-09-15 00:19:57 +000047 std::string Name;
48 Record *TheDef;
Andrew Trick2062b122012-10-03 23:06:28 +000049 bool IsRead;
Andrew Trick92649882012-09-22 02:24:21 +000050 bool IsAlias;
Andrew Trick48605c32012-09-15 00:19:57 +000051 bool HasVariants;
52 bool IsVariadic;
53 bool IsSequence;
54 IdxVec Sequence;
Andrew Trick92649882012-09-22 02:24:21 +000055 RecVec Aliases;
Andrew Trick48605c32012-09-15 00:19:57 +000056
Andrew Trick2062b122012-10-03 23:06:28 +000057 CodeGenSchedRW(): Index(0), TheDef(0), IsAlias(false), HasVariants(false),
Andrew Trick92649882012-09-22 02:24:21 +000058 IsVariadic(false), IsSequence(false) {}
Andrew Trick2062b122012-10-03 23:06:28 +000059 CodeGenSchedRW(unsigned Idx, Record *Def): Index(Idx), TheDef(Def),
60 IsAlias(false), IsVariadic(false) {
Andrew Trick48605c32012-09-15 00:19:57 +000061 Name = Def->getName();
Andrew Trick2062b122012-10-03 23:06:28 +000062 IsRead = Def->isSubClassOf("SchedRead");
Andrew Trick48605c32012-09-15 00:19:57 +000063 HasVariants = Def->isSubClassOf("SchedVariant");
64 if (HasVariants)
65 IsVariadic = Def->getValueAsBit("Variadic");
66
67 // Read records don't currently have sequences, but it can be easily
68 // added. Note that implicit Reads (from ReadVariant) may have a Sequence
69 // (but no record).
70 IsSequence = Def->isSubClassOf("WriteSequence");
71 }
72
Andrew Trick2062b122012-10-03 23:06:28 +000073 CodeGenSchedRW(unsigned Idx, bool Read, const IdxVec &Seq,
74 const std::string &Name):
75 Index(Idx), Name(Name), TheDef(0), IsRead(Read), IsAlias(false),
76 HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) {
Andrew Trick48605c32012-09-15 00:19:57 +000077 assert(Sequence.size() > 1 && "implied sequence needs >1 RWs");
78 }
79
80 bool isValid() const {
81 assert((!HasVariants || TheDef) && "Variant write needs record def");
82 assert((!IsVariadic || HasVariants) && "Variadic write needs variants");
83 assert((!IsSequence || !HasVariants) && "Sequence can't have variant");
84 assert((!IsSequence || !Sequence.empty()) && "Sequence should be nonempty");
Andrew Trick92649882012-09-22 02:24:21 +000085 assert((!IsAlias || Aliases.empty()) && "Alias cannot have aliases");
Andrew Trick48605c32012-09-15 00:19:57 +000086 return TheDef || !Sequence.empty();
87 }
88
89#ifndef NDEBUG
90 void dump() const;
91#endif
92};
93
Andrew Tricke076bb12012-09-18 04:03:30 +000094/// Represent a transition between SchedClasses induced by SchedVariant.
Andrew Trick5e613c22012-09-15 00:19:59 +000095struct CodeGenSchedTransition {
96 unsigned ToClassIdx;
97 IdxVec ProcIndices;
98 RecVec PredTerm;
99};
100
Andrew Trick48605c32012-09-15 00:19:57 +0000101/// Scheduling class.
102///
103/// Each instruction description will be mapped to a scheduling class. There are
104/// four types of classes:
105///
106/// 1) An explicitly defined itinerary class with ItinClassDef set.
107/// Writes and ReadDefs are empty. ProcIndices contains 0 for any processor.
108///
109/// 2) An implied class with a list of SchedWrites and SchedReads that are
110/// defined in an instruction definition and which are common across all
111/// subtargets. ProcIndices contains 0 for any processor.
112///
113/// 3) An implied class with a list of InstRW records that map instructions to
114/// SchedWrites and SchedReads per-processor. InstrClassMap should map the same
115/// instructions to this class. ProcIndices contains all the processors that
116/// provided InstrRW records for this class. ItinClassDef or Writes/Reads may
117/// still be defined for processors with no InstRW entry.
118///
119/// 4) An inferred class represents a variant of another class that may be
120/// resolved at runtime. ProcIndices contains the set of processors that may
121/// require the class. ProcIndices are propagated through SchedClasses as
122/// variants are expanded. Multiple SchedClasses may be inferred from an
123/// itinerary class. Each inherits the processor index from the ItinRW record
124/// that mapped the itinerary class to the variant Writes or Reads.
Andrew Trick2661b412012-07-07 04:00:00 +0000125struct CodeGenSchedClass {
126 std::string Name;
Andrew Trick2661b412012-07-07 04:00:00 +0000127 Record *ItinClassDef;
128
Andrew Trick48605c32012-09-15 00:19:57 +0000129 IdxVec Writes;
130 IdxVec Reads;
131 // Sorted list of ProcIdx, where ProcIdx==0 implies any processor.
132 IdxVec ProcIndices;
133
Andrew Trick5e613c22012-09-15 00:19:59 +0000134 std::vector<CodeGenSchedTransition> Transitions;
135
Andrew Trick92649882012-09-22 02:24:21 +0000136 // InstRW records associated with this class. These records may refer to an
137 // Instruction no longer mapped to this class by InstrClassMap. These
138 // Instructions should be ignored by this class because they have been split
139 // off to join another inferred class.
Andrew Trick48605c32012-09-15 00:19:57 +0000140 RecVec InstRWs;
141
142 CodeGenSchedClass(): ItinClassDef(0) {}
143 CodeGenSchedClass(Record *rec): ItinClassDef(rec) {
Andrew Trick2661b412012-07-07 04:00:00 +0000144 Name = rec->getName();
Andrew Trick48605c32012-09-15 00:19:57 +0000145 ProcIndices.push_back(0);
Andrew Trick2661b412012-07-07 04:00:00 +0000146 }
Andrew Trick48605c32012-09-15 00:19:57 +0000147
148#ifndef NDEBUG
149 void dump(const CodeGenSchedModels *SchedModels) const;
150#endif
Andrew Trick2661b412012-07-07 04:00:00 +0000151};
152
153// Processor model.
154//
155// ModelName is a unique name used to name an instantiation of MCSchedModel.
156//
157// ModelDef is NULL for inferred Models. This happens when a processor defines
158// an itinerary but no machine model. If the processer defines neither a machine
159// model nor itinerary, then ModelDef remains pointing to NoModel. NoModel has
160// the special "NoModel" field set to true.
161//
162// ItinsDef always points to a valid record definition, but may point to the
163// default NoItineraries. NoItineraries has an empty list of InstrItinData
164// records.
165//
166// ItinDefList orders this processor's InstrItinData records by SchedClass idx.
167struct CodeGenProcModel {
Andrew Trick48605c32012-09-15 00:19:57 +0000168 unsigned Index;
Andrew Trick2661b412012-07-07 04:00:00 +0000169 std::string ModelName;
170 Record *ModelDef;
171 Record *ItinsDef;
172
Andrew Trick48605c32012-09-15 00:19:57 +0000173 // Derived members...
Andrew Trick2661b412012-07-07 04:00:00 +0000174
Andrew Trick48605c32012-09-15 00:19:57 +0000175 // Array of InstrItinData records indexed by a CodeGenSchedClass index.
176 // This list is empty if the Processor has no value for Itineraries.
177 // Initialized by collectProcItins().
178 RecVec ItinDefList;
179
180 // Map itinerary classes to per-operand resources.
181 // This list is empty if no ItinRW refers to this Processor.
182 RecVec ItinRWDefs;
183
Andrew Trick3cbd1782012-09-15 00:20:02 +0000184 // All read/write resources associated with this processor.
185 RecVec WriteResDefs;
186 RecVec ReadAdvanceDefs;
187
188 // Per-operand machine model resources associated with this processor.
189 RecVec ProcResourceDefs;
190
Andrew Trick48605c32012-09-15 00:19:57 +0000191 CodeGenProcModel(unsigned Idx, const std::string &Name, Record *MDef,
192 Record *IDef) :
193 Index(Idx), ModelName(Name), ModelDef(MDef), ItinsDef(IDef) {}
194
Andrew Trick3cbd1782012-09-15 00:20:02 +0000195 bool hasInstrSchedModel() const {
196 return !WriteResDefs.empty() || !ItinRWDefs.empty();
197 }
198
199 unsigned getProcResourceIdx(Record *PRDef) const;
200
Andrew Trick48605c32012-09-15 00:19:57 +0000201#ifndef NDEBUG
202 void dump() const;
203#endif
Andrew Trick2661b412012-07-07 04:00:00 +0000204};
205
Andrew Trick48605c32012-09-15 00:19:57 +0000206/// Top level container for machine model data.
Andrew Trick2661b412012-07-07 04:00:00 +0000207class CodeGenSchedModels {
208 RecordKeeper &Records;
209 const CodeGenTarget &Target;
210
Andrew Trick48605c32012-09-15 00:19:57 +0000211 // List of unique processor models.
212 std::vector<CodeGenProcModel> ProcModels;
213
214 // Map Processor's MachineModel or ProcItin to a CodeGenProcModel index.
215 typedef DenseMap<Record*, unsigned> ProcModelMapTy;
216 ProcModelMapTy ProcModelMap;
217
218 // Per-operand SchedReadWrite types.
219 std::vector<CodeGenSchedRW> SchedWrites;
220 std::vector<CodeGenSchedRW> SchedReads;
221
Andrew Trick2661b412012-07-07 04:00:00 +0000222 // List of unique SchedClasses.
223 std::vector<CodeGenSchedClass> SchedClasses;
224
225 // Map SchedClass name to itinerary index.
Andrew Trick48605c32012-09-15 00:19:57 +0000226 // These are either explicit itinerary classes or classes implied by
227 // instruction definitions with SchedReadWrite lists.
Andrew Trick2661b412012-07-07 04:00:00 +0000228 StringMap<unsigned> SchedClassIdxMap;
229
230 // SchedClass indices 1 up to and including NumItineraryClasses identify
231 // itinerary classes that are explicitly used for this target's instruction
232 // definitions. NoItinerary always has index 0 regardless of whether it is
233 // explicitly referenced.
234 //
Andrew Trick48605c32012-09-15 00:19:57 +0000235 // Any implied SchedClass has an index greater than NumItineraryClasses.
Andrew Trick2661b412012-07-07 04:00:00 +0000236 unsigned NumItineraryClasses;
237
Andrew Trick48605c32012-09-15 00:19:57 +0000238 // Any inferred SchedClass has an index greater than NumInstrSchedClassses.
239 unsigned NumInstrSchedClasses;
Andrew Trick2661b412012-07-07 04:00:00 +0000240
Andrew Trick48605c32012-09-15 00:19:57 +0000241 // Map Instruction to SchedClass index. Only for Instructions mentioned in
Andrew Trick92649882012-09-22 02:24:21 +0000242 // InstRW records.
Andrew Trick48605c32012-09-15 00:19:57 +0000243 typedef DenseMap<Record*, unsigned> InstClassMapTy;
244 InstClassMapTy InstrClassMap;
Andrew Trick2661b412012-07-07 04:00:00 +0000245
246public:
247 CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT);
248
Andrew Trick48605c32012-09-15 00:19:57 +0000249 Record *getModelOrItinDef(Record *ProcDef) const {
250 Record *ModelDef = ProcDef->getValueAsDef("SchedModel");
251 Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");
252 if (!ItinsDef->getValueAsListOfDefs("IID").empty()) {
253 assert(ModelDef->getValueAsBit("NoModel")
254 && "Itineraries must be defined within SchedMachineModel");
255 return ItinsDef;
256 }
257 return ModelDef;
258 }
259
260 const CodeGenProcModel &getModelForProc(Record *ProcDef) const {
261 Record *ModelDef = getModelOrItinDef(ProcDef);
262 ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
263 assert(I != ProcModelMap.end() && "missing machine model");
264 return ProcModels[I->second];
265 }
266
267 const CodeGenProcModel &getProcModel(Record *ModelDef) const {
268 ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
269 assert(I != ProcModelMap.end() && "missing machine model");
270 return ProcModels[I->second];
271 }
272
273 // Iterate over the unique processor models.
274 typedef std::vector<CodeGenProcModel>::const_iterator ProcIter;
275 ProcIter procModelBegin() const { return ProcModels.begin(); }
276 ProcIter procModelEnd() const { return ProcModels.end(); }
277
278 // Get a SchedWrite from its index.
279 const CodeGenSchedRW &getSchedWrite(unsigned Idx) const {
280 assert(Idx < SchedWrites.size() && "bad SchedWrite index");
281 assert(SchedWrites[Idx].isValid() && "invalid SchedWrite");
282 return SchedWrites[Idx];
283 }
284 // Get a SchedWrite from its index.
285 const CodeGenSchedRW &getSchedRead(unsigned Idx) const {
286 assert(Idx < SchedReads.size() && "bad SchedRead index");
287 assert(SchedReads[Idx].isValid() && "invalid SchedRead");
288 return SchedReads[Idx];
289 }
290
291 const CodeGenSchedRW &getSchedRW(unsigned Idx, bool IsRead) const {
292 return IsRead ? getSchedRead(Idx) : getSchedWrite(Idx);
293 }
Andrew Trick2062b122012-10-03 23:06:28 +0000294 CodeGenSchedRW &getSchedRW(Record *Def) {
Andrew Trick92649882012-09-22 02:24:21 +0000295 bool IsRead = Def->isSubClassOf("SchedRead");
Andrew Trick2062b122012-10-03 23:06:28 +0000296 unsigned Idx = getSchedRWIdx(Def, IsRead);
Andrew Trick92649882012-09-22 02:24:21 +0000297 return const_cast<CodeGenSchedRW&>(
298 IsRead ? getSchedRead(Idx) : getSchedWrite(Idx));
299 }
Andrew Trick2062b122012-10-03 23:06:28 +0000300 const CodeGenSchedRW &getSchedRW(Record*Def) const {
301 return const_cast<CodeGenSchedModels&>(*this).getSchedRW(Def);
Andrew Trick92649882012-09-22 02:24:21 +0000302 }
Andrew Trick48605c32012-09-15 00:19:57 +0000303
304 unsigned getSchedRWIdx(Record *Def, bool IsRead, unsigned After = 0) const;
305
Andrew Trick3b8fb642012-09-19 04:43:19 +0000306 // Return true if the given write record is referenced by a ReadAdvance.
307 bool hasReadOfWrite(Record *WriteDef) const;
308
Andrew Trick2661b412012-07-07 04:00:00 +0000309 // Check if any instructions are assigned to an explicit itinerary class other
310 // than NoItinerary.
311 bool hasItineraryClasses() const { return NumItineraryClasses > 0; }
312
313 // Return the number of itinerary classes in use by this target's instruction
314 // descriptions, not including "NoItinerary".
315 unsigned numItineraryClasses() const {
316 return NumItineraryClasses;
317 }
318
319 // Get a SchedClass from its index.
Andrew Trick48605c32012-09-15 00:19:57 +0000320 CodeGenSchedClass &getSchedClass(unsigned Idx) {
321 assert(Idx < SchedClasses.size() && "bad SchedClass index");
322 return SchedClasses[Idx];
323 }
324 const CodeGenSchedClass &getSchedClass(unsigned Idx) const {
Andrew Trick2661b412012-07-07 04:00:00 +0000325 assert(Idx < SchedClasses.size() && "bad SchedClass index");
326 return SchedClasses[Idx];
327 }
328
Andrew Trick48605c32012-09-15 00:19:57 +0000329 // Get the SchedClass index for an instruction. Instructions with no
330 // itinerary, no SchedReadWrites, and no InstrReadWrites references return 0
331 // for NoItinerary.
332 unsigned getSchedClassIdx(const CodeGenInstruction &Inst) const;
333
334 unsigned getSchedClassIdx(const RecVec &RWDefs) const;
335
336 unsigned getSchedClassIdxForItin(const Record *ItinDef) {
337 return SchedClassIdxMap[ItinDef->getName()];
Andrew Trick2661b412012-07-07 04:00:00 +0000338 }
339
Andrew Trick48605c32012-09-15 00:19:57 +0000340 typedef std::vector<CodeGenSchedClass>::const_iterator SchedClassIter;
341 SchedClassIter schedClassBegin() const { return SchedClasses.begin(); }
342 SchedClassIter schedClassEnd() const { return SchedClasses.end(); }
Andrew Trick2661b412012-07-07 04:00:00 +0000343
Andrew Trick48605c32012-09-15 00:19:57 +0000344 void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const;
345 void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const;
Andrew Trick5e613c22012-09-15 00:19:59 +0000346 void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const;
Andrew Trick2062b122012-10-03 23:06:28 +0000347 void expandRWSeqForProc(unsigned RWIdx, IdxVec &RWSeq, bool IsRead,
348 const CodeGenProcModel &ProcModel) const;
Andrew Trick48605c32012-09-15 00:19:57 +0000349
350 unsigned addSchedClass(const IdxVec &OperWrites, const IdxVec &OperReads,
351 const IdxVec &ProcIndices);
352
353 unsigned findOrInsertRW(ArrayRef<unsigned> Seq, bool IsRead);
354
355 unsigned findSchedClassIdx(const IdxVec &Writes, const IdxVec &Reads) const;
Andrew Trick2661b412012-07-07 04:00:00 +0000356
Andrew Trick3cbd1782012-09-15 00:20:02 +0000357 Record *findProcResUnits(Record *ProcResKind,
358 const CodeGenProcModel &PM) const;
359
Andrew Trick2661b412012-07-07 04:00:00 +0000360private:
Andrew Trick48605c32012-09-15 00:19:57 +0000361 void collectProcModels();
Andrew Trick2661b412012-07-07 04:00:00 +0000362
363 // Initialize a new processor model if it is unique.
364 void addProcModel(Record *ProcDef);
365
Andrew Trick48605c32012-09-15 00:19:57 +0000366 void collectSchedRW();
367
368 std::string genRWName(const IdxVec& Seq, bool IsRead);
369 unsigned findRWForSequence(const IdxVec &Seq, bool IsRead);
370
371 void collectSchedClasses();
372
373 std::string createSchedClassName(const IdxVec &OperWrites,
374 const IdxVec &OperReads);
375 std::string createSchedClassName(const RecVec &InstDefs);
376 void createInstRWClass(Record *InstRWDef);
377
378 void collectProcItins();
379
380 void collectProcItinRW();
Andrew Trick5e613c22012-09-15 00:19:59 +0000381
382 void inferSchedClasses();
383
384 void inferFromRW(const IdxVec &OperWrites, const IdxVec &OperReads,
385 unsigned FromClassIdx, const IdxVec &ProcIndices);
386 void inferFromItinClass(Record *ItinClassDef, unsigned FromClassIdx);
387 void inferFromInstRWs(unsigned SCIdx);
Andrew Trick3cbd1782012-09-15 00:20:02 +0000388
389 void collectProcResources();
390
391 void collectItinProcResources(Record *ItinClassDef);
392
393 void collectRWResources(const IdxVec &Writes, const IdxVec &Reads,
394 const IdxVec &ProcIndices);
395
396 void addProcResource(Record *ProcResourceKind, CodeGenProcModel &PM);
397
398 void addWriteRes(Record *ProcWriteResDef, unsigned PIdx);
399
400 void addReadAdvance(Record *ProcReadAdvanceDef, unsigned PIdx);
Andrew Trick2661b412012-07-07 04:00:00 +0000401};
402
403} // namespace llvm
404
405#endif