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", 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 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 const std::pair
<APInt
, APInt
> &LhsMasks
= OpcodeMasks
[LhsIdx
];
372 const std::pair
<APInt
, APInt
> &RhsMasks
= OpcodeMasks
[RhsIdx
];
374 auto LessThan
= [](const APInt
&Lhs
, const APInt
&Rhs
) {
375 unsigned LhsCountPopulation
= Lhs
.countPopulation();
376 unsigned RhsCountPopulation
= Rhs
.countPopulation();
377 return ((LhsCountPopulation
< RhsCountPopulation
) ||
378 ((LhsCountPopulation
== RhsCountPopulation
) &&
379 (Lhs
.countLeadingZeros() > Rhs
.countLeadingZeros())));
382 if (LhsMasks
.first
!= RhsMasks
.first
)
383 return LessThan(LhsMasks
.first
, RhsMasks
.first
);
385 if (LhsMasks
.second
!= RhsMasks
.second
)
386 return LessThan(LhsMasks
.second
, RhsMasks
.second
);
388 return LhsIdx
< RhsIdx
;
391 // Now construct opcode groups. Groups are used by the SubtargetEmitter when
392 // expanding the body of a STIPredicate function. In particular, each opcode
393 // group is expanded into a sequence of labels in a switch statement.
394 // It identifies opcodes for which different processors define same predicates
395 // and same opcode masks.
396 for (OpcodeMapPair
&Info
: OpcodeMappings
)
397 Fn
.addOpcode(Info
.first
, std::move(Info
.second
));
400 void CodeGenSchedModels::collectSTIPredicates() {
401 // Map STIPredicateDecl records to elements of vector
402 // CodeGenSchedModels::STIPredicates.
403 DenseMap
<const Record
*, unsigned> Decl2Index
;
405 RecVec RV
= Records
.getAllDerivedDefinitions("STIPredicate");
406 for (const Record
*R
: RV
) {
407 const Record
*Decl
= R
->getValueAsDef("Declaration");
409 const auto It
= Decl2Index
.find(Decl
);
410 if (It
== Decl2Index
.end()) {
411 Decl2Index
[Decl
] = STIPredicates
.size();
412 STIPredicateFunction
Predicate(Decl
);
413 Predicate
.addDefinition(R
);
414 STIPredicates
.emplace_back(std::move(Predicate
));
418 STIPredicateFunction
&PreviousDef
= STIPredicates
[It
->second
];
419 PreviousDef
.addDefinition(R
);
422 for (STIPredicateFunction
&Fn
: STIPredicates
)
423 processSTIPredicate(Fn
, ProcModelMap
);
426 void OpcodeInfo::addPredicateForProcModel(const llvm::APInt
&CpuMask
,
427 const llvm::APInt
&OperandMask
,
428 const Record
*Predicate
) {
429 auto It
= llvm::find_if(
430 Predicates
, [&OperandMask
, &Predicate
](const PredicateInfo
&P
) {
431 return P
.Predicate
== Predicate
&& P
.OperandMask
== OperandMask
;
433 if (It
== Predicates
.end()) {
434 Predicates
.emplace_back(CpuMask
, OperandMask
, Predicate
);
437 It
->ProcModelMask
|= CpuMask
;
440 void CodeGenSchedModels::checkMCInstPredicates() const {
441 RecVec MCPredicates
= Records
.getAllDerivedDefinitions("TIIPredicate");
442 if (MCPredicates
.empty())
445 // A target cannot have multiple TIIPredicate definitions with a same name.
446 llvm::StringMap
<const Record
*> TIIPredicates(MCPredicates
.size());
447 for (const Record
*TIIPred
: MCPredicates
) {
448 StringRef Name
= TIIPred
->getValueAsString("FunctionName");
449 StringMap
<const Record
*>::const_iterator It
= TIIPredicates
.find(Name
);
450 if (It
== TIIPredicates
.end()) {
451 TIIPredicates
[Name
] = TIIPred
;
455 PrintError(TIIPred
->getLoc(),
456 "TIIPredicate " + Name
+ " is multiply defined.");
457 PrintNote(It
->second
->getLoc(),
458 " Previous definition of " + Name
+ " was here.");
459 PrintFatalError(TIIPred
->getLoc(),
460 "Found conflicting definitions of TIIPredicate.");
464 void CodeGenSchedModels::collectRetireControlUnits() {
465 RecVec Units
= Records
.getAllDerivedDefinitions("RetireControlUnit");
467 for (Record
*RCU
: Units
) {
468 CodeGenProcModel
&PM
= getProcModel(RCU
->getValueAsDef("SchedModel"));
469 if (PM
.RetireControlUnit
) {
470 PrintError(RCU
->getLoc(),
471 "Expected a single RetireControlUnit definition");
472 PrintNote(PM
.RetireControlUnit
->getLoc(),
473 "Previous definition of RetireControlUnit was here");
475 PM
.RetireControlUnit
= RCU
;
479 void CodeGenSchedModels::collectLoadStoreQueueInfo() {
480 RecVec Queues
= Records
.getAllDerivedDefinitions("MemoryQueue");
482 for (Record
*Queue
: Queues
) {
483 CodeGenProcModel
&PM
= getProcModel(Queue
->getValueAsDef("SchedModel"));
484 if (Queue
->isSubClassOf("LoadQueue")) {
486 PrintError(Queue
->getLoc(),
487 "Expected a single LoadQueue definition");
488 PrintNote(PM
.LoadQueue
->getLoc(),
489 "Previous definition of LoadQueue was here");
492 PM
.LoadQueue
= Queue
;
495 if (Queue
->isSubClassOf("StoreQueue")) {
497 PrintError(Queue
->getLoc(),
498 "Expected a single StoreQueue definition");
499 PrintNote(PM
.LoadQueue
->getLoc(),
500 "Previous definition of StoreQueue was here");
503 PM
.StoreQueue
= Queue
;
508 /// Collect optional processor information.
509 void CodeGenSchedModels::collectOptionalProcessorInfo() {
510 // Find register file definitions for each processor.
511 collectRegisterFiles();
513 // Collect processor RetireControlUnit descriptors if available.
514 collectRetireControlUnits();
516 // Collect information about load/store queues.
517 collectLoadStoreQueueInfo();
522 /// Gather all processor models.
523 void CodeGenSchedModels::collectProcModels() {
524 RecVec ProcRecords
= Records
.getAllDerivedDefinitions("Processor");
525 llvm::sort(ProcRecords
, LessRecordFieldName());
527 // Reserve space because we can. Reallocation would be ok.
528 ProcModels
.reserve(ProcRecords
.size()+1);
530 // Use idx=0 for NoModel/NoItineraries.
531 Record
*NoModelDef
= Records
.getDef("NoSchedModel");
532 Record
*NoItinsDef
= Records
.getDef("NoItineraries");
533 ProcModels
.emplace_back(0, "NoSchedModel", NoModelDef
, NoItinsDef
);
534 ProcModelMap
[NoModelDef
] = 0;
536 // For each processor, find a unique machine model.
537 LLVM_DEBUG(dbgs() << "+++ PROCESSOR MODELs (addProcModel) +++\n");
538 for (Record
*ProcRecord
: ProcRecords
)
539 addProcModel(ProcRecord
);
542 /// Get a unique processor model based on the defined MachineModel and
543 /// ProcessorItineraries.
544 void CodeGenSchedModels::addProcModel(Record
*ProcDef
) {
545 Record
*ModelKey
= getModelOrItinDef(ProcDef
);
546 if (!ProcModelMap
.insert(std::make_pair(ModelKey
, ProcModels
.size())).second
)
549 std::string Name
= ModelKey
->getName();
550 if (ModelKey
->isSubClassOf("SchedMachineModel")) {
551 Record
*ItinsDef
= ModelKey
->getValueAsDef("Itineraries");
552 ProcModels
.emplace_back(ProcModels
.size(), Name
, ModelKey
, ItinsDef
);
555 // An itinerary is defined without a machine model. Infer a new model.
556 if (!ModelKey
->getValueAsListOfDefs("IID").empty())
557 Name
= Name
+ "Model";
558 ProcModels
.emplace_back(ProcModels
.size(), Name
,
559 ProcDef
->getValueAsDef("SchedModel"), ModelKey
);
561 LLVM_DEBUG(ProcModels
.back().dump());
564 // Recursively find all reachable SchedReadWrite records.
565 static void scanSchedRW(Record
*RWDef
, RecVec
&RWDefs
,
566 SmallPtrSet
<Record
*, 16> &RWSet
) {
567 if (!RWSet
.insert(RWDef
).second
)
569 RWDefs
.push_back(RWDef
);
570 // Reads don't currently have sequence records, but it can be added later.
571 if (RWDef
->isSubClassOf("WriteSequence")) {
572 RecVec Seq
= RWDef
->getValueAsListOfDefs("Writes");
573 for (Record
*WSRec
: Seq
)
574 scanSchedRW(WSRec
, RWDefs
, RWSet
);
576 else if (RWDef
->isSubClassOf("SchedVariant")) {
577 // Visit each variant (guarded by a different predicate).
578 RecVec Vars
= RWDef
->getValueAsListOfDefs("Variants");
579 for (Record
*Variant
: Vars
) {
580 // Visit each RW in the sequence selected by the current variant.
581 RecVec Selected
= Variant
->getValueAsListOfDefs("Selected");
582 for (Record
*SelDef
: Selected
)
583 scanSchedRW(SelDef
, RWDefs
, RWSet
);
588 // Collect and sort all SchedReadWrites reachable via tablegen records.
589 // More may be inferred later when inferring new SchedClasses from variants.
590 void CodeGenSchedModels::collectSchedRW() {
591 // Reserve idx=0 for invalid writes/reads.
592 SchedWrites
.resize(1);
593 SchedReads
.resize(1);
595 SmallPtrSet
<Record
*, 16> RWSet
;
597 // Find all SchedReadWrites referenced by instruction defs.
598 RecVec SWDefs
, SRDefs
;
599 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
600 Record
*SchedDef
= Inst
->TheDef
;
601 if (SchedDef
->isValueUnset("SchedRW"))
603 RecVec RWs
= SchedDef
->getValueAsListOfDefs("SchedRW");
604 for (Record
*RW
: RWs
) {
605 if (RW
->isSubClassOf("SchedWrite"))
606 scanSchedRW(RW
, SWDefs
, RWSet
);
608 assert(RW
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
609 scanSchedRW(RW
, SRDefs
, RWSet
);
613 // Find all ReadWrites referenced by InstRW.
614 RecVec InstRWDefs
= Records
.getAllDerivedDefinitions("InstRW");
615 for (Record
*InstRWDef
: InstRWDefs
) {
616 // For all OperandReadWrites.
617 RecVec RWDefs
= InstRWDef
->getValueAsListOfDefs("OperandReadWrites");
618 for (Record
*RWDef
: RWDefs
) {
619 if (RWDef
->isSubClassOf("SchedWrite"))
620 scanSchedRW(RWDef
, SWDefs
, RWSet
);
622 assert(RWDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
623 scanSchedRW(RWDef
, SRDefs
, RWSet
);
627 // Find all ReadWrites referenced by ItinRW.
628 RecVec ItinRWDefs
= Records
.getAllDerivedDefinitions("ItinRW");
629 for (Record
*ItinRWDef
: ItinRWDefs
) {
630 // For all OperandReadWrites.
631 RecVec RWDefs
= ItinRWDef
->getValueAsListOfDefs("OperandReadWrites");
632 for (Record
*RWDef
: RWDefs
) {
633 if (RWDef
->isSubClassOf("SchedWrite"))
634 scanSchedRW(RWDef
, SWDefs
, RWSet
);
636 assert(RWDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
637 scanSchedRW(RWDef
, SRDefs
, RWSet
);
641 // Find all ReadWrites referenced by SchedAlias. AliasDefs needs to be sorted
642 // for the loop below that initializes Alias vectors.
643 RecVec AliasDefs
= Records
.getAllDerivedDefinitions("SchedAlias");
644 llvm::sort(AliasDefs
, LessRecord());
645 for (Record
*ADef
: AliasDefs
) {
646 Record
*MatchDef
= ADef
->getValueAsDef("MatchRW");
647 Record
*AliasDef
= ADef
->getValueAsDef("AliasRW");
648 if (MatchDef
->isSubClassOf("SchedWrite")) {
649 if (!AliasDef
->isSubClassOf("SchedWrite"))
650 PrintFatalError(ADef
->getLoc(), "SchedWrite Alias must be SchedWrite");
651 scanSchedRW(AliasDef
, SWDefs
, RWSet
);
654 assert(MatchDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
655 if (!AliasDef
->isSubClassOf("SchedRead"))
656 PrintFatalError(ADef
->getLoc(), "SchedRead Alias must be SchedRead");
657 scanSchedRW(AliasDef
, SRDefs
, RWSet
);
660 // Sort and add the SchedReadWrites directly referenced by instructions or
661 // itinerary resources. Index reads and writes in separate domains.
662 llvm::sort(SWDefs
, LessRecord());
663 for (Record
*SWDef
: SWDefs
) {
664 assert(!getSchedRWIdx(SWDef
, /*IsRead=*/false) && "duplicate SchedWrite");
665 SchedWrites
.emplace_back(SchedWrites
.size(), SWDef
);
667 llvm::sort(SRDefs
, LessRecord());
668 for (Record
*SRDef
: SRDefs
) {
669 assert(!getSchedRWIdx(SRDef
, /*IsRead-*/true) && "duplicate SchedWrite");
670 SchedReads
.emplace_back(SchedReads
.size(), SRDef
);
672 // Initialize WriteSequence vectors.
673 for (CodeGenSchedRW
&CGRW
: SchedWrites
) {
674 if (!CGRW
.IsSequence
)
676 findRWs(CGRW
.TheDef
->getValueAsListOfDefs("Writes"), CGRW
.Sequence
,
679 // Initialize Aliases vectors.
680 for (Record
*ADef
: AliasDefs
) {
681 Record
*AliasDef
= ADef
->getValueAsDef("AliasRW");
682 getSchedRW(AliasDef
).IsAlias
= true;
683 Record
*MatchDef
= ADef
->getValueAsDef("MatchRW");
684 CodeGenSchedRW
&RW
= getSchedRW(MatchDef
);
686 PrintFatalError(ADef
->getLoc(), "Cannot Alias an Alias");
687 RW
.Aliases
.push_back(ADef
);
690 dbgs() << "\n+++ SCHED READS and WRITES (collectSchedRW) +++\n";
691 for (unsigned WIdx
= 0, WEnd
= SchedWrites
.size(); WIdx
!= WEnd
; ++WIdx
) {
692 dbgs() << WIdx
<< ": ";
693 SchedWrites
[WIdx
].dump();
695 } for (unsigned RIdx
= 0, REnd
= SchedReads
.size(); RIdx
!= REnd
;
697 dbgs() << RIdx
<< ": ";
698 SchedReads
[RIdx
].dump();
700 } RecVec RWDefs
= Records
.getAllDerivedDefinitions("SchedReadWrite");
703 if (!getSchedRWIdx(RWDef
, RWDef
->isSubClassOf("SchedRead"))) {
704 StringRef Name
= RWDef
->getName();
705 if (Name
!= "NoWrite" && Name
!= "ReadDefault")
706 dbgs() << "Unused SchedReadWrite " << Name
<< '\n';
711 /// Compute a SchedWrite name from a sequence of writes.
712 std::string
CodeGenSchedModels::genRWName(ArrayRef
<unsigned> Seq
, bool IsRead
) {
713 std::string
Name("(");
714 for (auto I
= Seq
.begin(), E
= Seq
.end(); I
!= E
; ++I
) {
715 if (I
!= Seq
.begin())
717 Name
+= getSchedRW(*I
, IsRead
).Name
;
723 unsigned CodeGenSchedModels::getSchedRWIdx(const Record
*Def
,
725 const std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
726 const auto I
= find_if(
727 RWVec
, [Def
](const CodeGenSchedRW
&RW
) { return RW
.TheDef
== Def
; });
728 return I
== RWVec
.end() ? 0 : std::distance(RWVec
.begin(), I
);
731 bool CodeGenSchedModels::hasReadOfWrite(Record
*WriteDef
) const {
732 for (const CodeGenSchedRW
&Read
: SchedReads
) {
733 Record
*ReadDef
= Read
.TheDef
;
734 if (!ReadDef
|| !ReadDef
->isSubClassOf("ProcReadAdvance"))
737 RecVec ValidWrites
= ReadDef
->getValueAsListOfDefs("ValidWrites");
738 if (is_contained(ValidWrites
, WriteDef
)) {
745 static void splitSchedReadWrites(const RecVec
&RWDefs
,
746 RecVec
&WriteDefs
, RecVec
&ReadDefs
) {
747 for (Record
*RWDef
: RWDefs
) {
748 if (RWDef
->isSubClassOf("SchedWrite"))
749 WriteDefs
.push_back(RWDef
);
751 assert(RWDef
->isSubClassOf("SchedRead") && "unknown SchedReadWrite");
752 ReadDefs
.push_back(RWDef
);
757 // Split the SchedReadWrites defs and call findRWs for each list.
758 void CodeGenSchedModels::findRWs(const RecVec
&RWDefs
,
759 IdxVec
&Writes
, IdxVec
&Reads
) const {
762 splitSchedReadWrites(RWDefs
, WriteDefs
, ReadDefs
);
763 findRWs(WriteDefs
, Writes
, false);
764 findRWs(ReadDefs
, Reads
, true);
767 // Call getSchedRWIdx for all elements in a sequence of SchedRW defs.
768 void CodeGenSchedModels::findRWs(const RecVec
&RWDefs
, IdxVec
&RWs
,
770 for (Record
*RWDef
: RWDefs
) {
771 unsigned Idx
= getSchedRWIdx(RWDef
, IsRead
);
772 assert(Idx
&& "failed to collect SchedReadWrite");
777 void CodeGenSchedModels::expandRWSequence(unsigned RWIdx
, IdxVec
&RWSeq
,
779 const CodeGenSchedRW
&SchedRW
= getSchedRW(RWIdx
, IsRead
);
780 if (!SchedRW
.IsSequence
) {
781 RWSeq
.push_back(RWIdx
);
785 SchedRW
.TheDef
? SchedRW
.TheDef
->getValueAsInt("Repeat") : 1;
786 for (int i
= 0; i
< Repeat
; ++i
) {
787 for (unsigned I
: SchedRW
.Sequence
) {
788 expandRWSequence(I
, RWSeq
, IsRead
);
793 // Expand a SchedWrite as a sequence following any aliases that coincide with
794 // the given processor model.
795 void CodeGenSchedModels::expandRWSeqForProc(
796 unsigned RWIdx
, IdxVec
&RWSeq
, bool IsRead
,
797 const CodeGenProcModel
&ProcModel
) const {
799 const CodeGenSchedRW
&SchedWrite
= getSchedRW(RWIdx
, IsRead
);
800 Record
*AliasDef
= nullptr;
801 for (const Record
*Rec
: SchedWrite
.Aliases
) {
802 const CodeGenSchedRW
&AliasRW
= getSchedRW(Rec
->getValueAsDef("AliasRW"));
803 if (Rec
->getValueInit("SchedModel")->isComplete()) {
804 Record
*ModelDef
= Rec
->getValueAsDef("SchedModel");
805 if (&getProcModel(ModelDef
) != &ProcModel
)
809 PrintFatalError(AliasRW
.TheDef
->getLoc(), "Multiple aliases "
810 "defined for processor " + ProcModel
.ModelName
+
811 " Ensure only one SchedAlias exists per RW.");
812 AliasDef
= AliasRW
.TheDef
;
815 expandRWSeqForProc(getSchedRWIdx(AliasDef
, IsRead
),
816 RWSeq
, IsRead
,ProcModel
);
819 if (!SchedWrite
.IsSequence
) {
820 RWSeq
.push_back(RWIdx
);
824 SchedWrite
.TheDef
? SchedWrite
.TheDef
->getValueAsInt("Repeat") : 1;
825 for (int I
= 0, E
= Repeat
; I
< E
; ++I
) {
826 for (unsigned Idx
: SchedWrite
.Sequence
) {
827 expandRWSeqForProc(Idx
, RWSeq
, IsRead
, ProcModel
);
832 // Find the existing SchedWrite that models this sequence of writes.
833 unsigned CodeGenSchedModels::findRWForSequence(ArrayRef
<unsigned> Seq
,
835 std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
837 auto I
= find_if(RWVec
, [Seq
](CodeGenSchedRW
&RW
) {
838 return makeArrayRef(RW
.Sequence
) == Seq
;
840 // Index zero reserved for invalid RW.
841 return I
== RWVec
.end() ? 0 : std::distance(RWVec
.begin(), I
);
844 /// Add this ReadWrite if it doesn't already exist.
845 unsigned CodeGenSchedModels::findOrInsertRW(ArrayRef
<unsigned> Seq
,
847 assert(!Seq
.empty() && "cannot insert empty sequence");
851 unsigned Idx
= findRWForSequence(Seq
, IsRead
);
855 std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
856 unsigned RWIdx
= RWVec
.size();
857 CodeGenSchedRW
SchedRW(RWIdx
, IsRead
, Seq
, genRWName(Seq
, IsRead
));
858 RWVec
.push_back(SchedRW
);
862 /// Visit all the instruction definitions for this target to gather and
863 /// enumerate the itinerary classes. These are the explicitly specified
864 /// SchedClasses. More SchedClasses may be inferred.
865 void CodeGenSchedModels::collectSchedClasses() {
867 // NoItinerary is always the first class at Idx=0
868 assert(SchedClasses
.empty() && "Expected empty sched class");
869 SchedClasses
.emplace_back(0, "NoInstrModel",
870 Records
.getDef("NoItinerary"));
871 SchedClasses
.back().ProcIndices
.push_back(0);
873 // Create a SchedClass for each unique combination of itinerary class and
875 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
876 Record
*ItinDef
= Inst
->TheDef
->getValueAsDef("Itinerary");
877 IdxVec Writes
, Reads
;
878 if (!Inst
->TheDef
->isValueUnset("SchedRW"))
879 findRWs(Inst
->TheDef
->getValueAsListOfDefs("SchedRW"), Writes
, Reads
);
881 // ProcIdx == 0 indicates the class applies to all processors.
882 unsigned SCIdx
= addSchedClass(ItinDef
, Writes
, Reads
, /*ProcIndices*/{0});
883 InstrClassMap
[Inst
->TheDef
] = SCIdx
;
885 // Create classes for InstRW defs.
886 RecVec InstRWDefs
= Records
.getAllDerivedDefinitions("InstRW");
887 llvm::sort(InstRWDefs
, LessRecord());
888 LLVM_DEBUG(dbgs() << "\n+++ SCHED CLASSES (createInstRWClass) +++\n");
889 for (Record
*RWDef
: InstRWDefs
)
890 createInstRWClass(RWDef
);
892 NumInstrSchedClasses
= SchedClasses
.size();
894 bool EnableDump
= false;
895 LLVM_DEBUG(EnableDump
= true);
901 << "\n+++ ITINERARIES and/or MACHINE MODELS (collectSchedClasses) +++\n");
902 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
903 StringRef InstName
= Inst
->TheDef
->getName();
904 unsigned SCIdx
= getSchedClassIdx(*Inst
);
907 if (!Inst
->hasNoSchedulingInfo
)
908 dbgs() << "No machine model for " << Inst
->TheDef
->getName() << '\n';
912 CodeGenSchedClass
&SC
= getSchedClass(SCIdx
);
913 if (SC
.ProcIndices
[0] != 0)
914 PrintFatalError(Inst
->TheDef
->getLoc(), "Instruction's sched class "
915 "must not be subtarget specific.");
918 if (SC
.ItinClassDef
->getName() != "NoItinerary") {
919 ProcIndices
.push_back(0);
920 dbgs() << "Itinerary for " << InstName
<< ": "
921 << SC
.ItinClassDef
->getName() << '\n';
923 if (!SC
.Writes
.empty()) {
924 ProcIndices
.push_back(0);
926 dbgs() << "SchedRW machine model for " << InstName
;
927 for (IdxIter WI
= SC
.Writes
.begin(), WE
= SC
.Writes
.end(); WI
!= WE
;
929 dbgs() << " " << SchedWrites
[*WI
].Name
;
930 for (IdxIter RI
= SC
.Reads
.begin(), RE
= SC
.Reads
.end(); RI
!= RE
; ++RI
)
931 dbgs() << " " << SchedReads
[*RI
].Name
;
935 const RecVec
&RWDefs
= SchedClasses
[SCIdx
].InstRWs
;
936 for (Record
*RWDef
: RWDefs
) {
937 const CodeGenProcModel
&ProcModel
=
938 getProcModel(RWDef
->getValueAsDef("SchedModel"));
939 ProcIndices
.push_back(ProcModel
.Index
);
940 LLVM_DEBUG(dbgs() << "InstRW on " << ProcModel
.ModelName
<< " for "
944 findRWs(RWDef
->getValueAsListOfDefs("OperandReadWrites"),
947 for (unsigned WIdx
: Writes
)
948 dbgs() << " " << SchedWrites
[WIdx
].Name
;
949 for (unsigned RIdx
: Reads
)
950 dbgs() << " " << SchedReads
[RIdx
].Name
;
954 // If ProcIndices contains zero, the class applies to all processors.
956 if (!std::count(ProcIndices
.begin(), ProcIndices
.end(), 0)) {
957 for (const CodeGenProcModel
&PM
: ProcModels
) {
958 if (!std::count(ProcIndices
.begin(), ProcIndices
.end(), PM
.Index
))
959 dbgs() << "No machine model for " << Inst
->TheDef
->getName()
960 << " on processor " << PM
.ModelName
<< '\n';
967 // Get the SchedClass index for an instruction.
969 CodeGenSchedModels::getSchedClassIdx(const CodeGenInstruction
&Inst
) const {
970 return InstrClassMap
.lookup(Inst
.TheDef
);
974 CodeGenSchedModels::createSchedClassName(Record
*ItinClassDef
,
975 ArrayRef
<unsigned> OperWrites
,
976 ArrayRef
<unsigned> OperReads
) {
979 if (ItinClassDef
&& ItinClassDef
->getName() != "NoItinerary")
980 Name
= ItinClassDef
->getName();
981 for (unsigned Idx
: OperWrites
) {
984 Name
+= SchedWrites
[Idx
].Name
;
986 for (unsigned Idx
: OperReads
) {
988 Name
+= SchedReads
[Idx
].Name
;
993 std::string
CodeGenSchedModels::createSchedClassName(const RecVec
&InstDefs
) {
996 for (RecIter I
= InstDefs
.begin(), E
= InstDefs
.end(); I
!= E
; ++I
) {
997 if (I
!= InstDefs
.begin())
999 Name
+= (*I
)->getName();
1004 /// Add an inferred sched class from an itinerary class and per-operand list of
1005 /// SchedWrites and SchedReads. ProcIndices contains the set of IDs of
1006 /// processors that may utilize this class.
1007 unsigned CodeGenSchedModels::addSchedClass(Record
*ItinClassDef
,
1008 ArrayRef
<unsigned> OperWrites
,
1009 ArrayRef
<unsigned> OperReads
,
1010 ArrayRef
<unsigned> ProcIndices
) {
1011 assert(!ProcIndices
.empty() && "expect at least one ProcIdx");
1013 auto IsKeyEqual
= [=](const CodeGenSchedClass
&SC
) {
1014 return SC
.isKeyEqual(ItinClassDef
, OperWrites
, OperReads
);
1017 auto I
= find_if(make_range(schedClassBegin(), schedClassEnd()), IsKeyEqual
);
1018 unsigned Idx
= I
== schedClassEnd() ? 0 : std::distance(schedClassBegin(), I
);
1019 if (Idx
|| SchedClasses
[0].isKeyEqual(ItinClassDef
, OperWrites
, OperReads
)) {
1021 std::set_union(SchedClasses
[Idx
].ProcIndices
.begin(),
1022 SchedClasses
[Idx
].ProcIndices
.end(),
1023 ProcIndices
.begin(), ProcIndices
.end(),
1024 std::back_inserter(PI
));
1025 SchedClasses
[Idx
].ProcIndices
= std::move(PI
);
1028 Idx
= SchedClasses
.size();
1029 SchedClasses
.emplace_back(Idx
,
1030 createSchedClassName(ItinClassDef
, OperWrites
,
1033 CodeGenSchedClass
&SC
= SchedClasses
.back();
1034 SC
.Writes
= OperWrites
;
1035 SC
.Reads
= OperReads
;
1036 SC
.ProcIndices
= ProcIndices
;
1041 // Create classes for each set of opcodes that are in the same InstReadWrite
1042 // definition across all processors.
1043 void CodeGenSchedModels::createInstRWClass(Record
*InstRWDef
) {
1044 // ClassInstrs will hold an entry for each subset of Instrs in InstRWDef that
1045 // intersects with an existing class via a previous InstRWDef. Instrs that do
1046 // not intersect with an existing class refer back to their former class as
1047 // determined from ItinDef or SchedRW.
1048 SmallMapVector
<unsigned, SmallVector
<Record
*, 8>, 4> ClassInstrs
;
1049 // Sort Instrs into sets.
1050 const RecVec
*InstDefs
= Sets
.expand(InstRWDef
);
1051 if (InstDefs
->empty())
1052 PrintFatalError(InstRWDef
->getLoc(), "No matching instruction opcodes");
1054 for (Record
*InstDef
: *InstDefs
) {
1055 InstClassMapTy::const_iterator Pos
= InstrClassMap
.find(InstDef
);
1056 if (Pos
== InstrClassMap
.end())
1057 PrintFatalError(InstDef
->getLoc(), "No sched class for instruction.");
1058 unsigned SCIdx
= Pos
->second
;
1059 ClassInstrs
[SCIdx
].push_back(InstDef
);
1061 // For each set of Instrs, create a new class if necessary, and map or remap
1062 // the Instrs to it.
1063 for (auto &Entry
: ClassInstrs
) {
1064 unsigned OldSCIdx
= Entry
.first
;
1065 ArrayRef
<Record
*> InstDefs
= Entry
.second
;
1066 // If the all instrs in the current class are accounted for, then leave
1067 // them mapped to their old class.
1069 const RecVec
&RWDefs
= SchedClasses
[OldSCIdx
].InstRWs
;
1070 if (!RWDefs
.empty()) {
1071 const RecVec
*OrigInstDefs
= Sets
.expand(RWDefs
[0]);
1072 unsigned OrigNumInstrs
=
1073 count_if(*OrigInstDefs
, [&](Record
*OIDef
) {
1074 return InstrClassMap
[OIDef
] == OldSCIdx
;
1076 if (OrigNumInstrs
== InstDefs
.size()) {
1077 assert(SchedClasses
[OldSCIdx
].ProcIndices
[0] == 0 &&
1078 "expected a generic SchedClass");
1079 Record
*RWModelDef
= InstRWDef
->getValueAsDef("SchedModel");
1080 // Make sure we didn't already have a InstRW containing this
1081 // instruction on this model.
1082 for (Record
*RWD
: RWDefs
) {
1083 if (RWD
->getValueAsDef("SchedModel") == RWModelDef
&&
1084 RWModelDef
->getValueAsBit("FullInstRWOverlapCheck")) {
1085 for (Record
*Inst
: InstDefs
) {
1086 PrintFatalError(InstRWDef
->getLoc(), "Overlapping InstRW def " +
1087 Inst
->getName() + " also matches " +
1088 RWD
->getValue("Instrs")->getValue()->getAsString());
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 for (Record
*InstDef
: InstDefs
) {
1118 PrintFatalError(OldRWDef
->getLoc(), "Overlapping InstRW def " +
1119 InstDef
->getName() + " also matches " +
1120 OldRWDef
->getValue("Instrs")->getValue()->getAsString());
1123 assert(OldRWDef
!= InstRWDef
&&
1124 "SchedClass has duplicate InstRW def");
1125 SC
.InstRWs
.push_back(OldRWDef
);
1128 // Map each Instr to this new class.
1129 for (Record
*InstDef
: InstDefs
)
1130 InstrClassMap
[InstDef
] = SCIdx
;
1131 SC
.InstRWs
.push_back(InstRWDef
);
1135 // True if collectProcItins found anything.
1136 bool CodeGenSchedModels::hasItineraries() const {
1137 for (const CodeGenProcModel
&PM
: make_range(procModelBegin(),procModelEnd()))
1138 if (PM
.hasItineraries())
1143 // Gather the processor itineraries.
1144 void CodeGenSchedModels::collectProcItins() {
1145 LLVM_DEBUG(dbgs() << "\n+++ PROBLEM ITINERARIES (collectProcItins) +++\n");
1146 for (CodeGenProcModel
&ProcModel
: ProcModels
) {
1147 if (!ProcModel
.hasItineraries())
1150 RecVec ItinRecords
= ProcModel
.ItinsDef
->getValueAsListOfDefs("IID");
1151 assert(!ItinRecords
.empty() && "ProcModel.hasItineraries is incorrect");
1153 // Populate ItinDefList with Itinerary records.
1154 ProcModel
.ItinDefList
.resize(NumInstrSchedClasses
);
1156 // Insert each itinerary data record in the correct position within
1157 // the processor model's ItinDefList.
1158 for (Record
*ItinData
: ItinRecords
) {
1159 const Record
*ItinDef
= ItinData
->getValueAsDef("TheClass");
1160 bool FoundClass
= false;
1162 for (const CodeGenSchedClass
&SC
:
1163 make_range(schedClassBegin(), schedClassEnd())) {
1164 // Multiple SchedClasses may share an itinerary. Update all of them.
1165 if (SC
.ItinClassDef
== ItinDef
) {
1166 ProcModel
.ItinDefList
[SC
.Index
] = ItinData
;
1171 LLVM_DEBUG(dbgs() << ProcModel
.ItinsDef
->getName()
1172 << " missing class for itinerary "
1173 << ItinDef
->getName() << '\n');
1176 // Check for missing itinerary entries.
1177 assert(!ProcModel
.ItinDefList
[0] && "NoItinerary class can't have rec");
1179 for (unsigned i
= 1, N
= ProcModel
.ItinDefList
.size(); i
< N
; ++i
) {
1180 if (!ProcModel
.ItinDefList
[i
])
1181 dbgs() << ProcModel
.ItinsDef
->getName()
1182 << " missing itinerary for class " << SchedClasses
[i
].Name
1188 // Gather the read/write types for each itinerary class.
1189 void CodeGenSchedModels::collectProcItinRW() {
1190 RecVec ItinRWDefs
= Records
.getAllDerivedDefinitions("ItinRW");
1191 llvm::sort(ItinRWDefs
, LessRecord());
1192 for (Record
*RWDef
: ItinRWDefs
) {
1193 if (!RWDef
->getValueInit("SchedModel")->isComplete())
1194 PrintFatalError(RWDef
->getLoc(), "SchedModel is undefined");
1195 Record
*ModelDef
= RWDef
->getValueAsDef("SchedModel");
1196 ProcModelMapTy::const_iterator I
= ProcModelMap
.find(ModelDef
);
1197 if (I
== ProcModelMap
.end()) {
1198 PrintFatalError(RWDef
->getLoc(), "Undefined SchedMachineModel "
1199 + ModelDef
->getName());
1201 ProcModels
[I
->second
].ItinRWDefs
.push_back(RWDef
);
1205 // Gather the unsupported features for processor models.
1206 void CodeGenSchedModels::collectProcUnsupportedFeatures() {
1207 for (CodeGenProcModel
&ProcModel
: ProcModels
) {
1208 for (Record
*Pred
: ProcModel
.ModelDef
->getValueAsListOfDefs("UnsupportedFeatures")) {
1209 ProcModel
.UnsupportedFeaturesDefs
.push_back(Pred
);
1214 /// Infer new classes from existing classes. In the process, this may create new
1215 /// SchedWrites from sequences of existing SchedWrites.
1216 void CodeGenSchedModels::inferSchedClasses() {
1218 dbgs() << "\n+++ INFERRING SCHED CLASSES (inferSchedClasses) +++\n");
1219 LLVM_DEBUG(dbgs() << NumInstrSchedClasses
<< " instr sched classes.\n");
1221 // Visit all existing classes and newly created classes.
1222 for (unsigned Idx
= 0; Idx
!= SchedClasses
.size(); ++Idx
) {
1223 assert(SchedClasses
[Idx
].Index
== Idx
&& "bad SCIdx");
1225 if (SchedClasses
[Idx
].ItinClassDef
)
1226 inferFromItinClass(SchedClasses
[Idx
].ItinClassDef
, Idx
);
1227 if (!SchedClasses
[Idx
].InstRWs
.empty())
1228 inferFromInstRWs(Idx
);
1229 if (!SchedClasses
[Idx
].Writes
.empty()) {
1230 inferFromRW(SchedClasses
[Idx
].Writes
, SchedClasses
[Idx
].Reads
,
1231 Idx
, SchedClasses
[Idx
].ProcIndices
);
1233 assert(SchedClasses
.size() < (NumInstrSchedClasses
*6) &&
1234 "too many SchedVariants");
1238 /// Infer classes from per-processor itinerary resources.
1239 void CodeGenSchedModels::inferFromItinClass(Record
*ItinClassDef
,
1240 unsigned FromClassIdx
) {
1241 for (unsigned PIdx
= 0, PEnd
= ProcModels
.size(); PIdx
!= PEnd
; ++PIdx
) {
1242 const CodeGenProcModel
&PM
= ProcModels
[PIdx
];
1243 // For all ItinRW entries.
1244 bool HasMatch
= false;
1245 for (const Record
*Rec
: PM
.ItinRWDefs
) {
1246 RecVec Matched
= Rec
->getValueAsListOfDefs("MatchedItinClasses");
1247 if (!std::count(Matched
.begin(), Matched
.end(), ItinClassDef
))
1250 PrintFatalError(Rec
->getLoc(), "Duplicate itinerary class "
1251 + ItinClassDef
->getName()
1252 + " in ItinResources for " + PM
.ModelName
);
1254 IdxVec Writes
, Reads
;
1255 findRWs(Rec
->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1256 inferFromRW(Writes
, Reads
, FromClassIdx
, PIdx
);
1261 /// Infer classes from per-processor InstReadWrite definitions.
1262 void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx
) {
1263 for (unsigned I
= 0, E
= SchedClasses
[SCIdx
].InstRWs
.size(); I
!= E
; ++I
) {
1264 assert(SchedClasses
[SCIdx
].InstRWs
.size() == E
&& "InstrRWs was mutated!");
1265 Record
*Rec
= SchedClasses
[SCIdx
].InstRWs
[I
];
1266 const RecVec
*InstDefs
= Sets
.expand(Rec
);
1267 RecIter II
= InstDefs
->begin(), IE
= InstDefs
->end();
1268 for (; II
!= IE
; ++II
) {
1269 if (InstrClassMap
[*II
] == SCIdx
)
1272 // If this class no longer has any instructions mapped to it, it has become
1276 IdxVec Writes
, Reads
;
1277 findRWs(Rec
->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1278 unsigned PIdx
= getProcModel(Rec
->getValueAsDef("SchedModel")).Index
;
1279 inferFromRW(Writes
, Reads
, SCIdx
, PIdx
); // May mutate SchedClasses.
1285 // Helper for substituteVariantOperand.
1286 struct TransVariant
{
1287 Record
*VarOrSeqDef
; // Variant or sequence.
1288 unsigned RWIdx
; // Index of this variant or sequence's matched type.
1289 unsigned ProcIdx
; // Processor model index or zero for any.
1290 unsigned TransVecIdx
; // Index into PredTransitions::TransVec.
1292 TransVariant(Record
*def
, unsigned rwi
, unsigned pi
, unsigned ti
):
1293 VarOrSeqDef(def
), RWIdx(rwi
), ProcIdx(pi
), TransVecIdx(ti
) {}
1296 // Associate a predicate with the SchedReadWrite that it guards.
1297 // RWIdx is the index of the read/write variant.
1303 PredCheck(bool r
, unsigned w
, Record
*p
): IsRead(r
), RWIdx(w
), Predicate(p
) {}
1306 // A Predicate transition is a list of RW sequences guarded by a PredTerm.
1307 struct PredTransition
{
1308 // A predicate term is a conjunction of PredChecks.
1309 SmallVector
<PredCheck
, 4> PredTerm
;
1310 SmallVector
<SmallVector
<unsigned,4>, 16> WriteSequences
;
1311 SmallVector
<SmallVector
<unsigned,4>, 16> ReadSequences
;
1312 SmallVector
<unsigned, 4> ProcIndices
;
1315 // Encapsulate a set of partially constructed transitions.
1316 // The results are built by repeated calls to substituteVariants.
1317 class PredTransitions
{
1318 CodeGenSchedModels
&SchedModels
;
1321 std::vector
<PredTransition
> TransVec
;
1323 PredTransitions(CodeGenSchedModels
&sm
): SchedModels(sm
) {}
1325 void substituteVariantOperand(const SmallVectorImpl
<unsigned> &RWSeq
,
1326 bool IsRead
, unsigned StartIdx
);
1328 void substituteVariants(const PredTransition
&Trans
);
1335 bool mutuallyExclusive(Record
*PredDef
, ArrayRef
<PredCheck
> Term
);
1336 void getIntersectingVariants(
1337 const CodeGenSchedRW
&SchedRW
, unsigned TransIdx
,
1338 std::vector
<TransVariant
> &IntersectingVariants
);
1339 void pushVariant(const TransVariant
&VInfo
, bool IsRead
);
1342 } // end anonymous namespace
1344 // Return true if this predicate is mutually exclusive with a PredTerm. This
1345 // degenerates into checking if the predicate is mutually exclusive with any
1346 // predicate in the Term's conjunction.
1348 // All predicates associated with a given SchedRW are considered mutually
1349 // exclusive. This should work even if the conditions expressed by the
1350 // predicates are not exclusive because the predicates for a given SchedWrite
1351 // are always checked in the order they are defined in the .td file. Later
1352 // conditions implicitly negate any prior condition.
1353 bool PredTransitions::mutuallyExclusive(Record
*PredDef
,
1354 ArrayRef
<PredCheck
> Term
) {
1355 for (const PredCheck
&PC
: Term
) {
1356 if (PC
.Predicate
== PredDef
)
1359 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(PC
.RWIdx
, PC
.IsRead
);
1360 assert(SchedRW
.HasVariants
&& "PredCheck must refer to a SchedVariant");
1361 RecVec Variants
= SchedRW
.TheDef
->getValueAsListOfDefs("Variants");
1362 if (any_of(Variants
, [PredDef
](const Record
*R
) {
1363 return R
->getValueAsDef("Predicate") == PredDef
;
1370 static bool hasAliasedVariants(const CodeGenSchedRW
&RW
,
1371 CodeGenSchedModels
&SchedModels
) {
1375 for (Record
*Alias
: RW
.Aliases
) {
1376 const CodeGenSchedRW
&AliasRW
=
1377 SchedModels
.getSchedRW(Alias
->getValueAsDef("AliasRW"));
1378 if (AliasRW
.HasVariants
)
1380 if (AliasRW
.IsSequence
) {
1382 SchedModels
.expandRWSequence(AliasRW
.Index
, ExpandedRWs
, AliasRW
.IsRead
);
1383 for (unsigned SI
: ExpandedRWs
) {
1384 if (hasAliasedVariants(SchedModels
.getSchedRW(SI
, AliasRW
.IsRead
),
1393 static bool hasVariant(ArrayRef
<PredTransition
> Transitions
,
1394 CodeGenSchedModels
&SchedModels
) {
1395 for (const PredTransition
&PTI
: Transitions
) {
1396 for (const SmallVectorImpl
<unsigned> &WSI
: PTI
.WriteSequences
)
1397 for (unsigned WI
: WSI
)
1398 if (hasAliasedVariants(SchedModels
.getSchedWrite(WI
), SchedModels
))
1401 for (const SmallVectorImpl
<unsigned> &RSI
: PTI
.ReadSequences
)
1402 for (unsigned RI
: RSI
)
1403 if (hasAliasedVariants(SchedModels
.getSchedRead(RI
), SchedModels
))
1409 // Populate IntersectingVariants with any variants or aliased sequences of the
1410 // given SchedRW whose processor indices and predicates are not mutually
1411 // exclusive with the given transition.
1412 void PredTransitions::getIntersectingVariants(
1413 const CodeGenSchedRW
&SchedRW
, unsigned TransIdx
,
1414 std::vector
<TransVariant
> &IntersectingVariants
) {
1416 bool GenericRW
= false;
1418 std::vector
<TransVariant
> Variants
;
1419 if (SchedRW
.HasVariants
) {
1420 unsigned VarProcIdx
= 0;
1421 if (SchedRW
.TheDef
->getValueInit("SchedModel")->isComplete()) {
1422 Record
*ModelDef
= SchedRW
.TheDef
->getValueAsDef("SchedModel");
1423 VarProcIdx
= SchedModels
.getProcModel(ModelDef
).Index
;
1425 // Push each variant. Assign TransVecIdx later.
1426 const RecVec VarDefs
= SchedRW
.TheDef
->getValueAsListOfDefs("Variants");
1427 for (Record
*VarDef
: VarDefs
)
1428 Variants
.emplace_back(VarDef
, SchedRW
.Index
, VarProcIdx
, 0);
1429 if (VarProcIdx
== 0)
1432 for (RecIter AI
= SchedRW
.Aliases
.begin(), AE
= SchedRW
.Aliases
.end();
1434 // If either the SchedAlias itself or the SchedReadWrite that it aliases
1435 // to is defined within a processor model, constrain all variants to
1437 unsigned AliasProcIdx
= 0;
1438 if ((*AI
)->getValueInit("SchedModel")->isComplete()) {
1439 Record
*ModelDef
= (*AI
)->getValueAsDef("SchedModel");
1440 AliasProcIdx
= SchedModels
.getProcModel(ModelDef
).Index
;
1442 const CodeGenSchedRW
&AliasRW
=
1443 SchedModels
.getSchedRW((*AI
)->getValueAsDef("AliasRW"));
1445 if (AliasRW
.HasVariants
) {
1446 const RecVec VarDefs
= AliasRW
.TheDef
->getValueAsListOfDefs("Variants");
1447 for (Record
*VD
: VarDefs
)
1448 Variants
.emplace_back(VD
, AliasRW
.Index
, AliasProcIdx
, 0);
1450 if (AliasRW
.IsSequence
)
1451 Variants
.emplace_back(AliasRW
.TheDef
, SchedRW
.Index
, AliasProcIdx
, 0);
1452 if (AliasProcIdx
== 0)
1455 for (TransVariant
&Variant
: Variants
) {
1456 // Don't expand variants if the processor models don't intersect.
1457 // A zero processor index means any processor.
1458 SmallVectorImpl
<unsigned> &ProcIndices
= TransVec
[TransIdx
].ProcIndices
;
1459 if (ProcIndices
[0] && Variant
.ProcIdx
) {
1460 unsigned Cnt
= std::count(ProcIndices
.begin(), ProcIndices
.end(),
1465 const CodeGenProcModel
&PM
=
1466 *(SchedModels
.procModelBegin() + Variant
.ProcIdx
);
1467 PrintFatalError(Variant
.VarOrSeqDef
->getLoc(),
1468 "Multiple variants defined for processor " +
1470 " Ensure only one SchedAlias exists per RW.");
1473 if (Variant
.VarOrSeqDef
->isSubClassOf("SchedVar")) {
1474 Record
*PredDef
= Variant
.VarOrSeqDef
->getValueAsDef("Predicate");
1475 if (mutuallyExclusive(PredDef
, TransVec
[TransIdx
].PredTerm
))
1478 if (IntersectingVariants
.empty()) {
1479 // The first variant builds on the existing transition.
1480 Variant
.TransVecIdx
= TransIdx
;
1481 IntersectingVariants
.push_back(Variant
);
1484 // Push another copy of the current transition for more variants.
1485 Variant
.TransVecIdx
= TransVec
.size();
1486 IntersectingVariants
.push_back(Variant
);
1487 TransVec
.push_back(TransVec
[TransIdx
]);
1490 if (GenericRW
&& IntersectingVariants
.empty()) {
1491 PrintFatalError(SchedRW
.TheDef
->getLoc(), "No variant of this type has "
1492 "a matching predicate on any processor");
1496 // Push the Reads/Writes selected by this variant onto the PredTransition
1497 // specified by VInfo.
1498 void PredTransitions::
1499 pushVariant(const TransVariant
&VInfo
, bool IsRead
) {
1500 PredTransition
&Trans
= TransVec
[VInfo
.TransVecIdx
];
1502 // If this operand transition is reached through a processor-specific alias,
1503 // then the whole transition is specific to this processor.
1504 if (VInfo
.ProcIdx
!= 0)
1505 Trans
.ProcIndices
.assign(1, VInfo
.ProcIdx
);
1508 if (VInfo
.VarOrSeqDef
->isSubClassOf("SchedVar")) {
1509 Record
*PredDef
= VInfo
.VarOrSeqDef
->getValueAsDef("Predicate");
1510 Trans
.PredTerm
.emplace_back(IsRead
, VInfo
.RWIdx
,PredDef
);
1511 RecVec SelectedDefs
= VInfo
.VarOrSeqDef
->getValueAsListOfDefs("Selected");
1512 SchedModels
.findRWs(SelectedDefs
, SelectedRWs
, IsRead
);
1515 assert(VInfo
.VarOrSeqDef
->isSubClassOf("WriteSequence") &&
1516 "variant must be a SchedVariant or aliased WriteSequence");
1517 SelectedRWs
.push_back(SchedModels
.getSchedRWIdx(VInfo
.VarOrSeqDef
, IsRead
));
1520 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(VInfo
.RWIdx
, IsRead
);
1522 SmallVectorImpl
<SmallVector
<unsigned,4>> &RWSequences
= IsRead
1523 ? Trans
.ReadSequences
: Trans
.WriteSequences
;
1524 if (SchedRW
.IsVariadic
) {
1525 unsigned OperIdx
= RWSequences
.size()-1;
1526 // Make N-1 copies of this transition's last sequence.
1527 RWSequences
.insert(RWSequences
.end(), SelectedRWs
.size() - 1,
1528 RWSequences
[OperIdx
]);
1529 // Push each of the N elements of the SelectedRWs onto a copy of the last
1530 // sequence (split the current operand into N operands).
1531 // Note that write sequences should be expanded within this loop--the entire
1532 // sequence belongs to a single operand.
1533 for (IdxIter RWI
= SelectedRWs
.begin(), RWE
= SelectedRWs
.end();
1534 RWI
!= RWE
; ++RWI
, ++OperIdx
) {
1537 ExpandedRWs
.push_back(*RWI
);
1539 SchedModels
.expandRWSequence(*RWI
, ExpandedRWs
, IsRead
);
1540 RWSequences
[OperIdx
].insert(RWSequences
[OperIdx
].end(),
1541 ExpandedRWs
.begin(), ExpandedRWs
.end());
1543 assert(OperIdx
== RWSequences
.size() && "missed a sequence");
1546 // Push this transition's expanded sequence onto this transition's last
1547 // sequence (add to the current operand's sequence).
1548 SmallVectorImpl
<unsigned> &Seq
= RWSequences
.back();
1550 for (IdxIter RWI
= SelectedRWs
.begin(), RWE
= SelectedRWs
.end();
1551 RWI
!= RWE
; ++RWI
) {
1553 ExpandedRWs
.push_back(*RWI
);
1555 SchedModels
.expandRWSequence(*RWI
, ExpandedRWs
, IsRead
);
1557 Seq
.insert(Seq
.end(), ExpandedRWs
.begin(), ExpandedRWs
.end());
1561 // RWSeq is a sequence of all Reads or all Writes for the next read or write
1562 // operand. StartIdx is an index into TransVec where partial results
1563 // starts. RWSeq must be applied to all transitions between StartIdx and the end
1565 void PredTransitions::substituteVariantOperand(
1566 const SmallVectorImpl
<unsigned> &RWSeq
, bool IsRead
, unsigned StartIdx
) {
1568 // Visit each original RW within the current sequence.
1569 for (SmallVectorImpl
<unsigned>::const_iterator
1570 RWI
= RWSeq
.begin(), RWE
= RWSeq
.end(); RWI
!= RWE
; ++RWI
) {
1571 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(*RWI
, IsRead
);
1572 // Push this RW on all partial PredTransitions or distribute variants.
1573 // New PredTransitions may be pushed within this loop which should not be
1574 // revisited (TransEnd must be loop invariant).
1575 for (unsigned TransIdx
= StartIdx
, TransEnd
= TransVec
.size();
1576 TransIdx
!= TransEnd
; ++TransIdx
) {
1577 // In the common case, push RW onto the current operand's sequence.
1578 if (!hasAliasedVariants(SchedRW
, SchedModels
)) {
1580 TransVec
[TransIdx
].ReadSequences
.back().push_back(*RWI
);
1582 TransVec
[TransIdx
].WriteSequences
.back().push_back(*RWI
);
1585 // Distribute this partial PredTransition across intersecting variants.
1586 // This will push a copies of TransVec[TransIdx] on the back of TransVec.
1587 std::vector
<TransVariant
> IntersectingVariants
;
1588 getIntersectingVariants(SchedRW
, TransIdx
, IntersectingVariants
);
1589 // Now expand each variant on top of its copy of the transition.
1590 for (std::vector
<TransVariant
>::const_iterator
1591 IVI
= IntersectingVariants
.begin(),
1592 IVE
= IntersectingVariants
.end();
1593 IVI
!= IVE
; ++IVI
) {
1594 pushVariant(*IVI
, IsRead
);
1600 // For each variant of a Read/Write in Trans, substitute the sequence of
1601 // Read/Writes guarded by the variant. This is exponential in the number of
1602 // variant Read/Writes, but in practice detection of mutually exclusive
1603 // predicates should result in linear growth in the total number variants.
1605 // This is one step in a breadth-first search of nested variants.
1606 void PredTransitions::substituteVariants(const PredTransition
&Trans
) {
1607 // Build up a set of partial results starting at the back of
1608 // PredTransitions. Remember the first new transition.
1609 unsigned StartIdx
= TransVec
.size();
1610 TransVec
.emplace_back();
1611 TransVec
.back().PredTerm
= Trans
.PredTerm
;
1612 TransVec
.back().ProcIndices
= Trans
.ProcIndices
;
1614 // Visit each original write sequence.
1615 for (SmallVectorImpl
<SmallVector
<unsigned,4>>::const_iterator
1616 WSI
= Trans
.WriteSequences
.begin(), WSE
= Trans
.WriteSequences
.end();
1617 WSI
!= WSE
; ++WSI
) {
1618 // Push a new (empty) write sequence onto all partial Transitions.
1619 for (std::vector
<PredTransition
>::iterator I
=
1620 TransVec
.begin() + StartIdx
, E
= TransVec
.end(); I
!= E
; ++I
) {
1621 I
->WriteSequences
.emplace_back();
1623 substituteVariantOperand(*WSI
, /*IsRead=*/false, StartIdx
);
1625 // Visit each original read sequence.
1626 for (SmallVectorImpl
<SmallVector
<unsigned,4>>::const_iterator
1627 RSI
= Trans
.ReadSequences
.begin(), RSE
= Trans
.ReadSequences
.end();
1628 RSI
!= RSE
; ++RSI
) {
1629 // Push a new (empty) read sequence onto all partial Transitions.
1630 for (std::vector
<PredTransition
>::iterator I
=
1631 TransVec
.begin() + StartIdx
, E
= TransVec
.end(); I
!= E
; ++I
) {
1632 I
->ReadSequences
.emplace_back();
1634 substituteVariantOperand(*RSI
, /*IsRead=*/true, StartIdx
);
1638 // Create a new SchedClass for each variant found by inferFromRW. Pass
1639 static void inferFromTransitions(ArrayRef
<PredTransition
> LastTransitions
,
1640 unsigned FromClassIdx
,
1641 CodeGenSchedModels
&SchedModels
) {
1642 // For each PredTransition, create a new CodeGenSchedTransition, which usually
1643 // requires creating a new SchedClass.
1644 for (ArrayRef
<PredTransition
>::iterator
1645 I
= LastTransitions
.begin(), E
= LastTransitions
.end(); I
!= E
; ++I
) {
1646 IdxVec OperWritesVariant
;
1647 transform(I
->WriteSequences
, std::back_inserter(OperWritesVariant
),
1648 [&SchedModels
](ArrayRef
<unsigned> WS
) {
1649 return SchedModels
.findOrInsertRW(WS
, /*IsRead=*/false);
1651 IdxVec OperReadsVariant
;
1652 transform(I
->ReadSequences
, std::back_inserter(OperReadsVariant
),
1653 [&SchedModels
](ArrayRef
<unsigned> RS
) {
1654 return SchedModels
.findOrInsertRW(RS
, /*IsRead=*/true);
1656 CodeGenSchedTransition SCTrans
;
1657 SCTrans
.ToClassIdx
=
1658 SchedModels
.addSchedClass(/*ItinClassDef=*/nullptr, OperWritesVariant
,
1659 OperReadsVariant
, I
->ProcIndices
);
1660 SCTrans
.ProcIndices
.assign(I
->ProcIndices
.begin(), I
->ProcIndices
.end());
1661 // The final PredTerm is unique set of predicates guarding the transition.
1663 transform(I
->PredTerm
, std::back_inserter(Preds
),
1664 [](const PredCheck
&P
) {
1667 Preds
.erase(std::unique(Preds
.begin(), Preds
.end()), Preds
.end());
1668 SCTrans
.PredTerm
= std::move(Preds
);
1669 SchedModels
.getSchedClass(FromClassIdx
)
1670 .Transitions
.push_back(std::move(SCTrans
));
1674 // Create new SchedClasses for the given ReadWrite list. If any of the
1675 // ReadWrites refers to a SchedVariant, create a new SchedClass for each variant
1676 // of the ReadWrite list, following Aliases if necessary.
1677 void CodeGenSchedModels::inferFromRW(ArrayRef
<unsigned> OperWrites
,
1678 ArrayRef
<unsigned> OperReads
,
1679 unsigned FromClassIdx
,
1680 ArrayRef
<unsigned> ProcIndices
) {
1681 LLVM_DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices
);
1684 // Create a seed transition with an empty PredTerm and the expanded sequences
1685 // of SchedWrites for the current SchedClass.
1686 std::vector
<PredTransition
> LastTransitions
;
1687 LastTransitions
.emplace_back();
1688 LastTransitions
.back().ProcIndices
.append(ProcIndices
.begin(),
1691 for (unsigned WriteIdx
: OperWrites
) {
1693 expandRWSequence(WriteIdx
, WriteSeq
, /*IsRead=*/false);
1694 LastTransitions
[0].WriteSequences
.emplace_back();
1695 SmallVectorImpl
<unsigned> &Seq
= LastTransitions
[0].WriteSequences
.back();
1696 Seq
.append(WriteSeq
.begin(), WriteSeq
.end());
1697 LLVM_DEBUG(dbgs() << "("; dumpIdxVec(Seq
); dbgs() << ") ");
1699 LLVM_DEBUG(dbgs() << " Reads: ");
1700 for (unsigned ReadIdx
: OperReads
) {
1702 expandRWSequence(ReadIdx
, ReadSeq
, /*IsRead=*/true);
1703 LastTransitions
[0].ReadSequences
.emplace_back();
1704 SmallVectorImpl
<unsigned> &Seq
= LastTransitions
[0].ReadSequences
.back();
1705 Seq
.append(ReadSeq
.begin(), ReadSeq
.end());
1706 LLVM_DEBUG(dbgs() << "("; dumpIdxVec(Seq
); dbgs() << ") ");
1708 LLVM_DEBUG(dbgs() << '\n');
1710 // Collect all PredTransitions for individual operands.
1711 // Iterate until no variant writes remain.
1712 while (hasVariant(LastTransitions
, *this)) {
1713 PredTransitions
Transitions(*this);
1714 for (const PredTransition
&Trans
: LastTransitions
)
1715 Transitions
.substituteVariants(Trans
);
1716 LLVM_DEBUG(Transitions
.dump());
1717 LastTransitions
.swap(Transitions
.TransVec
);
1719 // If the first transition has no variants, nothing to do.
1720 if (LastTransitions
[0].PredTerm
.empty())
1723 // WARNING: We are about to mutate the SchedClasses vector. Do not refer to
1724 // OperWrites, OperReads, or ProcIndices after calling inferFromTransitions.
1725 inferFromTransitions(LastTransitions
, FromClassIdx
, *this);
1728 // Check if any processor resource group contains all resource records in
1730 bool CodeGenSchedModels::hasSuperGroup(RecVec
&SubUnits
, CodeGenProcModel
&PM
) {
1731 for (unsigned i
= 0, e
= PM
.ProcResourceDefs
.size(); i
< e
; ++i
) {
1732 if (!PM
.ProcResourceDefs
[i
]->isSubClassOf("ProcResGroup"))
1735 PM
.ProcResourceDefs
[i
]->getValueAsListOfDefs("Resources");
1736 RecIter RI
= SubUnits
.begin(), RE
= SubUnits
.end();
1737 for ( ; RI
!= RE
; ++RI
) {
1738 if (!is_contained(SuperUnits
, *RI
)) {
1748 // Verify that overlapping groups have a common supergroup.
1749 void CodeGenSchedModels::verifyProcResourceGroups(CodeGenProcModel
&PM
) {
1750 for (unsigned i
= 0, e
= PM
.ProcResourceDefs
.size(); i
< e
; ++i
) {
1751 if (!PM
.ProcResourceDefs
[i
]->isSubClassOf("ProcResGroup"))
1754 PM
.ProcResourceDefs
[i
]->getValueAsListOfDefs("Resources");
1755 for (unsigned j
= i
+1; j
< e
; ++j
) {
1756 if (!PM
.ProcResourceDefs
[j
]->isSubClassOf("ProcResGroup"))
1759 PM
.ProcResourceDefs
[j
]->getValueAsListOfDefs("Resources");
1760 if (std::find_first_of(CheckUnits
.begin(), CheckUnits
.end(),
1761 OtherUnits
.begin(), OtherUnits
.end())
1762 != CheckUnits
.end()) {
1763 // CheckUnits and OtherUnits overlap
1764 OtherUnits
.insert(OtherUnits
.end(), CheckUnits
.begin(),
1766 if (!hasSuperGroup(OtherUnits
, PM
)) {
1767 PrintFatalError((PM
.ProcResourceDefs
[i
])->getLoc(),
1768 "proc resource group overlaps with "
1769 + PM
.ProcResourceDefs
[j
]->getName()
1770 + " but no supergroup contains both.");
1777 // Collect all the RegisterFile definitions available in this target.
1778 void CodeGenSchedModels::collectRegisterFiles() {
1779 RecVec RegisterFileDefs
= Records
.getAllDerivedDefinitions("RegisterFile");
1781 // RegisterFiles is the vector of CodeGenRegisterFile.
1782 for (Record
*RF
: RegisterFileDefs
) {
1783 // For each register file definition, construct a CodeGenRegisterFile object
1784 // and add it to the appropriate scheduling model.
1785 CodeGenProcModel
&PM
= getProcModel(RF
->getValueAsDef("SchedModel"));
1786 PM
.RegisterFiles
.emplace_back(CodeGenRegisterFile(RF
->getName(),RF
));
1787 CodeGenRegisterFile
&CGRF
= PM
.RegisterFiles
.back();
1788 CGRF
.MaxMovesEliminatedPerCycle
=
1789 RF
->getValueAsInt("MaxMovesEliminatedPerCycle");
1790 CGRF
.AllowZeroMoveEliminationOnly
=
1791 RF
->getValueAsBit("AllowZeroMoveEliminationOnly");
1793 // Now set the number of physical registers as well as the cost of registers
1794 // in each register class.
1795 CGRF
.NumPhysRegs
= RF
->getValueAsInt("NumPhysRegs");
1796 if (!CGRF
.NumPhysRegs
) {
1797 PrintFatalError(RF
->getLoc(),
1798 "Invalid RegisterFile with zero physical registers");
1801 RecVec RegisterClasses
= RF
->getValueAsListOfDefs("RegClasses");
1802 std::vector
<int64_t> RegisterCosts
= RF
->getValueAsListOfInts("RegCosts");
1803 ListInit
*MoveElimInfo
= RF
->getValueAsListInit("AllowMoveElimination");
1804 for (unsigned I
= 0, E
= RegisterClasses
.size(); I
< E
; ++I
) {
1805 int Cost
= RegisterCosts
.size() > I
? RegisterCosts
[I
] : 1;
1807 bool AllowMoveElim
= false;
1808 if (MoveElimInfo
->size() > I
) {
1809 BitInit
*Val
= cast
<BitInit
>(MoveElimInfo
->getElement(I
));
1810 AllowMoveElim
= Val
->getValue();
1813 CGRF
.Costs
.emplace_back(RegisterClasses
[I
], Cost
, AllowMoveElim
);
1818 // Collect and sort WriteRes, ReadAdvance, and ProcResources.
1819 void CodeGenSchedModels::collectProcResources() {
1820 ProcResourceDefs
= Records
.getAllDerivedDefinitions("ProcResourceUnits");
1821 ProcResGroups
= Records
.getAllDerivedDefinitions("ProcResGroup");
1823 // Add any subtarget-specific SchedReadWrites that are directly associated
1824 // with processor resources. Refer to the parent SchedClass's ProcIndices to
1825 // determine which processors they apply to.
1826 for (const CodeGenSchedClass
&SC
:
1827 make_range(schedClassBegin(), schedClassEnd())) {
1828 if (SC
.ItinClassDef
) {
1829 collectItinProcResources(SC
.ItinClassDef
);
1833 // This class may have a default ReadWrite list which can be overriden by
1834 // InstRW definitions.
1835 for (Record
*RW
: SC
.InstRWs
) {
1836 Record
*RWModelDef
= RW
->getValueAsDef("SchedModel");
1837 unsigned PIdx
= getProcModel(RWModelDef
).Index
;
1838 IdxVec Writes
, Reads
;
1839 findRWs(RW
->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1840 collectRWResources(Writes
, Reads
, PIdx
);
1843 collectRWResources(SC
.Writes
, SC
.Reads
, SC
.ProcIndices
);
1845 // Add resources separately defined by each subtarget.
1846 RecVec WRDefs
= Records
.getAllDerivedDefinitions("WriteRes");
1847 for (Record
*WR
: WRDefs
) {
1848 Record
*ModelDef
= WR
->getValueAsDef("SchedModel");
1849 addWriteRes(WR
, getProcModel(ModelDef
).Index
);
1851 RecVec SWRDefs
= Records
.getAllDerivedDefinitions("SchedWriteRes");
1852 for (Record
*SWR
: SWRDefs
) {
1853 Record
*ModelDef
= SWR
->getValueAsDef("SchedModel");
1854 addWriteRes(SWR
, getProcModel(ModelDef
).Index
);
1856 RecVec RADefs
= Records
.getAllDerivedDefinitions("ReadAdvance");
1857 for (Record
*RA
: RADefs
) {
1858 Record
*ModelDef
= RA
->getValueAsDef("SchedModel");
1859 addReadAdvance(RA
, getProcModel(ModelDef
).Index
);
1861 RecVec SRADefs
= Records
.getAllDerivedDefinitions("SchedReadAdvance");
1862 for (Record
*SRA
: SRADefs
) {
1863 if (SRA
->getValueInit("SchedModel")->isComplete()) {
1864 Record
*ModelDef
= SRA
->getValueAsDef("SchedModel");
1865 addReadAdvance(SRA
, getProcModel(ModelDef
).Index
);
1868 // Add ProcResGroups that are defined within this processor model, which may
1869 // not be directly referenced but may directly specify a buffer size.
1870 RecVec ProcResGroups
= Records
.getAllDerivedDefinitions("ProcResGroup");
1871 for (Record
*PRG
: ProcResGroups
) {
1872 if (!PRG
->getValueInit("SchedModel")->isComplete())
1874 CodeGenProcModel
&PM
= getProcModel(PRG
->getValueAsDef("SchedModel"));
1875 if (!is_contained(PM
.ProcResourceDefs
, PRG
))
1876 PM
.ProcResourceDefs
.push_back(PRG
);
1878 // Add ProcResourceUnits unconditionally.
1879 for (Record
*PRU
: Records
.getAllDerivedDefinitions("ProcResourceUnits")) {
1880 if (!PRU
->getValueInit("SchedModel")->isComplete())
1882 CodeGenProcModel
&PM
= getProcModel(PRU
->getValueAsDef("SchedModel"));
1883 if (!is_contained(PM
.ProcResourceDefs
, PRU
))
1884 PM
.ProcResourceDefs
.push_back(PRU
);
1886 // Finalize each ProcModel by sorting the record arrays.
1887 for (CodeGenProcModel
&PM
: ProcModels
) {
1888 llvm::sort(PM
.WriteResDefs
, LessRecord());
1889 llvm::sort(PM
.ReadAdvanceDefs
, LessRecord());
1890 llvm::sort(PM
.ProcResourceDefs
, LessRecord());
1893 dbgs() << "WriteResDefs: "; for (RecIter RI
= PM
.WriteResDefs
.begin(),
1894 RE
= PM
.WriteResDefs
.end();
1896 if ((*RI
)->isSubClassOf("WriteRes"))
1897 dbgs() << (*RI
)->getValueAsDef("WriteType")->getName() << " ";
1899 dbgs() << (*RI
)->getName() << " ";
1900 } dbgs() << "\nReadAdvanceDefs: ";
1901 for (RecIter RI
= PM
.ReadAdvanceDefs
.begin(),
1902 RE
= PM
.ReadAdvanceDefs
.end();
1904 if ((*RI
)->isSubClassOf("ReadAdvance"))
1905 dbgs() << (*RI
)->getValueAsDef("ReadType")->getName() << " ";
1907 dbgs() << (*RI
)->getName() << " ";
1909 << "\nProcResourceDefs: ";
1910 for (RecIter RI
= PM
.ProcResourceDefs
.begin(),
1911 RE
= PM
.ProcResourceDefs
.end();
1912 RI
!= RE
; ++RI
) { dbgs() << (*RI
)->getName() << " "; } dbgs()
1914 verifyProcResourceGroups(PM
);
1917 ProcResourceDefs
.clear();
1918 ProcResGroups
.clear();
1921 void CodeGenSchedModels::checkCompleteness() {
1922 bool Complete
= true;
1923 bool HadCompleteModel
= false;
1924 for (const CodeGenProcModel
&ProcModel
: procModels()) {
1925 const bool HasItineraries
= ProcModel
.hasItineraries();
1926 if (!ProcModel
.ModelDef
->getValueAsBit("CompleteModel"))
1928 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
1929 if (Inst
->hasNoSchedulingInfo
)
1931 if (ProcModel
.isUnsupported(*Inst
))
1933 unsigned SCIdx
= getSchedClassIdx(*Inst
);
1935 if (Inst
->TheDef
->isValueUnset("SchedRW") && !HadCompleteModel
) {
1936 PrintError(Inst
->TheDef
->getLoc(),
1937 "No schedule information for instruction '" +
1938 Inst
->TheDef
->getName() + "' in SchedMachineModel '" +
1939 ProcModel
.ModelDef
->getName() + "'");
1945 const CodeGenSchedClass
&SC
= getSchedClass(SCIdx
);
1946 if (!SC
.Writes
.empty())
1948 if (HasItineraries
&& SC
.ItinClassDef
!= nullptr &&
1949 SC
.ItinClassDef
->getName() != "NoItinerary")
1952 const RecVec
&InstRWs
= SC
.InstRWs
;
1953 auto I
= find_if(InstRWs
, [&ProcModel
](const Record
*R
) {
1954 return R
->getValueAsDef("SchedModel") == ProcModel
.ModelDef
;
1956 if (I
== InstRWs
.end()) {
1957 PrintError(Inst
->TheDef
->getLoc(), "'" + ProcModel
.ModelName
+
1958 "' lacks information for '" +
1959 Inst
->TheDef
->getName() + "'");
1963 HadCompleteModel
= true;
1966 errs() << "\n\nIncomplete schedule models found.\n"
1967 << "- Consider setting 'CompleteModel = 0' while developing new models.\n"
1968 << "- Pseudo instructions can be marked with 'hasNoSchedulingInfo = 1'.\n"
1969 << "- Instructions should usually have Sched<[...]> as a superclass, "
1970 "you may temporarily use an empty list.\n"
1971 << "- Instructions related to unsupported features can be excluded with "
1972 "list<Predicate> UnsupportedFeatures = [HasA,..,HasY]; in the "
1973 "processor model.\n\n";
1974 PrintFatalError("Incomplete schedule model");
1978 // Collect itinerary class resources for each processor.
1979 void CodeGenSchedModels::collectItinProcResources(Record
*ItinClassDef
) {
1980 for (unsigned PIdx
= 0, PEnd
= ProcModels
.size(); PIdx
!= PEnd
; ++PIdx
) {
1981 const CodeGenProcModel
&PM
= ProcModels
[PIdx
];
1982 // For all ItinRW entries.
1983 bool HasMatch
= false;
1984 for (RecIter II
= PM
.ItinRWDefs
.begin(), IE
= PM
.ItinRWDefs
.end();
1986 RecVec Matched
= (*II
)->getValueAsListOfDefs("MatchedItinClasses");
1987 if (!std::count(Matched
.begin(), Matched
.end(), ItinClassDef
))
1990 PrintFatalError((*II
)->getLoc(), "Duplicate itinerary class "
1991 + ItinClassDef
->getName()
1992 + " in ItinResources for " + PM
.ModelName
);
1994 IdxVec Writes
, Reads
;
1995 findRWs((*II
)->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1996 collectRWResources(Writes
, Reads
, PIdx
);
2001 void CodeGenSchedModels::collectRWResources(unsigned RWIdx
, bool IsRead
,
2002 ArrayRef
<unsigned> ProcIndices
) {
2003 const CodeGenSchedRW
&SchedRW
= getSchedRW(RWIdx
, IsRead
);
2004 if (SchedRW
.TheDef
) {
2005 if (!IsRead
&& SchedRW
.TheDef
->isSubClassOf("SchedWriteRes")) {
2006 for (unsigned Idx
: ProcIndices
)
2007 addWriteRes(SchedRW
.TheDef
, Idx
);
2009 else if (IsRead
&& SchedRW
.TheDef
->isSubClassOf("SchedReadAdvance")) {
2010 for (unsigned Idx
: ProcIndices
)
2011 addReadAdvance(SchedRW
.TheDef
, Idx
);
2014 for (RecIter AI
= SchedRW
.Aliases
.begin(), AE
= SchedRW
.Aliases
.end();
2016 IdxVec AliasProcIndices
;
2017 if ((*AI
)->getValueInit("SchedModel")->isComplete()) {
2018 AliasProcIndices
.push_back(
2019 getProcModel((*AI
)->getValueAsDef("SchedModel")).Index
);
2022 AliasProcIndices
= ProcIndices
;
2023 const CodeGenSchedRW
&AliasRW
= getSchedRW((*AI
)->getValueAsDef("AliasRW"));
2024 assert(AliasRW
.IsRead
== IsRead
&& "cannot alias reads to writes");
2027 expandRWSequence(AliasRW
.Index
, ExpandedRWs
, IsRead
);
2028 for (IdxIter SI
= ExpandedRWs
.begin(), SE
= ExpandedRWs
.end();
2030 collectRWResources(*SI
, IsRead
, AliasProcIndices
);
2035 // Collect resources for a set of read/write types and processor indices.
2036 void CodeGenSchedModels::collectRWResources(ArrayRef
<unsigned> Writes
,
2037 ArrayRef
<unsigned> Reads
,
2038 ArrayRef
<unsigned> ProcIndices
) {
2039 for (unsigned Idx
: Writes
)
2040 collectRWResources(Idx
, /*IsRead=*/false, ProcIndices
);
2042 for (unsigned Idx
: Reads
)
2043 collectRWResources(Idx
, /*IsRead=*/true, ProcIndices
);
2046 // Find the processor's resource units for this kind of resource.
2047 Record
*CodeGenSchedModels::findProcResUnits(Record
*ProcResKind
,
2048 const CodeGenProcModel
&PM
,
2049 ArrayRef
<SMLoc
> Loc
) const {
2050 if (ProcResKind
->isSubClassOf("ProcResourceUnits"))
2053 Record
*ProcUnitDef
= nullptr;
2054 assert(!ProcResourceDefs
.empty());
2055 assert(!ProcResGroups
.empty());
2057 for (Record
*ProcResDef
: ProcResourceDefs
) {
2058 if (ProcResDef
->getValueAsDef("Kind") == ProcResKind
2059 && ProcResDef
->getValueAsDef("SchedModel") == PM
.ModelDef
) {
2061 PrintFatalError(Loc
,
2062 "Multiple ProcessorResourceUnits associated with "
2063 + ProcResKind
->getName());
2065 ProcUnitDef
= ProcResDef
;
2068 for (Record
*ProcResGroup
: ProcResGroups
) {
2069 if (ProcResGroup
== ProcResKind
2070 && ProcResGroup
->getValueAsDef("SchedModel") == PM
.ModelDef
) {
2072 PrintFatalError(Loc
,
2073 "Multiple ProcessorResourceUnits associated with "
2074 + ProcResKind
->getName());
2076 ProcUnitDef
= ProcResGroup
;
2080 PrintFatalError(Loc
,
2081 "No ProcessorResources associated with "
2082 + ProcResKind
->getName());
2087 // Iteratively add a resource and its super resources.
2088 void CodeGenSchedModels::addProcResource(Record
*ProcResKind
,
2089 CodeGenProcModel
&PM
,
2090 ArrayRef
<SMLoc
> Loc
) {
2092 Record
*ProcResUnits
= findProcResUnits(ProcResKind
, PM
, Loc
);
2094 // See if this ProcResource is already associated with this processor.
2095 if (is_contained(PM
.ProcResourceDefs
, ProcResUnits
))
2098 PM
.ProcResourceDefs
.push_back(ProcResUnits
);
2099 if (ProcResUnits
->isSubClassOf("ProcResGroup"))
2102 if (!ProcResUnits
->getValueInit("Super")->isComplete())
2105 ProcResKind
= ProcResUnits
->getValueAsDef("Super");
2109 // Add resources for a SchedWrite to this processor if they don't exist.
2110 void CodeGenSchedModels::addWriteRes(Record
*ProcWriteResDef
, unsigned PIdx
) {
2111 assert(PIdx
&& "don't add resources to an invalid Processor model");
2113 RecVec
&WRDefs
= ProcModels
[PIdx
].WriteResDefs
;
2114 if (is_contained(WRDefs
, ProcWriteResDef
))
2116 WRDefs
.push_back(ProcWriteResDef
);
2118 // Visit ProcResourceKinds referenced by the newly discovered WriteRes.
2119 RecVec ProcResDefs
= ProcWriteResDef
->getValueAsListOfDefs("ProcResources");
2120 for (RecIter WritePRI
= ProcResDefs
.begin(), WritePRE
= ProcResDefs
.end();
2121 WritePRI
!= WritePRE
; ++WritePRI
) {
2122 addProcResource(*WritePRI
, ProcModels
[PIdx
], ProcWriteResDef
->getLoc());
2126 // Add resources for a ReadAdvance to this processor if they don't exist.
2127 void CodeGenSchedModels::addReadAdvance(Record
*ProcReadAdvanceDef
,
2129 RecVec
&RADefs
= ProcModels
[PIdx
].ReadAdvanceDefs
;
2130 if (is_contained(RADefs
, ProcReadAdvanceDef
))
2132 RADefs
.push_back(ProcReadAdvanceDef
);
2135 unsigned CodeGenProcModel::getProcResourceIdx(Record
*PRDef
) const {
2136 RecIter PRPos
= find(ProcResourceDefs
, PRDef
);
2137 if (PRPos
== ProcResourceDefs
.end())
2138 PrintFatalError(PRDef
->getLoc(), "ProcResource def is not included in "
2139 "the ProcResources list for " + ModelName
);
2140 // Idx=0 is reserved for invalid.
2141 return 1 + (PRPos
- ProcResourceDefs
.begin());
2144 bool CodeGenProcModel::isUnsupported(const CodeGenInstruction
&Inst
) const {
2145 for (const Record
*TheDef
: UnsupportedFeaturesDefs
) {
2146 for (const Record
*PredDef
: Inst
.TheDef
->getValueAsListOfDefs("Predicates")) {
2147 if (TheDef
->getName() == PredDef
->getName())
2155 void CodeGenProcModel::dump() const {
2156 dbgs() << Index
<< ": " << ModelName
<< " "
2157 << (ModelDef
? ModelDef
->getName() : "inferred") << " "
2158 << (ItinsDef
? ItinsDef
->getName() : "no itinerary") << '\n';
2161 void CodeGenSchedRW::dump() const {
2162 dbgs() << Name
<< (IsVariadic
? " (V) " : " ");
2165 dumpIdxVec(Sequence
);
2170 void CodeGenSchedClass::dump(const CodeGenSchedModels
* SchedModels
) const {
2171 dbgs() << "SCHEDCLASS " << Index
<< ":" << Name
<< '\n'
2173 for (unsigned i
= 0, N
= Writes
.size(); i
< N
; ++i
) {
2174 SchedModels
->getSchedWrite(Writes
[i
]).dump();
2180 dbgs() << "\n Reads: ";
2181 for (unsigned i
= 0, N
= Reads
.size(); i
< N
; ++i
) {
2182 SchedModels
->getSchedRead(Reads
[i
]).dump();
2188 dbgs() << "\n ProcIdx: "; dumpIdxVec(ProcIndices
); dbgs() << '\n';
2189 if (!Transitions
.empty()) {
2190 dbgs() << "\n Transitions for Proc ";
2191 for (const CodeGenSchedTransition
&Transition
: Transitions
) {
2192 dumpIdxVec(Transition
.ProcIndices
);
2197 void PredTransitions::dump() const {
2198 dbgs() << "Expanded Variants:\n";
2199 for (std::vector
<PredTransition
>::const_iterator
2200 TI
= TransVec
.begin(), TE
= TransVec
.end(); TI
!= TE
; ++TI
) {
2202 for (SmallVectorImpl
<PredCheck
>::const_iterator
2203 PCI
= TI
->PredTerm
.begin(), PCE
= TI
->PredTerm
.end();
2204 PCI
!= PCE
; ++PCI
) {
2205 if (PCI
!= TI
->PredTerm
.begin())
2207 dbgs() << SchedModels
.getSchedRW(PCI
->RWIdx
, PCI
->IsRead
).Name
2208 << ":" << PCI
->Predicate
->getName();
2210 dbgs() << "},\n => {";
2211 for (SmallVectorImpl
<SmallVector
<unsigned,4>>::const_iterator
2212 WSI
= TI
->WriteSequences
.begin(), WSE
= TI
->WriteSequences
.end();
2213 WSI
!= WSE
; ++WSI
) {
2215 for (SmallVectorImpl
<unsigned>::const_iterator
2216 WI
= WSI
->begin(), WE
= WSI
->end(); WI
!= WE
; ++WI
) {
2217 if (WI
!= WSI
->begin())
2219 dbgs() << SchedModels
.getSchedWrite(*WI
).Name
;