1 //===- CodeGenSchedule.cpp - Scheduling MachineModels ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines structures to encapsulate the machine model as decribed in
11 // the target description.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "subtarget-emitter"
17 #include "CodeGenSchedule.h"
18 #include "CodeGenTarget.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Regex.h"
22 #include "llvm/TableGen/Error.h"
27 static void dumpIdxVec(const IdxVec
&V
) {
28 for (unsigned i
= 0, e
= V
.size(); i
< e
; ++i
) {
29 dbgs() << V
[i
] << ", ";
32 static void dumpIdxVec(const SmallVectorImpl
<unsigned> &V
) {
33 for (unsigned i
= 0, e
= V
.size(); i
< e
; ++i
) {
34 dbgs() << V
[i
] << ", ";
39 // (instrs a, b, ...) Evaluate and union all arguments. Identical to AddOp.
40 struct InstrsOp
: public SetTheory::Operator
{
41 void apply(SetTheory
&ST
, DagInit
*Expr
, SetTheory::RecSet
&Elts
,
42 ArrayRef
<SMLoc
> Loc
) {
43 ST
.evaluate(Expr
->arg_begin(), Expr
->arg_end(), Elts
, Loc
);
47 // (instregex "OpcPat",...) Find all instructions matching an opcode pattern.
49 // TODO: Since this is a prefix match, perform a binary search over the
50 // instruction names using lower_bound. Note that the predefined instrs must be
51 // scanned linearly first. However, this is only safe if the regex pattern has
52 // no top-level bars. The DAG already has a list of patterns, so there's no
53 // reason to use top-level bars, but we need a way to verify they don't exist
54 // before implementing the optimization.
55 struct InstRegexOp
: public SetTheory::Operator
{
56 const CodeGenTarget
&Target
;
57 InstRegexOp(const CodeGenTarget
&t
): Target(t
) {}
59 void apply(SetTheory
&ST
, DagInit
*Expr
, SetTheory::RecSet
&Elts
,
60 ArrayRef
<SMLoc
> Loc
) {
61 SmallVector
<Regex
*, 4> RegexList
;
62 for (DagInit::const_arg_iterator
63 AI
= Expr
->arg_begin(), AE
= Expr
->arg_end(); AI
!= AE
; ++AI
) {
64 StringInit
*SI
= dyn_cast
<StringInit
>(*AI
);
66 PrintFatalError(Loc
, "instregex requires pattern string: "
67 + Expr
->getAsString());
68 std::string pat
= SI
->getValue();
69 // Implement a python-style prefix match.
72 pat
.insert(pat
.end(), ')');
74 RegexList
.push_back(new Regex(pat
));
76 for (CodeGenTarget::inst_iterator I
= Target
.inst_begin(),
77 E
= Target
.inst_end(); I
!= E
; ++I
) {
78 for (SmallVectorImpl
<Regex
*>::iterator
79 RI
= RegexList
.begin(), RE
= RegexList
.end(); RI
!= RE
; ++RI
) {
80 if ((*RI
)->match((*I
)->TheDef
->getName()))
81 Elts
.insert((*I
)->TheDef
);
84 DeleteContainerPointers(RegexList
);
88 /// CodeGenModels ctor interprets machine model records and populates maps.
89 CodeGenSchedModels::CodeGenSchedModels(RecordKeeper
&RK
,
90 const CodeGenTarget
&TGT
):
91 Records(RK
), Target(TGT
) {
93 Sets
.addFieldExpander("InstRW", "Instrs");
95 // Allow Set evaluation to recognize the dags used in InstRW records:
96 // (instrs Op1, Op1...)
97 Sets
.addOperator("instrs", new InstrsOp
);
98 Sets
.addOperator("instregex", new InstRegexOp(Target
));
100 // Instantiate a CodeGenProcModel for each SchedMachineModel with the values
101 // that are explicitly referenced in tablegen records. Resources associated
102 // with each processor will be derived later. Populate ProcModelMap with the
103 // CodeGenProcModel instances.
106 // Instantiate a CodeGenSchedRW for each SchedReadWrite record explicitly
107 // defined, and populate SchedReads and SchedWrites vectors. Implicit
108 // SchedReadWrites that represent sequences derived from expanded variant will
109 // be inferred later.
112 // Instantiate a CodeGenSchedClass for each unique SchedRW signature directly
113 // required by an instruction definition, and populate SchedClassIdxMap. Set
114 // NumItineraryClasses to the number of explicit itinerary classes referenced
115 // by instructions. Set NumInstrSchedClasses to the number of itinerary
116 // classes plus any classes implied by instructions that derive from class
117 // Sched and provide SchedRW list. This does not infer any new classes from
119 collectSchedClasses();
121 // Find instruction itineraries for each processor. Sort and populate
122 // CodeGenProcModel::ItinDefList. (Cycle-to-cycle itineraries). This requires
123 // all itinerary classes to be discovered.
126 // Find ItinRW records for each processor and itinerary class.
127 // (For per-operand resources mapped to itinerary classes).
130 // Infer new SchedClasses from SchedVariant.
133 // Populate each CodeGenProcModel's WriteResDefs, ReadAdvanceDefs, and
135 collectProcResources();
138 /// Gather all processor models.
139 void CodeGenSchedModels::collectProcModels() {
140 RecVec ProcRecords
= Records
.getAllDerivedDefinitions("Processor");
141 std::sort(ProcRecords
.begin(), ProcRecords
.end(), LessRecordFieldName());
143 // Reserve space because we can. Reallocation would be ok.
144 ProcModels
.reserve(ProcRecords
.size()+1);
146 // Use idx=0 for NoModel/NoItineraries.
147 Record
*NoModelDef
= Records
.getDef("NoSchedModel");
148 Record
*NoItinsDef
= Records
.getDef("NoItineraries");
149 ProcModels
.push_back(CodeGenProcModel(0, "NoSchedModel",
150 NoModelDef
, NoItinsDef
));
151 ProcModelMap
[NoModelDef
] = 0;
153 // For each processor, find a unique machine model.
154 for (unsigned i
= 0, N
= ProcRecords
.size(); i
< N
; ++i
)
155 addProcModel(ProcRecords
[i
]);
158 /// Get a unique processor model based on the defined MachineModel and
159 /// ProcessorItineraries.
160 void CodeGenSchedModels::addProcModel(Record
*ProcDef
) {
161 Record
*ModelKey
= getModelOrItinDef(ProcDef
);
162 if (!ProcModelMap
.insert(std::make_pair(ModelKey
, ProcModels
.size())).second
)
165 std::string Name
= ModelKey
->getName();
166 if (ModelKey
->isSubClassOf("SchedMachineModel")) {
167 Record
*ItinsDef
= ModelKey
->getValueAsDef("Itineraries");
168 ProcModels
.push_back(
169 CodeGenProcModel(ProcModels
.size(), Name
, ModelKey
, ItinsDef
));
172 // An itinerary is defined without a machine model. Infer a new model.
173 if (!ModelKey
->getValueAsListOfDefs("IID").empty())
174 Name
= Name
+ "Model";
175 ProcModels
.push_back(
176 CodeGenProcModel(ProcModels
.size(), Name
,
177 ProcDef
->getValueAsDef("SchedModel"), ModelKey
));
179 DEBUG(ProcModels
.back().dump());
182 // Recursively find all reachable SchedReadWrite records.
183 static void scanSchedRW(Record
*RWDef
, RecVec
&RWDefs
,
184 SmallPtrSet
<Record
*, 16> &RWSet
) {
185 if (!RWSet
.insert(RWDef
))
187 RWDefs
.push_back(RWDef
);
188 // Reads don't current have sequence records, but it can be added later.
189 if (RWDef
->isSubClassOf("WriteSequence")) {
190 RecVec Seq
= RWDef
->getValueAsListOfDefs("Writes");
191 for (RecIter I
= Seq
.begin(), E
= Seq
.end(); I
!= E
; ++I
)
192 scanSchedRW(*I
, RWDefs
, RWSet
);
194 else if (RWDef
->isSubClassOf("SchedVariant")) {
195 // Visit each variant (guarded by a different predicate).
196 RecVec Vars
= RWDef
->getValueAsListOfDefs("Variants");
197 for (RecIter VI
= Vars
.begin(), VE
= Vars
.end(); VI
!= VE
; ++VI
) {
198 // Visit each RW in the sequence selected by the current variant.
199 RecVec Selected
= (*VI
)->getValueAsListOfDefs("Selected");
200 for (RecIter I
= Selected
.begin(), E
= Selected
.end(); I
!= E
; ++I
)
201 scanSchedRW(*I
, RWDefs
, RWSet
);
206 // Collect and sort all SchedReadWrites reachable via tablegen records.
207 // More may be inferred later when inferring new SchedClasses from variants.
208 void CodeGenSchedModels::collectSchedRW() {
209 // Reserve idx=0 for invalid writes/reads.
210 SchedWrites
.resize(1);
211 SchedReads
.resize(1);
213 SmallPtrSet
<Record
*, 16> RWSet
;
215 // Find all SchedReadWrites referenced by instruction defs.
216 RecVec SWDefs
, SRDefs
;
217 for (CodeGenTarget::inst_iterator I
= Target
.inst_begin(),
218 E
= Target
.inst_end(); I
!= E
; ++I
) {
219 Record
*SchedDef
= (*I
)->TheDef
;
220 if (SchedDef
->isValueUnset("SchedRW"))
222 RecVec RWs
= SchedDef
->getValueAsListOfDefs("SchedRW");
223 for (RecIter RWI
= RWs
.begin(), RWE
= RWs
.end(); RWI
!= RWE
; ++RWI
) {
224 if ((*RWI
)->isSubClassOf("SchedWrite"))
225 scanSchedRW(*RWI
, SWDefs
, RWSet
);
227 assert((*RWI
)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
228 scanSchedRW(*RWI
, SRDefs
, RWSet
);
232 // Find all ReadWrites referenced by InstRW.
233 RecVec InstRWDefs
= Records
.getAllDerivedDefinitions("InstRW");
234 for (RecIter OI
= InstRWDefs
.begin(), OE
= InstRWDefs
.end(); OI
!= OE
; ++OI
) {
235 // For all OperandReadWrites.
236 RecVec RWDefs
= (*OI
)->getValueAsListOfDefs("OperandReadWrites");
237 for (RecIter RWI
= RWDefs
.begin(), RWE
= RWDefs
.end();
239 if ((*RWI
)->isSubClassOf("SchedWrite"))
240 scanSchedRW(*RWI
, SWDefs
, RWSet
);
242 assert((*RWI
)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
243 scanSchedRW(*RWI
, SRDefs
, RWSet
);
247 // Find all ReadWrites referenced by ItinRW.
248 RecVec ItinRWDefs
= Records
.getAllDerivedDefinitions("ItinRW");
249 for (RecIter II
= ItinRWDefs
.begin(), IE
= ItinRWDefs
.end(); II
!= IE
; ++II
) {
250 // For all OperandReadWrites.
251 RecVec RWDefs
= (*II
)->getValueAsListOfDefs("OperandReadWrites");
252 for (RecIter RWI
= RWDefs
.begin(), RWE
= RWDefs
.end();
254 if ((*RWI
)->isSubClassOf("SchedWrite"))
255 scanSchedRW(*RWI
, SWDefs
, RWSet
);
257 assert((*RWI
)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
258 scanSchedRW(*RWI
, SRDefs
, RWSet
);
262 // Find all ReadWrites referenced by SchedAlias. AliasDefs needs to be sorted
263 // for the loop below that initializes Alias vectors.
264 RecVec AliasDefs
= Records
.getAllDerivedDefinitions("SchedAlias");
265 std::sort(AliasDefs
.begin(), AliasDefs
.end(), LessRecord());
266 for (RecIter AI
= AliasDefs
.begin(), AE
= AliasDefs
.end(); AI
!= AE
; ++AI
) {
267 Record
*MatchDef
= (*AI
)->getValueAsDef("MatchRW");
268 Record
*AliasDef
= (*AI
)->getValueAsDef("AliasRW");
269 if (MatchDef
->isSubClassOf("SchedWrite")) {
270 if (!AliasDef
->isSubClassOf("SchedWrite"))
271 PrintFatalError((*AI
)->getLoc(), "SchedWrite Alias must be SchedWrite");
272 scanSchedRW(AliasDef
, SWDefs
, RWSet
);
275 assert(MatchDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
276 if (!AliasDef
->isSubClassOf("SchedRead"))
277 PrintFatalError((*AI
)->getLoc(), "SchedRead Alias must be SchedRead");
278 scanSchedRW(AliasDef
, SRDefs
, RWSet
);
281 // Sort and add the SchedReadWrites directly referenced by instructions or
282 // itinerary resources. Index reads and writes in separate domains.
283 std::sort(SWDefs
.begin(), SWDefs
.end(), LessRecord());
284 for (RecIter SWI
= SWDefs
.begin(), SWE
= SWDefs
.end(); SWI
!= SWE
; ++SWI
) {
285 assert(!getSchedRWIdx(*SWI
, /*IsRead=*/false) && "duplicate SchedWrite");
286 SchedWrites
.push_back(CodeGenSchedRW(SchedWrites
.size(), *SWI
));
288 std::sort(SRDefs
.begin(), SRDefs
.end(), LessRecord());
289 for (RecIter SRI
= SRDefs
.begin(), SRE
= SRDefs
.end(); SRI
!= SRE
; ++SRI
) {
290 assert(!getSchedRWIdx(*SRI
, /*IsRead-*/true) && "duplicate SchedWrite");
291 SchedReads
.push_back(CodeGenSchedRW(SchedReads
.size(), *SRI
));
293 // Initialize WriteSequence vectors.
294 for (std::vector
<CodeGenSchedRW
>::iterator WI
= SchedWrites
.begin(),
295 WE
= SchedWrites
.end(); WI
!= WE
; ++WI
) {
298 findRWs(WI
->TheDef
->getValueAsListOfDefs("Writes"), WI
->Sequence
,
301 // Initialize Aliases vectors.
302 for (RecIter AI
= AliasDefs
.begin(), AE
= AliasDefs
.end(); AI
!= AE
; ++AI
) {
303 Record
*AliasDef
= (*AI
)->getValueAsDef("AliasRW");
304 getSchedRW(AliasDef
).IsAlias
= true;
305 Record
*MatchDef
= (*AI
)->getValueAsDef("MatchRW");
306 CodeGenSchedRW
&RW
= getSchedRW(MatchDef
);
308 PrintFatalError((*AI
)->getLoc(), "Cannot Alias an Alias");
309 RW
.Aliases
.push_back(*AI
);
312 for (unsigned WIdx
= 0, WEnd
= SchedWrites
.size(); WIdx
!= WEnd
; ++WIdx
) {
313 dbgs() << WIdx
<< ": ";
314 SchedWrites
[WIdx
].dump();
317 for (unsigned RIdx
= 0, REnd
= SchedReads
.size(); RIdx
!= REnd
; ++RIdx
) {
318 dbgs() << RIdx
<< ": ";
319 SchedReads
[RIdx
].dump();
322 RecVec RWDefs
= Records
.getAllDerivedDefinitions("SchedReadWrite");
323 for (RecIter RI
= RWDefs
.begin(), RE
= RWDefs
.end();
325 if (!getSchedRWIdx(*RI
, (*RI
)->isSubClassOf("SchedRead"))) {
326 const std::string
&Name
= (*RI
)->getName();
327 if (Name
!= "NoWrite" && Name
!= "ReadDefault")
328 dbgs() << "Unused SchedReadWrite " << (*RI
)->getName() << '\n';
333 /// Compute a SchedWrite name from a sequence of writes.
334 std::string
CodeGenSchedModels::genRWName(const IdxVec
& Seq
, bool IsRead
) {
335 std::string
Name("(");
336 for (IdxIter I
= Seq
.begin(), E
= Seq
.end(); I
!= E
; ++I
) {
337 if (I
!= Seq
.begin())
339 Name
+= getSchedRW(*I
, IsRead
).Name
;
345 unsigned CodeGenSchedModels::getSchedRWIdx(Record
*Def
, bool IsRead
,
346 unsigned After
) const {
347 const std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
348 assert(After
< RWVec
.size() && "start position out of bounds");
349 for (std::vector
<CodeGenSchedRW
>::const_iterator I
= RWVec
.begin() + After
,
350 E
= RWVec
.end(); I
!= E
; ++I
) {
351 if (I
->TheDef
== Def
)
352 return I
- RWVec
.begin();
357 bool CodeGenSchedModels::hasReadOfWrite(Record
*WriteDef
) const {
358 for (unsigned i
= 0, e
= SchedReads
.size(); i
< e
; ++i
) {
359 Record
*ReadDef
= SchedReads
[i
].TheDef
;
360 if (!ReadDef
|| !ReadDef
->isSubClassOf("ProcReadAdvance"))
363 RecVec ValidWrites
= ReadDef
->getValueAsListOfDefs("ValidWrites");
364 if (std::find(ValidWrites
.begin(), ValidWrites
.end(), WriteDef
)
365 != ValidWrites
.end()) {
373 void splitSchedReadWrites(const RecVec
&RWDefs
,
374 RecVec
&WriteDefs
, RecVec
&ReadDefs
) {
375 for (RecIter RWI
= RWDefs
.begin(), RWE
= RWDefs
.end(); RWI
!= RWE
; ++RWI
) {
376 if ((*RWI
)->isSubClassOf("SchedWrite"))
377 WriteDefs
.push_back(*RWI
);
379 assert((*RWI
)->isSubClassOf("SchedRead") && "unknown SchedReadWrite");
380 ReadDefs
.push_back(*RWI
);
386 // Split the SchedReadWrites defs and call findRWs for each list.
387 void CodeGenSchedModels::findRWs(const RecVec
&RWDefs
,
388 IdxVec
&Writes
, IdxVec
&Reads
) const {
391 splitSchedReadWrites(RWDefs
, WriteDefs
, ReadDefs
);
392 findRWs(WriteDefs
, Writes
, false);
393 findRWs(ReadDefs
, Reads
, true);
396 // Call getSchedRWIdx for all elements in a sequence of SchedRW defs.
397 void CodeGenSchedModels::findRWs(const RecVec
&RWDefs
, IdxVec
&RWs
,
399 for (RecIter RI
= RWDefs
.begin(), RE
= RWDefs
.end(); RI
!= RE
; ++RI
) {
400 unsigned Idx
= getSchedRWIdx(*RI
, IsRead
);
401 assert(Idx
&& "failed to collect SchedReadWrite");
406 void CodeGenSchedModels::expandRWSequence(unsigned RWIdx
, IdxVec
&RWSeq
,
408 const CodeGenSchedRW
&SchedRW
= getSchedRW(RWIdx
, IsRead
);
409 if (!SchedRW
.IsSequence
) {
410 RWSeq
.push_back(RWIdx
);
414 SchedRW
.TheDef
? SchedRW
.TheDef
->getValueAsInt("Repeat") : 1;
415 for (int i
= 0; i
< Repeat
; ++i
) {
416 for (IdxIter I
= SchedRW
.Sequence
.begin(), E
= SchedRW
.Sequence
.end();
418 expandRWSequence(*I
, RWSeq
, IsRead
);
423 // Expand a SchedWrite as a sequence following any aliases that coincide with
424 // the given processor model.
425 void CodeGenSchedModels::expandRWSeqForProc(
426 unsigned RWIdx
, IdxVec
&RWSeq
, bool IsRead
,
427 const CodeGenProcModel
&ProcModel
) const {
429 const CodeGenSchedRW
&SchedWrite
= getSchedRW(RWIdx
, IsRead
);
430 Record
*AliasDef
= 0;
431 for (RecIter AI
= SchedWrite
.Aliases
.begin(), AE
= SchedWrite
.Aliases
.end();
433 const CodeGenSchedRW
&AliasRW
= getSchedRW((*AI
)->getValueAsDef("AliasRW"));
434 if ((*AI
)->getValueInit("SchedModel")->isComplete()) {
435 Record
*ModelDef
= (*AI
)->getValueAsDef("SchedModel");
436 if (&getProcModel(ModelDef
) != &ProcModel
)
440 PrintFatalError(AliasRW
.TheDef
->getLoc(), "Multiple aliases "
441 "defined for processor " + ProcModel
.ModelName
+
442 " Ensure only one SchedAlias exists per RW.");
443 AliasDef
= AliasRW
.TheDef
;
446 expandRWSeqForProc(getSchedRWIdx(AliasDef
, IsRead
),
447 RWSeq
, IsRead
,ProcModel
);
450 if (!SchedWrite
.IsSequence
) {
451 RWSeq
.push_back(RWIdx
);
455 SchedWrite
.TheDef
? SchedWrite
.TheDef
->getValueAsInt("Repeat") : 1;
456 for (int i
= 0; i
< Repeat
; ++i
) {
457 for (IdxIter I
= SchedWrite
.Sequence
.begin(), E
= SchedWrite
.Sequence
.end();
459 expandRWSeqForProc(*I
, RWSeq
, IsRead
, ProcModel
);
464 // Find the existing SchedWrite that models this sequence of writes.
465 unsigned CodeGenSchedModels::findRWForSequence(const IdxVec
&Seq
,
467 std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
469 for (std::vector
<CodeGenSchedRW
>::iterator I
= RWVec
.begin(), E
= RWVec
.end();
471 if (I
->Sequence
== Seq
)
472 return I
- RWVec
.begin();
474 // Index zero reserved for invalid RW.
478 /// Add this ReadWrite if it doesn't already exist.
479 unsigned CodeGenSchedModels::findOrInsertRW(ArrayRef
<unsigned> Seq
,
481 assert(!Seq
.empty() && "cannot insert empty sequence");
485 unsigned Idx
= findRWForSequence(Seq
, IsRead
);
489 unsigned RWIdx
= IsRead
? SchedReads
.size() : SchedWrites
.size();
490 CodeGenSchedRW
SchedRW(RWIdx
, IsRead
, Seq
, genRWName(Seq
, IsRead
));
492 SchedReads
.push_back(SchedRW
);
494 SchedWrites
.push_back(SchedRW
);
498 /// Visit all the instruction definitions for this target to gather and
499 /// enumerate the itinerary classes. These are the explicitly specified
500 /// SchedClasses. More SchedClasses may be inferred.
501 void CodeGenSchedModels::collectSchedClasses() {
503 // NoItinerary is always the first class at Idx=0
504 SchedClasses
.resize(1);
505 SchedClasses
.back().Index
= 0;
506 SchedClasses
.back().Name
= "NoInstrModel";
507 SchedClasses
.back().ItinClassDef
= Records
.getDef("NoItinerary");
508 SchedClasses
.back().ProcIndices
.push_back(0);
510 // Create a SchedClass for each unique combination of itinerary class and
512 for (CodeGenTarget::inst_iterator I
= Target
.inst_begin(),
513 E
= Target
.inst_end(); I
!= E
; ++I
) {
514 Record
*ItinDef
= (*I
)->TheDef
->getValueAsDef("Itinerary");
515 IdxVec Writes
, Reads
;
516 if (!(*I
)->TheDef
->isValueUnset("SchedRW"))
517 findRWs((*I
)->TheDef
->getValueAsListOfDefs("SchedRW"), Writes
, Reads
);
519 // ProcIdx == 0 indicates the class applies to all processors.
520 IdxVec
ProcIndices(1, 0);
522 unsigned SCIdx
= addSchedClass(ItinDef
, Writes
, Reads
, ProcIndices
);
523 InstrClassMap
[(*I
)->TheDef
] = SCIdx
;
525 // Create classes for InstRW defs.
526 RecVec InstRWDefs
= Records
.getAllDerivedDefinitions("InstRW");
527 std::sort(InstRWDefs
.begin(), InstRWDefs
.end(), LessRecord());
528 for (RecIter OI
= InstRWDefs
.begin(), OE
= InstRWDefs
.end(); OI
!= OE
; ++OI
)
529 createInstRWClass(*OI
);
531 NumInstrSchedClasses
= SchedClasses
.size();
533 bool EnableDump
= false;
534 DEBUG(EnableDump
= true);
538 for (CodeGenTarget::inst_iterator I
= Target
.inst_begin(),
539 E
= Target
.inst_end(); I
!= E
; ++I
) {
541 std::string InstName
= (*I
)->TheDef
->getName();
542 unsigned SCIdx
= InstrClassMap
.lookup((*I
)->TheDef
);
544 dbgs() << "No machine model for " << (*I
)->TheDef
->getName() << '\n';
547 CodeGenSchedClass
&SC
= getSchedClass(SCIdx
);
548 if (SC
.ProcIndices
[0] != 0)
549 PrintFatalError((*I
)->TheDef
->getLoc(), "Instruction's sched class "
550 "must not be subtarget specific.");
553 if (SC
.ItinClassDef
->getName() != "NoItinerary") {
554 ProcIndices
.push_back(0);
555 dbgs() << "Itinerary for " << InstName
<< ": "
556 << SC
.ItinClassDef
->getName() << '\n';
558 if (!SC
.Writes
.empty()) {
559 ProcIndices
.push_back(0);
560 dbgs() << "SchedRW machine model for " << InstName
;
561 for (IdxIter WI
= SC
.Writes
.begin(), WE
= SC
.Writes
.end(); WI
!= WE
; ++WI
)
562 dbgs() << " " << SchedWrites
[*WI
].Name
;
563 for (IdxIter RI
= SC
.Reads
.begin(), RE
= SC
.Reads
.end(); RI
!= RE
; ++RI
)
564 dbgs() << " " << SchedReads
[*RI
].Name
;
567 const RecVec
&RWDefs
= SchedClasses
[SCIdx
].InstRWs
;
568 for (RecIter RWI
= RWDefs
.begin(), RWE
= RWDefs
.end();
570 const CodeGenProcModel
&ProcModel
=
571 getProcModel((*RWI
)->getValueAsDef("SchedModel"));
572 ProcIndices
.push_back(ProcModel
.Index
);
573 dbgs() << "InstRW on " << ProcModel
.ModelName
<< " for " << InstName
;
576 findRWs((*RWI
)->getValueAsListOfDefs("OperandReadWrites"),
578 for (IdxIter WI
= Writes
.begin(), WE
= Writes
.end(); WI
!= WE
; ++WI
)
579 dbgs() << " " << SchedWrites
[*WI
].Name
;
580 for (IdxIter RI
= Reads
.begin(), RE
= Reads
.end(); RI
!= RE
; ++RI
)
581 dbgs() << " " << SchedReads
[*RI
].Name
;
584 for (std::vector
<CodeGenProcModel
>::iterator PI
= ProcModels
.begin(),
585 PE
= ProcModels
.end(); PI
!= PE
; ++PI
) {
586 if (!std::count(ProcIndices
.begin(), ProcIndices
.end(), PI
->Index
))
587 dbgs() << "No machine model for " << (*I
)->TheDef
->getName()
588 << " on processor " << PI
->ModelName
<< '\n';
593 /// Find an SchedClass that has been inferred from a per-operand list of
594 /// SchedWrites and SchedReads.
595 unsigned CodeGenSchedModels::findSchedClassIdx(Record
*ItinClassDef
,
596 const IdxVec
&Writes
,
597 const IdxVec
&Reads
) const {
598 for (SchedClassIter I
= schedClassBegin(), E
= schedClassEnd(); I
!= E
; ++I
) {
599 if (I
->ItinClassDef
== ItinClassDef
600 && I
->Writes
== Writes
&& I
->Reads
== Reads
) {
601 return I
- schedClassBegin();
607 // Get the SchedClass index for an instruction.
608 unsigned CodeGenSchedModels::getSchedClassIdx(
609 const CodeGenInstruction
&Inst
) const {
611 return InstrClassMap
.lookup(Inst
.TheDef
);
614 std::string
CodeGenSchedModels::createSchedClassName(
615 Record
*ItinClassDef
, const IdxVec
&OperWrites
, const IdxVec
&OperReads
) {
618 if (ItinClassDef
&& ItinClassDef
->getName() != "NoItinerary")
619 Name
= ItinClassDef
->getName();
620 for (IdxIter WI
= OperWrites
.begin(), WE
= OperWrites
.end(); WI
!= WE
; ++WI
) {
623 Name
+= SchedWrites
[*WI
].Name
;
625 for (IdxIter RI
= OperReads
.begin(), RE
= OperReads
.end(); RI
!= RE
; ++RI
) {
627 Name
+= SchedReads
[*RI
].Name
;
632 std::string
CodeGenSchedModels::createSchedClassName(const RecVec
&InstDefs
) {
635 for (RecIter I
= InstDefs
.begin(), E
= InstDefs
.end(); I
!= E
; ++I
) {
636 if (I
!= InstDefs
.begin())
638 Name
+= (*I
)->getName();
643 /// Add an inferred sched class from an itinerary class and per-operand list of
644 /// SchedWrites and SchedReads. ProcIndices contains the set of IDs of
645 /// processors that may utilize this class.
646 unsigned CodeGenSchedModels::addSchedClass(Record
*ItinClassDef
,
647 const IdxVec
&OperWrites
,
648 const IdxVec
&OperReads
,
649 const IdxVec
&ProcIndices
)
651 assert(!ProcIndices
.empty() && "expect at least one ProcIdx");
653 unsigned Idx
= findSchedClassIdx(ItinClassDef
, OperWrites
, OperReads
);
654 if (Idx
|| SchedClasses
[0].isKeyEqual(ItinClassDef
, OperWrites
, OperReads
)) {
656 std::set_union(SchedClasses
[Idx
].ProcIndices
.begin(),
657 SchedClasses
[Idx
].ProcIndices
.end(),
658 ProcIndices
.begin(), ProcIndices
.end(),
659 std::back_inserter(PI
));
660 SchedClasses
[Idx
].ProcIndices
.swap(PI
);
663 Idx
= SchedClasses
.size();
664 SchedClasses
.resize(Idx
+1);
665 CodeGenSchedClass
&SC
= SchedClasses
.back();
667 SC
.Name
= createSchedClassName(ItinClassDef
, OperWrites
, OperReads
);
668 SC
.ItinClassDef
= ItinClassDef
;
669 SC
.Writes
= OperWrites
;
670 SC
.Reads
= OperReads
;
671 SC
.ProcIndices
= ProcIndices
;
676 // Create classes for each set of opcodes that are in the same InstReadWrite
677 // definition across all processors.
678 void CodeGenSchedModels::createInstRWClass(Record
*InstRWDef
) {
679 // ClassInstrs will hold an entry for each subset of Instrs in InstRWDef that
680 // intersects with an existing class via a previous InstRWDef. Instrs that do
681 // not intersect with an existing class refer back to their former class as
682 // determined from ItinDef or SchedRW.
683 SmallVector
<std::pair
<unsigned, SmallVector
<Record
*, 8> >, 4> ClassInstrs
;
684 // Sort Instrs into sets.
685 const RecVec
*InstDefs
= Sets
.expand(InstRWDef
);
686 if (InstDefs
->empty())
687 PrintFatalError(InstRWDef
->getLoc(), "No matching instruction opcodes");
689 for (RecIter I
= InstDefs
->begin(), E
= InstDefs
->end(); I
!= E
; ++I
) {
690 InstClassMapTy::const_iterator Pos
= InstrClassMap
.find(*I
);
691 if (Pos
== InstrClassMap
.end())
692 PrintFatalError((*I
)->getLoc(), "No sched class for instruction.");
693 unsigned SCIdx
= Pos
->second
;
694 unsigned CIdx
= 0, CEnd
= ClassInstrs
.size();
695 for (; CIdx
!= CEnd
; ++CIdx
) {
696 if (ClassInstrs
[CIdx
].first
== SCIdx
)
700 ClassInstrs
.resize(CEnd
+ 1);
701 ClassInstrs
[CIdx
].first
= SCIdx
;
703 ClassInstrs
[CIdx
].second
.push_back(*I
);
705 // For each set of Instrs, create a new class if necessary, and map or remap
707 unsigned CIdx
= 0, CEnd
= ClassInstrs
.size();
708 for (; CIdx
!= CEnd
; ++CIdx
) {
709 unsigned OldSCIdx
= ClassInstrs
[CIdx
].first
;
710 ArrayRef
<Record
*> InstDefs
= ClassInstrs
[CIdx
].second
;
711 // If the all instrs in the current class are accounted for, then leave
712 // them mapped to their old class.
713 if (OldSCIdx
&& SchedClasses
[OldSCIdx
].InstRWs
.size() == InstDefs
.size()) {
714 assert(SchedClasses
[OldSCIdx
].ProcIndices
[0] == 0 &&
715 "expected a generic SchedClass");
718 unsigned SCIdx
= SchedClasses
.size();
719 SchedClasses
.resize(SCIdx
+1);
720 CodeGenSchedClass
&SC
= SchedClasses
.back();
722 SC
.Name
= createSchedClassName(InstDefs
);
723 // Preserve ItinDef and Writes/Reads for processors without an InstRW entry.
724 SC
.ItinClassDef
= SchedClasses
[OldSCIdx
].ItinClassDef
;
725 SC
.Writes
= SchedClasses
[OldSCIdx
].Writes
;
726 SC
.Reads
= SchedClasses
[OldSCIdx
].Reads
;
727 SC
.ProcIndices
.push_back(0);
728 // Map each Instr to this new class.
729 // Note that InstDefs may be a smaller list than InstRWDef's "Instrs".
730 Record
*RWModelDef
= InstRWDef
->getValueAsDef("SchedModel");
731 SmallSet
<unsigned, 4> RemappedClassIDs
;
732 for (ArrayRef
<Record
*>::const_iterator
733 II
= InstDefs
.begin(), IE
= InstDefs
.end(); II
!= IE
; ++II
) {
734 unsigned OldSCIdx
= InstrClassMap
[*II
];
735 if (OldSCIdx
&& RemappedClassIDs
.insert(OldSCIdx
)) {
736 for (RecIter RI
= SchedClasses
[OldSCIdx
].InstRWs
.begin(),
737 RE
= SchedClasses
[OldSCIdx
].InstRWs
.end(); RI
!= RE
; ++RI
) {
738 if ((*RI
)->getValueAsDef("SchedModel") == RWModelDef
) {
739 PrintFatalError(InstRWDef
->getLoc(), "Overlapping InstRW def " +
740 (*II
)->getName() + " also matches " +
741 (*RI
)->getValue("Instrs")->getValue()->getAsString());
743 assert(*RI
!= InstRWDef
&& "SchedClass has duplicate InstRW def");
744 SC
.InstRWs
.push_back(*RI
);
747 InstrClassMap
[*II
] = SCIdx
;
749 SC
.InstRWs
.push_back(InstRWDef
);
753 // True if collectProcItins found anything.
754 bool CodeGenSchedModels::hasItineraries() const {
755 for (CodeGenSchedModels::ProcIter PI
= procModelBegin(), PE
= procModelEnd();
757 if (PI
->hasItineraries())
763 // Gather the processor itineraries.
764 void CodeGenSchedModels::collectProcItins() {
765 for (std::vector
<CodeGenProcModel
>::iterator PI
= ProcModels
.begin(),
766 PE
= ProcModels
.end(); PI
!= PE
; ++PI
) {
767 CodeGenProcModel
&ProcModel
= *PI
;
768 if (!ProcModel
.hasItineraries())
771 RecVec ItinRecords
= ProcModel
.ItinsDef
->getValueAsListOfDefs("IID");
772 assert(!ItinRecords
.empty() && "ProcModel.hasItineraries is incorrect");
774 // Populate ItinDefList with Itinerary records.
775 ProcModel
.ItinDefList
.resize(NumInstrSchedClasses
);
777 // Insert each itinerary data record in the correct position within
778 // the processor model's ItinDefList.
779 for (unsigned i
= 0, N
= ItinRecords
.size(); i
< N
; i
++) {
780 Record
*ItinData
= ItinRecords
[i
];
781 Record
*ItinDef
= ItinData
->getValueAsDef("TheClass");
782 SchedClassIter SCI
= schedClassBegin(), SCE
= schedClassEnd();
783 for( ; SCI
!= SCE
; ++SCI
) {
784 if (SCI
->ItinClassDef
== ItinDef
) {
785 ProcModel
.ItinDefList
[SCI
->Index
] = ItinData
;
790 DEBUG(dbgs() << ProcModel
.ItinsDef
->getName()
791 << " missing class for itinerary " << ItinDef
->getName() << '\n');
794 // Check for missing itinerary entries.
795 assert(!ProcModel
.ItinDefList
[0] && "NoItinerary class can't have rec");
797 for (unsigned i
= 1, N
= ProcModel
.ItinDefList
.size(); i
< N
; ++i
) {
798 if (!ProcModel
.ItinDefList
[i
])
799 dbgs() << ProcModel
.ItinsDef
->getName()
800 << " missing itinerary for class "
801 << SchedClasses
[i
].Name
<< '\n';
806 // Gather the read/write types for each itinerary class.
807 void CodeGenSchedModels::collectProcItinRW() {
808 RecVec ItinRWDefs
= Records
.getAllDerivedDefinitions("ItinRW");
809 std::sort(ItinRWDefs
.begin(), ItinRWDefs
.end(), LessRecord());
810 for (RecIter II
= ItinRWDefs
.begin(), IE
= ItinRWDefs
.end(); II
!= IE
; ++II
) {
811 if (!(*II
)->getValueInit("SchedModel")->isComplete())
812 PrintFatalError((*II
)->getLoc(), "SchedModel is undefined");
813 Record
*ModelDef
= (*II
)->getValueAsDef("SchedModel");
814 ProcModelMapTy::const_iterator I
= ProcModelMap
.find(ModelDef
);
815 if (I
== ProcModelMap
.end()) {
816 PrintFatalError((*II
)->getLoc(), "Undefined SchedMachineModel "
817 + ModelDef
->getName());
819 ProcModels
[I
->second
].ItinRWDefs
.push_back(*II
);
823 /// Infer new classes from existing classes. In the process, this may create new
824 /// SchedWrites from sequences of existing SchedWrites.
825 void CodeGenSchedModels::inferSchedClasses() {
826 DEBUG(dbgs() << NumInstrSchedClasses
<< " instr sched classes.\n");
828 // Visit all existing classes and newly created classes.
829 for (unsigned Idx
= 0; Idx
!= SchedClasses
.size(); ++Idx
) {
830 assert(SchedClasses
[Idx
].Index
== Idx
&& "bad SCIdx");
832 if (SchedClasses
[Idx
].ItinClassDef
)
833 inferFromItinClass(SchedClasses
[Idx
].ItinClassDef
, Idx
);
834 if (!SchedClasses
[Idx
].InstRWs
.empty())
835 inferFromInstRWs(Idx
);
836 if (!SchedClasses
[Idx
].Writes
.empty()) {
837 inferFromRW(SchedClasses
[Idx
].Writes
, SchedClasses
[Idx
].Reads
,
838 Idx
, SchedClasses
[Idx
].ProcIndices
);
840 assert(SchedClasses
.size() < (NumInstrSchedClasses
*6) &&
841 "too many SchedVariants");
845 /// Infer classes from per-processor itinerary resources.
846 void CodeGenSchedModels::inferFromItinClass(Record
*ItinClassDef
,
847 unsigned FromClassIdx
) {
848 for (unsigned PIdx
= 0, PEnd
= ProcModels
.size(); PIdx
!= PEnd
; ++PIdx
) {
849 const CodeGenProcModel
&PM
= ProcModels
[PIdx
];
850 // For all ItinRW entries.
851 bool HasMatch
= false;
852 for (RecIter II
= PM
.ItinRWDefs
.begin(), IE
= PM
.ItinRWDefs
.end();
854 RecVec Matched
= (*II
)->getValueAsListOfDefs("MatchedItinClasses");
855 if (!std::count(Matched
.begin(), Matched
.end(), ItinClassDef
))
858 PrintFatalError((*II
)->getLoc(), "Duplicate itinerary class "
859 + ItinClassDef
->getName()
860 + " in ItinResources for " + PM
.ModelName
);
862 IdxVec Writes
, Reads
;
863 findRWs((*II
)->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
864 IdxVec
ProcIndices(1, PIdx
);
865 inferFromRW(Writes
, Reads
, FromClassIdx
, ProcIndices
);
870 /// Infer classes from per-processor InstReadWrite definitions.
871 void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx
) {
872 const RecVec
&RWDefs
= SchedClasses
[SCIdx
].InstRWs
;
873 for (RecIter RWI
= RWDefs
.begin(), RWE
= RWDefs
.end(); RWI
!= RWE
; ++RWI
) {
874 const RecVec
*InstDefs
= Sets
.expand(*RWI
);
875 RecIter II
= InstDefs
->begin(), IE
= InstDefs
->end();
876 for (; II
!= IE
; ++II
) {
877 if (InstrClassMap
[*II
] == SCIdx
)
880 // If this class no longer has any instructions mapped to it, it has become
884 IdxVec Writes
, Reads
;
885 findRWs((*RWI
)->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
886 unsigned PIdx
= getProcModel((*RWI
)->getValueAsDef("SchedModel")).Index
;
887 IdxVec
ProcIndices(1, PIdx
);
888 inferFromRW(Writes
, Reads
, SCIdx
, ProcIndices
);
893 // Helper for substituteVariantOperand.
894 struct TransVariant
{
895 Record
*VarOrSeqDef
; // Variant or sequence.
896 unsigned RWIdx
; // Index of this variant or sequence's matched type.
897 unsigned ProcIdx
; // Processor model index or zero for any.
898 unsigned TransVecIdx
; // Index into PredTransitions::TransVec.
900 TransVariant(Record
*def
, unsigned rwi
, unsigned pi
, unsigned ti
):
901 VarOrSeqDef(def
), RWIdx(rwi
), ProcIdx(pi
), TransVecIdx(ti
) {}
904 // Associate a predicate with the SchedReadWrite that it guards.
905 // RWIdx is the index of the read/write variant.
911 PredCheck(bool r
, unsigned w
, Record
*p
): IsRead(r
), RWIdx(w
), Predicate(p
) {}
914 // A Predicate transition is a list of RW sequences guarded by a PredTerm.
915 struct PredTransition
{
916 // A predicate term is a conjunction of PredChecks.
917 SmallVector
<PredCheck
, 4> PredTerm
;
918 SmallVector
<SmallVector
<unsigned,4>, 16> WriteSequences
;
919 SmallVector
<SmallVector
<unsigned,4>, 16> ReadSequences
;
920 SmallVector
<unsigned, 4> ProcIndices
;
923 // Encapsulate a set of partially constructed transitions.
924 // The results are built by repeated calls to substituteVariants.
925 class PredTransitions
{
926 CodeGenSchedModels
&SchedModels
;
929 std::vector
<PredTransition
> TransVec
;
931 PredTransitions(CodeGenSchedModels
&sm
): SchedModels(sm
) {}
933 void substituteVariantOperand(const SmallVectorImpl
<unsigned> &RWSeq
,
934 bool IsRead
, unsigned StartIdx
);
936 void substituteVariants(const PredTransition
&Trans
);
943 bool mutuallyExclusive(Record
*PredDef
, ArrayRef
<PredCheck
> Term
);
944 void getIntersectingVariants(
945 const CodeGenSchedRW
&SchedRW
, unsigned TransIdx
,
946 std::vector
<TransVariant
> &IntersectingVariants
);
947 void pushVariant(const TransVariant
&VInfo
, bool IsRead
);
951 // Return true if this predicate is mutually exclusive with a PredTerm. This
952 // degenerates into checking if the predicate is mutually exclusive with any
953 // predicate in the Term's conjunction.
955 // All predicates associated with a given SchedRW are considered mutually
956 // exclusive. This should work even if the conditions expressed by the
957 // predicates are not exclusive because the predicates for a given SchedWrite
958 // are always checked in the order they are defined in the .td file. Later
959 // conditions implicitly negate any prior condition.
960 bool PredTransitions::mutuallyExclusive(Record
*PredDef
,
961 ArrayRef
<PredCheck
> Term
) {
963 for (ArrayRef
<PredCheck
>::iterator I
= Term
.begin(), E
= Term
.end();
965 if (I
->Predicate
== PredDef
)
968 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(I
->RWIdx
, I
->IsRead
);
969 assert(SchedRW
.HasVariants
&& "PredCheck must refer to a SchedVariant");
970 RecVec Variants
= SchedRW
.TheDef
->getValueAsListOfDefs("Variants");
971 for (RecIter VI
= Variants
.begin(), VE
= Variants
.end(); VI
!= VE
; ++VI
) {
972 if ((*VI
)->getValueAsDef("Predicate") == PredDef
)
979 static bool hasAliasedVariants(const CodeGenSchedRW
&RW
,
980 CodeGenSchedModels
&SchedModels
) {
984 for (RecIter I
= RW
.Aliases
.begin(), E
= RW
.Aliases
.end(); I
!= E
; ++I
) {
985 const CodeGenSchedRW
&AliasRW
=
986 SchedModels
.getSchedRW((*I
)->getValueAsDef("AliasRW"));
987 if (AliasRW
.HasVariants
)
989 if (AliasRW
.IsSequence
) {
991 SchedModels
.expandRWSequence(AliasRW
.Index
, ExpandedRWs
, AliasRW
.IsRead
);
992 for (IdxIter SI
= ExpandedRWs
.begin(), SE
= ExpandedRWs
.end();
994 if (hasAliasedVariants(SchedModels
.getSchedRW(*SI
, AliasRW
.IsRead
),
1004 static bool hasVariant(ArrayRef
<PredTransition
> Transitions
,
1005 CodeGenSchedModels
&SchedModels
) {
1006 for (ArrayRef
<PredTransition
>::iterator
1007 PTI
= Transitions
.begin(), PTE
= Transitions
.end();
1008 PTI
!= PTE
; ++PTI
) {
1009 for (SmallVectorImpl
<SmallVector
<unsigned,4> >::const_iterator
1010 WSI
= PTI
->WriteSequences
.begin(), WSE
= PTI
->WriteSequences
.end();
1011 WSI
!= WSE
; ++WSI
) {
1012 for (SmallVectorImpl
<unsigned>::const_iterator
1013 WI
= WSI
->begin(), WE
= WSI
->end(); WI
!= WE
; ++WI
) {
1014 if (hasAliasedVariants(SchedModels
.getSchedWrite(*WI
), SchedModels
))
1018 for (SmallVectorImpl
<SmallVector
<unsigned,4> >::const_iterator
1019 RSI
= PTI
->ReadSequences
.begin(), RSE
= PTI
->ReadSequences
.end();
1020 RSI
!= RSE
; ++RSI
) {
1021 for (SmallVectorImpl
<unsigned>::const_iterator
1022 RI
= RSI
->begin(), RE
= RSI
->end(); RI
!= RE
; ++RI
) {
1023 if (hasAliasedVariants(SchedModels
.getSchedRead(*RI
), SchedModels
))
1031 // Populate IntersectingVariants with any variants or aliased sequences of the
1032 // given SchedRW whose processor indices and predicates are not mutually
1033 // exclusive with the given transition,
1034 void PredTransitions::getIntersectingVariants(
1035 const CodeGenSchedRW
&SchedRW
, unsigned TransIdx
,
1036 std::vector
<TransVariant
> &IntersectingVariants
) {
1038 std::vector
<TransVariant
> Variants
;
1039 if (SchedRW
.HasVariants
) {
1040 unsigned VarProcIdx
= 0;
1041 if (SchedRW
.TheDef
->getValueInit("SchedModel")->isComplete()) {
1042 Record
*ModelDef
= SchedRW
.TheDef
->getValueAsDef("SchedModel");
1043 VarProcIdx
= SchedModels
.getProcModel(ModelDef
).Index
;
1045 // Push each variant. Assign TransVecIdx later.
1046 const RecVec VarDefs
= SchedRW
.TheDef
->getValueAsListOfDefs("Variants");
1047 for (RecIter RI
= VarDefs
.begin(), RE
= VarDefs
.end(); RI
!= RE
; ++RI
)
1048 Variants
.push_back(TransVariant(*RI
, SchedRW
.Index
, VarProcIdx
, 0));
1050 for (RecIter AI
= SchedRW
.Aliases
.begin(), AE
= SchedRW
.Aliases
.end();
1052 // If either the SchedAlias itself or the SchedReadWrite that it aliases
1053 // to is defined within a processor model, constrain all variants to
1055 unsigned AliasProcIdx
= 0;
1056 if ((*AI
)->getValueInit("SchedModel")->isComplete()) {
1057 Record
*ModelDef
= (*AI
)->getValueAsDef("SchedModel");
1058 AliasProcIdx
= SchedModels
.getProcModel(ModelDef
).Index
;
1060 const CodeGenSchedRW
&AliasRW
=
1061 SchedModels
.getSchedRW((*AI
)->getValueAsDef("AliasRW"));
1063 if (AliasRW
.HasVariants
) {
1064 const RecVec VarDefs
= AliasRW
.TheDef
->getValueAsListOfDefs("Variants");
1065 for (RecIter RI
= VarDefs
.begin(), RE
= VarDefs
.end(); RI
!= RE
; ++RI
)
1066 Variants
.push_back(TransVariant(*RI
, AliasRW
.Index
, AliasProcIdx
, 0));
1068 if (AliasRW
.IsSequence
) {
1070 TransVariant(AliasRW
.TheDef
, SchedRW
.Index
, AliasProcIdx
, 0));
1073 for (unsigned VIdx
= 0, VEnd
= Variants
.size(); VIdx
!= VEnd
; ++VIdx
) {
1074 TransVariant
&Variant
= Variants
[VIdx
];
1075 // Don't expand variants if the processor models don't intersect.
1076 // A zero processor index means any processor.
1077 SmallVector
<unsigned, 4> &ProcIndices
= TransVec
[TransIdx
].ProcIndices
;
1078 if (ProcIndices
[0] && Variants
[VIdx
].ProcIdx
) {
1079 unsigned Cnt
= std::count(ProcIndices
.begin(), ProcIndices
.end(),
1084 const CodeGenProcModel
&PM
=
1085 *(SchedModels
.procModelBegin() + Variant
.ProcIdx
);
1086 PrintFatalError(Variant
.VarOrSeqDef
->getLoc(),
1087 "Multiple variants defined for processor " +
1089 " Ensure only one SchedAlias exists per RW.");
1092 if (Variant
.VarOrSeqDef
->isSubClassOf("SchedVar")) {
1093 Record
*PredDef
= Variant
.VarOrSeqDef
->getValueAsDef("Predicate");
1094 if (mutuallyExclusive(PredDef
, TransVec
[TransIdx
].PredTerm
))
1097 if (IntersectingVariants
.empty()) {
1098 // The first variant builds on the existing transition.
1099 Variant
.TransVecIdx
= TransIdx
;
1100 IntersectingVariants
.push_back(Variant
);
1103 // Push another copy of the current transition for more variants.
1104 Variant
.TransVecIdx
= TransVec
.size();
1105 IntersectingVariants
.push_back(Variant
);
1106 TransVec
.push_back(TransVec
[TransIdx
]);
1111 // Push the Reads/Writes selected by this variant onto the PredTransition
1112 // specified by VInfo.
1113 void PredTransitions::
1114 pushVariant(const TransVariant
&VInfo
, bool IsRead
) {
1116 PredTransition
&Trans
= TransVec
[VInfo
.TransVecIdx
];
1118 // If this operand transition is reached through a processor-specific alias,
1119 // then the whole transition is specific to this processor.
1120 if (VInfo
.ProcIdx
!= 0)
1121 Trans
.ProcIndices
.assign(1, VInfo
.ProcIdx
);
1124 if (VInfo
.VarOrSeqDef
->isSubClassOf("SchedVar")) {
1125 Record
*PredDef
= VInfo
.VarOrSeqDef
->getValueAsDef("Predicate");
1126 Trans
.PredTerm
.push_back(PredCheck(IsRead
, VInfo
.RWIdx
,PredDef
));
1127 RecVec SelectedDefs
= VInfo
.VarOrSeqDef
->getValueAsListOfDefs("Selected");
1128 SchedModels
.findRWs(SelectedDefs
, SelectedRWs
, IsRead
);
1131 assert(VInfo
.VarOrSeqDef
->isSubClassOf("WriteSequence") &&
1132 "variant must be a SchedVariant or aliased WriteSequence");
1133 SelectedRWs
.push_back(SchedModels
.getSchedRWIdx(VInfo
.VarOrSeqDef
, IsRead
));
1136 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(VInfo
.RWIdx
, IsRead
);
1138 SmallVectorImpl
<SmallVector
<unsigned,4> > &RWSequences
= IsRead
1139 ? Trans
.ReadSequences
: Trans
.WriteSequences
;
1140 if (SchedRW
.IsVariadic
) {
1141 unsigned OperIdx
= RWSequences
.size()-1;
1142 // Make N-1 copies of this transition's last sequence.
1143 for (unsigned i
= 1, e
= SelectedRWs
.size(); i
!= e
; ++i
) {
1144 RWSequences
.push_back(RWSequences
[OperIdx
]);
1146 // Push each of the N elements of the SelectedRWs onto a copy of the last
1147 // sequence (split the current operand into N operands).
1148 // Note that write sequences should be expanded within this loop--the entire
1149 // sequence belongs to a single operand.
1150 for (IdxIter RWI
= SelectedRWs
.begin(), RWE
= SelectedRWs
.end();
1151 RWI
!= RWE
; ++RWI
, ++OperIdx
) {
1154 ExpandedRWs
.push_back(*RWI
);
1156 SchedModels
.expandRWSequence(*RWI
, ExpandedRWs
, IsRead
);
1157 RWSequences
[OperIdx
].insert(RWSequences
[OperIdx
].end(),
1158 ExpandedRWs
.begin(), ExpandedRWs
.end());
1160 assert(OperIdx
== RWSequences
.size() && "missed a sequence");
1163 // Push this transition's expanded sequence onto this transition's last
1164 // sequence (add to the current operand's sequence).
1165 SmallVectorImpl
<unsigned> &Seq
= RWSequences
.back();
1167 for (IdxIter RWI
= SelectedRWs
.begin(), RWE
= SelectedRWs
.end();
1168 RWI
!= RWE
; ++RWI
) {
1170 ExpandedRWs
.push_back(*RWI
);
1172 SchedModels
.expandRWSequence(*RWI
, ExpandedRWs
, IsRead
);
1174 Seq
.insert(Seq
.end(), ExpandedRWs
.begin(), ExpandedRWs
.end());
1178 // RWSeq is a sequence of all Reads or all Writes for the next read or write
1179 // operand. StartIdx is an index into TransVec where partial results
1180 // starts. RWSeq must be applied to all transitions between StartIdx and the end
1182 void PredTransitions::substituteVariantOperand(
1183 const SmallVectorImpl
<unsigned> &RWSeq
, bool IsRead
, unsigned StartIdx
) {
1185 // Visit each original RW within the current sequence.
1186 for (SmallVectorImpl
<unsigned>::const_iterator
1187 RWI
= RWSeq
.begin(), RWE
= RWSeq
.end(); RWI
!= RWE
; ++RWI
) {
1188 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(*RWI
, IsRead
);
1189 // Push this RW on all partial PredTransitions or distribute variants.
1190 // New PredTransitions may be pushed within this loop which should not be
1191 // revisited (TransEnd must be loop invariant).
1192 for (unsigned TransIdx
= StartIdx
, TransEnd
= TransVec
.size();
1193 TransIdx
!= TransEnd
; ++TransIdx
) {
1194 // In the common case, push RW onto the current operand's sequence.
1195 if (!hasAliasedVariants(SchedRW
, SchedModels
)) {
1197 TransVec
[TransIdx
].ReadSequences
.back().push_back(*RWI
);
1199 TransVec
[TransIdx
].WriteSequences
.back().push_back(*RWI
);
1202 // Distribute this partial PredTransition across intersecting variants.
1203 // This will push a copies of TransVec[TransIdx] on the back of TransVec.
1204 std::vector
<TransVariant
> IntersectingVariants
;
1205 getIntersectingVariants(SchedRW
, TransIdx
, IntersectingVariants
);
1206 if (IntersectingVariants
.empty())
1207 PrintFatalError(SchedRW
.TheDef
->getLoc(),
1208 "No variant of this type has "
1209 "a matching predicate on any processor");
1210 // Now expand each variant on top of its copy of the transition.
1211 for (std::vector
<TransVariant
>::const_iterator
1212 IVI
= IntersectingVariants
.begin(),
1213 IVE
= IntersectingVariants
.end();
1214 IVI
!= IVE
; ++IVI
) {
1215 pushVariant(*IVI
, IsRead
);
1221 // For each variant of a Read/Write in Trans, substitute the sequence of
1222 // Read/Writes guarded by the variant. This is exponential in the number of
1223 // variant Read/Writes, but in practice detection of mutually exclusive
1224 // predicates should result in linear growth in the total number variants.
1226 // This is one step in a breadth-first search of nested variants.
1227 void PredTransitions::substituteVariants(const PredTransition
&Trans
) {
1228 // Build up a set of partial results starting at the back of
1229 // PredTransitions. Remember the first new transition.
1230 unsigned StartIdx
= TransVec
.size();
1231 TransVec
.resize(TransVec
.size() + 1);
1232 TransVec
.back().PredTerm
= Trans
.PredTerm
;
1233 TransVec
.back().ProcIndices
= Trans
.ProcIndices
;
1235 // Visit each original write sequence.
1236 for (SmallVectorImpl
<SmallVector
<unsigned,4> >::const_iterator
1237 WSI
= Trans
.WriteSequences
.begin(), WSE
= Trans
.WriteSequences
.end();
1238 WSI
!= WSE
; ++WSI
) {
1239 // Push a new (empty) write sequence onto all partial Transitions.
1240 for (std::vector
<PredTransition
>::iterator I
=
1241 TransVec
.begin() + StartIdx
, E
= TransVec
.end(); I
!= E
; ++I
) {
1242 I
->WriteSequences
.resize(I
->WriteSequences
.size() + 1);
1244 substituteVariantOperand(*WSI
, /*IsRead=*/false, StartIdx
);
1246 // Visit each original read sequence.
1247 for (SmallVectorImpl
<SmallVector
<unsigned,4> >::const_iterator
1248 RSI
= Trans
.ReadSequences
.begin(), RSE
= Trans
.ReadSequences
.end();
1249 RSI
!= RSE
; ++RSI
) {
1250 // Push a new (empty) read sequence onto all partial Transitions.
1251 for (std::vector
<PredTransition
>::iterator I
=
1252 TransVec
.begin() + StartIdx
, E
= TransVec
.end(); I
!= E
; ++I
) {
1253 I
->ReadSequences
.resize(I
->ReadSequences
.size() + 1);
1255 substituteVariantOperand(*RSI
, /*IsRead=*/true, StartIdx
);
1259 // Create a new SchedClass for each variant found by inferFromRW. Pass
1260 static void inferFromTransitions(ArrayRef
<PredTransition
> LastTransitions
,
1261 unsigned FromClassIdx
,
1262 CodeGenSchedModels
&SchedModels
) {
1263 // For each PredTransition, create a new CodeGenSchedTransition, which usually
1264 // requires creating a new SchedClass.
1265 for (ArrayRef
<PredTransition
>::iterator
1266 I
= LastTransitions
.begin(), E
= LastTransitions
.end(); I
!= E
; ++I
) {
1267 IdxVec OperWritesVariant
;
1268 for (SmallVectorImpl
<SmallVector
<unsigned,4> >::const_iterator
1269 WSI
= I
->WriteSequences
.begin(), WSE
= I
->WriteSequences
.end();
1270 WSI
!= WSE
; ++WSI
) {
1271 // Create a new write representing the expanded sequence.
1272 OperWritesVariant
.push_back(
1273 SchedModels
.findOrInsertRW(*WSI
, /*IsRead=*/false));
1275 IdxVec OperReadsVariant
;
1276 for (SmallVectorImpl
<SmallVector
<unsigned,4> >::const_iterator
1277 RSI
= I
->ReadSequences
.begin(), RSE
= I
->ReadSequences
.end();
1278 RSI
!= RSE
; ++RSI
) {
1279 // Create a new read representing the expanded sequence.
1280 OperReadsVariant
.push_back(
1281 SchedModels
.findOrInsertRW(*RSI
, /*IsRead=*/true));
1283 IdxVec
ProcIndices(I
->ProcIndices
.begin(), I
->ProcIndices
.end());
1284 CodeGenSchedTransition SCTrans
;
1285 SCTrans
.ToClassIdx
=
1286 SchedModels
.addSchedClass(/*ItinClassDef=*/0, OperWritesVariant
,
1287 OperReadsVariant
, ProcIndices
);
1288 SCTrans
.ProcIndices
= ProcIndices
;
1289 // The final PredTerm is unique set of predicates guarding the transition.
1291 for (SmallVectorImpl
<PredCheck
>::const_iterator
1292 PI
= I
->PredTerm
.begin(), PE
= I
->PredTerm
.end(); PI
!= PE
; ++PI
) {
1293 Preds
.push_back(PI
->Predicate
);
1295 RecIter PredsEnd
= std::unique(Preds
.begin(), Preds
.end());
1296 Preds
.resize(PredsEnd
- Preds
.begin());
1297 SCTrans
.PredTerm
= Preds
;
1298 SchedModels
.getSchedClass(FromClassIdx
).Transitions
.push_back(SCTrans
);
1302 // Create new SchedClasses for the given ReadWrite list. If any of the
1303 // ReadWrites refers to a SchedVariant, create a new SchedClass for each variant
1304 // of the ReadWrite list, following Aliases if necessary.
1305 void CodeGenSchedModels::inferFromRW(const IdxVec
&OperWrites
,
1306 const IdxVec
&OperReads
,
1307 unsigned FromClassIdx
,
1308 const IdxVec
&ProcIndices
) {
1309 DEBUG(dbgs() << "INFER RW: ");
1311 // Create a seed transition with an empty PredTerm and the expanded sequences
1312 // of SchedWrites for the current SchedClass.
1313 std::vector
<PredTransition
> LastTransitions
;
1314 LastTransitions
.resize(1);
1315 LastTransitions
.back().ProcIndices
.append(ProcIndices
.begin(),
1318 for (IdxIter I
= OperWrites
.begin(), E
= OperWrites
.end(); I
!= E
; ++I
) {
1320 expandRWSequence(*I
, WriteSeq
, /*IsRead=*/false);
1321 unsigned Idx
= LastTransitions
[0].WriteSequences
.size();
1322 LastTransitions
[0].WriteSequences
.resize(Idx
+ 1);
1323 SmallVectorImpl
<unsigned> &Seq
= LastTransitions
[0].WriteSequences
[Idx
];
1324 for (IdxIter WI
= WriteSeq
.begin(), WE
= WriteSeq
.end(); WI
!= WE
; ++WI
)
1326 DEBUG(dbgs() << "("; dumpIdxVec(Seq
); dbgs() << ") ");
1328 DEBUG(dbgs() << " Reads: ");
1329 for (IdxIter I
= OperReads
.begin(), E
= OperReads
.end(); I
!= E
; ++I
) {
1331 expandRWSequence(*I
, ReadSeq
, /*IsRead=*/true);
1332 unsigned Idx
= LastTransitions
[0].ReadSequences
.size();
1333 LastTransitions
[0].ReadSequences
.resize(Idx
+ 1);
1334 SmallVectorImpl
<unsigned> &Seq
= LastTransitions
[0].ReadSequences
[Idx
];
1335 for (IdxIter RI
= ReadSeq
.begin(), RE
= ReadSeq
.end(); RI
!= RE
; ++RI
)
1337 DEBUG(dbgs() << "("; dumpIdxVec(Seq
); dbgs() << ") ");
1339 DEBUG(dbgs() << '\n');
1341 // Collect all PredTransitions for individual operands.
1342 // Iterate until no variant writes remain.
1343 while (hasVariant(LastTransitions
, *this)) {
1344 PredTransitions
Transitions(*this);
1345 for (std::vector
<PredTransition
>::const_iterator
1346 I
= LastTransitions
.begin(), E
= LastTransitions
.end();
1348 Transitions
.substituteVariants(*I
);
1350 DEBUG(Transitions
.dump());
1351 LastTransitions
.swap(Transitions
.TransVec
);
1353 // If the first transition has no variants, nothing to do.
1354 if (LastTransitions
[0].PredTerm
.empty())
1357 // WARNING: We are about to mutate the SchedClasses vector. Do not refer to
1358 // OperWrites, OperReads, or ProcIndices after calling inferFromTransitions.
1359 inferFromTransitions(LastTransitions
, FromClassIdx
, *this);
1362 // Collect and sort WriteRes, ReadAdvance, and ProcResources.
1363 void CodeGenSchedModels::collectProcResources() {
1364 // Add any subtarget-specific SchedReadWrites that are directly associated
1365 // with processor resources. Refer to the parent SchedClass's ProcIndices to
1366 // determine which processors they apply to.
1367 for (SchedClassIter SCI
= schedClassBegin(), SCE
= schedClassEnd();
1368 SCI
!= SCE
; ++SCI
) {
1369 if (SCI
->ItinClassDef
)
1370 collectItinProcResources(SCI
->ItinClassDef
);
1372 // This class may have a default ReadWrite list which can be overriden by
1373 // InstRW definitions.
1374 if (!SCI
->InstRWs
.empty()) {
1375 for (RecIter RWI
= SCI
->InstRWs
.begin(), RWE
= SCI
->InstRWs
.end();
1376 RWI
!= RWE
; ++RWI
) {
1377 Record
*RWModelDef
= (*RWI
)->getValueAsDef("SchedModel");
1378 IdxVec
ProcIndices(1, getProcModel(RWModelDef
).Index
);
1379 IdxVec Writes
, Reads
;
1380 findRWs((*RWI
)->getValueAsListOfDefs("OperandReadWrites"),
1382 collectRWResources(Writes
, Reads
, ProcIndices
);
1385 collectRWResources(SCI
->Writes
, SCI
->Reads
, SCI
->ProcIndices
);
1388 // Add resources separately defined by each subtarget.
1389 RecVec WRDefs
= Records
.getAllDerivedDefinitions("WriteRes");
1390 for (RecIter WRI
= WRDefs
.begin(), WRE
= WRDefs
.end(); WRI
!= WRE
; ++WRI
) {
1391 Record
*ModelDef
= (*WRI
)->getValueAsDef("SchedModel");
1392 addWriteRes(*WRI
, getProcModel(ModelDef
).Index
);
1394 RecVec RADefs
= Records
.getAllDerivedDefinitions("ReadAdvance");
1395 for (RecIter RAI
= RADefs
.begin(), RAE
= RADefs
.end(); RAI
!= RAE
; ++RAI
) {
1396 Record
*ModelDef
= (*RAI
)->getValueAsDef("SchedModel");
1397 addReadAdvance(*RAI
, getProcModel(ModelDef
).Index
);
1399 // Finalize each ProcModel by sorting the record arrays.
1400 for (unsigned PIdx
= 0, PEnd
= ProcModels
.size(); PIdx
!= PEnd
; ++PIdx
) {
1401 CodeGenProcModel
&PM
= ProcModels
[PIdx
];
1402 std::sort(PM
.WriteResDefs
.begin(), PM
.WriteResDefs
.end(),
1404 std::sort(PM
.ReadAdvanceDefs
.begin(), PM
.ReadAdvanceDefs
.end(),
1406 std::sort(PM
.ProcResourceDefs
.begin(), PM
.ProcResourceDefs
.end(),
1410 dbgs() << "WriteResDefs: ";
1411 for (RecIter RI
= PM
.WriteResDefs
.begin(),
1412 RE
= PM
.WriteResDefs
.end(); RI
!= RE
; ++RI
) {
1413 if ((*RI
)->isSubClassOf("WriteRes"))
1414 dbgs() << (*RI
)->getValueAsDef("WriteType")->getName() << " ";
1416 dbgs() << (*RI
)->getName() << " ";
1418 dbgs() << "\nReadAdvanceDefs: ";
1419 for (RecIter RI
= PM
.ReadAdvanceDefs
.begin(),
1420 RE
= PM
.ReadAdvanceDefs
.end(); RI
!= RE
; ++RI
) {
1421 if ((*RI
)->isSubClassOf("ReadAdvance"))
1422 dbgs() << (*RI
)->getValueAsDef("ReadType")->getName() << " ";
1424 dbgs() << (*RI
)->getName() << " ";
1426 dbgs() << "\nProcResourceDefs: ";
1427 for (RecIter RI
= PM
.ProcResourceDefs
.begin(),
1428 RE
= PM
.ProcResourceDefs
.end(); RI
!= RE
; ++RI
) {
1429 dbgs() << (*RI
)->getName() << " ";
1435 // Collect itinerary class resources for each processor.
1436 void CodeGenSchedModels::collectItinProcResources(Record
*ItinClassDef
) {
1437 for (unsigned PIdx
= 0, PEnd
= ProcModels
.size(); PIdx
!= PEnd
; ++PIdx
) {
1438 const CodeGenProcModel
&PM
= ProcModels
[PIdx
];
1439 // For all ItinRW entries.
1440 bool HasMatch
= false;
1441 for (RecIter II
= PM
.ItinRWDefs
.begin(), IE
= PM
.ItinRWDefs
.end();
1443 RecVec Matched
= (*II
)->getValueAsListOfDefs("MatchedItinClasses");
1444 if (!std::count(Matched
.begin(), Matched
.end(), ItinClassDef
))
1447 PrintFatalError((*II
)->getLoc(), "Duplicate itinerary class "
1448 + ItinClassDef
->getName()
1449 + " in ItinResources for " + PM
.ModelName
);
1451 IdxVec Writes
, Reads
;
1452 findRWs((*II
)->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1453 IdxVec
ProcIndices(1, PIdx
);
1454 collectRWResources(Writes
, Reads
, ProcIndices
);
1459 void CodeGenSchedModels::collectRWResources(unsigned RWIdx
, bool IsRead
,
1460 const IdxVec
&ProcIndices
) {
1461 const CodeGenSchedRW
&SchedRW
= getSchedRW(RWIdx
, IsRead
);
1462 if (SchedRW
.TheDef
) {
1463 if (!IsRead
&& SchedRW
.TheDef
->isSubClassOf("SchedWriteRes")) {
1464 for (IdxIter PI
= ProcIndices
.begin(), PE
= ProcIndices
.end();
1466 addWriteRes(SchedRW
.TheDef
, *PI
);
1469 else if (IsRead
&& SchedRW
.TheDef
->isSubClassOf("SchedReadAdvance")) {
1470 for (IdxIter PI
= ProcIndices
.begin(), PE
= ProcIndices
.end();
1472 addReadAdvance(SchedRW
.TheDef
, *PI
);
1476 for (RecIter AI
= SchedRW
.Aliases
.begin(), AE
= SchedRW
.Aliases
.end();
1478 IdxVec AliasProcIndices
;
1479 if ((*AI
)->getValueInit("SchedModel")->isComplete()) {
1480 AliasProcIndices
.push_back(
1481 getProcModel((*AI
)->getValueAsDef("SchedModel")).Index
);
1484 AliasProcIndices
= ProcIndices
;
1485 const CodeGenSchedRW
&AliasRW
= getSchedRW((*AI
)->getValueAsDef("AliasRW"));
1486 assert(AliasRW
.IsRead
== IsRead
&& "cannot alias reads to writes");
1489 expandRWSequence(AliasRW
.Index
, ExpandedRWs
, IsRead
);
1490 for (IdxIter SI
= ExpandedRWs
.begin(), SE
= ExpandedRWs
.end();
1492 collectRWResources(*SI
, IsRead
, AliasProcIndices
);
1497 // Collect resources for a set of read/write types and processor indices.
1498 void CodeGenSchedModels::collectRWResources(const IdxVec
&Writes
,
1499 const IdxVec
&Reads
,
1500 const IdxVec
&ProcIndices
) {
1502 for (IdxIter WI
= Writes
.begin(), WE
= Writes
.end(); WI
!= WE
; ++WI
)
1503 collectRWResources(*WI
, /*IsRead=*/false, ProcIndices
);
1505 for (IdxIter RI
= Reads
.begin(), RE
= Reads
.end(); RI
!= RE
; ++RI
)
1506 collectRWResources(*RI
, /*IsRead=*/true, ProcIndices
);
1510 // Find the processor's resource units for this kind of resource.
1511 Record
*CodeGenSchedModels::findProcResUnits(Record
*ProcResKind
,
1512 const CodeGenProcModel
&PM
) const {
1513 if (ProcResKind
->isSubClassOf("ProcResourceUnits"))
1516 Record
*ProcUnitDef
= 0;
1517 RecVec ProcResourceDefs
=
1518 Records
.getAllDerivedDefinitions("ProcResourceUnits");
1520 for (RecIter RI
= ProcResourceDefs
.begin(), RE
= ProcResourceDefs
.end();
1523 if ((*RI
)->getValueAsDef("Kind") == ProcResKind
1524 && (*RI
)->getValueAsDef("SchedModel") == PM
.ModelDef
) {
1526 PrintFatalError((*RI
)->getLoc(),
1527 "Multiple ProcessorResourceUnits associated with "
1528 + ProcResKind
->getName());
1533 RecVec ProcResGroups
= Records
.getAllDerivedDefinitions("ProcResGroup");
1534 for (RecIter RI
= ProcResGroups
.begin(), RE
= ProcResGroups
.end();
1537 if (*RI
== ProcResKind
1538 && (*RI
)->getValueAsDef("SchedModel") == PM
.ModelDef
) {
1540 PrintFatalError((*RI
)->getLoc(),
1541 "Multiple ProcessorResourceUnits associated with "
1542 + ProcResKind
->getName());
1548 PrintFatalError(ProcResKind
->getLoc(),
1549 "No ProcessorResources associated with "
1550 + ProcResKind
->getName());
1555 // Iteratively add a resource and its super resources.
1556 void CodeGenSchedModels::addProcResource(Record
*ProcResKind
,
1557 CodeGenProcModel
&PM
) {
1559 Record
*ProcResUnits
= findProcResUnits(ProcResKind
, PM
);
1561 // See if this ProcResource is already associated with this processor.
1562 RecIter I
= std::find(PM
.ProcResourceDefs
.begin(),
1563 PM
.ProcResourceDefs
.end(), ProcResUnits
);
1564 if (I
!= PM
.ProcResourceDefs
.end())
1567 PM
.ProcResourceDefs
.push_back(ProcResUnits
);
1568 if (ProcResUnits
->isSubClassOf("ProcResGroup"))
1571 if (!ProcResUnits
->getValueInit("Super")->isComplete())
1574 ProcResKind
= ProcResUnits
->getValueAsDef("Super");
1578 // Add resources for a SchedWrite to this processor if they don't exist.
1579 void CodeGenSchedModels::addWriteRes(Record
*ProcWriteResDef
, unsigned PIdx
) {
1580 assert(PIdx
&& "don't add resources to an invalid Processor model");
1582 RecVec
&WRDefs
= ProcModels
[PIdx
].WriteResDefs
;
1583 RecIter WRI
= std::find(WRDefs
.begin(), WRDefs
.end(), ProcWriteResDef
);
1584 if (WRI
!= WRDefs
.end())
1586 WRDefs
.push_back(ProcWriteResDef
);
1588 // Visit ProcResourceKinds referenced by the newly discovered WriteRes.
1589 RecVec ProcResDefs
= ProcWriteResDef
->getValueAsListOfDefs("ProcResources");
1590 for (RecIter WritePRI
= ProcResDefs
.begin(), WritePRE
= ProcResDefs
.end();
1591 WritePRI
!= WritePRE
; ++WritePRI
) {
1592 addProcResource(*WritePRI
, ProcModels
[PIdx
]);
1596 // Add resources for a ReadAdvance to this processor if they don't exist.
1597 void CodeGenSchedModels::addReadAdvance(Record
*ProcReadAdvanceDef
,
1599 RecVec
&RADefs
= ProcModels
[PIdx
].ReadAdvanceDefs
;
1600 RecIter I
= std::find(RADefs
.begin(), RADefs
.end(), ProcReadAdvanceDef
);
1601 if (I
!= RADefs
.end())
1603 RADefs
.push_back(ProcReadAdvanceDef
);
1606 unsigned CodeGenProcModel::getProcResourceIdx(Record
*PRDef
) const {
1607 RecIter PRPos
= std::find(ProcResourceDefs
.begin(), ProcResourceDefs
.end(),
1609 if (PRPos
== ProcResourceDefs
.end())
1610 PrintFatalError(PRDef
->getLoc(), "ProcResource def is not included in "
1611 "the ProcResources list for " + ModelName
);
1612 // Idx=0 is reserved for invalid.
1613 return 1 + (PRPos
- ProcResourceDefs
.begin());
1617 void CodeGenProcModel::dump() const {
1618 dbgs() << Index
<< ": " << ModelName
<< " "
1619 << (ModelDef
? ModelDef
->getName() : "inferred") << " "
1620 << (ItinsDef
? ItinsDef
->getName() : "no itinerary") << '\n';
1623 void CodeGenSchedRW::dump() const {
1624 dbgs() << Name
<< (IsVariadic
? " (V) " : " ");
1627 dumpIdxVec(Sequence
);
1632 void CodeGenSchedClass::dump(const CodeGenSchedModels
* SchedModels
) const {
1633 dbgs() << "SCHEDCLASS " << Index
<< ":" << Name
<< '\n'
1635 for (unsigned i
= 0, N
= Writes
.size(); i
< N
; ++i
) {
1636 SchedModels
->getSchedWrite(Writes
[i
]).dump();
1642 dbgs() << "\n Reads: ";
1643 for (unsigned i
= 0, N
= Reads
.size(); i
< N
; ++i
) {
1644 SchedModels
->getSchedRead(Reads
[i
]).dump();
1650 dbgs() << "\n ProcIdx: "; dumpIdxVec(ProcIndices
); dbgs() << '\n';
1653 void PredTransitions::dump() const {
1654 dbgs() << "Expanded Variants:\n";
1655 for (std::vector
<PredTransition
>::const_iterator
1656 TI
= TransVec
.begin(), TE
= TransVec
.end(); TI
!= TE
; ++TI
) {
1658 for (SmallVectorImpl
<PredCheck
>::const_iterator
1659 PCI
= TI
->PredTerm
.begin(), PCE
= TI
->PredTerm
.end();
1660 PCI
!= PCE
; ++PCI
) {
1661 if (PCI
!= TI
->PredTerm
.begin())
1663 dbgs() << SchedModels
.getSchedRW(PCI
->RWIdx
, PCI
->IsRead
).Name
1664 << ":" << PCI
->Predicate
->getName();
1666 dbgs() << "},\n => {";
1667 for (SmallVectorImpl
<SmallVector
<unsigned,4> >::const_iterator
1668 WSI
= TI
->WriteSequences
.begin(), WSE
= TI
->WriteSequences
.end();
1669 WSI
!= WSE
; ++WSI
) {
1671 for (SmallVectorImpl
<unsigned>::const_iterator
1672 WI
= WSI
->begin(), WE
= WSI
->end(); WI
!= WE
; ++WI
) {
1673 if (WI
!= WSI
->begin())
1675 dbgs() << SchedModels
.getSchedWrite(*WI
).Name
;