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
: make_range(Expr
->arg_begin(), Expr
->arg_end())) {
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
= 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", llvm::make_unique
<InstrsOp
>());
176 Sets
.addOperator("instregex", llvm::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 PrintNote(It
->second
->getLoc(), "Previous declaration was here.");
252 PrintFatalError(R
->getLoc(), "Invalid STIPredicateDecl found.");
255 // Disallow InstructionEquivalenceClasses with an empty instruction list.
257 Records
.getAllDerivedDefinitions("InstructionEquivalenceClass");
258 for (const Record
*R
: Defs
) {
259 RecVec Opcodes
= R
->getValueAsListOfDefs("Opcodes");
260 if (Opcodes
.empty()) {
261 PrintFatalError(R
->getLoc(), "Invalid InstructionEquivalenceClass "
262 "defined with an empty opcode list.");
267 // Used by function `processSTIPredicate` to construct a mask of machine
268 // instruction operands.
269 static APInt
constructOperandMask(ArrayRef
<int64_t> Indices
) {
274 int64_t MaxIndex
= *std::max_element(Indices
.begin(), Indices
.end());
275 assert(MaxIndex
>= 0 && "Invalid negative indices in input!");
276 OperandMask
= OperandMask
.zext(MaxIndex
+ 1);
277 for (const int64_t Index
: Indices
) {
278 assert(Index
>= 0 && "Invalid negative indices!");
279 OperandMask
.setBit(Index
);
286 processSTIPredicate(STIPredicateFunction
&Fn
,
287 const DenseMap
<Record
*, unsigned> &ProcModelMap
) {
288 DenseMap
<const Record
*, unsigned> Opcode2Index
;
289 using OpcodeMapPair
= std::pair
<const Record
*, OpcodeInfo
>;
290 std::vector
<OpcodeMapPair
> OpcodeMappings
;
291 std::vector
<std::pair
<APInt
, APInt
>> OpcodeMasks
;
293 DenseMap
<const Record
*, unsigned> Predicate2Index
;
294 unsigned NumUniquePredicates
= 0;
296 // Number unique predicates and opcodes used by InstructionEquivalenceClass
297 // definitions. Each unique opcode will be associated with an OpcodeInfo
299 for (const Record
*Def
: Fn
.getDefinitions()) {
300 RecVec Classes
= Def
->getValueAsListOfDefs("Classes");
301 for (const Record
*EC
: Classes
) {
302 const Record
*Pred
= EC
->getValueAsDef("Predicate");
303 if (Predicate2Index
.find(Pred
) == Predicate2Index
.end())
304 Predicate2Index
[Pred
] = NumUniquePredicates
++;
306 RecVec Opcodes
= EC
->getValueAsListOfDefs("Opcodes");
307 for (const Record
*Opcode
: Opcodes
) {
308 if (Opcode2Index
.find(Opcode
) == Opcode2Index
.end()) {
309 Opcode2Index
[Opcode
] = OpcodeMappings
.size();
310 OpcodeMappings
.emplace_back(Opcode
, OpcodeInfo());
316 // Initialize vector `OpcodeMasks` with default values. We want to keep track
317 // of which processors "use" which opcodes. We also want to be able to
318 // identify predicates that are used by different processors for a same
320 // This information is used later on by this algorithm to sort OpcodeMapping
321 // elements based on their processor and predicate sets.
322 OpcodeMasks
.resize(OpcodeMappings
.size());
323 APInt
DefaultProcMask(ProcModelMap
.size(), 0);
324 APInt
DefaultPredMask(NumUniquePredicates
, 0);
325 for (std::pair
<APInt
, APInt
> &MaskPair
: OpcodeMasks
)
326 MaskPair
= std::make_pair(DefaultProcMask
, DefaultPredMask
);
328 // Construct a OpcodeInfo object for every unique opcode declared by an
329 // InstructionEquivalenceClass definition.
330 for (const Record
*Def
: Fn
.getDefinitions()) {
331 RecVec Classes
= Def
->getValueAsListOfDefs("Classes");
332 const Record
*SchedModel
= Def
->getValueAsDef("SchedModel");
333 unsigned ProcIndex
= ProcModelMap
.find(SchedModel
)->second
;
334 APInt
ProcMask(ProcModelMap
.size(), 0);
335 ProcMask
.setBit(ProcIndex
);
337 for (const Record
*EC
: Classes
) {
338 RecVec Opcodes
= EC
->getValueAsListOfDefs("Opcodes");
340 std::vector
<int64_t> OpIndices
=
341 EC
->getValueAsListOfInts("OperandIndices");
342 APInt OperandMask
= constructOperandMask(OpIndices
);
344 const Record
*Pred
= EC
->getValueAsDef("Predicate");
345 APInt
PredMask(NumUniquePredicates
, 0);
346 PredMask
.setBit(Predicate2Index
[Pred
]);
348 for (const Record
*Opcode
: Opcodes
) {
349 unsigned OpcodeIdx
= Opcode2Index
[Opcode
];
350 if (OpcodeMasks
[OpcodeIdx
].first
[ProcIndex
]) {
351 std::string Message
=
352 "Opcode " + Opcode
->getName().str() +
353 " used by multiple InstructionEquivalenceClass definitions.";
354 PrintFatalError(EC
->getLoc(), Message
);
356 OpcodeMasks
[OpcodeIdx
].first
|= ProcMask
;
357 OpcodeMasks
[OpcodeIdx
].second
|= PredMask
;
358 OpcodeInfo
&OI
= OpcodeMappings
[OpcodeIdx
].second
;
360 OI
.addPredicateForProcModel(ProcMask
, OperandMask
, Pred
);
365 // Sort OpcodeMappings elements based on their CPU and predicate masks.
366 // As a last resort, order elements by opcode identifier.
367 llvm::sort(OpcodeMappings
,
368 [&](const OpcodeMapPair
&Lhs
, const OpcodeMapPair
&Rhs
) {
369 unsigned LhsIdx
= Opcode2Index
[Lhs
.first
];
370 unsigned RhsIdx
= Opcode2Index
[Rhs
.first
];
371 std::pair
<APInt
, APInt
> &LhsMasks
= OpcodeMasks
[LhsIdx
];
372 std::pair
<APInt
, APInt
> &RhsMasks
= OpcodeMasks
[RhsIdx
];
374 if (LhsMasks
.first
!= RhsMasks
.first
) {
375 if (LhsMasks
.first
.countPopulation() <
376 RhsMasks
.first
.countPopulation())
378 return LhsMasks
.first
.countLeadingZeros() >
379 RhsMasks
.first
.countLeadingZeros();
382 if (LhsMasks
.second
!= RhsMasks
.second
) {
383 if (LhsMasks
.second
.countPopulation() <
384 RhsMasks
.second
.countPopulation())
386 return LhsMasks
.second
.countLeadingZeros() >
387 RhsMasks
.second
.countLeadingZeros();
390 return LhsIdx
< RhsIdx
;
393 // Now construct opcode groups. Groups are used by the SubtargetEmitter when
394 // expanding the body of a STIPredicate function. In particular, each opcode
395 // group is expanded into a sequence of labels in a switch statement.
396 // It identifies opcodes for which different processors define same predicates
397 // and same opcode masks.
398 for (OpcodeMapPair
&Info
: OpcodeMappings
)
399 Fn
.addOpcode(Info
.first
, std::move(Info
.second
));
402 void CodeGenSchedModels::collectSTIPredicates() {
403 // Map STIPredicateDecl records to elements of vector
404 // CodeGenSchedModels::STIPredicates.
405 DenseMap
<const Record
*, unsigned> Decl2Index
;
407 RecVec RV
= Records
.getAllDerivedDefinitions("STIPredicate");
408 for (const Record
*R
: RV
) {
409 const Record
*Decl
= R
->getValueAsDef("Declaration");
411 const auto It
= Decl2Index
.find(Decl
);
412 if (It
== Decl2Index
.end()) {
413 Decl2Index
[Decl
] = STIPredicates
.size();
414 STIPredicateFunction
Predicate(Decl
);
415 Predicate
.addDefinition(R
);
416 STIPredicates
.emplace_back(std::move(Predicate
));
420 STIPredicateFunction
&PreviousDef
= STIPredicates
[It
->second
];
421 PreviousDef
.addDefinition(R
);
424 for (STIPredicateFunction
&Fn
: STIPredicates
)
425 processSTIPredicate(Fn
, ProcModelMap
);
428 void OpcodeInfo::addPredicateForProcModel(const llvm::APInt
&CpuMask
,
429 const llvm::APInt
&OperandMask
,
430 const Record
*Predicate
) {
431 auto It
= llvm::find_if(
432 Predicates
, [&OperandMask
, &Predicate
](const PredicateInfo
&P
) {
433 return P
.Predicate
== Predicate
&& P
.OperandMask
== OperandMask
;
435 if (It
== Predicates
.end()) {
436 Predicates
.emplace_back(CpuMask
, OperandMask
, Predicate
);
439 It
->ProcModelMask
|= CpuMask
;
442 void CodeGenSchedModels::checkMCInstPredicates() const {
443 RecVec MCPredicates
= Records
.getAllDerivedDefinitions("TIIPredicate");
444 if (MCPredicates
.empty())
447 // A target cannot have multiple TIIPredicate definitions with a same name.
448 llvm::StringMap
<const Record
*> TIIPredicates(MCPredicates
.size());
449 for (const Record
*TIIPred
: MCPredicates
) {
450 StringRef Name
= TIIPred
->getValueAsString("FunctionName");
451 StringMap
<const Record
*>::const_iterator It
= TIIPredicates
.find(Name
);
452 if (It
== TIIPredicates
.end()) {
453 TIIPredicates
[Name
] = TIIPred
;
457 PrintError(TIIPred
->getLoc(),
458 "TIIPredicate " + Name
+ " is multiply defined.");
459 PrintNote(It
->second
->getLoc(),
460 " Previous definition of " + Name
+ " was here.");
461 PrintFatalError(TIIPred
->getLoc(),
462 "Found conflicting definitions of TIIPredicate.");
466 void CodeGenSchedModels::collectRetireControlUnits() {
467 RecVec Units
= Records
.getAllDerivedDefinitions("RetireControlUnit");
469 for (Record
*RCU
: Units
) {
470 CodeGenProcModel
&PM
= getProcModel(RCU
->getValueAsDef("SchedModel"));
471 if (PM
.RetireControlUnit
) {
472 PrintError(RCU
->getLoc(),
473 "Expected a single RetireControlUnit definition");
474 PrintNote(PM
.RetireControlUnit
->getLoc(),
475 "Previous definition of RetireControlUnit was here");
477 PM
.RetireControlUnit
= RCU
;
481 void CodeGenSchedModels::collectLoadStoreQueueInfo() {
482 RecVec Queues
= Records
.getAllDerivedDefinitions("MemoryQueue");
484 for (Record
*Queue
: Queues
) {
485 CodeGenProcModel
&PM
= getProcModel(Queue
->getValueAsDef("SchedModel"));
486 if (Queue
->isSubClassOf("LoadQueue")) {
488 PrintError(Queue
->getLoc(),
489 "Expected a single LoadQueue definition");
490 PrintNote(PM
.LoadQueue
->getLoc(),
491 "Previous definition of LoadQueue was here");
494 PM
.LoadQueue
= Queue
;
497 if (Queue
->isSubClassOf("StoreQueue")) {
499 PrintError(Queue
->getLoc(),
500 "Expected a single StoreQueue definition");
501 PrintNote(PM
.LoadQueue
->getLoc(),
502 "Previous definition of StoreQueue was here");
505 PM
.StoreQueue
= Queue
;
510 /// Collect optional processor information.
511 void CodeGenSchedModels::collectOptionalProcessorInfo() {
512 // Find register file definitions for each processor.
513 collectRegisterFiles();
515 // Collect processor RetireControlUnit descriptors if available.
516 collectRetireControlUnits();
518 // Collect information about load/store queues.
519 collectLoadStoreQueueInfo();
524 /// Gather all processor models.
525 void CodeGenSchedModels::collectProcModels() {
526 RecVec ProcRecords
= Records
.getAllDerivedDefinitions("Processor");
527 llvm::sort(ProcRecords
, LessRecordFieldName());
529 // Reserve space because we can. Reallocation would be ok.
530 ProcModels
.reserve(ProcRecords
.size()+1);
532 // Use idx=0 for NoModel/NoItineraries.
533 Record
*NoModelDef
= Records
.getDef("NoSchedModel");
534 Record
*NoItinsDef
= Records
.getDef("NoItineraries");
535 ProcModels
.emplace_back(0, "NoSchedModel", NoModelDef
, NoItinsDef
);
536 ProcModelMap
[NoModelDef
] = 0;
538 // For each processor, find a unique machine model.
539 LLVM_DEBUG(dbgs() << "+++ PROCESSOR MODELs (addProcModel) +++\n");
540 for (Record
*ProcRecord
: ProcRecords
)
541 addProcModel(ProcRecord
);
544 /// Get a unique processor model based on the defined MachineModel and
545 /// ProcessorItineraries.
546 void CodeGenSchedModels::addProcModel(Record
*ProcDef
) {
547 Record
*ModelKey
= getModelOrItinDef(ProcDef
);
548 if (!ProcModelMap
.insert(std::make_pair(ModelKey
, ProcModels
.size())).second
)
551 std::string Name
= ModelKey
->getName();
552 if (ModelKey
->isSubClassOf("SchedMachineModel")) {
553 Record
*ItinsDef
= ModelKey
->getValueAsDef("Itineraries");
554 ProcModels
.emplace_back(ProcModels
.size(), Name
, ModelKey
, ItinsDef
);
557 // An itinerary is defined without a machine model. Infer a new model.
558 if (!ModelKey
->getValueAsListOfDefs("IID").empty())
559 Name
= Name
+ "Model";
560 ProcModels
.emplace_back(ProcModels
.size(), Name
,
561 ProcDef
->getValueAsDef("SchedModel"), ModelKey
);
563 LLVM_DEBUG(ProcModels
.back().dump());
566 // Recursively find all reachable SchedReadWrite records.
567 static void scanSchedRW(Record
*RWDef
, RecVec
&RWDefs
,
568 SmallPtrSet
<Record
*, 16> &RWSet
) {
569 if (!RWSet
.insert(RWDef
).second
)
571 RWDefs
.push_back(RWDef
);
572 // Reads don't currently have sequence records, but it can be added later.
573 if (RWDef
->isSubClassOf("WriteSequence")) {
574 RecVec Seq
= RWDef
->getValueAsListOfDefs("Writes");
575 for (Record
*WSRec
: Seq
)
576 scanSchedRW(WSRec
, RWDefs
, RWSet
);
578 else if (RWDef
->isSubClassOf("SchedVariant")) {
579 // Visit each variant (guarded by a different predicate).
580 RecVec Vars
= RWDef
->getValueAsListOfDefs("Variants");
581 for (Record
*Variant
: Vars
) {
582 // Visit each RW in the sequence selected by the current variant.
583 RecVec Selected
= Variant
->getValueAsListOfDefs("Selected");
584 for (Record
*SelDef
: Selected
)
585 scanSchedRW(SelDef
, RWDefs
, RWSet
);
590 // Collect and sort all SchedReadWrites reachable via tablegen records.
591 // More may be inferred later when inferring new SchedClasses from variants.
592 void CodeGenSchedModels::collectSchedRW() {
593 // Reserve idx=0 for invalid writes/reads.
594 SchedWrites
.resize(1);
595 SchedReads
.resize(1);
597 SmallPtrSet
<Record
*, 16> RWSet
;
599 // Find all SchedReadWrites referenced by instruction defs.
600 RecVec SWDefs
, SRDefs
;
601 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
602 Record
*SchedDef
= Inst
->TheDef
;
603 if (SchedDef
->isValueUnset("SchedRW"))
605 RecVec RWs
= SchedDef
->getValueAsListOfDefs("SchedRW");
606 for (Record
*RW
: RWs
) {
607 if (RW
->isSubClassOf("SchedWrite"))
608 scanSchedRW(RW
, SWDefs
, RWSet
);
610 assert(RW
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
611 scanSchedRW(RW
, SRDefs
, RWSet
);
615 // Find all ReadWrites referenced by InstRW.
616 RecVec InstRWDefs
= Records
.getAllDerivedDefinitions("InstRW");
617 for (Record
*InstRWDef
: InstRWDefs
) {
618 // For all OperandReadWrites.
619 RecVec RWDefs
= InstRWDef
->getValueAsListOfDefs("OperandReadWrites");
620 for (Record
*RWDef
: RWDefs
) {
621 if (RWDef
->isSubClassOf("SchedWrite"))
622 scanSchedRW(RWDef
, SWDefs
, RWSet
);
624 assert(RWDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
625 scanSchedRW(RWDef
, SRDefs
, RWSet
);
629 // Find all ReadWrites referenced by ItinRW.
630 RecVec ItinRWDefs
= Records
.getAllDerivedDefinitions("ItinRW");
631 for (Record
*ItinRWDef
: ItinRWDefs
) {
632 // For all OperandReadWrites.
633 RecVec RWDefs
= ItinRWDef
->getValueAsListOfDefs("OperandReadWrites");
634 for (Record
*RWDef
: RWDefs
) {
635 if (RWDef
->isSubClassOf("SchedWrite"))
636 scanSchedRW(RWDef
, SWDefs
, RWSet
);
638 assert(RWDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
639 scanSchedRW(RWDef
, SRDefs
, RWSet
);
643 // Find all ReadWrites referenced by SchedAlias. AliasDefs needs to be sorted
644 // for the loop below that initializes Alias vectors.
645 RecVec AliasDefs
= Records
.getAllDerivedDefinitions("SchedAlias");
646 llvm::sort(AliasDefs
, LessRecord());
647 for (Record
*ADef
: AliasDefs
) {
648 Record
*MatchDef
= ADef
->getValueAsDef("MatchRW");
649 Record
*AliasDef
= ADef
->getValueAsDef("AliasRW");
650 if (MatchDef
->isSubClassOf("SchedWrite")) {
651 if (!AliasDef
->isSubClassOf("SchedWrite"))
652 PrintFatalError(ADef
->getLoc(), "SchedWrite Alias must be SchedWrite");
653 scanSchedRW(AliasDef
, SWDefs
, RWSet
);
656 assert(MatchDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
657 if (!AliasDef
->isSubClassOf("SchedRead"))
658 PrintFatalError(ADef
->getLoc(), "SchedRead Alias must be SchedRead");
659 scanSchedRW(AliasDef
, SRDefs
, RWSet
);
662 // Sort and add the SchedReadWrites directly referenced by instructions or
663 // itinerary resources. Index reads and writes in separate domains.
664 llvm::sort(SWDefs
, LessRecord());
665 for (Record
*SWDef
: SWDefs
) {
666 assert(!getSchedRWIdx(SWDef
, /*IsRead=*/false) && "duplicate SchedWrite");
667 SchedWrites
.emplace_back(SchedWrites
.size(), SWDef
);
669 llvm::sort(SRDefs
, LessRecord());
670 for (Record
*SRDef
: SRDefs
) {
671 assert(!getSchedRWIdx(SRDef
, /*IsRead-*/true) && "duplicate SchedWrite");
672 SchedReads
.emplace_back(SchedReads
.size(), SRDef
);
674 // Initialize WriteSequence vectors.
675 for (CodeGenSchedRW
&CGRW
: SchedWrites
) {
676 if (!CGRW
.IsSequence
)
678 findRWs(CGRW
.TheDef
->getValueAsListOfDefs("Writes"), CGRW
.Sequence
,
681 // Initialize Aliases vectors.
682 for (Record
*ADef
: AliasDefs
) {
683 Record
*AliasDef
= ADef
->getValueAsDef("AliasRW");
684 getSchedRW(AliasDef
).IsAlias
= true;
685 Record
*MatchDef
= ADef
->getValueAsDef("MatchRW");
686 CodeGenSchedRW
&RW
= getSchedRW(MatchDef
);
688 PrintFatalError(ADef
->getLoc(), "Cannot Alias an Alias");
689 RW
.Aliases
.push_back(ADef
);
692 dbgs() << "\n+++ SCHED READS and WRITES (collectSchedRW) +++\n";
693 for (unsigned WIdx
= 0, WEnd
= SchedWrites
.size(); WIdx
!= WEnd
; ++WIdx
) {
694 dbgs() << WIdx
<< ": ";
695 SchedWrites
[WIdx
].dump();
697 } for (unsigned RIdx
= 0, REnd
= SchedReads
.size(); RIdx
!= REnd
;
699 dbgs() << RIdx
<< ": ";
700 SchedReads
[RIdx
].dump();
702 } RecVec RWDefs
= Records
.getAllDerivedDefinitions("SchedReadWrite");
705 if (!getSchedRWIdx(RWDef
, RWDef
->isSubClassOf("SchedRead"))) {
706 StringRef Name
= RWDef
->getName();
707 if (Name
!= "NoWrite" && Name
!= "ReadDefault")
708 dbgs() << "Unused SchedReadWrite " << Name
<< '\n';
713 /// Compute a SchedWrite name from a sequence of writes.
714 std::string
CodeGenSchedModels::genRWName(ArrayRef
<unsigned> Seq
, bool IsRead
) {
715 std::string
Name("(");
716 for (auto I
= Seq
.begin(), E
= Seq
.end(); I
!= E
; ++I
) {
717 if (I
!= Seq
.begin())
719 Name
+= getSchedRW(*I
, IsRead
).Name
;
725 unsigned CodeGenSchedModels::getSchedRWIdx(const Record
*Def
,
727 const std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
728 const auto I
= find_if(
729 RWVec
, [Def
](const CodeGenSchedRW
&RW
) { return RW
.TheDef
== Def
; });
730 return I
== RWVec
.end() ? 0 : std::distance(RWVec
.begin(), I
);
733 bool CodeGenSchedModels::hasReadOfWrite(Record
*WriteDef
) const {
734 for (const CodeGenSchedRW
&Read
: SchedReads
) {
735 Record
*ReadDef
= Read
.TheDef
;
736 if (!ReadDef
|| !ReadDef
->isSubClassOf("ProcReadAdvance"))
739 RecVec ValidWrites
= ReadDef
->getValueAsListOfDefs("ValidWrites");
740 if (is_contained(ValidWrites
, WriteDef
)) {
747 static void splitSchedReadWrites(const RecVec
&RWDefs
,
748 RecVec
&WriteDefs
, RecVec
&ReadDefs
) {
749 for (Record
*RWDef
: RWDefs
) {
750 if (RWDef
->isSubClassOf("SchedWrite"))
751 WriteDefs
.push_back(RWDef
);
753 assert(RWDef
->isSubClassOf("SchedRead") && "unknown SchedReadWrite");
754 ReadDefs
.push_back(RWDef
);
759 // Split the SchedReadWrites defs and call findRWs for each list.
760 void CodeGenSchedModels::findRWs(const RecVec
&RWDefs
,
761 IdxVec
&Writes
, IdxVec
&Reads
) const {
764 splitSchedReadWrites(RWDefs
, WriteDefs
, ReadDefs
);
765 findRWs(WriteDefs
, Writes
, false);
766 findRWs(ReadDefs
, Reads
, true);
769 // Call getSchedRWIdx for all elements in a sequence of SchedRW defs.
770 void CodeGenSchedModels::findRWs(const RecVec
&RWDefs
, IdxVec
&RWs
,
772 for (Record
*RWDef
: RWDefs
) {
773 unsigned Idx
= getSchedRWIdx(RWDef
, IsRead
);
774 assert(Idx
&& "failed to collect SchedReadWrite");
779 void CodeGenSchedModels::expandRWSequence(unsigned RWIdx
, IdxVec
&RWSeq
,
781 const CodeGenSchedRW
&SchedRW
= getSchedRW(RWIdx
, IsRead
);
782 if (!SchedRW
.IsSequence
) {
783 RWSeq
.push_back(RWIdx
);
787 SchedRW
.TheDef
? SchedRW
.TheDef
->getValueAsInt("Repeat") : 1;
788 for (int i
= 0; i
< Repeat
; ++i
) {
789 for (unsigned I
: SchedRW
.Sequence
) {
790 expandRWSequence(I
, RWSeq
, IsRead
);
795 // Expand a SchedWrite as a sequence following any aliases that coincide with
796 // the given processor model.
797 void CodeGenSchedModels::expandRWSeqForProc(
798 unsigned RWIdx
, IdxVec
&RWSeq
, bool IsRead
,
799 const CodeGenProcModel
&ProcModel
) const {
801 const CodeGenSchedRW
&SchedWrite
= getSchedRW(RWIdx
, IsRead
);
802 Record
*AliasDef
= nullptr;
803 for (const Record
*Rec
: SchedWrite
.Aliases
) {
804 const CodeGenSchedRW
&AliasRW
= getSchedRW(Rec
->getValueAsDef("AliasRW"));
805 if (Rec
->getValueInit("SchedModel")->isComplete()) {
806 Record
*ModelDef
= Rec
->getValueAsDef("SchedModel");
807 if (&getProcModel(ModelDef
) != &ProcModel
)
811 PrintFatalError(AliasRW
.TheDef
->getLoc(), "Multiple aliases "
812 "defined for processor " + ProcModel
.ModelName
+
813 " Ensure only one SchedAlias exists per RW.");
814 AliasDef
= AliasRW
.TheDef
;
817 expandRWSeqForProc(getSchedRWIdx(AliasDef
, IsRead
),
818 RWSeq
, IsRead
,ProcModel
);
821 if (!SchedWrite
.IsSequence
) {
822 RWSeq
.push_back(RWIdx
);
826 SchedWrite
.TheDef
? SchedWrite
.TheDef
->getValueAsInt("Repeat") : 1;
827 for (int I
= 0, E
= Repeat
; I
< E
; ++I
) {
828 for (unsigned Idx
: SchedWrite
.Sequence
) {
829 expandRWSeqForProc(Idx
, RWSeq
, IsRead
, ProcModel
);
834 // Find the existing SchedWrite that models this sequence of writes.
835 unsigned CodeGenSchedModels::findRWForSequence(ArrayRef
<unsigned> Seq
,
837 std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
839 auto I
= find_if(RWVec
, [Seq
](CodeGenSchedRW
&RW
) {
840 return makeArrayRef(RW
.Sequence
) == Seq
;
842 // Index zero reserved for invalid RW.
843 return I
== RWVec
.end() ? 0 : std::distance(RWVec
.begin(), I
);
846 /// Add this ReadWrite if it doesn't already exist.
847 unsigned CodeGenSchedModels::findOrInsertRW(ArrayRef
<unsigned> Seq
,
849 assert(!Seq
.empty() && "cannot insert empty sequence");
853 unsigned Idx
= findRWForSequence(Seq
, IsRead
);
857 std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
858 unsigned RWIdx
= RWVec
.size();
859 CodeGenSchedRW
SchedRW(RWIdx
, IsRead
, Seq
, genRWName(Seq
, IsRead
));
860 RWVec
.push_back(SchedRW
);
864 /// Visit all the instruction definitions for this target to gather and
865 /// enumerate the itinerary classes. These are the explicitly specified
866 /// SchedClasses. More SchedClasses may be inferred.
867 void CodeGenSchedModels::collectSchedClasses() {
869 // NoItinerary is always the first class at Idx=0
870 assert(SchedClasses
.empty() && "Expected empty sched class");
871 SchedClasses
.emplace_back(0, "NoInstrModel",
872 Records
.getDef("NoItinerary"));
873 SchedClasses
.back().ProcIndices
.push_back(0);
875 // Create a SchedClass for each unique combination of itinerary class and
877 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
878 Record
*ItinDef
= Inst
->TheDef
->getValueAsDef("Itinerary");
879 IdxVec Writes
, Reads
;
880 if (!Inst
->TheDef
->isValueUnset("SchedRW"))
881 findRWs(Inst
->TheDef
->getValueAsListOfDefs("SchedRW"), Writes
, Reads
);
883 // ProcIdx == 0 indicates the class applies to all processors.
884 unsigned SCIdx
= addSchedClass(ItinDef
, Writes
, Reads
, /*ProcIndices*/{0});
885 InstrClassMap
[Inst
->TheDef
] = SCIdx
;
887 // Create classes for InstRW defs.
888 RecVec InstRWDefs
= Records
.getAllDerivedDefinitions("InstRW");
889 llvm::sort(InstRWDefs
, LessRecord());
890 LLVM_DEBUG(dbgs() << "\n+++ SCHED CLASSES (createInstRWClass) +++\n");
891 for (Record
*RWDef
: InstRWDefs
)
892 createInstRWClass(RWDef
);
894 NumInstrSchedClasses
= SchedClasses
.size();
896 bool EnableDump
= false;
897 LLVM_DEBUG(EnableDump
= true);
903 << "\n+++ ITINERARIES and/or MACHINE MODELS (collectSchedClasses) +++\n");
904 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
905 StringRef InstName
= Inst
->TheDef
->getName();
906 unsigned SCIdx
= getSchedClassIdx(*Inst
);
909 if (!Inst
->hasNoSchedulingInfo
)
910 dbgs() << "No machine model for " << Inst
->TheDef
->getName() << '\n';
914 CodeGenSchedClass
&SC
= getSchedClass(SCIdx
);
915 if (SC
.ProcIndices
[0] != 0)
916 PrintFatalError(Inst
->TheDef
->getLoc(), "Instruction's sched class "
917 "must not be subtarget specific.");
920 if (SC
.ItinClassDef
->getName() != "NoItinerary") {
921 ProcIndices
.push_back(0);
922 dbgs() << "Itinerary for " << InstName
<< ": "
923 << SC
.ItinClassDef
->getName() << '\n';
925 if (!SC
.Writes
.empty()) {
926 ProcIndices
.push_back(0);
928 dbgs() << "SchedRW machine model for " << InstName
;
929 for (IdxIter WI
= SC
.Writes
.begin(), WE
= SC
.Writes
.end(); WI
!= WE
;
931 dbgs() << " " << SchedWrites
[*WI
].Name
;
932 for (IdxIter RI
= SC
.Reads
.begin(), RE
= SC
.Reads
.end(); RI
!= RE
; ++RI
)
933 dbgs() << " " << SchedReads
[*RI
].Name
;
937 const RecVec
&RWDefs
= SchedClasses
[SCIdx
].InstRWs
;
938 for (Record
*RWDef
: RWDefs
) {
939 const CodeGenProcModel
&ProcModel
=
940 getProcModel(RWDef
->getValueAsDef("SchedModel"));
941 ProcIndices
.push_back(ProcModel
.Index
);
942 LLVM_DEBUG(dbgs() << "InstRW on " << ProcModel
.ModelName
<< " for "
946 findRWs(RWDef
->getValueAsListOfDefs("OperandReadWrites"),
949 for (unsigned WIdx
: Writes
)
950 dbgs() << " " << SchedWrites
[WIdx
].Name
;
951 for (unsigned RIdx
: Reads
)
952 dbgs() << " " << SchedReads
[RIdx
].Name
;
956 // If ProcIndices contains zero, the class applies to all processors.
958 if (!std::count(ProcIndices
.begin(), ProcIndices
.end(), 0)) {
959 for (const CodeGenProcModel
&PM
: ProcModels
) {
960 if (!std::count(ProcIndices
.begin(), ProcIndices
.end(), PM
.Index
))
961 dbgs() << "No machine model for " << Inst
->TheDef
->getName()
962 << " on processor " << PM
.ModelName
<< '\n';
969 // Get the SchedClass index for an instruction.
971 CodeGenSchedModels::getSchedClassIdx(const CodeGenInstruction
&Inst
) const {
972 return InstrClassMap
.lookup(Inst
.TheDef
);
976 CodeGenSchedModels::createSchedClassName(Record
*ItinClassDef
,
977 ArrayRef
<unsigned> OperWrites
,
978 ArrayRef
<unsigned> OperReads
) {
981 if (ItinClassDef
&& ItinClassDef
->getName() != "NoItinerary")
982 Name
= ItinClassDef
->getName();
983 for (unsigned Idx
: OperWrites
) {
986 Name
+= SchedWrites
[Idx
].Name
;
988 for (unsigned Idx
: OperReads
) {
990 Name
+= SchedReads
[Idx
].Name
;
995 std::string
CodeGenSchedModels::createSchedClassName(const RecVec
&InstDefs
) {
998 for (RecIter I
= InstDefs
.begin(), E
= InstDefs
.end(); I
!= E
; ++I
) {
999 if (I
!= InstDefs
.begin())
1001 Name
+= (*I
)->getName();
1006 /// Add an inferred sched class from an itinerary class and per-operand list of
1007 /// SchedWrites and SchedReads. ProcIndices contains the set of IDs of
1008 /// processors that may utilize this class.
1009 unsigned CodeGenSchedModels::addSchedClass(Record
*ItinClassDef
,
1010 ArrayRef
<unsigned> OperWrites
,
1011 ArrayRef
<unsigned> OperReads
,
1012 ArrayRef
<unsigned> ProcIndices
) {
1013 assert(!ProcIndices
.empty() && "expect at least one ProcIdx");
1015 auto IsKeyEqual
= [=](const CodeGenSchedClass
&SC
) {
1016 return SC
.isKeyEqual(ItinClassDef
, OperWrites
, OperReads
);
1019 auto I
= find_if(make_range(schedClassBegin(), schedClassEnd()), IsKeyEqual
);
1020 unsigned Idx
= I
== schedClassEnd() ? 0 : std::distance(schedClassBegin(), I
);
1021 if (Idx
|| SchedClasses
[0].isKeyEqual(ItinClassDef
, OperWrites
, OperReads
)) {
1023 std::set_union(SchedClasses
[Idx
].ProcIndices
.begin(),
1024 SchedClasses
[Idx
].ProcIndices
.end(),
1025 ProcIndices
.begin(), ProcIndices
.end(),
1026 std::back_inserter(PI
));
1027 SchedClasses
[Idx
].ProcIndices
= std::move(PI
);
1030 Idx
= SchedClasses
.size();
1031 SchedClasses
.emplace_back(Idx
,
1032 createSchedClassName(ItinClassDef
, OperWrites
,
1035 CodeGenSchedClass
&SC
= SchedClasses
.back();
1036 SC
.Writes
= OperWrites
;
1037 SC
.Reads
= OperReads
;
1038 SC
.ProcIndices
= ProcIndices
;
1043 // Create classes for each set of opcodes that are in the same InstReadWrite
1044 // definition across all processors.
1045 void CodeGenSchedModels::createInstRWClass(Record
*InstRWDef
) {
1046 // ClassInstrs will hold an entry for each subset of Instrs in InstRWDef that
1047 // intersects with an existing class via a previous InstRWDef. Instrs that do
1048 // not intersect with an existing class refer back to their former class as
1049 // determined from ItinDef or SchedRW.
1050 SmallMapVector
<unsigned, SmallVector
<Record
*, 8>, 4> ClassInstrs
;
1051 // Sort Instrs into sets.
1052 const RecVec
*InstDefs
= Sets
.expand(InstRWDef
);
1053 if (InstDefs
->empty())
1054 PrintFatalError(InstRWDef
->getLoc(), "No matching instruction opcodes");
1056 for (Record
*InstDef
: *InstDefs
) {
1057 InstClassMapTy::const_iterator Pos
= InstrClassMap
.find(InstDef
);
1058 if (Pos
== InstrClassMap
.end())
1059 PrintFatalError(InstDef
->getLoc(), "No sched class for instruction.");
1060 unsigned SCIdx
= Pos
->second
;
1061 ClassInstrs
[SCIdx
].push_back(InstDef
);
1063 // For each set of Instrs, create a new class if necessary, and map or remap
1064 // the Instrs to it.
1065 for (auto &Entry
: ClassInstrs
) {
1066 unsigned OldSCIdx
= Entry
.first
;
1067 ArrayRef
<Record
*> InstDefs
= Entry
.second
;
1068 // If the all instrs in the current class are accounted for, then leave
1069 // them mapped to their old class.
1071 const RecVec
&RWDefs
= SchedClasses
[OldSCIdx
].InstRWs
;
1072 if (!RWDefs
.empty()) {
1073 const RecVec
*OrigInstDefs
= Sets
.expand(RWDefs
[0]);
1074 unsigned OrigNumInstrs
=
1075 count_if(*OrigInstDefs
, [&](Record
*OIDef
) {
1076 return InstrClassMap
[OIDef
] == OldSCIdx
;
1078 if (OrigNumInstrs
== InstDefs
.size()) {
1079 assert(SchedClasses
[OldSCIdx
].ProcIndices
[0] == 0 &&
1080 "expected a generic SchedClass");
1081 Record
*RWModelDef
= InstRWDef
->getValueAsDef("SchedModel");
1082 // Make sure we didn't already have a InstRW containing this
1083 // instruction on this model.
1084 for (Record
*RWD
: RWDefs
) {
1085 if (RWD
->getValueAsDef("SchedModel") == RWModelDef
&&
1086 RWModelDef
->getValueAsBit("FullInstRWOverlapCheck")) {
1087 for (Record
*Inst
: InstDefs
) {
1088 PrintFatalError(InstRWDef
->getLoc(), "Overlapping InstRW def " +
1089 Inst
->getName() + " also matches " +
1090 RWD
->getValue("Instrs")->getValue()->getAsString());
1094 LLVM_DEBUG(dbgs() << "InstRW: Reuse SC " << OldSCIdx
<< ":"
1095 << SchedClasses
[OldSCIdx
].Name
<< " on "
1096 << RWModelDef
->getName() << "\n");
1097 SchedClasses
[OldSCIdx
].InstRWs
.push_back(InstRWDef
);
1102 unsigned SCIdx
= SchedClasses
.size();
1103 SchedClasses
.emplace_back(SCIdx
, createSchedClassName(InstDefs
), nullptr);
1104 CodeGenSchedClass
&SC
= SchedClasses
.back();
1105 LLVM_DEBUG(dbgs() << "InstRW: New SC " << SCIdx
<< ":" << SC
.Name
<< " on "
1106 << InstRWDef
->getValueAsDef("SchedModel")->getName()
1109 // Preserve ItinDef and Writes/Reads for processors without an InstRW entry.
1110 SC
.ItinClassDef
= SchedClasses
[OldSCIdx
].ItinClassDef
;
1111 SC
.Writes
= SchedClasses
[OldSCIdx
].Writes
;
1112 SC
.Reads
= SchedClasses
[OldSCIdx
].Reads
;
1113 SC
.ProcIndices
.push_back(0);
1114 // If we had an old class, copy it's InstRWs to this new class.
1116 Record
*RWModelDef
= InstRWDef
->getValueAsDef("SchedModel");
1117 for (Record
*OldRWDef
: SchedClasses
[OldSCIdx
].InstRWs
) {
1118 if (OldRWDef
->getValueAsDef("SchedModel") == RWModelDef
) {
1119 for (Record
*InstDef
: InstDefs
) {
1120 PrintFatalError(OldRWDef
->getLoc(), "Overlapping InstRW def " +
1121 InstDef
->getName() + " also matches " +
1122 OldRWDef
->getValue("Instrs")->getValue()->getAsString());
1125 assert(OldRWDef
!= InstRWDef
&&
1126 "SchedClass has duplicate InstRW def");
1127 SC
.InstRWs
.push_back(OldRWDef
);
1130 // Map each Instr to this new class.
1131 for (Record
*InstDef
: InstDefs
)
1132 InstrClassMap
[InstDef
] = SCIdx
;
1133 SC
.InstRWs
.push_back(InstRWDef
);
1137 // True if collectProcItins found anything.
1138 bool CodeGenSchedModels::hasItineraries() const {
1139 for (const CodeGenProcModel
&PM
: make_range(procModelBegin(),procModelEnd()))
1140 if (PM
.hasItineraries())
1145 // Gather the processor itineraries.
1146 void CodeGenSchedModels::collectProcItins() {
1147 LLVM_DEBUG(dbgs() << "\n+++ PROBLEM ITINERARIES (collectProcItins) +++\n");
1148 for (CodeGenProcModel
&ProcModel
: ProcModels
) {
1149 if (!ProcModel
.hasItineraries())
1152 RecVec ItinRecords
= ProcModel
.ItinsDef
->getValueAsListOfDefs("IID");
1153 assert(!ItinRecords
.empty() && "ProcModel.hasItineraries is incorrect");
1155 // Populate ItinDefList with Itinerary records.
1156 ProcModel
.ItinDefList
.resize(NumInstrSchedClasses
);
1158 // Insert each itinerary data record in the correct position within
1159 // the processor model's ItinDefList.
1160 for (Record
*ItinData
: ItinRecords
) {
1161 const Record
*ItinDef
= ItinData
->getValueAsDef("TheClass");
1162 bool FoundClass
= false;
1164 for (const CodeGenSchedClass
&SC
:
1165 make_range(schedClassBegin(), schedClassEnd())) {
1166 // Multiple SchedClasses may share an itinerary. Update all of them.
1167 if (SC
.ItinClassDef
== ItinDef
) {
1168 ProcModel
.ItinDefList
[SC
.Index
] = ItinData
;
1173 LLVM_DEBUG(dbgs() << ProcModel
.ItinsDef
->getName()
1174 << " missing class for itinerary "
1175 << ItinDef
->getName() << '\n');
1178 // Check for missing itinerary entries.
1179 assert(!ProcModel
.ItinDefList
[0] && "NoItinerary class can't have rec");
1181 for (unsigned i
= 1, N
= ProcModel
.ItinDefList
.size(); i
< N
; ++i
) {
1182 if (!ProcModel
.ItinDefList
[i
])
1183 dbgs() << ProcModel
.ItinsDef
->getName()
1184 << " missing itinerary for class " << SchedClasses
[i
].Name
1190 // Gather the read/write types for each itinerary class.
1191 void CodeGenSchedModels::collectProcItinRW() {
1192 RecVec ItinRWDefs
= Records
.getAllDerivedDefinitions("ItinRW");
1193 llvm::sort(ItinRWDefs
, LessRecord());
1194 for (Record
*RWDef
: ItinRWDefs
) {
1195 if (!RWDef
->getValueInit("SchedModel")->isComplete())
1196 PrintFatalError(RWDef
->getLoc(), "SchedModel is undefined");
1197 Record
*ModelDef
= RWDef
->getValueAsDef("SchedModel");
1198 ProcModelMapTy::const_iterator I
= ProcModelMap
.find(ModelDef
);
1199 if (I
== ProcModelMap
.end()) {
1200 PrintFatalError(RWDef
->getLoc(), "Undefined SchedMachineModel "
1201 + ModelDef
->getName());
1203 ProcModels
[I
->second
].ItinRWDefs
.push_back(RWDef
);
1207 // Gather the unsupported features for processor models.
1208 void CodeGenSchedModels::collectProcUnsupportedFeatures() {
1209 for (CodeGenProcModel
&ProcModel
: ProcModels
) {
1210 for (Record
*Pred
: ProcModel
.ModelDef
->getValueAsListOfDefs("UnsupportedFeatures")) {
1211 ProcModel
.UnsupportedFeaturesDefs
.push_back(Pred
);
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 (!std::count(Matched
.begin(), Matched
.end(), 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.
1287 // Helper for substituteVariantOperand.
1288 struct TransVariant
{
1289 Record
*VarOrSeqDef
; // Variant or sequence.
1290 unsigned RWIdx
; // Index of this variant or sequence's matched type.
1291 unsigned ProcIdx
; // Processor model index or zero for any.
1292 unsigned TransVecIdx
; // Index into PredTransitions::TransVec.
1294 TransVariant(Record
*def
, unsigned rwi
, unsigned pi
, unsigned ti
):
1295 VarOrSeqDef(def
), RWIdx(rwi
), ProcIdx(pi
), TransVecIdx(ti
) {}
1298 // Associate a predicate with the SchedReadWrite that it guards.
1299 // RWIdx is the index of the read/write variant.
1305 PredCheck(bool r
, unsigned w
, Record
*p
): IsRead(r
), RWIdx(w
), Predicate(p
) {}
1308 // A Predicate transition is a list of RW sequences guarded by a PredTerm.
1309 struct PredTransition
{
1310 // A predicate term is a conjunction of PredChecks.
1311 SmallVector
<PredCheck
, 4> PredTerm
;
1312 SmallVector
<SmallVector
<unsigned,4>, 16> WriteSequences
;
1313 SmallVector
<SmallVector
<unsigned,4>, 16> ReadSequences
;
1314 SmallVector
<unsigned, 4> ProcIndices
;
1317 // Encapsulate a set of partially constructed transitions.
1318 // The results are built by repeated calls to substituteVariants.
1319 class PredTransitions
{
1320 CodeGenSchedModels
&SchedModels
;
1323 std::vector
<PredTransition
> TransVec
;
1325 PredTransitions(CodeGenSchedModels
&sm
): SchedModels(sm
) {}
1327 void substituteVariantOperand(const SmallVectorImpl
<unsigned> &RWSeq
,
1328 bool IsRead
, unsigned StartIdx
);
1330 void substituteVariants(const PredTransition
&Trans
);
1337 bool mutuallyExclusive(Record
*PredDef
, ArrayRef
<PredCheck
> Term
);
1338 void getIntersectingVariants(
1339 const CodeGenSchedRW
&SchedRW
, unsigned TransIdx
,
1340 std::vector
<TransVariant
> &IntersectingVariants
);
1341 void pushVariant(const TransVariant
&VInfo
, bool IsRead
);
1344 } // end anonymous namespace
1346 // Return true if this predicate is mutually exclusive with a PredTerm. This
1347 // degenerates into checking if the predicate is mutually exclusive with any
1348 // predicate in the Term's conjunction.
1350 // All predicates associated with a given SchedRW are considered mutually
1351 // exclusive. This should work even if the conditions expressed by the
1352 // predicates are not exclusive because the predicates for a given SchedWrite
1353 // are always checked in the order they are defined in the .td file. Later
1354 // conditions implicitly negate any prior condition.
1355 bool PredTransitions::mutuallyExclusive(Record
*PredDef
,
1356 ArrayRef
<PredCheck
> Term
) {
1357 for (const PredCheck
&PC
: Term
) {
1358 if (PC
.Predicate
== PredDef
)
1361 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(PC
.RWIdx
, PC
.IsRead
);
1362 assert(SchedRW
.HasVariants
&& "PredCheck must refer to a SchedVariant");
1363 RecVec Variants
= SchedRW
.TheDef
->getValueAsListOfDefs("Variants");
1364 if (any_of(Variants
, [PredDef
](const Record
*R
) {
1365 return R
->getValueAsDef("Predicate") == PredDef
;
1372 static bool hasAliasedVariants(const CodeGenSchedRW
&RW
,
1373 CodeGenSchedModels
&SchedModels
) {
1377 for (Record
*Alias
: RW
.Aliases
) {
1378 const CodeGenSchedRW
&AliasRW
=
1379 SchedModels
.getSchedRW(Alias
->getValueAsDef("AliasRW"));
1380 if (AliasRW
.HasVariants
)
1382 if (AliasRW
.IsSequence
) {
1384 SchedModels
.expandRWSequence(AliasRW
.Index
, ExpandedRWs
, AliasRW
.IsRead
);
1385 for (unsigned SI
: ExpandedRWs
) {
1386 if (hasAliasedVariants(SchedModels
.getSchedRW(SI
, AliasRW
.IsRead
),
1395 static bool hasVariant(ArrayRef
<PredTransition
> Transitions
,
1396 CodeGenSchedModels
&SchedModels
) {
1397 for (const PredTransition
&PTI
: Transitions
) {
1398 for (const SmallVectorImpl
<unsigned> &WSI
: PTI
.WriteSequences
)
1399 for (unsigned WI
: WSI
)
1400 if (hasAliasedVariants(SchedModels
.getSchedWrite(WI
), SchedModels
))
1403 for (const SmallVectorImpl
<unsigned> &RSI
: PTI
.ReadSequences
)
1404 for (unsigned RI
: RSI
)
1405 if (hasAliasedVariants(SchedModels
.getSchedRead(RI
), SchedModels
))
1411 // Populate IntersectingVariants with any variants or aliased sequences of the
1412 // given SchedRW whose processor indices and predicates are not mutually
1413 // exclusive with the given transition.
1414 void PredTransitions::getIntersectingVariants(
1415 const CodeGenSchedRW
&SchedRW
, unsigned TransIdx
,
1416 std::vector
<TransVariant
> &IntersectingVariants
) {
1418 bool GenericRW
= false;
1420 std::vector
<TransVariant
> Variants
;
1421 if (SchedRW
.HasVariants
) {
1422 unsigned VarProcIdx
= 0;
1423 if (SchedRW
.TheDef
->getValueInit("SchedModel")->isComplete()) {
1424 Record
*ModelDef
= SchedRW
.TheDef
->getValueAsDef("SchedModel");
1425 VarProcIdx
= SchedModels
.getProcModel(ModelDef
).Index
;
1427 // Push each variant. Assign TransVecIdx later.
1428 const RecVec VarDefs
= SchedRW
.TheDef
->getValueAsListOfDefs("Variants");
1429 for (Record
*VarDef
: VarDefs
)
1430 Variants
.emplace_back(VarDef
, SchedRW
.Index
, VarProcIdx
, 0);
1431 if (VarProcIdx
== 0)
1434 for (RecIter AI
= SchedRW
.Aliases
.begin(), AE
= SchedRW
.Aliases
.end();
1436 // If either the SchedAlias itself or the SchedReadWrite that it aliases
1437 // to is defined within a processor model, constrain all variants to
1439 unsigned AliasProcIdx
= 0;
1440 if ((*AI
)->getValueInit("SchedModel")->isComplete()) {
1441 Record
*ModelDef
= (*AI
)->getValueAsDef("SchedModel");
1442 AliasProcIdx
= SchedModels
.getProcModel(ModelDef
).Index
;
1444 const CodeGenSchedRW
&AliasRW
=
1445 SchedModels
.getSchedRW((*AI
)->getValueAsDef("AliasRW"));
1447 if (AliasRW
.HasVariants
) {
1448 const RecVec VarDefs
= AliasRW
.TheDef
->getValueAsListOfDefs("Variants");
1449 for (Record
*VD
: VarDefs
)
1450 Variants
.emplace_back(VD
, AliasRW
.Index
, AliasProcIdx
, 0);
1452 if (AliasRW
.IsSequence
)
1453 Variants
.emplace_back(AliasRW
.TheDef
, SchedRW
.Index
, AliasProcIdx
, 0);
1454 if (AliasProcIdx
== 0)
1457 for (TransVariant
&Variant
: Variants
) {
1458 // Don't expand variants if the processor models don't intersect.
1459 // A zero processor index means any processor.
1460 SmallVectorImpl
<unsigned> &ProcIndices
= TransVec
[TransIdx
].ProcIndices
;
1461 if (ProcIndices
[0] && Variant
.ProcIdx
) {
1462 unsigned Cnt
= std::count(ProcIndices
.begin(), ProcIndices
.end(),
1467 const CodeGenProcModel
&PM
=
1468 *(SchedModels
.procModelBegin() + Variant
.ProcIdx
);
1469 PrintFatalError(Variant
.VarOrSeqDef
->getLoc(),
1470 "Multiple variants defined for processor " +
1472 " Ensure only one SchedAlias exists per RW.");
1475 if (Variant
.VarOrSeqDef
->isSubClassOf("SchedVar")) {
1476 Record
*PredDef
= Variant
.VarOrSeqDef
->getValueAsDef("Predicate");
1477 if (mutuallyExclusive(PredDef
, TransVec
[TransIdx
].PredTerm
))
1480 if (IntersectingVariants
.empty()) {
1481 // The first variant builds on the existing transition.
1482 Variant
.TransVecIdx
= TransIdx
;
1483 IntersectingVariants
.push_back(Variant
);
1486 // Push another copy of the current transition for more variants.
1487 Variant
.TransVecIdx
= TransVec
.size();
1488 IntersectingVariants
.push_back(Variant
);
1489 TransVec
.push_back(TransVec
[TransIdx
]);
1492 if (GenericRW
&& IntersectingVariants
.empty()) {
1493 PrintFatalError(SchedRW
.TheDef
->getLoc(), "No variant of this type has "
1494 "a matching predicate on any processor");
1498 // Push the Reads/Writes selected by this variant onto the PredTransition
1499 // specified by VInfo.
1500 void PredTransitions::
1501 pushVariant(const TransVariant
&VInfo
, bool IsRead
) {
1502 PredTransition
&Trans
= TransVec
[VInfo
.TransVecIdx
];
1504 // If this operand transition is reached through a processor-specific alias,
1505 // then the whole transition is specific to this processor.
1506 if (VInfo
.ProcIdx
!= 0)
1507 Trans
.ProcIndices
.assign(1, VInfo
.ProcIdx
);
1510 if (VInfo
.VarOrSeqDef
->isSubClassOf("SchedVar")) {
1511 Record
*PredDef
= VInfo
.VarOrSeqDef
->getValueAsDef("Predicate");
1512 Trans
.PredTerm
.emplace_back(IsRead
, VInfo
.RWIdx
,PredDef
);
1513 RecVec SelectedDefs
= VInfo
.VarOrSeqDef
->getValueAsListOfDefs("Selected");
1514 SchedModels
.findRWs(SelectedDefs
, SelectedRWs
, IsRead
);
1517 assert(VInfo
.VarOrSeqDef
->isSubClassOf("WriteSequence") &&
1518 "variant must be a SchedVariant or aliased WriteSequence");
1519 SelectedRWs
.push_back(SchedModels
.getSchedRWIdx(VInfo
.VarOrSeqDef
, IsRead
));
1522 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(VInfo
.RWIdx
, IsRead
);
1524 SmallVectorImpl
<SmallVector
<unsigned,4>> &RWSequences
= IsRead
1525 ? Trans
.ReadSequences
: Trans
.WriteSequences
;
1526 if (SchedRW
.IsVariadic
) {
1527 unsigned OperIdx
= RWSequences
.size()-1;
1528 // Make N-1 copies of this transition's last sequence.
1529 RWSequences
.insert(RWSequences
.end(), SelectedRWs
.size() - 1,
1530 RWSequences
[OperIdx
]);
1531 // Push each of the N elements of the SelectedRWs onto a copy of the last
1532 // sequence (split the current operand into N operands).
1533 // Note that write sequences should be expanded within this loop--the entire
1534 // sequence belongs to a single operand.
1535 for (IdxIter RWI
= SelectedRWs
.begin(), RWE
= SelectedRWs
.end();
1536 RWI
!= RWE
; ++RWI
, ++OperIdx
) {
1539 ExpandedRWs
.push_back(*RWI
);
1541 SchedModels
.expandRWSequence(*RWI
, ExpandedRWs
, IsRead
);
1542 RWSequences
[OperIdx
].insert(RWSequences
[OperIdx
].end(),
1543 ExpandedRWs
.begin(), ExpandedRWs
.end());
1545 assert(OperIdx
== RWSequences
.size() && "missed a sequence");
1548 // Push this transition's expanded sequence onto this transition's last
1549 // sequence (add to the current operand's sequence).
1550 SmallVectorImpl
<unsigned> &Seq
= RWSequences
.back();
1552 for (IdxIter RWI
= SelectedRWs
.begin(), RWE
= SelectedRWs
.end();
1553 RWI
!= RWE
; ++RWI
) {
1555 ExpandedRWs
.push_back(*RWI
);
1557 SchedModels
.expandRWSequence(*RWI
, ExpandedRWs
, IsRead
);
1559 Seq
.insert(Seq
.end(), ExpandedRWs
.begin(), ExpandedRWs
.end());
1563 // RWSeq is a sequence of all Reads or all Writes for the next read or write
1564 // operand. StartIdx is an index into TransVec where partial results
1565 // starts. RWSeq must be applied to all transitions between StartIdx and the end
1567 void PredTransitions::substituteVariantOperand(
1568 const SmallVectorImpl
<unsigned> &RWSeq
, bool IsRead
, unsigned StartIdx
) {
1570 // Visit each original RW within the current sequence.
1571 for (SmallVectorImpl
<unsigned>::const_iterator
1572 RWI
= RWSeq
.begin(), RWE
= RWSeq
.end(); RWI
!= RWE
; ++RWI
) {
1573 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(*RWI
, IsRead
);
1574 // Push this RW on all partial PredTransitions or distribute variants.
1575 // New PredTransitions may be pushed within this loop which should not be
1576 // revisited (TransEnd must be loop invariant).
1577 for (unsigned TransIdx
= StartIdx
, TransEnd
= TransVec
.size();
1578 TransIdx
!= TransEnd
; ++TransIdx
) {
1579 // In the common case, push RW onto the current operand's sequence.
1580 if (!hasAliasedVariants(SchedRW
, SchedModels
)) {
1582 TransVec
[TransIdx
].ReadSequences
.back().push_back(*RWI
);
1584 TransVec
[TransIdx
].WriteSequences
.back().push_back(*RWI
);
1587 // Distribute this partial PredTransition across intersecting variants.
1588 // This will push a copies of TransVec[TransIdx] on the back of TransVec.
1589 std::vector
<TransVariant
> IntersectingVariants
;
1590 getIntersectingVariants(SchedRW
, TransIdx
, IntersectingVariants
);
1591 // Now expand each variant on top of its copy of the transition.
1592 for (std::vector
<TransVariant
>::const_iterator
1593 IVI
= IntersectingVariants
.begin(),
1594 IVE
= IntersectingVariants
.end();
1595 IVI
!= IVE
; ++IVI
) {
1596 pushVariant(*IVI
, IsRead
);
1602 // For each variant of a Read/Write in Trans, substitute the sequence of
1603 // Read/Writes guarded by the variant. This is exponential in the number of
1604 // variant Read/Writes, but in practice detection of mutually exclusive
1605 // predicates should result in linear growth in the total number variants.
1607 // This is one step in a breadth-first search of nested variants.
1608 void PredTransitions::substituteVariants(const PredTransition
&Trans
) {
1609 // Build up a set of partial results starting at the back of
1610 // PredTransitions. Remember the first new transition.
1611 unsigned StartIdx
= TransVec
.size();
1612 TransVec
.emplace_back();
1613 TransVec
.back().PredTerm
= Trans
.PredTerm
;
1614 TransVec
.back().ProcIndices
= Trans
.ProcIndices
;
1616 // Visit each original write sequence.
1617 for (SmallVectorImpl
<SmallVector
<unsigned,4>>::const_iterator
1618 WSI
= Trans
.WriteSequences
.begin(), WSE
= Trans
.WriteSequences
.end();
1619 WSI
!= WSE
; ++WSI
) {
1620 // Push a new (empty) write sequence onto all partial Transitions.
1621 for (std::vector
<PredTransition
>::iterator I
=
1622 TransVec
.begin() + StartIdx
, E
= TransVec
.end(); I
!= E
; ++I
) {
1623 I
->WriteSequences
.emplace_back();
1625 substituteVariantOperand(*WSI
, /*IsRead=*/false, StartIdx
);
1627 // Visit each original read sequence.
1628 for (SmallVectorImpl
<SmallVector
<unsigned,4>>::const_iterator
1629 RSI
= Trans
.ReadSequences
.begin(), RSE
= Trans
.ReadSequences
.end();
1630 RSI
!= RSE
; ++RSI
) {
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 substituteVariantOperand(*RSI
, /*IsRead=*/true, StartIdx
);
1640 // Create a new SchedClass for each variant found by inferFromRW. Pass
1641 static void inferFromTransitions(ArrayRef
<PredTransition
> LastTransitions
,
1642 unsigned FromClassIdx
,
1643 CodeGenSchedModels
&SchedModels
) {
1644 // For each PredTransition, create a new CodeGenSchedTransition, which usually
1645 // requires creating a new SchedClass.
1646 for (ArrayRef
<PredTransition
>::iterator
1647 I
= LastTransitions
.begin(), E
= LastTransitions
.end(); I
!= E
; ++I
) {
1648 IdxVec OperWritesVariant
;
1649 transform(I
->WriteSequences
, std::back_inserter(OperWritesVariant
),
1650 [&SchedModels
](ArrayRef
<unsigned> WS
) {
1651 return SchedModels
.findOrInsertRW(WS
, /*IsRead=*/false);
1653 IdxVec OperReadsVariant
;
1654 transform(I
->ReadSequences
, std::back_inserter(OperReadsVariant
),
1655 [&SchedModels
](ArrayRef
<unsigned> RS
) {
1656 return SchedModels
.findOrInsertRW(RS
, /*IsRead=*/true);
1658 CodeGenSchedTransition SCTrans
;
1659 SCTrans
.ToClassIdx
=
1660 SchedModels
.addSchedClass(/*ItinClassDef=*/nullptr, OperWritesVariant
,
1661 OperReadsVariant
, I
->ProcIndices
);
1662 SCTrans
.ProcIndices
.assign(I
->ProcIndices
.begin(), I
->ProcIndices
.end());
1663 // The final PredTerm is unique set of predicates guarding the transition.
1665 transform(I
->PredTerm
, std::back_inserter(Preds
),
1666 [](const PredCheck
&P
) {
1669 Preds
.erase(std::unique(Preds
.begin(), Preds
.end()), Preds
.end());
1670 SCTrans
.PredTerm
= std::move(Preds
);
1671 SchedModels
.getSchedClass(FromClassIdx
)
1672 .Transitions
.push_back(std::move(SCTrans
));
1676 // Create new SchedClasses for the given ReadWrite list. If any of the
1677 // ReadWrites refers to a SchedVariant, create a new SchedClass for each variant
1678 // of the ReadWrite list, following Aliases if necessary.
1679 void CodeGenSchedModels::inferFromRW(ArrayRef
<unsigned> OperWrites
,
1680 ArrayRef
<unsigned> OperReads
,
1681 unsigned FromClassIdx
,
1682 ArrayRef
<unsigned> ProcIndices
) {
1683 LLVM_DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices
);
1686 // Create a seed transition with an empty PredTerm and the expanded sequences
1687 // of SchedWrites for the current SchedClass.
1688 std::vector
<PredTransition
> LastTransitions
;
1689 LastTransitions
.emplace_back();
1690 LastTransitions
.back().ProcIndices
.append(ProcIndices
.begin(),
1693 for (unsigned WriteIdx
: OperWrites
) {
1695 expandRWSequence(WriteIdx
, WriteSeq
, /*IsRead=*/false);
1696 LastTransitions
[0].WriteSequences
.emplace_back();
1697 SmallVectorImpl
<unsigned> &Seq
= LastTransitions
[0].WriteSequences
.back();
1698 Seq
.append(WriteSeq
.begin(), WriteSeq
.end());
1699 LLVM_DEBUG(dbgs() << "("; dumpIdxVec(Seq
); dbgs() << ") ");
1701 LLVM_DEBUG(dbgs() << " Reads: ");
1702 for (unsigned ReadIdx
: OperReads
) {
1704 expandRWSequence(ReadIdx
, ReadSeq
, /*IsRead=*/true);
1705 LastTransitions
[0].ReadSequences
.emplace_back();
1706 SmallVectorImpl
<unsigned> &Seq
= LastTransitions
[0].ReadSequences
.back();
1707 Seq
.append(ReadSeq
.begin(), ReadSeq
.end());
1708 LLVM_DEBUG(dbgs() << "("; dumpIdxVec(Seq
); dbgs() << ") ");
1710 LLVM_DEBUG(dbgs() << '\n');
1712 // Collect all PredTransitions for individual operands.
1713 // Iterate until no variant writes remain.
1714 while (hasVariant(LastTransitions
, *this)) {
1715 PredTransitions
Transitions(*this);
1716 for (const PredTransition
&Trans
: LastTransitions
)
1717 Transitions
.substituteVariants(Trans
);
1718 LLVM_DEBUG(Transitions
.dump());
1719 LastTransitions
.swap(Transitions
.TransVec
);
1721 // If the first transition has no variants, nothing to do.
1722 if (LastTransitions
[0].PredTerm
.empty())
1725 // WARNING: We are about to mutate the SchedClasses vector. Do not refer to
1726 // OperWrites, OperReads, or ProcIndices after calling inferFromTransitions.
1727 inferFromTransitions(LastTransitions
, FromClassIdx
, *this);
1730 // Check if any processor resource group contains all resource records in
1732 bool CodeGenSchedModels::hasSuperGroup(RecVec
&SubUnits
, CodeGenProcModel
&PM
) {
1733 for (unsigned i
= 0, e
= PM
.ProcResourceDefs
.size(); i
< e
; ++i
) {
1734 if (!PM
.ProcResourceDefs
[i
]->isSubClassOf("ProcResGroup"))
1737 PM
.ProcResourceDefs
[i
]->getValueAsListOfDefs("Resources");
1738 RecIter RI
= SubUnits
.begin(), RE
= SubUnits
.end();
1739 for ( ; RI
!= RE
; ++RI
) {
1740 if (!is_contained(SuperUnits
, *RI
)) {
1750 // Verify that overlapping groups have a common supergroup.
1751 void CodeGenSchedModels::verifyProcResourceGroups(CodeGenProcModel
&PM
) {
1752 for (unsigned i
= 0, e
= PM
.ProcResourceDefs
.size(); i
< e
; ++i
) {
1753 if (!PM
.ProcResourceDefs
[i
]->isSubClassOf("ProcResGroup"))
1756 PM
.ProcResourceDefs
[i
]->getValueAsListOfDefs("Resources");
1757 for (unsigned j
= i
+1; j
< e
; ++j
) {
1758 if (!PM
.ProcResourceDefs
[j
]->isSubClassOf("ProcResGroup"))
1761 PM
.ProcResourceDefs
[j
]->getValueAsListOfDefs("Resources");
1762 if (std::find_first_of(CheckUnits
.begin(), CheckUnits
.end(),
1763 OtherUnits
.begin(), OtherUnits
.end())
1764 != CheckUnits
.end()) {
1765 // CheckUnits and OtherUnits overlap
1766 OtherUnits
.insert(OtherUnits
.end(), CheckUnits
.begin(),
1768 if (!hasSuperGroup(OtherUnits
, PM
)) {
1769 PrintFatalError((PM
.ProcResourceDefs
[i
])->getLoc(),
1770 "proc resource group overlaps with "
1771 + PM
.ProcResourceDefs
[j
]->getName()
1772 + " but no supergroup contains both.");
1779 // Collect all the RegisterFile definitions available in this target.
1780 void CodeGenSchedModels::collectRegisterFiles() {
1781 RecVec RegisterFileDefs
= Records
.getAllDerivedDefinitions("RegisterFile");
1783 // RegisterFiles is the vector of CodeGenRegisterFile.
1784 for (Record
*RF
: RegisterFileDefs
) {
1785 // For each register file definition, construct a CodeGenRegisterFile object
1786 // and add it to the appropriate scheduling model.
1787 CodeGenProcModel
&PM
= getProcModel(RF
->getValueAsDef("SchedModel"));
1788 PM
.RegisterFiles
.emplace_back(CodeGenRegisterFile(RF
->getName(),RF
));
1789 CodeGenRegisterFile
&CGRF
= PM
.RegisterFiles
.back();
1790 CGRF
.MaxMovesEliminatedPerCycle
=
1791 RF
->getValueAsInt("MaxMovesEliminatedPerCycle");
1792 CGRF
.AllowZeroMoveEliminationOnly
=
1793 RF
->getValueAsBit("AllowZeroMoveEliminationOnly");
1795 // Now set the number of physical registers as well as the cost of registers
1796 // in each register class.
1797 CGRF
.NumPhysRegs
= RF
->getValueAsInt("NumPhysRegs");
1798 if (!CGRF
.NumPhysRegs
) {
1799 PrintFatalError(RF
->getLoc(),
1800 "Invalid RegisterFile with zero physical registers");
1803 RecVec RegisterClasses
= RF
->getValueAsListOfDefs("RegClasses");
1804 std::vector
<int64_t> RegisterCosts
= RF
->getValueAsListOfInts("RegCosts");
1805 ListInit
*MoveElimInfo
= RF
->getValueAsListInit("AllowMoveElimination");
1806 for (unsigned I
= 0, E
= RegisterClasses
.size(); I
< E
; ++I
) {
1807 int Cost
= RegisterCosts
.size() > I
? RegisterCosts
[I
] : 1;
1809 bool AllowMoveElim
= false;
1810 if (MoveElimInfo
->size() > I
) {
1811 BitInit
*Val
= cast
<BitInit
>(MoveElimInfo
->getElement(I
));
1812 AllowMoveElim
= Val
->getValue();
1815 CGRF
.Costs
.emplace_back(RegisterClasses
[I
], Cost
, AllowMoveElim
);
1820 // Collect and sort WriteRes, ReadAdvance, and ProcResources.
1821 void CodeGenSchedModels::collectProcResources() {
1822 ProcResourceDefs
= Records
.getAllDerivedDefinitions("ProcResourceUnits");
1823 ProcResGroups
= Records
.getAllDerivedDefinitions("ProcResGroup");
1825 // Add any subtarget-specific SchedReadWrites that are directly associated
1826 // with processor resources. Refer to the parent SchedClass's ProcIndices to
1827 // determine which processors they apply to.
1828 for (const CodeGenSchedClass
&SC
:
1829 make_range(schedClassBegin(), schedClassEnd())) {
1830 if (SC
.ItinClassDef
) {
1831 collectItinProcResources(SC
.ItinClassDef
);
1835 // This class may have a default ReadWrite list which can be overriden by
1836 // InstRW definitions.
1837 for (Record
*RW
: SC
.InstRWs
) {
1838 Record
*RWModelDef
= RW
->getValueAsDef("SchedModel");
1839 unsigned PIdx
= getProcModel(RWModelDef
).Index
;
1840 IdxVec Writes
, Reads
;
1841 findRWs(RW
->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1842 collectRWResources(Writes
, Reads
, PIdx
);
1845 collectRWResources(SC
.Writes
, SC
.Reads
, SC
.ProcIndices
);
1847 // Add resources separately defined by each subtarget.
1848 RecVec WRDefs
= Records
.getAllDerivedDefinitions("WriteRes");
1849 for (Record
*WR
: WRDefs
) {
1850 Record
*ModelDef
= WR
->getValueAsDef("SchedModel");
1851 addWriteRes(WR
, getProcModel(ModelDef
).Index
);
1853 RecVec SWRDefs
= Records
.getAllDerivedDefinitions("SchedWriteRes");
1854 for (Record
*SWR
: SWRDefs
) {
1855 Record
*ModelDef
= SWR
->getValueAsDef("SchedModel");
1856 addWriteRes(SWR
, getProcModel(ModelDef
).Index
);
1858 RecVec RADefs
= Records
.getAllDerivedDefinitions("ReadAdvance");
1859 for (Record
*RA
: RADefs
) {
1860 Record
*ModelDef
= RA
->getValueAsDef("SchedModel");
1861 addReadAdvance(RA
, getProcModel(ModelDef
).Index
);
1863 RecVec SRADefs
= Records
.getAllDerivedDefinitions("SchedReadAdvance");
1864 for (Record
*SRA
: SRADefs
) {
1865 if (SRA
->getValueInit("SchedModel")->isComplete()) {
1866 Record
*ModelDef
= SRA
->getValueAsDef("SchedModel");
1867 addReadAdvance(SRA
, getProcModel(ModelDef
).Index
);
1870 // Add ProcResGroups that are defined within this processor model, which may
1871 // not be directly referenced but may directly specify a buffer size.
1872 RecVec ProcResGroups
= Records
.getAllDerivedDefinitions("ProcResGroup");
1873 for (Record
*PRG
: ProcResGroups
) {
1874 if (!PRG
->getValueInit("SchedModel")->isComplete())
1876 CodeGenProcModel
&PM
= getProcModel(PRG
->getValueAsDef("SchedModel"));
1877 if (!is_contained(PM
.ProcResourceDefs
, PRG
))
1878 PM
.ProcResourceDefs
.push_back(PRG
);
1880 // Add ProcResourceUnits unconditionally.
1881 for (Record
*PRU
: Records
.getAllDerivedDefinitions("ProcResourceUnits")) {
1882 if (!PRU
->getValueInit("SchedModel")->isComplete())
1884 CodeGenProcModel
&PM
= getProcModel(PRU
->getValueAsDef("SchedModel"));
1885 if (!is_contained(PM
.ProcResourceDefs
, PRU
))
1886 PM
.ProcResourceDefs
.push_back(PRU
);
1888 // Finalize each ProcModel by sorting the record arrays.
1889 for (CodeGenProcModel
&PM
: ProcModels
) {
1890 llvm::sort(PM
.WriteResDefs
, LessRecord());
1891 llvm::sort(PM
.ReadAdvanceDefs
, LessRecord());
1892 llvm::sort(PM
.ProcResourceDefs
, LessRecord());
1895 dbgs() << "WriteResDefs: "; for (RecIter RI
= PM
.WriteResDefs
.begin(),
1896 RE
= PM
.WriteResDefs
.end();
1898 if ((*RI
)->isSubClassOf("WriteRes"))
1899 dbgs() << (*RI
)->getValueAsDef("WriteType")->getName() << " ";
1901 dbgs() << (*RI
)->getName() << " ";
1902 } dbgs() << "\nReadAdvanceDefs: ";
1903 for (RecIter RI
= PM
.ReadAdvanceDefs
.begin(),
1904 RE
= PM
.ReadAdvanceDefs
.end();
1906 if ((*RI
)->isSubClassOf("ReadAdvance"))
1907 dbgs() << (*RI
)->getValueAsDef("ReadType")->getName() << " ";
1909 dbgs() << (*RI
)->getName() << " ";
1911 << "\nProcResourceDefs: ";
1912 for (RecIter RI
= PM
.ProcResourceDefs
.begin(),
1913 RE
= PM
.ProcResourceDefs
.end();
1914 RI
!= RE
; ++RI
) { dbgs() << (*RI
)->getName() << " "; } dbgs()
1916 verifyProcResourceGroups(PM
);
1919 ProcResourceDefs
.clear();
1920 ProcResGroups
.clear();
1923 void CodeGenSchedModels::checkCompleteness() {
1924 bool Complete
= true;
1925 bool HadCompleteModel
= false;
1926 for (const CodeGenProcModel
&ProcModel
: procModels()) {
1927 const bool HasItineraries
= ProcModel
.hasItineraries();
1928 if (!ProcModel
.ModelDef
->getValueAsBit("CompleteModel"))
1930 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
1931 if (Inst
->hasNoSchedulingInfo
)
1933 if (ProcModel
.isUnsupported(*Inst
))
1935 unsigned SCIdx
= getSchedClassIdx(*Inst
);
1937 if (Inst
->TheDef
->isValueUnset("SchedRW") && !HadCompleteModel
) {
1938 PrintError(Inst
->TheDef
->getLoc(),
1939 "No schedule information for instruction '" +
1940 Inst
->TheDef
->getName() + "'");
1946 const CodeGenSchedClass
&SC
= getSchedClass(SCIdx
);
1947 if (!SC
.Writes
.empty())
1949 if (HasItineraries
&& SC
.ItinClassDef
!= nullptr &&
1950 SC
.ItinClassDef
->getName() != "NoItinerary")
1953 const RecVec
&InstRWs
= SC
.InstRWs
;
1954 auto I
= find_if(InstRWs
, [&ProcModel
](const Record
*R
) {
1955 return R
->getValueAsDef("SchedModel") == ProcModel
.ModelDef
;
1957 if (I
== InstRWs
.end()) {
1958 PrintError(Inst
->TheDef
->getLoc(), "'" + ProcModel
.ModelName
+
1959 "' lacks information for '" +
1960 Inst
->TheDef
->getName() + "'");
1964 HadCompleteModel
= true;
1967 errs() << "\n\nIncomplete schedule models found.\n"
1968 << "- Consider setting 'CompleteModel = 0' while developing new models.\n"
1969 << "- Pseudo instructions can be marked with 'hasNoSchedulingInfo = 1'.\n"
1970 << "- Instructions should usually have Sched<[...]> as a superclass, "
1971 "you may temporarily use an empty list.\n"
1972 << "- Instructions related to unsupported features can be excluded with "
1973 "list<Predicate> UnsupportedFeatures = [HasA,..,HasY]; in the "
1974 "processor model.\n\n";
1975 PrintFatalError("Incomplete schedule model");
1979 // Collect itinerary class resources for each processor.
1980 void CodeGenSchedModels::collectItinProcResources(Record
*ItinClassDef
) {
1981 for (unsigned PIdx
= 0, PEnd
= ProcModels
.size(); PIdx
!= PEnd
; ++PIdx
) {
1982 const CodeGenProcModel
&PM
= ProcModels
[PIdx
];
1983 // For all ItinRW entries.
1984 bool HasMatch
= false;
1985 for (RecIter II
= PM
.ItinRWDefs
.begin(), IE
= PM
.ItinRWDefs
.end();
1987 RecVec Matched
= (*II
)->getValueAsListOfDefs("MatchedItinClasses");
1988 if (!std::count(Matched
.begin(), Matched
.end(), ItinClassDef
))
1991 PrintFatalError((*II
)->getLoc(), "Duplicate itinerary class "
1992 + ItinClassDef
->getName()
1993 + " in ItinResources for " + PM
.ModelName
);
1995 IdxVec Writes
, Reads
;
1996 findRWs((*II
)->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1997 collectRWResources(Writes
, Reads
, PIdx
);
2002 void CodeGenSchedModels::collectRWResources(unsigned RWIdx
, bool IsRead
,
2003 ArrayRef
<unsigned> ProcIndices
) {
2004 const CodeGenSchedRW
&SchedRW
= getSchedRW(RWIdx
, IsRead
);
2005 if (SchedRW
.TheDef
) {
2006 if (!IsRead
&& SchedRW
.TheDef
->isSubClassOf("SchedWriteRes")) {
2007 for (unsigned Idx
: ProcIndices
)
2008 addWriteRes(SchedRW
.TheDef
, Idx
);
2010 else if (IsRead
&& SchedRW
.TheDef
->isSubClassOf("SchedReadAdvance")) {
2011 for (unsigned Idx
: ProcIndices
)
2012 addReadAdvance(SchedRW
.TheDef
, Idx
);
2015 for (RecIter AI
= SchedRW
.Aliases
.begin(), AE
= SchedRW
.Aliases
.end();
2017 IdxVec AliasProcIndices
;
2018 if ((*AI
)->getValueInit("SchedModel")->isComplete()) {
2019 AliasProcIndices
.push_back(
2020 getProcModel((*AI
)->getValueAsDef("SchedModel")).Index
);
2023 AliasProcIndices
= ProcIndices
;
2024 const CodeGenSchedRW
&AliasRW
= getSchedRW((*AI
)->getValueAsDef("AliasRW"));
2025 assert(AliasRW
.IsRead
== IsRead
&& "cannot alias reads to writes");
2028 expandRWSequence(AliasRW
.Index
, ExpandedRWs
, IsRead
);
2029 for (IdxIter SI
= ExpandedRWs
.begin(), SE
= ExpandedRWs
.end();
2031 collectRWResources(*SI
, IsRead
, AliasProcIndices
);
2036 // Collect resources for a set of read/write types and processor indices.
2037 void CodeGenSchedModels::collectRWResources(ArrayRef
<unsigned> Writes
,
2038 ArrayRef
<unsigned> Reads
,
2039 ArrayRef
<unsigned> ProcIndices
) {
2040 for (unsigned Idx
: Writes
)
2041 collectRWResources(Idx
, /*IsRead=*/false, ProcIndices
);
2043 for (unsigned Idx
: Reads
)
2044 collectRWResources(Idx
, /*IsRead=*/true, ProcIndices
);
2047 // Find the processor's resource units for this kind of resource.
2048 Record
*CodeGenSchedModels::findProcResUnits(Record
*ProcResKind
,
2049 const CodeGenProcModel
&PM
,
2050 ArrayRef
<SMLoc
> Loc
) const {
2051 if (ProcResKind
->isSubClassOf("ProcResourceUnits"))
2054 Record
*ProcUnitDef
= nullptr;
2055 assert(!ProcResourceDefs
.empty());
2056 assert(!ProcResGroups
.empty());
2058 for (Record
*ProcResDef
: ProcResourceDefs
) {
2059 if (ProcResDef
->getValueAsDef("Kind") == ProcResKind
2060 && ProcResDef
->getValueAsDef("SchedModel") == PM
.ModelDef
) {
2062 PrintFatalError(Loc
,
2063 "Multiple ProcessorResourceUnits associated with "
2064 + ProcResKind
->getName());
2066 ProcUnitDef
= ProcResDef
;
2069 for (Record
*ProcResGroup
: ProcResGroups
) {
2070 if (ProcResGroup
== ProcResKind
2071 && ProcResGroup
->getValueAsDef("SchedModel") == PM
.ModelDef
) {
2073 PrintFatalError(Loc
,
2074 "Multiple ProcessorResourceUnits associated with "
2075 + ProcResKind
->getName());
2077 ProcUnitDef
= ProcResGroup
;
2081 PrintFatalError(Loc
,
2082 "No ProcessorResources associated with "
2083 + ProcResKind
->getName());
2088 // Iteratively add a resource and its super resources.
2089 void CodeGenSchedModels::addProcResource(Record
*ProcResKind
,
2090 CodeGenProcModel
&PM
,
2091 ArrayRef
<SMLoc
> Loc
) {
2093 Record
*ProcResUnits
= findProcResUnits(ProcResKind
, PM
, Loc
);
2095 // See if this ProcResource is already associated with this processor.
2096 if (is_contained(PM
.ProcResourceDefs
, ProcResUnits
))
2099 PM
.ProcResourceDefs
.push_back(ProcResUnits
);
2100 if (ProcResUnits
->isSubClassOf("ProcResGroup"))
2103 if (!ProcResUnits
->getValueInit("Super")->isComplete())
2106 ProcResKind
= ProcResUnits
->getValueAsDef("Super");
2110 // Add resources for a SchedWrite to this processor if they don't exist.
2111 void CodeGenSchedModels::addWriteRes(Record
*ProcWriteResDef
, unsigned PIdx
) {
2112 assert(PIdx
&& "don't add resources to an invalid Processor model");
2114 RecVec
&WRDefs
= ProcModels
[PIdx
].WriteResDefs
;
2115 if (is_contained(WRDefs
, ProcWriteResDef
))
2117 WRDefs
.push_back(ProcWriteResDef
);
2119 // Visit ProcResourceKinds referenced by the newly discovered WriteRes.
2120 RecVec ProcResDefs
= ProcWriteResDef
->getValueAsListOfDefs("ProcResources");
2121 for (RecIter WritePRI
= ProcResDefs
.begin(), WritePRE
= ProcResDefs
.end();
2122 WritePRI
!= WritePRE
; ++WritePRI
) {
2123 addProcResource(*WritePRI
, ProcModels
[PIdx
], ProcWriteResDef
->getLoc());
2127 // Add resources for a ReadAdvance to this processor if they don't exist.
2128 void CodeGenSchedModels::addReadAdvance(Record
*ProcReadAdvanceDef
,
2130 RecVec
&RADefs
= ProcModels
[PIdx
].ReadAdvanceDefs
;
2131 if (is_contained(RADefs
, ProcReadAdvanceDef
))
2133 RADefs
.push_back(ProcReadAdvanceDef
);
2136 unsigned CodeGenProcModel::getProcResourceIdx(Record
*PRDef
) const {
2137 RecIter PRPos
= find(ProcResourceDefs
, PRDef
);
2138 if (PRPos
== ProcResourceDefs
.end())
2139 PrintFatalError(PRDef
->getLoc(), "ProcResource def is not included in "
2140 "the ProcResources list for " + ModelName
);
2141 // Idx=0 is reserved for invalid.
2142 return 1 + (PRPos
- ProcResourceDefs
.begin());
2145 bool CodeGenProcModel::isUnsupported(const CodeGenInstruction
&Inst
) const {
2146 for (const Record
*TheDef
: UnsupportedFeaturesDefs
) {
2147 for (const Record
*PredDef
: Inst
.TheDef
->getValueAsListOfDefs("Predicates")) {
2148 if (TheDef
->getName() == PredDef
->getName())
2156 void CodeGenProcModel::dump() const {
2157 dbgs() << Index
<< ": " << ModelName
<< " "
2158 << (ModelDef
? ModelDef
->getName() : "inferred") << " "
2159 << (ItinsDef
? ItinsDef
->getName() : "no itinerary") << '\n';
2162 void CodeGenSchedRW::dump() const {
2163 dbgs() << Name
<< (IsVariadic
? " (V) " : " ");
2166 dumpIdxVec(Sequence
);
2171 void CodeGenSchedClass::dump(const CodeGenSchedModels
* SchedModels
) const {
2172 dbgs() << "SCHEDCLASS " << Index
<< ":" << Name
<< '\n'
2174 for (unsigned i
= 0, N
= Writes
.size(); i
< N
; ++i
) {
2175 SchedModels
->getSchedWrite(Writes
[i
]).dump();
2181 dbgs() << "\n Reads: ";
2182 for (unsigned i
= 0, N
= Reads
.size(); i
< N
; ++i
) {
2183 SchedModels
->getSchedRead(Reads
[i
]).dump();
2189 dbgs() << "\n ProcIdx: "; dumpIdxVec(ProcIndices
); dbgs() << '\n';
2190 if (!Transitions
.empty()) {
2191 dbgs() << "\n Transitions for Proc ";
2192 for (const CodeGenSchedTransition
&Transition
: Transitions
) {
2193 dumpIdxVec(Transition
.ProcIndices
);
2198 void PredTransitions::dump() const {
2199 dbgs() << "Expanded Variants:\n";
2200 for (std::vector
<PredTransition
>::const_iterator
2201 TI
= TransVec
.begin(), TE
= TransVec
.end(); TI
!= TE
; ++TI
) {
2203 for (SmallVectorImpl
<PredCheck
>::const_iterator
2204 PCI
= TI
->PredTerm
.begin(), PCE
= TI
->PredTerm
.end();
2205 PCI
!= PCE
; ++PCI
) {
2206 if (PCI
!= TI
->PredTerm
.begin())
2208 dbgs() << SchedModels
.getSchedRW(PCI
->RWIdx
, PCI
->IsRead
).Name
2209 << ":" << PCI
->Predicate
->getName();
2211 dbgs() << "},\n => {";
2212 for (SmallVectorImpl
<SmallVector
<unsigned,4>>::const_iterator
2213 WSI
= TI
->WriteSequences
.begin(), WSE
= TI
->WriteSequences
.end();
2214 WSI
!= WSE
; ++WSI
) {
2216 for (SmallVectorImpl
<unsigned>::const_iterator
2217 WI
= WSI
->begin(), WE
= WSI
->end(); WI
!= WE
; ++WI
) {
2218 if (WI
!= WSI
->begin())
2220 dbgs() << SchedModels
.getSchedWrite(*WI
).Name
;