1 //===- CodeGenSchedule.cpp - Scheduling MachineModels ---------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines structures to encapsulate the machine model as described in
10 // the target description.
12 //===----------------------------------------------------------------------===//
14 #include "CodeGenSchedule.h"
15 #include "CodeGenInstruction.h"
16 #include "CodeGenTarget.h"
17 #include "llvm/ADT/MapVector.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SmallPtrSet.h"
20 #include "llvm/ADT/SmallSet.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/Regex.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include "llvm/TableGen/Error.h"
33 #define DEBUG_TYPE "subtarget-emitter"
36 static void dumpIdxVec(ArrayRef
<unsigned> V
) {
37 for (unsigned Idx
: V
)
38 dbgs() << Idx
<< ", ";
44 // (instrs a, b, ...) Evaluate and union all arguments. Identical to AddOp.
45 struct InstrsOp
: public SetTheory::Operator
{
46 void apply(SetTheory
&ST
, DagInit
*Expr
, SetTheory::RecSet
&Elts
,
47 ArrayRef
<SMLoc
> Loc
) override
{
48 ST
.evaluate(Expr
->arg_begin(), Expr
->arg_end(), Elts
, Loc
);
52 // (instregex "OpcPat",...) Find all instructions matching an opcode pattern.
53 struct InstRegexOp
: public SetTheory::Operator
{
54 const CodeGenTarget
&Target
;
55 InstRegexOp(const CodeGenTarget
&t
): Target(t
) {}
57 /// Remove any text inside of parentheses from S.
58 static std::string
removeParens(llvm::StringRef S
) {
61 // NB: We don't care about escaped parens here.
78 void apply(SetTheory
&ST
, DagInit
*Expr
, SetTheory::RecSet
&Elts
,
79 ArrayRef
<SMLoc
> Loc
) override
{
80 ArrayRef
<const CodeGenInstruction
*> Instructions
=
81 Target
.getInstructionsByEnumValue();
83 unsigned NumGeneric
= Target
.getNumFixedInstructions();
84 unsigned NumPseudos
= Target
.getNumPseudoInstructions();
85 auto Generics
= Instructions
.slice(0, NumGeneric
);
86 auto Pseudos
= Instructions
.slice(NumGeneric
, NumPseudos
);
87 auto NonPseudos
= Instructions
.slice(NumGeneric
+ NumPseudos
);
89 for (Init
*Arg
: Expr
->getArgs()) {
90 StringInit
*SI
= dyn_cast
<StringInit
>(Arg
);
92 PrintFatalError(Loc
, "instregex requires pattern string: " +
94 StringRef Original
= SI
->getValue();
96 // Extract a prefix that we can binary search on.
97 static const char RegexMetachars
[] = "()^$|*+?.[]\\{}";
98 auto FirstMeta
= Original
.find_first_of(RegexMetachars
);
100 // Look for top-level | or ?. We cannot optimize them to binary search.
101 if (removeParens(Original
).find_first_of("|?") != std::string::npos
)
104 Optional
<Regex
> Regexpr
= None
;
105 StringRef Prefix
= Original
.substr(0, FirstMeta
);
106 StringRef PatStr
= Original
.substr(FirstMeta
);
107 if (!PatStr
.empty()) {
108 // For the rest use a python-style prefix match.
109 std::string pat
= std::string(PatStr
);
112 pat
.insert(pat
.end(), ')');
114 Regexpr
= Regex(pat
);
119 // The generic opcodes are unsorted, handle them manually.
120 for (auto *Inst
: Generics
) {
121 StringRef InstName
= Inst
->TheDef
->getName();
122 if (InstName
.startswith(Prefix
) &&
123 (!Regexpr
|| Regexpr
->match(InstName
.substr(Prefix
.size())))) {
124 Elts
.insert(Inst
->TheDef
);
129 // Target instructions are split into two ranges: pseudo instructions
130 // first, than non-pseudos. Each range is in lexicographical order
131 // sorted by name. Find the sub-ranges that start with our prefix.
133 bool operator()(const CodeGenInstruction
*LHS
, StringRef RHS
) {
134 return LHS
->TheDef
->getName() < RHS
;
136 bool operator()(StringRef LHS
, const CodeGenInstruction
*RHS
) {
137 return LHS
< RHS
->TheDef
->getName() &&
138 !RHS
->TheDef
->getName().startswith(LHS
);
142 std::equal_range(Pseudos
.begin(), Pseudos
.end(), Prefix
, Comp());
143 auto Range2
= std::equal_range(NonPseudos
.begin(), NonPseudos
.end(),
146 // For these ranges we know that instruction names start with the prefix.
147 // Check if there's a regex that needs to be checked.
148 const auto HandleNonGeneric
= [&](const CodeGenInstruction
*Inst
) {
149 StringRef InstName
= Inst
->TheDef
->getName();
150 if (!Regexpr
|| Regexpr
->match(InstName
.substr(Prefix
.size()))) {
151 Elts
.insert(Inst
->TheDef
);
155 std::for_each(Range1
.first
, Range1
.second
, HandleNonGeneric
);
156 std::for_each(Range2
.first
, Range2
.second
, HandleNonGeneric
);
159 PrintFatalError(Loc
, "instregex has no matches: " + Original
);
164 } // end anonymous namespace
166 /// CodeGenModels ctor interprets machine model records and populates maps.
167 CodeGenSchedModels::CodeGenSchedModels(RecordKeeper
&RK
,
168 const CodeGenTarget
&TGT
):
169 Records(RK
), Target(TGT
) {
171 Sets
.addFieldExpander("InstRW", "Instrs");
173 // Allow Set evaluation to recognize the dags used in InstRW records:
174 // (instrs Op1, Op1...)
175 Sets
.addOperator("instrs", std::make_unique
<InstrsOp
>());
176 Sets
.addOperator("instregex", std::make_unique
<InstRegexOp
>(Target
));
178 // Instantiate a CodeGenProcModel for each SchedMachineModel with the values
179 // that are explicitly referenced in tablegen records. Resources associated
180 // with each processor will be derived later. Populate ProcModelMap with the
181 // CodeGenProcModel instances.
184 // Instantiate a CodeGenSchedRW for each SchedReadWrite record explicitly
185 // defined, and populate SchedReads and SchedWrites vectors. Implicit
186 // SchedReadWrites that represent sequences derived from expanded variant will
187 // be inferred later.
190 // Instantiate a CodeGenSchedClass for each unique SchedRW signature directly
191 // required by an instruction definition, and populate SchedClassIdxMap. Set
192 // NumItineraryClasses to the number of explicit itinerary classes referenced
193 // by instructions. Set NumInstrSchedClasses to the number of itinerary
194 // classes plus any classes implied by instructions that derive from class
195 // Sched and provide SchedRW list. This does not infer any new classes from
197 collectSchedClasses();
199 // Find instruction itineraries for each processor. Sort and populate
200 // CodeGenProcModel::ItinDefList. (Cycle-to-cycle itineraries). This requires
201 // all itinerary classes to be discovered.
204 // Find ItinRW records for each processor and itinerary class.
205 // (For per-operand resources mapped to itinerary classes).
208 // Find UnsupportedFeatures records for each processor.
209 // (For per-operand resources mapped to itinerary classes).
210 collectProcUnsupportedFeatures();
212 // Infer new SchedClasses from SchedVariant.
215 // Populate each CodeGenProcModel's WriteResDefs, ReadAdvanceDefs, and
218 dbgs() << "\n+++ RESOURCE DEFINITIONS (collectProcResources) +++\n");
219 collectProcResources();
221 // Collect optional processor description.
222 collectOptionalProcessorInfo();
224 // Check MCInstPredicate definitions.
225 checkMCInstPredicates();
227 // Check STIPredicate definitions.
228 checkSTIPredicates();
230 // Find STIPredicate definitions for each processor model, and construct
231 // STIPredicateFunction objects.
232 collectSTIPredicates();
237 void CodeGenSchedModels::checkSTIPredicates() const {
238 DenseMap
<StringRef
, const Record
*> Declarations
;
240 // There cannot be multiple declarations with the same name.
241 const RecVec Decls
= Records
.getAllDerivedDefinitions("STIPredicateDecl");
242 for (const Record
*R
: Decls
) {
243 StringRef Name
= R
->getValueAsString("Name");
244 const auto It
= Declarations
.find(Name
);
245 if (It
== Declarations
.end()) {
246 Declarations
[Name
] = R
;
250 PrintError(R
->getLoc(), "STIPredicate " + Name
+ " multiply declared.");
251 PrintFatalNote(It
->second
->getLoc(), "Previous declaration was here.");
254 // Disallow InstructionEquivalenceClasses with an empty instruction list.
256 Records
.getAllDerivedDefinitions("InstructionEquivalenceClass");
257 for (const Record
*R
: Defs
) {
258 RecVec Opcodes
= R
->getValueAsListOfDefs("Opcodes");
259 if (Opcodes
.empty()) {
260 PrintFatalError(R
->getLoc(), "Invalid InstructionEquivalenceClass "
261 "defined with an empty opcode list.");
266 // Used by function `processSTIPredicate` to construct a mask of machine
267 // instruction operands.
268 static APInt
constructOperandMask(ArrayRef
<int64_t> Indices
) {
273 int64_t MaxIndex
= *std::max_element(Indices
.begin(), Indices
.end());
274 assert(MaxIndex
>= 0 && "Invalid negative indices in input!");
275 OperandMask
= OperandMask
.zext(MaxIndex
+ 1);
276 for (const int64_t Index
: Indices
) {
277 assert(Index
>= 0 && "Invalid negative indices!");
278 OperandMask
.setBit(Index
);
285 processSTIPredicate(STIPredicateFunction
&Fn
,
286 const ProcModelMapTy
&ProcModelMap
) {
287 DenseMap
<const Record
*, unsigned> Opcode2Index
;
288 using OpcodeMapPair
= std::pair
<const Record
*, OpcodeInfo
>;
289 std::vector
<OpcodeMapPair
> OpcodeMappings
;
290 std::vector
<std::pair
<APInt
, APInt
>> OpcodeMasks
;
292 DenseMap
<const Record
*, unsigned> Predicate2Index
;
293 unsigned NumUniquePredicates
= 0;
295 // Number unique predicates and opcodes used by InstructionEquivalenceClass
296 // definitions. Each unique opcode will be associated with an OpcodeInfo
298 for (const Record
*Def
: Fn
.getDefinitions()) {
299 RecVec Classes
= Def
->getValueAsListOfDefs("Classes");
300 for (const Record
*EC
: Classes
) {
301 const Record
*Pred
= EC
->getValueAsDef("Predicate");
302 if (Predicate2Index
.find(Pred
) == Predicate2Index
.end())
303 Predicate2Index
[Pred
] = NumUniquePredicates
++;
305 RecVec Opcodes
= EC
->getValueAsListOfDefs("Opcodes");
306 for (const Record
*Opcode
: Opcodes
) {
307 if (Opcode2Index
.find(Opcode
) == Opcode2Index
.end()) {
308 Opcode2Index
[Opcode
] = OpcodeMappings
.size();
309 OpcodeMappings
.emplace_back(Opcode
, OpcodeInfo());
315 // Initialize vector `OpcodeMasks` with default values. We want to keep track
316 // of which processors "use" which opcodes. We also want to be able to
317 // identify predicates that are used by different processors for a same
319 // This information is used later on by this algorithm to sort OpcodeMapping
320 // elements based on their processor and predicate sets.
321 OpcodeMasks
.resize(OpcodeMappings
.size());
322 APInt
DefaultProcMask(ProcModelMap
.size(), 0);
323 APInt
DefaultPredMask(NumUniquePredicates
, 0);
324 for (std::pair
<APInt
, APInt
> &MaskPair
: OpcodeMasks
)
325 MaskPair
= std::make_pair(DefaultProcMask
, DefaultPredMask
);
327 // Construct a OpcodeInfo object for every unique opcode declared by an
328 // InstructionEquivalenceClass definition.
329 for (const Record
*Def
: Fn
.getDefinitions()) {
330 RecVec Classes
= Def
->getValueAsListOfDefs("Classes");
331 const Record
*SchedModel
= Def
->getValueAsDef("SchedModel");
332 unsigned ProcIndex
= ProcModelMap
.find(SchedModel
)->second
;
333 APInt
ProcMask(ProcModelMap
.size(), 0);
334 ProcMask
.setBit(ProcIndex
);
336 for (const Record
*EC
: Classes
) {
337 RecVec Opcodes
= EC
->getValueAsListOfDefs("Opcodes");
339 std::vector
<int64_t> OpIndices
=
340 EC
->getValueAsListOfInts("OperandIndices");
341 APInt OperandMask
= constructOperandMask(OpIndices
);
343 const Record
*Pred
= EC
->getValueAsDef("Predicate");
344 APInt
PredMask(NumUniquePredicates
, 0);
345 PredMask
.setBit(Predicate2Index
[Pred
]);
347 for (const Record
*Opcode
: Opcodes
) {
348 unsigned OpcodeIdx
= Opcode2Index
[Opcode
];
349 if (OpcodeMasks
[OpcodeIdx
].first
[ProcIndex
]) {
350 std::string Message
=
351 "Opcode " + Opcode
->getName().str() +
352 " used by multiple InstructionEquivalenceClass definitions.";
353 PrintFatalError(EC
->getLoc(), Message
);
355 OpcodeMasks
[OpcodeIdx
].first
|= ProcMask
;
356 OpcodeMasks
[OpcodeIdx
].second
|= PredMask
;
357 OpcodeInfo
&OI
= OpcodeMappings
[OpcodeIdx
].second
;
359 OI
.addPredicateForProcModel(ProcMask
, OperandMask
, Pred
);
364 // Sort OpcodeMappings elements based on their CPU and predicate masks.
365 // As a last resort, order elements by opcode identifier.
366 llvm::sort(OpcodeMappings
,
367 [&](const OpcodeMapPair
&Lhs
, const OpcodeMapPair
&Rhs
) {
368 unsigned LhsIdx
= Opcode2Index
[Lhs
.first
];
369 unsigned RhsIdx
= Opcode2Index
[Rhs
.first
];
370 const std::pair
<APInt
, APInt
> &LhsMasks
= OpcodeMasks
[LhsIdx
];
371 const std::pair
<APInt
, APInt
> &RhsMasks
= OpcodeMasks
[RhsIdx
];
373 auto LessThan
= [](const APInt
&Lhs
, const APInt
&Rhs
) {
374 unsigned LhsCountPopulation
= Lhs
.countPopulation();
375 unsigned RhsCountPopulation
= Rhs
.countPopulation();
376 return ((LhsCountPopulation
< RhsCountPopulation
) ||
377 ((LhsCountPopulation
== RhsCountPopulation
) &&
378 (Lhs
.countLeadingZeros() > Rhs
.countLeadingZeros())));
381 if (LhsMasks
.first
!= RhsMasks
.first
)
382 return LessThan(LhsMasks
.first
, RhsMasks
.first
);
384 if (LhsMasks
.second
!= RhsMasks
.second
)
385 return LessThan(LhsMasks
.second
, RhsMasks
.second
);
387 return LhsIdx
< RhsIdx
;
390 // Now construct opcode groups. Groups are used by the SubtargetEmitter when
391 // expanding the body of a STIPredicate function. In particular, each opcode
392 // group is expanded into a sequence of labels in a switch statement.
393 // It identifies opcodes for which different processors define same predicates
394 // and same opcode masks.
395 for (OpcodeMapPair
&Info
: OpcodeMappings
)
396 Fn
.addOpcode(Info
.first
, std::move(Info
.second
));
399 void CodeGenSchedModels::collectSTIPredicates() {
400 // Map STIPredicateDecl records to elements of vector
401 // CodeGenSchedModels::STIPredicates.
402 DenseMap
<const Record
*, unsigned> Decl2Index
;
404 RecVec RV
= Records
.getAllDerivedDefinitions("STIPredicate");
405 for (const Record
*R
: RV
) {
406 const Record
*Decl
= R
->getValueAsDef("Declaration");
408 const auto It
= Decl2Index
.find(Decl
);
409 if (It
== Decl2Index
.end()) {
410 Decl2Index
[Decl
] = STIPredicates
.size();
411 STIPredicateFunction
Predicate(Decl
);
412 Predicate
.addDefinition(R
);
413 STIPredicates
.emplace_back(std::move(Predicate
));
417 STIPredicateFunction
&PreviousDef
= STIPredicates
[It
->second
];
418 PreviousDef
.addDefinition(R
);
421 for (STIPredicateFunction
&Fn
: STIPredicates
)
422 processSTIPredicate(Fn
, ProcModelMap
);
425 void OpcodeInfo::addPredicateForProcModel(const llvm::APInt
&CpuMask
,
426 const llvm::APInt
&OperandMask
,
427 const Record
*Predicate
) {
428 auto It
= llvm::find_if(
429 Predicates
, [&OperandMask
, &Predicate
](const PredicateInfo
&P
) {
430 return P
.Predicate
== Predicate
&& P
.OperandMask
== OperandMask
;
432 if (It
== Predicates
.end()) {
433 Predicates
.emplace_back(CpuMask
, OperandMask
, Predicate
);
436 It
->ProcModelMask
|= CpuMask
;
439 void CodeGenSchedModels::checkMCInstPredicates() const {
440 RecVec MCPredicates
= Records
.getAllDerivedDefinitions("TIIPredicate");
441 if (MCPredicates
.empty())
444 // A target cannot have multiple TIIPredicate definitions with a same name.
445 llvm::StringMap
<const Record
*> TIIPredicates(MCPredicates
.size());
446 for (const Record
*TIIPred
: MCPredicates
) {
447 StringRef Name
= TIIPred
->getValueAsString("FunctionName");
448 StringMap
<const Record
*>::const_iterator It
= TIIPredicates
.find(Name
);
449 if (It
== TIIPredicates
.end()) {
450 TIIPredicates
[Name
] = TIIPred
;
454 PrintError(TIIPred
->getLoc(),
455 "TIIPredicate " + Name
+ " is multiply defined.");
456 PrintFatalNote(It
->second
->getLoc(),
457 " Previous definition of " + Name
+ " was here.");
461 void CodeGenSchedModels::collectRetireControlUnits() {
462 RecVec Units
= Records
.getAllDerivedDefinitions("RetireControlUnit");
464 for (Record
*RCU
: Units
) {
465 CodeGenProcModel
&PM
= getProcModel(RCU
->getValueAsDef("SchedModel"));
466 if (PM
.RetireControlUnit
) {
467 PrintError(RCU
->getLoc(),
468 "Expected a single RetireControlUnit definition");
469 PrintNote(PM
.RetireControlUnit
->getLoc(),
470 "Previous definition of RetireControlUnit was here");
472 PM
.RetireControlUnit
= RCU
;
476 void CodeGenSchedModels::collectLoadStoreQueueInfo() {
477 RecVec Queues
= Records
.getAllDerivedDefinitions("MemoryQueue");
479 for (Record
*Queue
: Queues
) {
480 CodeGenProcModel
&PM
= getProcModel(Queue
->getValueAsDef("SchedModel"));
481 if (Queue
->isSubClassOf("LoadQueue")) {
483 PrintError(Queue
->getLoc(),
484 "Expected a single LoadQueue definition");
485 PrintNote(PM
.LoadQueue
->getLoc(),
486 "Previous definition of LoadQueue was here");
489 PM
.LoadQueue
= Queue
;
492 if (Queue
->isSubClassOf("StoreQueue")) {
494 PrintError(Queue
->getLoc(),
495 "Expected a single StoreQueue definition");
496 PrintNote(PM
.LoadQueue
->getLoc(),
497 "Previous definition of StoreQueue was here");
500 PM
.StoreQueue
= Queue
;
505 /// Collect optional processor information.
506 void CodeGenSchedModels::collectOptionalProcessorInfo() {
507 // Find register file definitions for each processor.
508 collectRegisterFiles();
510 // Collect processor RetireControlUnit descriptors if available.
511 collectRetireControlUnits();
513 // Collect information about load/store queues.
514 collectLoadStoreQueueInfo();
519 /// Gather all processor models.
520 void CodeGenSchedModels::collectProcModels() {
521 RecVec ProcRecords
= Records
.getAllDerivedDefinitions("Processor");
522 llvm::sort(ProcRecords
, LessRecordFieldName());
524 // Reserve space because we can. Reallocation would be ok.
525 ProcModels
.reserve(ProcRecords
.size()+1);
527 // Use idx=0 for NoModel/NoItineraries.
528 Record
*NoModelDef
= Records
.getDef("NoSchedModel");
529 Record
*NoItinsDef
= Records
.getDef("NoItineraries");
530 ProcModels
.emplace_back(0, "NoSchedModel", NoModelDef
, NoItinsDef
);
531 ProcModelMap
[NoModelDef
] = 0;
533 // For each processor, find a unique machine model.
534 LLVM_DEBUG(dbgs() << "+++ PROCESSOR MODELs (addProcModel) +++\n");
535 for (Record
*ProcRecord
: ProcRecords
)
536 addProcModel(ProcRecord
);
539 /// Get a unique processor model based on the defined MachineModel and
540 /// ProcessorItineraries.
541 void CodeGenSchedModels::addProcModel(Record
*ProcDef
) {
542 Record
*ModelKey
= getModelOrItinDef(ProcDef
);
543 if (!ProcModelMap
.insert(std::make_pair(ModelKey
, ProcModels
.size())).second
)
546 std::string Name
= std::string(ModelKey
->getName());
547 if (ModelKey
->isSubClassOf("SchedMachineModel")) {
548 Record
*ItinsDef
= ModelKey
->getValueAsDef("Itineraries");
549 ProcModels
.emplace_back(ProcModels
.size(), Name
, ModelKey
, ItinsDef
);
552 // An itinerary is defined without a machine model. Infer a new model.
553 if (!ModelKey
->getValueAsListOfDefs("IID").empty())
554 Name
= Name
+ "Model";
555 ProcModels
.emplace_back(ProcModels
.size(), Name
,
556 ProcDef
->getValueAsDef("SchedModel"), ModelKey
);
558 LLVM_DEBUG(ProcModels
.back().dump());
561 // Recursively find all reachable SchedReadWrite records.
562 static void scanSchedRW(Record
*RWDef
, RecVec
&RWDefs
,
563 SmallPtrSet
<Record
*, 16> &RWSet
) {
564 if (!RWSet
.insert(RWDef
).second
)
566 RWDefs
.push_back(RWDef
);
567 // Reads don't currently have sequence records, but it can be added later.
568 if (RWDef
->isSubClassOf("WriteSequence")) {
569 RecVec Seq
= RWDef
->getValueAsListOfDefs("Writes");
570 for (Record
*WSRec
: Seq
)
571 scanSchedRW(WSRec
, RWDefs
, RWSet
);
573 else if (RWDef
->isSubClassOf("SchedVariant")) {
574 // Visit each variant (guarded by a different predicate).
575 RecVec Vars
= RWDef
->getValueAsListOfDefs("Variants");
576 for (Record
*Variant
: Vars
) {
577 // Visit each RW in the sequence selected by the current variant.
578 RecVec Selected
= Variant
->getValueAsListOfDefs("Selected");
579 for (Record
*SelDef
: Selected
)
580 scanSchedRW(SelDef
, RWDefs
, RWSet
);
585 // Collect and sort all SchedReadWrites reachable via tablegen records.
586 // More may be inferred later when inferring new SchedClasses from variants.
587 void CodeGenSchedModels::collectSchedRW() {
588 // Reserve idx=0 for invalid writes/reads.
589 SchedWrites
.resize(1);
590 SchedReads
.resize(1);
592 SmallPtrSet
<Record
*, 16> RWSet
;
594 // Find all SchedReadWrites referenced by instruction defs.
595 RecVec SWDefs
, SRDefs
;
596 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
597 Record
*SchedDef
= Inst
->TheDef
;
598 if (SchedDef
->isValueUnset("SchedRW"))
600 RecVec RWs
= SchedDef
->getValueAsListOfDefs("SchedRW");
601 for (Record
*RW
: RWs
) {
602 if (RW
->isSubClassOf("SchedWrite"))
603 scanSchedRW(RW
, SWDefs
, RWSet
);
605 assert(RW
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
606 scanSchedRW(RW
, SRDefs
, RWSet
);
610 // Find all ReadWrites referenced by InstRW.
611 RecVec InstRWDefs
= Records
.getAllDerivedDefinitions("InstRW");
612 for (Record
*InstRWDef
: InstRWDefs
) {
613 // For all OperandReadWrites.
614 RecVec RWDefs
= InstRWDef
->getValueAsListOfDefs("OperandReadWrites");
615 for (Record
*RWDef
: RWDefs
) {
616 if (RWDef
->isSubClassOf("SchedWrite"))
617 scanSchedRW(RWDef
, SWDefs
, RWSet
);
619 assert(RWDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
620 scanSchedRW(RWDef
, SRDefs
, RWSet
);
624 // Find all ReadWrites referenced by ItinRW.
625 RecVec ItinRWDefs
= Records
.getAllDerivedDefinitions("ItinRW");
626 for (Record
*ItinRWDef
: ItinRWDefs
) {
627 // For all OperandReadWrites.
628 RecVec RWDefs
= ItinRWDef
->getValueAsListOfDefs("OperandReadWrites");
629 for (Record
*RWDef
: RWDefs
) {
630 if (RWDef
->isSubClassOf("SchedWrite"))
631 scanSchedRW(RWDef
, SWDefs
, RWSet
);
633 assert(RWDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
634 scanSchedRW(RWDef
, SRDefs
, RWSet
);
638 // Find all ReadWrites referenced by SchedAlias. AliasDefs needs to be sorted
639 // for the loop below that initializes Alias vectors.
640 RecVec AliasDefs
= Records
.getAllDerivedDefinitions("SchedAlias");
641 llvm::sort(AliasDefs
, LessRecord());
642 for (Record
*ADef
: AliasDefs
) {
643 Record
*MatchDef
= ADef
->getValueAsDef("MatchRW");
644 Record
*AliasDef
= ADef
->getValueAsDef("AliasRW");
645 if (MatchDef
->isSubClassOf("SchedWrite")) {
646 if (!AliasDef
->isSubClassOf("SchedWrite"))
647 PrintFatalError(ADef
->getLoc(), "SchedWrite Alias must be SchedWrite");
648 scanSchedRW(AliasDef
, SWDefs
, RWSet
);
651 assert(MatchDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
652 if (!AliasDef
->isSubClassOf("SchedRead"))
653 PrintFatalError(ADef
->getLoc(), "SchedRead Alias must be SchedRead");
654 scanSchedRW(AliasDef
, SRDefs
, RWSet
);
657 // Sort and add the SchedReadWrites directly referenced by instructions or
658 // itinerary resources. Index reads and writes in separate domains.
659 llvm::sort(SWDefs
, LessRecord());
660 for (Record
*SWDef
: SWDefs
) {
661 assert(!getSchedRWIdx(SWDef
, /*IsRead=*/false) && "duplicate SchedWrite");
662 SchedWrites
.emplace_back(SchedWrites
.size(), SWDef
);
664 llvm::sort(SRDefs
, LessRecord());
665 for (Record
*SRDef
: SRDefs
) {
666 assert(!getSchedRWIdx(SRDef
, /*IsRead-*/true) && "duplicate SchedWrite");
667 SchedReads
.emplace_back(SchedReads
.size(), SRDef
);
669 // Initialize WriteSequence vectors.
670 for (CodeGenSchedRW
&CGRW
: SchedWrites
) {
671 if (!CGRW
.IsSequence
)
673 findRWs(CGRW
.TheDef
->getValueAsListOfDefs("Writes"), CGRW
.Sequence
,
676 // Initialize Aliases vectors.
677 for (Record
*ADef
: AliasDefs
) {
678 Record
*AliasDef
= ADef
->getValueAsDef("AliasRW");
679 getSchedRW(AliasDef
).IsAlias
= true;
680 Record
*MatchDef
= ADef
->getValueAsDef("MatchRW");
681 CodeGenSchedRW
&RW
= getSchedRW(MatchDef
);
683 PrintFatalError(ADef
->getLoc(), "Cannot Alias an Alias");
684 RW
.Aliases
.push_back(ADef
);
687 dbgs() << "\n+++ SCHED READS and WRITES (collectSchedRW) +++\n";
688 for (unsigned WIdx
= 0, WEnd
= SchedWrites
.size(); WIdx
!= WEnd
; ++WIdx
) {
689 dbgs() << WIdx
<< ": ";
690 SchedWrites
[WIdx
].dump();
692 } for (unsigned RIdx
= 0, REnd
= SchedReads
.size(); RIdx
!= REnd
;
694 dbgs() << RIdx
<< ": ";
695 SchedReads
[RIdx
].dump();
697 } RecVec RWDefs
= Records
.getAllDerivedDefinitions("SchedReadWrite");
700 if (!getSchedRWIdx(RWDef
, RWDef
->isSubClassOf("SchedRead"))) {
701 StringRef Name
= RWDef
->getName();
702 if (Name
!= "NoWrite" && Name
!= "ReadDefault")
703 dbgs() << "Unused SchedReadWrite " << Name
<< '\n';
708 /// Compute a SchedWrite name from a sequence of writes.
709 std::string
CodeGenSchedModels::genRWName(ArrayRef
<unsigned> Seq
, bool IsRead
) {
710 std::string
Name("(");
711 ListSeparator
LS("_");
712 for (unsigned I
: Seq
) {
714 Name
+= getSchedRW(I
, IsRead
).Name
;
720 unsigned CodeGenSchedModels::getSchedRWIdx(const Record
*Def
,
722 const std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
723 const auto I
= find_if(
724 RWVec
, [Def
](const CodeGenSchedRW
&RW
) { return RW
.TheDef
== Def
; });
725 return I
== RWVec
.end() ? 0 : std::distance(RWVec
.begin(), I
);
728 bool CodeGenSchedModels::hasReadOfWrite(Record
*WriteDef
) const {
729 for (const CodeGenSchedRW
&Read
: SchedReads
) {
730 Record
*ReadDef
= Read
.TheDef
;
731 if (!ReadDef
|| !ReadDef
->isSubClassOf("ProcReadAdvance"))
734 RecVec ValidWrites
= ReadDef
->getValueAsListOfDefs("ValidWrites");
735 if (is_contained(ValidWrites
, WriteDef
)) {
742 static void splitSchedReadWrites(const RecVec
&RWDefs
,
743 RecVec
&WriteDefs
, RecVec
&ReadDefs
) {
744 for (Record
*RWDef
: RWDefs
) {
745 if (RWDef
->isSubClassOf("SchedWrite"))
746 WriteDefs
.push_back(RWDef
);
748 assert(RWDef
->isSubClassOf("SchedRead") && "unknown SchedReadWrite");
749 ReadDefs
.push_back(RWDef
);
754 // Split the SchedReadWrites defs and call findRWs for each list.
755 void CodeGenSchedModels::findRWs(const RecVec
&RWDefs
,
756 IdxVec
&Writes
, IdxVec
&Reads
) const {
759 splitSchedReadWrites(RWDefs
, WriteDefs
, ReadDefs
);
760 findRWs(WriteDefs
, Writes
, false);
761 findRWs(ReadDefs
, Reads
, true);
764 // Call getSchedRWIdx for all elements in a sequence of SchedRW defs.
765 void CodeGenSchedModels::findRWs(const RecVec
&RWDefs
, IdxVec
&RWs
,
767 for (Record
*RWDef
: RWDefs
) {
768 unsigned Idx
= getSchedRWIdx(RWDef
, IsRead
);
769 assert(Idx
&& "failed to collect SchedReadWrite");
774 void CodeGenSchedModels::expandRWSequence(unsigned RWIdx
, IdxVec
&RWSeq
,
776 const CodeGenSchedRW
&SchedRW
= getSchedRW(RWIdx
, IsRead
);
777 if (!SchedRW
.IsSequence
) {
778 RWSeq
.push_back(RWIdx
);
782 SchedRW
.TheDef
? SchedRW
.TheDef
->getValueAsInt("Repeat") : 1;
783 for (int i
= 0; i
< Repeat
; ++i
) {
784 for (unsigned I
: SchedRW
.Sequence
) {
785 expandRWSequence(I
, RWSeq
, IsRead
);
790 // Expand a SchedWrite as a sequence following any aliases that coincide with
791 // the given processor model.
792 void CodeGenSchedModels::expandRWSeqForProc(
793 unsigned RWIdx
, IdxVec
&RWSeq
, bool IsRead
,
794 const CodeGenProcModel
&ProcModel
) const {
796 const CodeGenSchedRW
&SchedWrite
= getSchedRW(RWIdx
, IsRead
);
797 Record
*AliasDef
= nullptr;
798 for (const Record
*Rec
: SchedWrite
.Aliases
) {
799 const CodeGenSchedRW
&AliasRW
= getSchedRW(Rec
->getValueAsDef("AliasRW"));
800 if (Rec
->getValueInit("SchedModel")->isComplete()) {
801 Record
*ModelDef
= Rec
->getValueAsDef("SchedModel");
802 if (&getProcModel(ModelDef
) != &ProcModel
)
806 PrintFatalError(AliasRW
.TheDef
->getLoc(), "Multiple aliases "
807 "defined for processor " + ProcModel
.ModelName
+
808 " Ensure only one SchedAlias exists per RW.");
809 AliasDef
= AliasRW
.TheDef
;
812 expandRWSeqForProc(getSchedRWIdx(AliasDef
, IsRead
),
813 RWSeq
, IsRead
,ProcModel
);
816 if (!SchedWrite
.IsSequence
) {
817 RWSeq
.push_back(RWIdx
);
821 SchedWrite
.TheDef
? SchedWrite
.TheDef
->getValueAsInt("Repeat") : 1;
822 for (int I
= 0, E
= Repeat
; I
< E
; ++I
) {
823 for (unsigned Idx
: SchedWrite
.Sequence
) {
824 expandRWSeqForProc(Idx
, RWSeq
, IsRead
, ProcModel
);
829 // Find the existing SchedWrite that models this sequence of writes.
830 unsigned CodeGenSchedModels::findRWForSequence(ArrayRef
<unsigned> Seq
,
832 std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
834 auto I
= find_if(RWVec
, [Seq
](CodeGenSchedRW
&RW
) {
835 return makeArrayRef(RW
.Sequence
) == Seq
;
837 // Index zero reserved for invalid RW.
838 return I
== RWVec
.end() ? 0 : std::distance(RWVec
.begin(), I
);
841 /// Add this ReadWrite if it doesn't already exist.
842 unsigned CodeGenSchedModels::findOrInsertRW(ArrayRef
<unsigned> Seq
,
844 assert(!Seq
.empty() && "cannot insert empty sequence");
848 unsigned Idx
= findRWForSequence(Seq
, IsRead
);
852 std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
853 unsigned RWIdx
= RWVec
.size();
854 CodeGenSchedRW
SchedRW(RWIdx
, IsRead
, Seq
, genRWName(Seq
, IsRead
));
855 RWVec
.push_back(SchedRW
);
859 /// Visit all the instruction definitions for this target to gather and
860 /// enumerate the itinerary classes. These are the explicitly specified
861 /// SchedClasses. More SchedClasses may be inferred.
862 void CodeGenSchedModels::collectSchedClasses() {
864 // NoItinerary is always the first class at Idx=0
865 assert(SchedClasses
.empty() && "Expected empty sched class");
866 SchedClasses
.emplace_back(0, "NoInstrModel",
867 Records
.getDef("NoItinerary"));
868 SchedClasses
.back().ProcIndices
.push_back(0);
870 // Create a SchedClass for each unique combination of itinerary class and
872 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
873 Record
*ItinDef
= Inst
->TheDef
->getValueAsDef("Itinerary");
874 IdxVec Writes
, Reads
;
875 if (!Inst
->TheDef
->isValueUnset("SchedRW"))
876 findRWs(Inst
->TheDef
->getValueAsListOfDefs("SchedRW"), Writes
, Reads
);
878 // ProcIdx == 0 indicates the class applies to all processors.
879 unsigned SCIdx
= addSchedClass(ItinDef
, Writes
, Reads
, /*ProcIndices*/{0});
880 InstrClassMap
[Inst
->TheDef
] = SCIdx
;
882 // Create classes for InstRW defs.
883 RecVec InstRWDefs
= Records
.getAllDerivedDefinitions("InstRW");
884 llvm::sort(InstRWDefs
, LessRecord());
885 LLVM_DEBUG(dbgs() << "\n+++ SCHED CLASSES (createInstRWClass) +++\n");
886 for (Record
*RWDef
: InstRWDefs
)
887 createInstRWClass(RWDef
);
889 NumInstrSchedClasses
= SchedClasses
.size();
891 bool EnableDump
= false;
892 LLVM_DEBUG(EnableDump
= true);
898 << "\n+++ ITINERARIES and/or MACHINE MODELS (collectSchedClasses) +++\n");
899 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
900 StringRef InstName
= Inst
->TheDef
->getName();
901 unsigned SCIdx
= getSchedClassIdx(*Inst
);
904 if (!Inst
->hasNoSchedulingInfo
)
905 dbgs() << "No machine model for " << Inst
->TheDef
->getName() << '\n';
909 CodeGenSchedClass
&SC
= getSchedClass(SCIdx
);
910 if (SC
.ProcIndices
[0] != 0)
911 PrintFatalError(Inst
->TheDef
->getLoc(), "Instruction's sched class "
912 "must not be subtarget specific.");
915 if (SC
.ItinClassDef
->getName() != "NoItinerary") {
916 ProcIndices
.push_back(0);
917 dbgs() << "Itinerary for " << InstName
<< ": "
918 << SC
.ItinClassDef
->getName() << '\n';
920 if (!SC
.Writes
.empty()) {
921 ProcIndices
.push_back(0);
923 dbgs() << "SchedRW machine model for " << InstName
;
924 for (unsigned int Write
: SC
.Writes
)
925 dbgs() << " " << SchedWrites
[Write
].Name
;
926 for (unsigned int Read
: SC
.Reads
)
927 dbgs() << " " << SchedReads
[Read
].Name
;
931 const RecVec
&RWDefs
= SchedClasses
[SCIdx
].InstRWs
;
932 for (Record
*RWDef
: RWDefs
) {
933 const CodeGenProcModel
&ProcModel
=
934 getProcModel(RWDef
->getValueAsDef("SchedModel"));
935 ProcIndices
.push_back(ProcModel
.Index
);
936 LLVM_DEBUG(dbgs() << "InstRW on " << ProcModel
.ModelName
<< " for "
940 findRWs(RWDef
->getValueAsListOfDefs("OperandReadWrites"),
943 for (unsigned WIdx
: Writes
)
944 dbgs() << " " << SchedWrites
[WIdx
].Name
;
945 for (unsigned RIdx
: Reads
)
946 dbgs() << " " << SchedReads
[RIdx
].Name
;
950 // If ProcIndices contains zero, the class applies to all processors.
952 if (!llvm::is_contained(ProcIndices
, 0)) {
953 for (const CodeGenProcModel
&PM
: ProcModels
) {
954 if (!llvm::is_contained(ProcIndices
, PM
.Index
))
955 dbgs() << "No machine model for " << Inst
->TheDef
->getName()
956 << " on processor " << PM
.ModelName
<< '\n';
963 // Get the SchedClass index for an instruction.
965 CodeGenSchedModels::getSchedClassIdx(const CodeGenInstruction
&Inst
) const {
966 return InstrClassMap
.lookup(Inst
.TheDef
);
970 CodeGenSchedModels::createSchedClassName(Record
*ItinClassDef
,
971 ArrayRef
<unsigned> OperWrites
,
972 ArrayRef
<unsigned> OperReads
) {
975 if (ItinClassDef
&& ItinClassDef
->getName() != "NoItinerary")
976 Name
= std::string(ItinClassDef
->getName());
977 for (unsigned Idx
: OperWrites
) {
980 Name
+= SchedWrites
[Idx
].Name
;
982 for (unsigned Idx
: OperReads
) {
984 Name
+= SchedReads
[Idx
].Name
;
989 std::string
CodeGenSchedModels::createSchedClassName(const RecVec
&InstDefs
) {
992 ListSeparator
LS("_");
993 for (const Record
*InstDef
: InstDefs
) {
995 Name
+= InstDef
->getName();
1000 /// Add an inferred sched class from an itinerary class and per-operand list of
1001 /// SchedWrites and SchedReads. ProcIndices contains the set of IDs of
1002 /// processors that may utilize this class.
1003 unsigned CodeGenSchedModels::addSchedClass(Record
*ItinClassDef
,
1004 ArrayRef
<unsigned> OperWrites
,
1005 ArrayRef
<unsigned> OperReads
,
1006 ArrayRef
<unsigned> ProcIndices
) {
1007 assert(!ProcIndices
.empty() && "expect at least one ProcIdx");
1009 auto IsKeyEqual
= [=](const CodeGenSchedClass
&SC
) {
1010 return SC
.isKeyEqual(ItinClassDef
, OperWrites
, OperReads
);
1013 auto I
= find_if(make_range(schedClassBegin(), schedClassEnd()), IsKeyEqual
);
1014 unsigned Idx
= I
== schedClassEnd() ? 0 : std::distance(schedClassBegin(), I
);
1015 if (Idx
|| SchedClasses
[0].isKeyEqual(ItinClassDef
, OperWrites
, OperReads
)) {
1017 std::set_union(SchedClasses
[Idx
].ProcIndices
.begin(),
1018 SchedClasses
[Idx
].ProcIndices
.end(),
1019 ProcIndices
.begin(), ProcIndices
.end(),
1020 std::back_inserter(PI
));
1021 SchedClasses
[Idx
].ProcIndices
= std::move(PI
);
1024 Idx
= SchedClasses
.size();
1025 SchedClasses
.emplace_back(Idx
,
1026 createSchedClassName(ItinClassDef
, OperWrites
,
1029 CodeGenSchedClass
&SC
= SchedClasses
.back();
1030 SC
.Writes
= OperWrites
;
1031 SC
.Reads
= OperReads
;
1032 SC
.ProcIndices
= ProcIndices
;
1037 // Create classes for each set of opcodes that are in the same InstReadWrite
1038 // definition across all processors.
1039 void CodeGenSchedModels::createInstRWClass(Record
*InstRWDef
) {
1040 // ClassInstrs will hold an entry for each subset of Instrs in InstRWDef that
1041 // intersects with an existing class via a previous InstRWDef. Instrs that do
1042 // not intersect with an existing class refer back to their former class as
1043 // determined from ItinDef or SchedRW.
1044 SmallMapVector
<unsigned, SmallVector
<Record
*, 8>, 4> ClassInstrs
;
1045 // Sort Instrs into sets.
1046 const RecVec
*InstDefs
= Sets
.expand(InstRWDef
);
1047 if (InstDefs
->empty())
1048 PrintFatalError(InstRWDef
->getLoc(), "No matching instruction opcodes");
1050 for (Record
*InstDef
: *InstDefs
) {
1051 InstClassMapTy::const_iterator Pos
= InstrClassMap
.find(InstDef
);
1052 if (Pos
== InstrClassMap
.end())
1053 PrintFatalError(InstDef
->getLoc(), "No sched class for instruction.");
1054 unsigned SCIdx
= Pos
->second
;
1055 ClassInstrs
[SCIdx
].push_back(InstDef
);
1057 // For each set of Instrs, create a new class if necessary, and map or remap
1058 // the Instrs to it.
1059 for (auto &Entry
: ClassInstrs
) {
1060 unsigned OldSCIdx
= Entry
.first
;
1061 ArrayRef
<Record
*> InstDefs
= Entry
.second
;
1062 // If the all instrs in the current class are accounted for, then leave
1063 // them mapped to their old class.
1065 const RecVec
&RWDefs
= SchedClasses
[OldSCIdx
].InstRWs
;
1066 if (!RWDefs
.empty()) {
1067 const RecVec
*OrigInstDefs
= Sets
.expand(RWDefs
[0]);
1068 unsigned OrigNumInstrs
=
1069 count_if(*OrigInstDefs
, [&](Record
*OIDef
) {
1070 return InstrClassMap
[OIDef
] == OldSCIdx
;
1072 if (OrigNumInstrs
== InstDefs
.size()) {
1073 assert(SchedClasses
[OldSCIdx
].ProcIndices
[0] == 0 &&
1074 "expected a generic SchedClass");
1075 Record
*RWModelDef
= InstRWDef
->getValueAsDef("SchedModel");
1076 // Make sure we didn't already have a InstRW containing this
1077 // instruction on this model.
1078 for (Record
*RWD
: RWDefs
) {
1079 if (RWD
->getValueAsDef("SchedModel") == RWModelDef
&&
1080 RWModelDef
->getValueAsBit("FullInstRWOverlapCheck")) {
1081 assert(!InstDefs
.empty()); // Checked at function start.
1083 InstRWDef
->getLoc(),
1084 "Overlapping InstRW definition for \"" +
1085 InstDefs
.front()->getName() +
1086 "\" also matches previous \"" +
1087 RWD
->getValue("Instrs")->getValue()->getAsString() +
1089 PrintFatalNote(RWD
->getLoc(), "Previous match was here.");
1092 LLVM_DEBUG(dbgs() << "InstRW: Reuse SC " << OldSCIdx
<< ":"
1093 << SchedClasses
[OldSCIdx
].Name
<< " on "
1094 << RWModelDef
->getName() << "\n");
1095 SchedClasses
[OldSCIdx
].InstRWs
.push_back(InstRWDef
);
1100 unsigned SCIdx
= SchedClasses
.size();
1101 SchedClasses
.emplace_back(SCIdx
, createSchedClassName(InstDefs
), nullptr);
1102 CodeGenSchedClass
&SC
= SchedClasses
.back();
1103 LLVM_DEBUG(dbgs() << "InstRW: New SC " << SCIdx
<< ":" << SC
.Name
<< " on "
1104 << InstRWDef
->getValueAsDef("SchedModel")->getName()
1107 // Preserve ItinDef and Writes/Reads for processors without an InstRW entry.
1108 SC
.ItinClassDef
= SchedClasses
[OldSCIdx
].ItinClassDef
;
1109 SC
.Writes
= SchedClasses
[OldSCIdx
].Writes
;
1110 SC
.Reads
= SchedClasses
[OldSCIdx
].Reads
;
1111 SC
.ProcIndices
.push_back(0);
1112 // If we had an old class, copy it's InstRWs to this new class.
1114 Record
*RWModelDef
= InstRWDef
->getValueAsDef("SchedModel");
1115 for (Record
*OldRWDef
: SchedClasses
[OldSCIdx
].InstRWs
) {
1116 if (OldRWDef
->getValueAsDef("SchedModel") == RWModelDef
) {
1117 assert(!InstDefs
.empty()); // Checked at function start.
1119 InstRWDef
->getLoc(),
1120 "Overlapping InstRW definition for \"" +
1121 InstDefs
.front()->getName() + "\" also matches previous \"" +
1122 OldRWDef
->getValue("Instrs")->getValue()->getAsString() +
1124 PrintFatalNote(OldRWDef
->getLoc(), "Previous match was here.");
1126 assert(OldRWDef
!= InstRWDef
&&
1127 "SchedClass has duplicate InstRW def");
1128 SC
.InstRWs
.push_back(OldRWDef
);
1131 // Map each Instr to this new class.
1132 for (Record
*InstDef
: InstDefs
)
1133 InstrClassMap
[InstDef
] = SCIdx
;
1134 SC
.InstRWs
.push_back(InstRWDef
);
1138 // True if collectProcItins found anything.
1139 bool CodeGenSchedModels::hasItineraries() const {
1140 for (const CodeGenProcModel
&PM
: make_range(procModelBegin(),procModelEnd()))
1141 if (PM
.hasItineraries())
1146 // Gather the processor itineraries.
1147 void CodeGenSchedModels::collectProcItins() {
1148 LLVM_DEBUG(dbgs() << "\n+++ PROBLEM ITINERARIES (collectProcItins) +++\n");
1149 for (CodeGenProcModel
&ProcModel
: ProcModels
) {
1150 if (!ProcModel
.hasItineraries())
1153 RecVec ItinRecords
= ProcModel
.ItinsDef
->getValueAsListOfDefs("IID");
1154 assert(!ItinRecords
.empty() && "ProcModel.hasItineraries is incorrect");
1156 // Populate ItinDefList with Itinerary records.
1157 ProcModel
.ItinDefList
.resize(NumInstrSchedClasses
);
1159 // Insert each itinerary data record in the correct position within
1160 // the processor model's ItinDefList.
1161 for (Record
*ItinData
: ItinRecords
) {
1162 const Record
*ItinDef
= ItinData
->getValueAsDef("TheClass");
1163 bool FoundClass
= false;
1165 for (const CodeGenSchedClass
&SC
:
1166 make_range(schedClassBegin(), schedClassEnd())) {
1167 // Multiple SchedClasses may share an itinerary. Update all of them.
1168 if (SC
.ItinClassDef
== ItinDef
) {
1169 ProcModel
.ItinDefList
[SC
.Index
] = ItinData
;
1174 LLVM_DEBUG(dbgs() << ProcModel
.ItinsDef
->getName()
1175 << " missing class for itinerary "
1176 << ItinDef
->getName() << '\n');
1179 // Check for missing itinerary entries.
1180 assert(!ProcModel
.ItinDefList
[0] && "NoItinerary class can't have rec");
1182 for (unsigned i
= 1, N
= ProcModel
.ItinDefList
.size(); i
< N
; ++i
) {
1183 if (!ProcModel
.ItinDefList
[i
])
1184 dbgs() << ProcModel
.ItinsDef
->getName()
1185 << " missing itinerary for class " << SchedClasses
[i
].Name
1191 // Gather the read/write types for each itinerary class.
1192 void CodeGenSchedModels::collectProcItinRW() {
1193 RecVec ItinRWDefs
= Records
.getAllDerivedDefinitions("ItinRW");
1194 llvm::sort(ItinRWDefs
, LessRecord());
1195 for (Record
*RWDef
: ItinRWDefs
) {
1196 if (!RWDef
->getValueInit("SchedModel")->isComplete())
1197 PrintFatalError(RWDef
->getLoc(), "SchedModel is undefined");
1198 Record
*ModelDef
= RWDef
->getValueAsDef("SchedModel");
1199 ProcModelMapTy::const_iterator I
= ProcModelMap
.find(ModelDef
);
1200 if (I
== ProcModelMap
.end()) {
1201 PrintFatalError(RWDef
->getLoc(), "Undefined SchedMachineModel "
1202 + ModelDef
->getName());
1204 ProcModels
[I
->second
].ItinRWDefs
.push_back(RWDef
);
1208 // Gather the unsupported features for processor models.
1209 void CodeGenSchedModels::collectProcUnsupportedFeatures() {
1210 for (CodeGenProcModel
&ProcModel
: ProcModels
)
1212 ProcModel
.UnsupportedFeaturesDefs
,
1213 ProcModel
.ModelDef
->getValueAsListOfDefs("UnsupportedFeatures"));
1216 /// Infer new classes from existing classes. In the process, this may create new
1217 /// SchedWrites from sequences of existing SchedWrites.
1218 void CodeGenSchedModels::inferSchedClasses() {
1220 dbgs() << "\n+++ INFERRING SCHED CLASSES (inferSchedClasses) +++\n");
1221 LLVM_DEBUG(dbgs() << NumInstrSchedClasses
<< " instr sched classes.\n");
1223 // Visit all existing classes and newly created classes.
1224 for (unsigned Idx
= 0; Idx
!= SchedClasses
.size(); ++Idx
) {
1225 assert(SchedClasses
[Idx
].Index
== Idx
&& "bad SCIdx");
1227 if (SchedClasses
[Idx
].ItinClassDef
)
1228 inferFromItinClass(SchedClasses
[Idx
].ItinClassDef
, Idx
);
1229 if (!SchedClasses
[Idx
].InstRWs
.empty())
1230 inferFromInstRWs(Idx
);
1231 if (!SchedClasses
[Idx
].Writes
.empty()) {
1232 inferFromRW(SchedClasses
[Idx
].Writes
, SchedClasses
[Idx
].Reads
,
1233 Idx
, SchedClasses
[Idx
].ProcIndices
);
1235 assert(SchedClasses
.size() < (NumInstrSchedClasses
*6) &&
1236 "too many SchedVariants");
1240 /// Infer classes from per-processor itinerary resources.
1241 void CodeGenSchedModels::inferFromItinClass(Record
*ItinClassDef
,
1242 unsigned FromClassIdx
) {
1243 for (unsigned PIdx
= 0, PEnd
= ProcModels
.size(); PIdx
!= PEnd
; ++PIdx
) {
1244 const CodeGenProcModel
&PM
= ProcModels
[PIdx
];
1245 // For all ItinRW entries.
1246 bool HasMatch
= false;
1247 for (const Record
*Rec
: PM
.ItinRWDefs
) {
1248 RecVec Matched
= Rec
->getValueAsListOfDefs("MatchedItinClasses");
1249 if (!llvm::is_contained(Matched
, ItinClassDef
))
1252 PrintFatalError(Rec
->getLoc(), "Duplicate itinerary class "
1253 + ItinClassDef
->getName()
1254 + " in ItinResources for " + PM
.ModelName
);
1256 IdxVec Writes
, Reads
;
1257 findRWs(Rec
->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1258 inferFromRW(Writes
, Reads
, FromClassIdx
, PIdx
);
1263 /// Infer classes from per-processor InstReadWrite definitions.
1264 void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx
) {
1265 for (unsigned I
= 0, E
= SchedClasses
[SCIdx
].InstRWs
.size(); I
!= E
; ++I
) {
1266 assert(SchedClasses
[SCIdx
].InstRWs
.size() == E
&& "InstrRWs was mutated!");
1267 Record
*Rec
= SchedClasses
[SCIdx
].InstRWs
[I
];
1268 const RecVec
*InstDefs
= Sets
.expand(Rec
);
1269 RecIter II
= InstDefs
->begin(), IE
= InstDefs
->end();
1270 for (; II
!= IE
; ++II
) {
1271 if (InstrClassMap
[*II
] == SCIdx
)
1274 // If this class no longer has any instructions mapped to it, it has become
1278 IdxVec Writes
, Reads
;
1279 findRWs(Rec
->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1280 unsigned PIdx
= getProcModel(Rec
->getValueAsDef("SchedModel")).Index
;
1281 inferFromRW(Writes
, Reads
, SCIdx
, PIdx
); // May mutate SchedClasses.
1282 SchedClasses
[SCIdx
].InstRWProcIndices
.insert(PIdx
);
1288 // Helper for substituteVariantOperand.
1289 struct TransVariant
{
1290 Record
*VarOrSeqDef
; // Variant or sequence.
1291 unsigned RWIdx
; // Index of this variant or sequence's matched type.
1292 unsigned ProcIdx
; // Processor model index or zero for any.
1293 unsigned TransVecIdx
; // Index into PredTransitions::TransVec.
1295 TransVariant(Record
*def
, unsigned rwi
, unsigned pi
, unsigned ti
):
1296 VarOrSeqDef(def
), RWIdx(rwi
), ProcIdx(pi
), TransVecIdx(ti
) {}
1299 // Associate a predicate with the SchedReadWrite that it guards.
1300 // RWIdx is the index of the read/write variant.
1306 PredCheck(bool r
, unsigned w
, Record
*p
): IsRead(r
), RWIdx(w
), Predicate(p
) {}
1309 // A Predicate transition is a list of RW sequences guarded by a PredTerm.
1310 struct PredTransition
{
1311 // A predicate term is a conjunction of PredChecks.
1312 SmallVector
<PredCheck
, 4> PredTerm
;
1313 SmallVector
<SmallVector
<unsigned,4>, 16> WriteSequences
;
1314 SmallVector
<SmallVector
<unsigned,4>, 16> ReadSequences
;
1315 unsigned ProcIndex
= 0;
1317 PredTransition() = default;
1318 PredTransition(ArrayRef
<PredCheck
> PT
, unsigned ProcId
) {
1319 PredTerm
.assign(PT
.begin(), PT
.end());
1324 // Encapsulate a set of partially constructed transitions.
1325 // The results are built by repeated calls to substituteVariants.
1326 class PredTransitions
{
1327 CodeGenSchedModels
&SchedModels
;
1330 std::vector
<PredTransition
> TransVec
;
1332 PredTransitions(CodeGenSchedModels
&sm
): SchedModels(sm
) {}
1334 bool substituteVariantOperand(const SmallVectorImpl
<unsigned> &RWSeq
,
1335 bool IsRead
, unsigned StartIdx
);
1337 bool substituteVariants(const PredTransition
&Trans
);
1344 bool mutuallyExclusive(Record
*PredDef
, ArrayRef
<Record
*> Preds
,
1345 ArrayRef
<PredCheck
> Term
);
1346 void getIntersectingVariants(
1347 const CodeGenSchedRW
&SchedRW
, unsigned TransIdx
,
1348 std::vector
<TransVariant
> &IntersectingVariants
);
1349 void pushVariant(const TransVariant
&VInfo
, bool IsRead
);
1352 } // end anonymous namespace
1354 // Return true if this predicate is mutually exclusive with a PredTerm. This
1355 // degenerates into checking if the predicate is mutually exclusive with any
1356 // predicate in the Term's conjunction.
1358 // All predicates associated with a given SchedRW are considered mutually
1359 // exclusive. This should work even if the conditions expressed by the
1360 // predicates are not exclusive because the predicates for a given SchedWrite
1361 // are always checked in the order they are defined in the .td file. Later
1362 // conditions implicitly negate any prior condition.
1363 bool PredTransitions::mutuallyExclusive(Record
*PredDef
,
1364 ArrayRef
<Record
*> Preds
,
1365 ArrayRef
<PredCheck
> Term
) {
1366 for (const PredCheck
&PC
: Term
) {
1367 if (PC
.Predicate
== PredDef
)
1370 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(PC
.RWIdx
, PC
.IsRead
);
1371 assert(SchedRW
.HasVariants
&& "PredCheck must refer to a SchedVariant");
1372 RecVec Variants
= SchedRW
.TheDef
->getValueAsListOfDefs("Variants");
1373 if (any_of(Variants
, [PredDef
](const Record
*R
) {
1374 return R
->getValueAsDef("Predicate") == PredDef
;
1376 // To check if PredDef is mutually exclusive with PC we also need to
1377 // check that PC.Predicate is exclusive with all predicates from variant
1378 // we're expanding. Consider following RW sequence with two variants
1379 // (1 & 2), where A, B and C are predicates from corresponding SchedVars:
1383 // Here C is not mutually exclusive with variant (1), because A doesn't
1384 // exist in variant (2). This means we have possible transitions from A
1385 // to C and from A to B, and fully expanded sequence would look like:
1387 // if (A & C) return ...;
1388 // if (A & B) return ...;
1389 // if (B) return ...;
1391 // Now let's consider another sequence:
1395 // Here A in variant (2) is mutually exclusive with variant (1), because
1396 // A also exists in (2). This means A->B transition is impossible and
1397 // expanded sequence would look like:
1399 // if (A) return ...;
1400 // if (B) return ...;
1401 if (!count(Preds
, PC
.Predicate
))
1409 static std::vector
<Record
*> getAllPredicates(ArrayRef
<TransVariant
> Variants
,
1411 std::vector
<Record
*> Preds
;
1412 for (auto &Variant
: Variants
) {
1413 if (!Variant
.VarOrSeqDef
->isSubClassOf("SchedVar"))
1415 Preds
.push_back(Variant
.VarOrSeqDef
->getValueAsDef("Predicate"));
1420 // Populate IntersectingVariants with any variants or aliased sequences of the
1421 // given SchedRW whose processor indices and predicates are not mutually
1422 // exclusive with the given transition.
1423 void PredTransitions::getIntersectingVariants(
1424 const CodeGenSchedRW
&SchedRW
, unsigned TransIdx
,
1425 std::vector
<TransVariant
> &IntersectingVariants
) {
1427 bool GenericRW
= false;
1429 std::vector
<TransVariant
> Variants
;
1430 if (SchedRW
.HasVariants
) {
1431 unsigned VarProcIdx
= 0;
1432 if (SchedRW
.TheDef
->getValueInit("SchedModel")->isComplete()) {
1433 Record
*ModelDef
= SchedRW
.TheDef
->getValueAsDef("SchedModel");
1434 VarProcIdx
= SchedModels
.getProcModel(ModelDef
).Index
;
1436 if (VarProcIdx
== 0 || VarProcIdx
== TransVec
[TransIdx
].ProcIndex
) {
1437 // Push each variant. Assign TransVecIdx later.
1438 const RecVec VarDefs
= SchedRW
.TheDef
->getValueAsListOfDefs("Variants");
1439 for (Record
*VarDef
: VarDefs
)
1440 Variants
.emplace_back(VarDef
, SchedRW
.Index
, VarProcIdx
, 0);
1441 if (VarProcIdx
== 0)
1445 for (RecIter AI
= SchedRW
.Aliases
.begin(), AE
= SchedRW
.Aliases
.end();
1447 // If either the SchedAlias itself or the SchedReadWrite that it aliases
1448 // to is defined within a processor model, constrain all variants to
1450 unsigned AliasProcIdx
= 0;
1451 if ((*AI
)->getValueInit("SchedModel")->isComplete()) {
1452 Record
*ModelDef
= (*AI
)->getValueAsDef("SchedModel");
1453 AliasProcIdx
= SchedModels
.getProcModel(ModelDef
).Index
;
1455 if (AliasProcIdx
&& AliasProcIdx
!= TransVec
[TransIdx
].ProcIndex
)
1457 if (!Variants
.empty()) {
1458 const CodeGenProcModel
&PM
=
1459 *(SchedModels
.procModelBegin() + AliasProcIdx
);
1460 PrintFatalError((*AI
)->getLoc(),
1461 "Multiple variants defined for processor " +
1463 " Ensure only one SchedAlias exists per RW.");
1466 const CodeGenSchedRW
&AliasRW
=
1467 SchedModels
.getSchedRW((*AI
)->getValueAsDef("AliasRW"));
1469 if (AliasRW
.HasVariants
) {
1470 const RecVec VarDefs
= AliasRW
.TheDef
->getValueAsListOfDefs("Variants");
1471 for (Record
*VD
: VarDefs
)
1472 Variants
.emplace_back(VD
, AliasRW
.Index
, AliasProcIdx
, 0);
1474 if (AliasRW
.IsSequence
)
1475 Variants
.emplace_back(AliasRW
.TheDef
, SchedRW
.Index
, AliasProcIdx
, 0);
1476 if (AliasProcIdx
== 0)
1479 std::vector
<Record
*> AllPreds
=
1480 getAllPredicates(Variants
, TransVec
[TransIdx
].ProcIndex
);
1481 for (TransVariant
&Variant
: Variants
) {
1482 // Don't expand variants if the processor models don't intersect.
1483 // A zero processor index means any processor.
1484 if (Variant
.VarOrSeqDef
->isSubClassOf("SchedVar")) {
1485 Record
*PredDef
= Variant
.VarOrSeqDef
->getValueAsDef("Predicate");
1486 if (mutuallyExclusive(PredDef
, AllPreds
, TransVec
[TransIdx
].PredTerm
))
1490 if (IntersectingVariants
.empty()) {
1491 // The first variant builds on the existing transition.
1492 Variant
.TransVecIdx
= TransIdx
;
1493 IntersectingVariants
.push_back(Variant
);
1496 // Push another copy of the current transition for more variants.
1497 Variant
.TransVecIdx
= TransVec
.size();
1498 IntersectingVariants
.push_back(Variant
);
1499 TransVec
.push_back(TransVec
[TransIdx
]);
1502 if (GenericRW
&& IntersectingVariants
.empty()) {
1503 PrintFatalError(SchedRW
.TheDef
->getLoc(), "No variant of this type has "
1504 "a matching predicate on any processor");
1508 // Push the Reads/Writes selected by this variant onto the PredTransition
1509 // specified by VInfo.
1510 void PredTransitions::
1511 pushVariant(const TransVariant
&VInfo
, bool IsRead
) {
1512 PredTransition
&Trans
= TransVec
[VInfo
.TransVecIdx
];
1514 // If this operand transition is reached through a processor-specific alias,
1515 // then the whole transition is specific to this processor.
1517 if (VInfo
.VarOrSeqDef
->isSubClassOf("SchedVar")) {
1518 Record
*PredDef
= VInfo
.VarOrSeqDef
->getValueAsDef("Predicate");
1519 Trans
.PredTerm
.emplace_back(IsRead
, VInfo
.RWIdx
,PredDef
);
1520 RecVec SelectedDefs
= VInfo
.VarOrSeqDef
->getValueAsListOfDefs("Selected");
1521 SchedModels
.findRWs(SelectedDefs
, SelectedRWs
, IsRead
);
1524 assert(VInfo
.VarOrSeqDef
->isSubClassOf("WriteSequence") &&
1525 "variant must be a SchedVariant or aliased WriteSequence");
1526 SelectedRWs
.push_back(SchedModels
.getSchedRWIdx(VInfo
.VarOrSeqDef
, IsRead
));
1529 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(VInfo
.RWIdx
, IsRead
);
1531 SmallVectorImpl
<SmallVector
<unsigned,4>> &RWSequences
= IsRead
1532 ? Trans
.ReadSequences
: Trans
.WriteSequences
;
1533 if (SchedRW
.IsVariadic
) {
1534 unsigned OperIdx
= RWSequences
.size()-1;
1535 // Make N-1 copies of this transition's last sequence.
1536 RWSequences
.reserve(RWSequences
.size() + SelectedRWs
.size() - 1);
1537 RWSequences
.insert(RWSequences
.end(), SelectedRWs
.size() - 1,
1538 RWSequences
[OperIdx
]);
1539 // Push each of the N elements of the SelectedRWs onto a copy of the last
1540 // sequence (split the current operand into N operands).
1541 // Note that write sequences should be expanded within this loop--the entire
1542 // sequence belongs to a single operand.
1543 for (IdxIter RWI
= SelectedRWs
.begin(), RWE
= SelectedRWs
.end();
1544 RWI
!= RWE
; ++RWI
, ++OperIdx
) {
1547 ExpandedRWs
.push_back(*RWI
);
1549 SchedModels
.expandRWSequence(*RWI
, ExpandedRWs
, IsRead
);
1550 llvm::append_range(RWSequences
[OperIdx
], ExpandedRWs
);
1552 assert(OperIdx
== RWSequences
.size() && "missed a sequence");
1555 // Push this transition's expanded sequence onto this transition's last
1556 // sequence (add to the current operand's sequence).
1557 SmallVectorImpl
<unsigned> &Seq
= RWSequences
.back();
1559 for (unsigned int SelectedRW
: SelectedRWs
) {
1561 ExpandedRWs
.push_back(SelectedRW
);
1563 SchedModels
.expandRWSequence(SelectedRW
, ExpandedRWs
, IsRead
);
1565 llvm::append_range(Seq
, ExpandedRWs
);
1569 // RWSeq is a sequence of all Reads or all Writes for the next read or write
1570 // operand. StartIdx is an index into TransVec where partial results
1571 // starts. RWSeq must be applied to all transitions between StartIdx and the end
1573 bool PredTransitions::substituteVariantOperand(
1574 const SmallVectorImpl
<unsigned> &RWSeq
, bool IsRead
, unsigned StartIdx
) {
1576 // Visit each original RW within the current sequence.
1577 for (unsigned int RWI
: RWSeq
) {
1578 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(RWI
, IsRead
);
1579 // Push this RW on all partial PredTransitions or distribute variants.
1580 // New PredTransitions may be pushed within this loop which should not be
1581 // revisited (TransEnd must be loop invariant).
1582 for (unsigned TransIdx
= StartIdx
, TransEnd
= TransVec
.size();
1583 TransIdx
!= TransEnd
; ++TransIdx
) {
1584 // Distribute this partial PredTransition across intersecting variants.
1585 // This will push a copies of TransVec[TransIdx] on the back of TransVec.
1586 std::vector
<TransVariant
> IntersectingVariants
;
1587 getIntersectingVariants(SchedRW
, TransIdx
, IntersectingVariants
);
1588 // Now expand each variant on top of its copy of the transition.
1589 for (const TransVariant
&IV
: IntersectingVariants
)
1590 pushVariant(IV
, IsRead
);
1591 if (IntersectingVariants
.empty()) {
1593 TransVec
[TransIdx
].ReadSequences
.back().push_back(RWI
);
1595 TransVec
[TransIdx
].WriteSequences
.back().push_back(RWI
);
1605 // For each variant of a Read/Write in Trans, substitute the sequence of
1606 // Read/Writes guarded by the variant. This is exponential in the number of
1607 // variant Read/Writes, but in practice detection of mutually exclusive
1608 // predicates should result in linear growth in the total number variants.
1610 // This is one step in a breadth-first search of nested variants.
1611 bool PredTransitions::substituteVariants(const PredTransition
&Trans
) {
1612 // Build up a set of partial results starting at the back of
1613 // PredTransitions. Remember the first new transition.
1614 unsigned StartIdx
= TransVec
.size();
1616 assert(Trans
.ProcIndex
!= 0);
1617 TransVec
.emplace_back(Trans
.PredTerm
, Trans
.ProcIndex
);
1619 // Visit each original write sequence.
1620 for (const auto &WriteSequence
: Trans
.WriteSequences
) {
1621 // Push a new (empty) write sequence onto all partial Transitions.
1622 for (std::vector
<PredTransition
>::iterator I
=
1623 TransVec
.begin() + StartIdx
, E
= TransVec
.end(); I
!= E
; ++I
) {
1624 I
->WriteSequences
.emplace_back();
1627 substituteVariantOperand(WriteSequence
, /*IsRead=*/false, StartIdx
);
1629 // Visit each original read sequence.
1630 for (const auto &ReadSequence
: Trans
.ReadSequences
) {
1631 // Push a new (empty) read sequence onto all partial Transitions.
1632 for (std::vector
<PredTransition
>::iterator I
=
1633 TransVec
.begin() + StartIdx
, E
= TransVec
.end(); I
!= E
; ++I
) {
1634 I
->ReadSequences
.emplace_back();
1636 Subst
|= substituteVariantOperand(ReadSequence
, /*IsRead=*/true, StartIdx
);
1641 static void addSequences(CodeGenSchedModels
&SchedModels
,
1642 const SmallVectorImpl
<SmallVector
<unsigned, 4>> &Seqs
,
1643 IdxVec
&Result
, bool IsRead
) {
1644 for (const auto &S
: Seqs
)
1646 Result
.push_back(SchedModels
.findOrInsertRW(S
, IsRead
));
1650 static void dumpRecVec(const RecVec
&RV
) {
1651 for (const Record
*R
: RV
)
1652 dbgs() << R
->getName() << ", ";
1656 static void dumpTransition(const CodeGenSchedModels
&SchedModels
,
1657 const CodeGenSchedClass
&FromSC
,
1658 const CodeGenSchedTransition
&SCTrans
,
1659 const RecVec
&Preds
) {
1660 LLVM_DEBUG(dbgs() << "Adding transition from " << FromSC
.Name
<< "("
1661 << FromSC
.Index
<< ") to "
1662 << SchedModels
.getSchedClass(SCTrans
.ToClassIdx
).Name
<< "("
1663 << SCTrans
.ToClassIdx
<< ") on pred term: (";
1665 dbgs() << ") on processor (" << SCTrans
.ProcIndex
<< ")\n");
1667 // Create a new SchedClass for each variant found by inferFromRW. Pass
1668 static void inferFromTransitions(ArrayRef
<PredTransition
> LastTransitions
,
1669 unsigned FromClassIdx
,
1670 CodeGenSchedModels
&SchedModels
) {
1671 // For each PredTransition, create a new CodeGenSchedTransition, which usually
1672 // requires creating a new SchedClass.
1673 for (const auto &LastTransition
: LastTransitions
) {
1674 // Variant expansion (substituteVariants) may create unconditional
1675 // transitions. We don't need to build sched classes for them.
1676 if (LastTransition
.PredTerm
.empty())
1678 IdxVec OperWritesVariant
, OperReadsVariant
;
1679 addSequences(SchedModels
, LastTransition
.WriteSequences
, OperWritesVariant
,
1681 addSequences(SchedModels
, LastTransition
.ReadSequences
, OperReadsVariant
,
1683 CodeGenSchedTransition SCTrans
;
1685 // Transition should not contain processor indices already assigned to
1686 // InstRWs in this scheduling class.
1687 const CodeGenSchedClass
&FromSC
= SchedModels
.getSchedClass(FromClassIdx
);
1688 if (FromSC
.InstRWProcIndices
.count(LastTransition
.ProcIndex
))
1690 SCTrans
.ProcIndex
= LastTransition
.ProcIndex
;
1691 SCTrans
.ToClassIdx
=
1692 SchedModels
.addSchedClass(/*ItinClassDef=*/nullptr, OperWritesVariant
,
1693 OperReadsVariant
, LastTransition
.ProcIndex
);
1695 // The final PredTerm is unique set of predicates guarding the transition.
1697 transform(LastTransition
.PredTerm
, std::back_inserter(Preds
),
1698 [](const PredCheck
&P
) { return P
.Predicate
; });
1699 Preds
.erase(std::unique(Preds
.begin(), Preds
.end()), Preds
.end());
1700 dumpTransition(SchedModels
, FromSC
, SCTrans
, Preds
);
1701 SCTrans
.PredTerm
= std::move(Preds
);
1702 SchedModels
.getSchedClass(FromClassIdx
)
1703 .Transitions
.push_back(std::move(SCTrans
));
1707 std::vector
<unsigned> CodeGenSchedModels::getAllProcIndices() const {
1708 std::vector
<unsigned> ProcIdVec
;
1709 for (const auto &PM
: ProcModelMap
)
1711 ProcIdVec
.push_back(PM
.second
);
1712 // The order of the keys (Record pointers) of ProcModelMap are not stable.
1713 // Sort to stabalize the values.
1714 llvm::sort(ProcIdVec
);
1718 static std::vector
<PredTransition
>
1719 makePerProcessorTransitions(const PredTransition
&Trans
,
1720 ArrayRef
<unsigned> ProcIndices
) {
1721 std::vector
<PredTransition
> PerCpuTransVec
;
1722 for (unsigned ProcId
: ProcIndices
) {
1723 assert(ProcId
!= 0);
1724 PerCpuTransVec
.push_back(Trans
);
1725 PerCpuTransVec
.back().ProcIndex
= ProcId
;
1727 return PerCpuTransVec
;
1730 // Create new SchedClasses for the given ReadWrite list. If any of the
1731 // ReadWrites refers to a SchedVariant, create a new SchedClass for each variant
1732 // of the ReadWrite list, following Aliases if necessary.
1733 void CodeGenSchedModels::inferFromRW(ArrayRef
<unsigned> OperWrites
,
1734 ArrayRef
<unsigned> OperReads
,
1735 unsigned FromClassIdx
,
1736 ArrayRef
<unsigned> ProcIndices
) {
1737 LLVM_DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices
);
1739 // Create a seed transition with an empty PredTerm and the expanded sequences
1740 // of SchedWrites for the current SchedClass.
1741 std::vector
<PredTransition
> LastTransitions
;
1742 LastTransitions
.emplace_back();
1744 for (unsigned WriteIdx
: OperWrites
) {
1746 expandRWSequence(WriteIdx
, WriteSeq
, /*IsRead=*/false);
1747 LastTransitions
[0].WriteSequences
.emplace_back();
1748 SmallVectorImpl
<unsigned> &Seq
= LastTransitions
[0].WriteSequences
.back();
1749 Seq
.append(WriteSeq
.begin(), WriteSeq
.end());
1750 LLVM_DEBUG(dbgs() << "("; dumpIdxVec(Seq
); dbgs() << ") ");
1752 LLVM_DEBUG(dbgs() << " Reads: ");
1753 for (unsigned ReadIdx
: OperReads
) {
1755 expandRWSequence(ReadIdx
, ReadSeq
, /*IsRead=*/true);
1756 LastTransitions
[0].ReadSequences
.emplace_back();
1757 SmallVectorImpl
<unsigned> &Seq
= LastTransitions
[0].ReadSequences
.back();
1758 Seq
.append(ReadSeq
.begin(), ReadSeq
.end());
1759 LLVM_DEBUG(dbgs() << "("; dumpIdxVec(Seq
); dbgs() << ") ");
1761 LLVM_DEBUG(dbgs() << '\n');
1763 LastTransitions
= makePerProcessorTransitions(
1764 LastTransitions
[0], llvm::is_contained(ProcIndices
, 0)
1765 ? ArrayRef
<unsigned>(getAllProcIndices())
1767 // Collect all PredTransitions for individual operands.
1768 // Iterate until no variant writes remain.
1769 bool SubstitutedAny
;
1771 SubstitutedAny
= false;
1772 PredTransitions
Transitions(*this);
1773 for (const PredTransition
&Trans
: LastTransitions
)
1774 SubstitutedAny
|= Transitions
.substituteVariants(Trans
);
1775 LLVM_DEBUG(Transitions
.dump());
1776 LastTransitions
.swap(Transitions
.TransVec
);
1777 } while (SubstitutedAny
);
1779 // WARNING: We are about to mutate the SchedClasses vector. Do not refer to
1780 // OperWrites, OperReads, or ProcIndices after calling inferFromTransitions.
1781 inferFromTransitions(LastTransitions
, FromClassIdx
, *this);
1784 // Check if any processor resource group contains all resource records in
1786 bool CodeGenSchedModels::hasSuperGroup(RecVec
&SubUnits
, CodeGenProcModel
&PM
) {
1787 for (Record
*ProcResourceDef
: PM
.ProcResourceDefs
) {
1788 if (!ProcResourceDef
->isSubClassOf("ProcResGroup"))
1790 RecVec SuperUnits
= ProcResourceDef
->getValueAsListOfDefs("Resources");
1791 RecIter RI
= SubUnits
.begin(), RE
= SubUnits
.end();
1792 for ( ; RI
!= RE
; ++RI
) {
1793 if (!is_contained(SuperUnits
, *RI
)) {
1803 // Verify that overlapping groups have a common supergroup.
1804 void CodeGenSchedModels::verifyProcResourceGroups(CodeGenProcModel
&PM
) {
1805 for (unsigned i
= 0, e
= PM
.ProcResourceDefs
.size(); i
< e
; ++i
) {
1806 if (!PM
.ProcResourceDefs
[i
]->isSubClassOf("ProcResGroup"))
1809 PM
.ProcResourceDefs
[i
]->getValueAsListOfDefs("Resources");
1810 for (unsigned j
= i
+1; j
< e
; ++j
) {
1811 if (!PM
.ProcResourceDefs
[j
]->isSubClassOf("ProcResGroup"))
1814 PM
.ProcResourceDefs
[j
]->getValueAsListOfDefs("Resources");
1815 if (std::find_first_of(CheckUnits
.begin(), CheckUnits
.end(),
1816 OtherUnits
.begin(), OtherUnits
.end())
1817 != CheckUnits
.end()) {
1818 // CheckUnits and OtherUnits overlap
1819 llvm::append_range(OtherUnits
, CheckUnits
);
1820 if (!hasSuperGroup(OtherUnits
, PM
)) {
1821 PrintFatalError((PM
.ProcResourceDefs
[i
])->getLoc(),
1822 "proc resource group overlaps with "
1823 + PM
.ProcResourceDefs
[j
]->getName()
1824 + " but no supergroup contains both.");
1831 // Collect all the RegisterFile definitions available in this target.
1832 void CodeGenSchedModels::collectRegisterFiles() {
1833 RecVec RegisterFileDefs
= Records
.getAllDerivedDefinitions("RegisterFile");
1835 // RegisterFiles is the vector of CodeGenRegisterFile.
1836 for (Record
*RF
: RegisterFileDefs
) {
1837 // For each register file definition, construct a CodeGenRegisterFile object
1838 // and add it to the appropriate scheduling model.
1839 CodeGenProcModel
&PM
= getProcModel(RF
->getValueAsDef("SchedModel"));
1840 PM
.RegisterFiles
.emplace_back(CodeGenRegisterFile(RF
->getName(),RF
));
1841 CodeGenRegisterFile
&CGRF
= PM
.RegisterFiles
.back();
1842 CGRF
.MaxMovesEliminatedPerCycle
=
1843 RF
->getValueAsInt("MaxMovesEliminatedPerCycle");
1844 CGRF
.AllowZeroMoveEliminationOnly
=
1845 RF
->getValueAsBit("AllowZeroMoveEliminationOnly");
1847 // Now set the number of physical registers as well as the cost of registers
1848 // in each register class.
1849 CGRF
.NumPhysRegs
= RF
->getValueAsInt("NumPhysRegs");
1850 if (!CGRF
.NumPhysRegs
) {
1851 PrintFatalError(RF
->getLoc(),
1852 "Invalid RegisterFile with zero physical registers");
1855 RecVec RegisterClasses
= RF
->getValueAsListOfDefs("RegClasses");
1856 std::vector
<int64_t> RegisterCosts
= RF
->getValueAsListOfInts("RegCosts");
1857 ListInit
*MoveElimInfo
= RF
->getValueAsListInit("AllowMoveElimination");
1858 for (unsigned I
= 0, E
= RegisterClasses
.size(); I
< E
; ++I
) {
1859 int Cost
= RegisterCosts
.size() > I
? RegisterCosts
[I
] : 1;
1861 bool AllowMoveElim
= false;
1862 if (MoveElimInfo
->size() > I
) {
1863 BitInit
*Val
= cast
<BitInit
>(MoveElimInfo
->getElement(I
));
1864 AllowMoveElim
= Val
->getValue();
1867 CGRF
.Costs
.emplace_back(RegisterClasses
[I
], Cost
, AllowMoveElim
);
1872 // Collect and sort WriteRes, ReadAdvance, and ProcResources.
1873 void CodeGenSchedModels::collectProcResources() {
1874 ProcResourceDefs
= Records
.getAllDerivedDefinitions("ProcResourceUnits");
1875 ProcResGroups
= Records
.getAllDerivedDefinitions("ProcResGroup");
1877 // Add any subtarget-specific SchedReadWrites that are directly associated
1878 // with processor resources. Refer to the parent SchedClass's ProcIndices to
1879 // determine which processors they apply to.
1880 for (const CodeGenSchedClass
&SC
:
1881 make_range(schedClassBegin(), schedClassEnd())) {
1882 if (SC
.ItinClassDef
) {
1883 collectItinProcResources(SC
.ItinClassDef
);
1887 // This class may have a default ReadWrite list which can be overriden by
1888 // InstRW definitions.
1889 for (Record
*RW
: SC
.InstRWs
) {
1890 Record
*RWModelDef
= RW
->getValueAsDef("SchedModel");
1891 unsigned PIdx
= getProcModel(RWModelDef
).Index
;
1892 IdxVec Writes
, Reads
;
1893 findRWs(RW
->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1894 collectRWResources(Writes
, Reads
, PIdx
);
1897 collectRWResources(SC
.Writes
, SC
.Reads
, SC
.ProcIndices
);
1899 // Add resources separately defined by each subtarget.
1900 RecVec WRDefs
= Records
.getAllDerivedDefinitions("WriteRes");
1901 for (Record
*WR
: WRDefs
) {
1902 Record
*ModelDef
= WR
->getValueAsDef("SchedModel");
1903 addWriteRes(WR
, getProcModel(ModelDef
).Index
);
1905 RecVec SWRDefs
= Records
.getAllDerivedDefinitions("SchedWriteRes");
1906 for (Record
*SWR
: SWRDefs
) {
1907 Record
*ModelDef
= SWR
->getValueAsDef("SchedModel");
1908 addWriteRes(SWR
, getProcModel(ModelDef
).Index
);
1910 RecVec RADefs
= Records
.getAllDerivedDefinitions("ReadAdvance");
1911 for (Record
*RA
: RADefs
) {
1912 Record
*ModelDef
= RA
->getValueAsDef("SchedModel");
1913 addReadAdvance(RA
, getProcModel(ModelDef
).Index
);
1915 RecVec SRADefs
= Records
.getAllDerivedDefinitions("SchedReadAdvance");
1916 for (Record
*SRA
: SRADefs
) {
1917 if (SRA
->getValueInit("SchedModel")->isComplete()) {
1918 Record
*ModelDef
= SRA
->getValueAsDef("SchedModel");
1919 addReadAdvance(SRA
, getProcModel(ModelDef
).Index
);
1922 // Add ProcResGroups that are defined within this processor model, which may
1923 // not be directly referenced but may directly specify a buffer size.
1924 RecVec ProcResGroups
= Records
.getAllDerivedDefinitions("ProcResGroup");
1925 for (Record
*PRG
: ProcResGroups
) {
1926 if (!PRG
->getValueInit("SchedModel")->isComplete())
1928 CodeGenProcModel
&PM
= getProcModel(PRG
->getValueAsDef("SchedModel"));
1929 if (!is_contained(PM
.ProcResourceDefs
, PRG
))
1930 PM
.ProcResourceDefs
.push_back(PRG
);
1932 // Add ProcResourceUnits unconditionally.
1933 for (Record
*PRU
: Records
.getAllDerivedDefinitions("ProcResourceUnits")) {
1934 if (!PRU
->getValueInit("SchedModel")->isComplete())
1936 CodeGenProcModel
&PM
= getProcModel(PRU
->getValueAsDef("SchedModel"));
1937 if (!is_contained(PM
.ProcResourceDefs
, PRU
))
1938 PM
.ProcResourceDefs
.push_back(PRU
);
1940 // Finalize each ProcModel by sorting the record arrays.
1941 for (CodeGenProcModel
&PM
: ProcModels
) {
1942 llvm::sort(PM
.WriteResDefs
, LessRecord());
1943 llvm::sort(PM
.ReadAdvanceDefs
, LessRecord());
1944 llvm::sort(PM
.ProcResourceDefs
, LessRecord());
1946 PM
.dump(); dbgs() << "WriteResDefs: "; for (auto WriteResDef
1947 : PM
.WriteResDefs
) {
1948 if (WriteResDef
->isSubClassOf("WriteRes"))
1949 dbgs() << WriteResDef
->getValueAsDef("WriteType")->getName() << " ";
1951 dbgs() << WriteResDef
->getName() << " ";
1952 } dbgs() << "\nReadAdvanceDefs: ";
1953 for (Record
*ReadAdvanceDef
1954 : PM
.ReadAdvanceDefs
) {
1955 if (ReadAdvanceDef
->isSubClassOf("ReadAdvance"))
1956 dbgs() << ReadAdvanceDef
->getValueAsDef("ReadType")->getName()
1959 dbgs() << ReadAdvanceDef
->getName() << " ";
1961 << "\nProcResourceDefs: ";
1962 for (Record
*ProcResourceDef
1963 : PM
.ProcResourceDefs
) {
1964 dbgs() << ProcResourceDef
->getName() << " ";
1967 verifyProcResourceGroups(PM
);
1970 ProcResourceDefs
.clear();
1971 ProcResGroups
.clear();
1974 void CodeGenSchedModels::checkCompleteness() {
1975 bool Complete
= true;
1976 bool HadCompleteModel
= false;
1977 for (const CodeGenProcModel
&ProcModel
: procModels()) {
1978 const bool HasItineraries
= ProcModel
.hasItineraries();
1979 if (!ProcModel
.ModelDef
->getValueAsBit("CompleteModel"))
1981 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
1982 if (Inst
->hasNoSchedulingInfo
)
1984 if (ProcModel
.isUnsupported(*Inst
))
1986 unsigned SCIdx
= getSchedClassIdx(*Inst
);
1988 if (Inst
->TheDef
->isValueUnset("SchedRW") && !HadCompleteModel
) {
1989 PrintError(Inst
->TheDef
->getLoc(),
1990 "No schedule information for instruction '" +
1991 Inst
->TheDef
->getName() + "' in SchedMachineModel '" +
1992 ProcModel
.ModelDef
->getName() + "'");
1998 const CodeGenSchedClass
&SC
= getSchedClass(SCIdx
);
1999 if (!SC
.Writes
.empty())
2001 if (HasItineraries
&& SC
.ItinClassDef
!= nullptr &&
2002 SC
.ItinClassDef
->getName() != "NoItinerary")
2005 const RecVec
&InstRWs
= SC
.InstRWs
;
2006 auto I
= find_if(InstRWs
, [&ProcModel
](const Record
*R
) {
2007 return R
->getValueAsDef("SchedModel") == ProcModel
.ModelDef
;
2009 if (I
== InstRWs
.end()) {
2010 PrintError(Inst
->TheDef
->getLoc(), "'" + ProcModel
.ModelName
+
2011 "' lacks information for '" +
2012 Inst
->TheDef
->getName() + "'");
2016 HadCompleteModel
= true;
2019 errs() << "\n\nIncomplete schedule models found.\n"
2020 << "- Consider setting 'CompleteModel = 0' while developing new models.\n"
2021 << "- Pseudo instructions can be marked with 'hasNoSchedulingInfo = 1'.\n"
2022 << "- Instructions should usually have Sched<[...]> as a superclass, "
2023 "you may temporarily use an empty list.\n"
2024 << "- Instructions related to unsupported features can be excluded with "
2025 "list<Predicate> UnsupportedFeatures = [HasA,..,HasY]; in the "
2026 "processor model.\n\n";
2027 PrintFatalError("Incomplete schedule model");
2031 // Collect itinerary class resources for each processor.
2032 void CodeGenSchedModels::collectItinProcResources(Record
*ItinClassDef
) {
2033 for (unsigned PIdx
= 0, PEnd
= ProcModels
.size(); PIdx
!= PEnd
; ++PIdx
) {
2034 const CodeGenProcModel
&PM
= ProcModels
[PIdx
];
2035 // For all ItinRW entries.
2036 bool HasMatch
= false;
2037 for (RecIter II
= PM
.ItinRWDefs
.begin(), IE
= PM
.ItinRWDefs
.end();
2039 RecVec Matched
= (*II
)->getValueAsListOfDefs("MatchedItinClasses");
2040 if (!llvm::is_contained(Matched
, ItinClassDef
))
2043 PrintFatalError((*II
)->getLoc(), "Duplicate itinerary class "
2044 + ItinClassDef
->getName()
2045 + " in ItinResources for " + PM
.ModelName
);
2047 IdxVec Writes
, Reads
;
2048 findRWs((*II
)->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
2049 collectRWResources(Writes
, Reads
, PIdx
);
2054 void CodeGenSchedModels::collectRWResources(unsigned RWIdx
, bool IsRead
,
2055 ArrayRef
<unsigned> ProcIndices
) {
2056 const CodeGenSchedRW
&SchedRW
= getSchedRW(RWIdx
, IsRead
);
2057 if (SchedRW
.TheDef
) {
2058 if (!IsRead
&& SchedRW
.TheDef
->isSubClassOf("SchedWriteRes")) {
2059 for (unsigned Idx
: ProcIndices
)
2060 addWriteRes(SchedRW
.TheDef
, Idx
);
2062 else if (IsRead
&& SchedRW
.TheDef
->isSubClassOf("SchedReadAdvance")) {
2063 for (unsigned Idx
: ProcIndices
)
2064 addReadAdvance(SchedRW
.TheDef
, Idx
);
2067 for (auto *Alias
: SchedRW
.Aliases
) {
2068 IdxVec AliasProcIndices
;
2069 if (Alias
->getValueInit("SchedModel")->isComplete()) {
2070 AliasProcIndices
.push_back(
2071 getProcModel(Alias
->getValueAsDef("SchedModel")).Index
);
2073 AliasProcIndices
= ProcIndices
;
2074 const CodeGenSchedRW
&AliasRW
= getSchedRW(Alias
->getValueAsDef("AliasRW"));
2075 assert(AliasRW
.IsRead
== IsRead
&& "cannot alias reads to writes");
2078 expandRWSequence(AliasRW
.Index
, ExpandedRWs
, IsRead
);
2079 for (unsigned int ExpandedRW
: ExpandedRWs
) {
2080 collectRWResources(ExpandedRW
, IsRead
, AliasProcIndices
);
2085 // Collect resources for a set of read/write types and processor indices.
2086 void CodeGenSchedModels::collectRWResources(ArrayRef
<unsigned> Writes
,
2087 ArrayRef
<unsigned> Reads
,
2088 ArrayRef
<unsigned> ProcIndices
) {
2089 for (unsigned Idx
: Writes
)
2090 collectRWResources(Idx
, /*IsRead=*/false, ProcIndices
);
2092 for (unsigned Idx
: Reads
)
2093 collectRWResources(Idx
, /*IsRead=*/true, ProcIndices
);
2096 // Find the processor's resource units for this kind of resource.
2097 Record
*CodeGenSchedModels::findProcResUnits(Record
*ProcResKind
,
2098 const CodeGenProcModel
&PM
,
2099 ArrayRef
<SMLoc
> Loc
) const {
2100 if (ProcResKind
->isSubClassOf("ProcResourceUnits"))
2103 Record
*ProcUnitDef
= nullptr;
2104 assert(!ProcResourceDefs
.empty());
2105 assert(!ProcResGroups
.empty());
2107 for (Record
*ProcResDef
: ProcResourceDefs
) {
2108 if (ProcResDef
->getValueAsDef("Kind") == ProcResKind
2109 && ProcResDef
->getValueAsDef("SchedModel") == PM
.ModelDef
) {
2111 PrintFatalError(Loc
,
2112 "Multiple ProcessorResourceUnits associated with "
2113 + ProcResKind
->getName());
2115 ProcUnitDef
= ProcResDef
;
2118 for (Record
*ProcResGroup
: ProcResGroups
) {
2119 if (ProcResGroup
== ProcResKind
2120 && ProcResGroup
->getValueAsDef("SchedModel") == PM
.ModelDef
) {
2122 PrintFatalError(Loc
,
2123 "Multiple ProcessorResourceUnits associated with "
2124 + ProcResKind
->getName());
2126 ProcUnitDef
= ProcResGroup
;
2130 PrintFatalError(Loc
,
2131 "No ProcessorResources associated with "
2132 + ProcResKind
->getName());
2137 // Iteratively add a resource and its super resources.
2138 void CodeGenSchedModels::addProcResource(Record
*ProcResKind
,
2139 CodeGenProcModel
&PM
,
2140 ArrayRef
<SMLoc
> Loc
) {
2142 Record
*ProcResUnits
= findProcResUnits(ProcResKind
, PM
, Loc
);
2144 // See if this ProcResource is already associated with this processor.
2145 if (is_contained(PM
.ProcResourceDefs
, ProcResUnits
))
2148 PM
.ProcResourceDefs
.push_back(ProcResUnits
);
2149 if (ProcResUnits
->isSubClassOf("ProcResGroup"))
2152 if (!ProcResUnits
->getValueInit("Super")->isComplete())
2155 ProcResKind
= ProcResUnits
->getValueAsDef("Super");
2159 // Add resources for a SchedWrite to this processor if they don't exist.
2160 void CodeGenSchedModels::addWriteRes(Record
*ProcWriteResDef
, unsigned PIdx
) {
2161 assert(PIdx
&& "don't add resources to an invalid Processor model");
2163 RecVec
&WRDefs
= ProcModels
[PIdx
].WriteResDefs
;
2164 if (is_contained(WRDefs
, ProcWriteResDef
))
2166 WRDefs
.push_back(ProcWriteResDef
);
2168 // Visit ProcResourceKinds referenced by the newly discovered WriteRes.
2169 RecVec ProcResDefs
= ProcWriteResDef
->getValueAsListOfDefs("ProcResources");
2170 for (auto *ProcResDef
: ProcResDefs
) {
2171 addProcResource(ProcResDef
, ProcModels
[PIdx
], ProcWriteResDef
->getLoc());
2175 // Add resources for a ReadAdvance to this processor if they don't exist.
2176 void CodeGenSchedModels::addReadAdvance(Record
*ProcReadAdvanceDef
,
2178 RecVec
&RADefs
= ProcModels
[PIdx
].ReadAdvanceDefs
;
2179 if (is_contained(RADefs
, ProcReadAdvanceDef
))
2181 RADefs
.push_back(ProcReadAdvanceDef
);
2184 unsigned CodeGenProcModel::getProcResourceIdx(Record
*PRDef
) const {
2185 RecIter PRPos
= find(ProcResourceDefs
, PRDef
);
2186 if (PRPos
== ProcResourceDefs
.end())
2187 PrintFatalError(PRDef
->getLoc(), "ProcResource def is not included in "
2188 "the ProcResources list for " + ModelName
);
2189 // Idx=0 is reserved for invalid.
2190 return 1 + (PRPos
- ProcResourceDefs
.begin());
2193 bool CodeGenProcModel::isUnsupported(const CodeGenInstruction
&Inst
) const {
2194 for (const Record
*TheDef
: UnsupportedFeaturesDefs
) {
2195 for (const Record
*PredDef
: Inst
.TheDef
->getValueAsListOfDefs("Predicates")) {
2196 if (TheDef
->getName() == PredDef
->getName())
2204 void CodeGenProcModel::dump() const {
2205 dbgs() << Index
<< ": " << ModelName
<< " "
2206 << (ModelDef
? ModelDef
->getName() : "inferred") << " "
2207 << (ItinsDef
? ItinsDef
->getName() : "no itinerary") << '\n';
2210 void CodeGenSchedRW::dump() const {
2211 dbgs() << Name
<< (IsVariadic
? " (V) " : " ");
2214 dumpIdxVec(Sequence
);
2219 void CodeGenSchedClass::dump(const CodeGenSchedModels
* SchedModels
) const {
2220 dbgs() << "SCHEDCLASS " << Index
<< ":" << Name
<< '\n'
2222 for (unsigned i
= 0, N
= Writes
.size(); i
< N
; ++i
) {
2223 SchedModels
->getSchedWrite(Writes
[i
]).dump();
2229 dbgs() << "\n Reads: ";
2230 for (unsigned i
= 0, N
= Reads
.size(); i
< N
; ++i
) {
2231 SchedModels
->getSchedRead(Reads
[i
]).dump();
2237 dbgs() << "\n ProcIdx: "; dumpIdxVec(ProcIndices
);
2238 if (!Transitions
.empty()) {
2239 dbgs() << "\n Transitions for Proc ";
2240 for (const CodeGenSchedTransition
&Transition
: Transitions
) {
2241 dbgs() << Transition
.ProcIndex
<< ", ";
2247 void PredTransitions::dump() const {
2248 dbgs() << "Expanded Variants:\n";
2249 for (const auto &TI
: TransVec
) {
2252 for (const PredCheck
&PC
: TI
.PredTerm
)
2253 dbgs() << LS
<< SchedModels
.getSchedRW(PC
.RWIdx
, PC
.IsRead
).Name
<< ":"
2254 << PC
.Predicate
->getName();
2255 dbgs() << "},\n => {";
2256 for (SmallVectorImpl
<SmallVector
<unsigned, 4>>::const_iterator
2257 WSI
= TI
.WriteSequences
.begin(),
2258 WSE
= TI
.WriteSequences
.end();
2259 WSI
!= WSE
; ++WSI
) {
2262 for (unsigned N
: *WSI
)
2263 dbgs() << LS
<< SchedModels
.getSchedWrite(N
).Name
;