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/SmallVector.h"
21 #include "llvm/Support/Casting.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/Regex.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/TableGen/Error.h"
32 #define DEBUG_TYPE "subtarget-emitter"
35 static void dumpIdxVec(ArrayRef
<unsigned> V
) {
36 for (unsigned Idx
: V
)
37 dbgs() << Idx
<< ", ";
43 // (instrs a, b, ...) Evaluate and union all arguments. Identical to AddOp.
44 struct InstrsOp
: public SetTheory::Operator
{
45 void apply(SetTheory
&ST
, DagInit
*Expr
, SetTheory::RecSet
&Elts
,
46 ArrayRef
<SMLoc
> Loc
) override
{
47 ST
.evaluate(Expr
->arg_begin(), Expr
->arg_end(), Elts
, Loc
);
51 // (instregex "OpcPat",...) Find all instructions matching an opcode pattern.
52 struct InstRegexOp
: public SetTheory::Operator
{
53 const CodeGenTarget
&Target
;
54 InstRegexOp(const CodeGenTarget
&t
): Target(t
) {}
56 /// Remove any text inside of parentheses from S.
57 static std::string
removeParens(llvm::StringRef S
) {
60 // NB: We don't care about escaped parens here.
77 void apply(SetTheory
&ST
, DagInit
*Expr
, SetTheory::RecSet
&Elts
,
78 ArrayRef
<SMLoc
> Loc
) override
{
79 ArrayRef
<const CodeGenInstruction
*> Instructions
=
80 Target
.getInstructionsByEnumValue();
82 unsigned NumGeneric
= Target
.getNumFixedInstructions();
83 unsigned NumPseudos
= Target
.getNumPseudoInstructions();
84 auto Generics
= Instructions
.slice(0, NumGeneric
);
85 auto Pseudos
= Instructions
.slice(NumGeneric
, NumPseudos
);
86 auto NonPseudos
= Instructions
.slice(NumGeneric
+ NumPseudos
);
88 for (Init
*Arg
: Expr
->getArgs()) {
89 StringInit
*SI
= dyn_cast
<StringInit
>(Arg
);
91 PrintFatalError(Loc
, "instregex requires pattern string: " +
93 StringRef Original
= SI
->getValue();
95 // Extract a prefix that we can binary search on.
96 static const char RegexMetachars
[] = "()^$|*+?.[]\\{}";
97 auto FirstMeta
= Original
.find_first_of(RegexMetachars
);
99 // Look for top-level | or ?. We cannot optimize them to binary search.
100 if (removeParens(Original
).find_first_of("|?") != std::string::npos
)
103 std::optional
<Regex
> Regexpr
;
104 StringRef Prefix
= Original
.substr(0, FirstMeta
);
105 StringRef PatStr
= Original
.substr(FirstMeta
);
106 if (!PatStr
.empty()) {
107 // For the rest use a python-style prefix match.
108 std::string pat
= std::string(PatStr
);
111 pat
.insert(pat
.end(), ')');
113 Regexpr
= Regex(pat
);
118 // The generic opcodes are unsorted, handle them manually.
119 for (auto *Inst
: Generics
) {
120 StringRef InstName
= Inst
->TheDef
->getName();
121 if (InstName
.startswith(Prefix
) &&
122 (!Regexpr
|| Regexpr
->match(InstName
.substr(Prefix
.size())))) {
123 Elts
.insert(Inst
->TheDef
);
128 // Target instructions are split into two ranges: pseudo instructions
129 // first, than non-pseudos. Each range is in lexicographical order
130 // sorted by name. Find the sub-ranges that start with our prefix.
132 bool operator()(const CodeGenInstruction
*LHS
, StringRef RHS
) {
133 return LHS
->TheDef
->getName() < RHS
;
135 bool operator()(StringRef LHS
, const CodeGenInstruction
*RHS
) {
136 return LHS
< RHS
->TheDef
->getName() &&
137 !RHS
->TheDef
->getName().startswith(LHS
);
141 std::equal_range(Pseudos
.begin(), Pseudos
.end(), Prefix
, Comp());
142 auto Range2
= std::equal_range(NonPseudos
.begin(), NonPseudos
.end(),
145 // For these ranges we know that instruction names start with the prefix.
146 // Check if there's a regex that needs to be checked.
147 const auto HandleNonGeneric
= [&](const CodeGenInstruction
*Inst
) {
148 StringRef InstName
= Inst
->TheDef
->getName();
149 if (!Regexpr
|| Regexpr
->match(InstName
.substr(Prefix
.size()))) {
150 Elts
.insert(Inst
->TheDef
);
154 std::for_each(Range1
.first
, Range1
.second
, HandleNonGeneric
);
155 std::for_each(Range2
.first
, Range2
.second
, HandleNonGeneric
);
158 PrintFatalError(Loc
, "instregex has no matches: " + Original
);
163 } // end anonymous namespace
165 /// CodeGenModels ctor interprets machine model records and populates maps.
166 CodeGenSchedModels::CodeGenSchedModels(RecordKeeper
&RK
,
167 const CodeGenTarget
&TGT
):
168 Records(RK
), Target(TGT
) {
170 Sets
.addFieldExpander("InstRW", "Instrs");
172 // Allow Set evaluation to recognize the dags used in InstRW records:
173 // (instrs Op1, Op1...)
174 Sets
.addOperator("instrs", std::make_unique
<InstrsOp
>());
175 Sets
.addOperator("instregex", std::make_unique
<InstRegexOp
>(Target
));
177 // Instantiate a CodeGenProcModel for each SchedMachineModel with the values
178 // that are explicitly referenced in tablegen records. Resources associated
179 // with each processor will be derived later. Populate ProcModelMap with the
180 // CodeGenProcModel instances.
183 // Instantiate a CodeGenSchedRW for each SchedReadWrite record explicitly
184 // defined, and populate SchedReads and SchedWrites vectors. Implicit
185 // SchedReadWrites that represent sequences derived from expanded variant will
186 // be inferred later.
189 // Instantiate a CodeGenSchedClass for each unique SchedRW signature directly
190 // required by an instruction definition, and populate SchedClassIdxMap. Set
191 // NumItineraryClasses to the number of explicit itinerary classes referenced
192 // by instructions. Set NumInstrSchedClasses to the number of itinerary
193 // classes plus any classes implied by instructions that derive from class
194 // Sched and provide SchedRW list. This does not infer any new classes from
196 collectSchedClasses();
198 // Find instruction itineraries for each processor. Sort and populate
199 // CodeGenProcModel::ItinDefList. (Cycle-to-cycle itineraries). This requires
200 // all itinerary classes to be discovered.
203 // Find ItinRW records for each processor and itinerary class.
204 // (For per-operand resources mapped to itinerary classes).
207 // Find UnsupportedFeatures records for each processor.
208 // (For per-operand resources mapped to itinerary classes).
209 collectProcUnsupportedFeatures();
211 // Infer new SchedClasses from SchedVariant.
214 // Populate each CodeGenProcModel's WriteResDefs, ReadAdvanceDefs, and
217 dbgs() << "\n+++ RESOURCE DEFINITIONS (collectProcResources) +++\n");
218 collectProcResources();
220 // Collect optional processor description.
221 collectOptionalProcessorInfo();
223 // Check MCInstPredicate definitions.
224 checkMCInstPredicates();
226 // Check STIPredicate definitions.
227 checkSTIPredicates();
229 // Find STIPredicate definitions for each processor model, and construct
230 // STIPredicateFunction objects.
231 collectSTIPredicates();
236 void CodeGenSchedModels::checkSTIPredicates() const {
237 DenseMap
<StringRef
, const Record
*> Declarations
;
239 // There cannot be multiple declarations with the same name.
240 const RecVec Decls
= Records
.getAllDerivedDefinitions("STIPredicateDecl");
241 for (const Record
*R
: Decls
) {
242 StringRef Name
= R
->getValueAsString("Name");
243 const auto It
= Declarations
.find(Name
);
244 if (It
== Declarations
.end()) {
245 Declarations
[Name
] = R
;
249 PrintError(R
->getLoc(), "STIPredicate " + Name
+ " multiply declared.");
250 PrintFatalNote(It
->second
->getLoc(), "Previous declaration was here.");
253 // Disallow InstructionEquivalenceClasses with an empty instruction list.
255 Records
.getAllDerivedDefinitions("InstructionEquivalenceClass");
256 for (const Record
*R
: Defs
) {
257 RecVec Opcodes
= R
->getValueAsListOfDefs("Opcodes");
258 if (Opcodes
.empty()) {
259 PrintFatalError(R
->getLoc(), "Invalid InstructionEquivalenceClass "
260 "defined with an empty opcode list.");
265 // Used by function `processSTIPredicate` to construct a mask of machine
266 // instruction operands.
267 static APInt
constructOperandMask(ArrayRef
<int64_t> Indices
) {
272 int64_t MaxIndex
= *std::max_element(Indices
.begin(), Indices
.end());
273 assert(MaxIndex
>= 0 && "Invalid negative indices in input!");
274 OperandMask
= OperandMask
.zext(MaxIndex
+ 1);
275 for (const int64_t Index
: Indices
) {
276 assert(Index
>= 0 && "Invalid negative indices!");
277 OperandMask
.setBit(Index
);
284 processSTIPredicate(STIPredicateFunction
&Fn
,
285 const ProcModelMapTy
&ProcModelMap
) {
286 DenseMap
<const Record
*, unsigned> Opcode2Index
;
287 using OpcodeMapPair
= std::pair
<const Record
*, OpcodeInfo
>;
288 std::vector
<OpcodeMapPair
> OpcodeMappings
;
289 std::vector
<std::pair
<APInt
, APInt
>> OpcodeMasks
;
291 DenseMap
<const Record
*, unsigned> Predicate2Index
;
292 unsigned NumUniquePredicates
= 0;
294 // Number unique predicates and opcodes used by InstructionEquivalenceClass
295 // definitions. Each unique opcode will be associated with an OpcodeInfo
297 for (const Record
*Def
: Fn
.getDefinitions()) {
298 RecVec Classes
= Def
->getValueAsListOfDefs("Classes");
299 for (const Record
*EC
: Classes
) {
300 const Record
*Pred
= EC
->getValueAsDef("Predicate");
301 if (!Predicate2Index
.contains(Pred
))
302 Predicate2Index
[Pred
] = NumUniquePredicates
++;
304 RecVec Opcodes
= EC
->getValueAsListOfDefs("Opcodes");
305 for (const Record
*Opcode
: Opcodes
) {
306 if (!Opcode2Index
.contains(Opcode
)) {
307 Opcode2Index
[Opcode
] = OpcodeMappings
.size();
308 OpcodeMappings
.emplace_back(Opcode
, OpcodeInfo());
314 // Initialize vector `OpcodeMasks` with default values. We want to keep track
315 // of which processors "use" which opcodes. We also want to be able to
316 // identify predicates that are used by different processors for a same
318 // This information is used later on by this algorithm to sort OpcodeMapping
319 // elements based on their processor and predicate sets.
320 OpcodeMasks
.resize(OpcodeMappings
.size());
321 APInt
DefaultProcMask(ProcModelMap
.size(), 0);
322 APInt
DefaultPredMask(NumUniquePredicates
, 0);
323 for (std::pair
<APInt
, APInt
> &MaskPair
: OpcodeMasks
)
324 MaskPair
= std::make_pair(DefaultProcMask
, DefaultPredMask
);
326 // Construct a OpcodeInfo object for every unique opcode declared by an
327 // InstructionEquivalenceClass definition.
328 for (const Record
*Def
: Fn
.getDefinitions()) {
329 RecVec Classes
= Def
->getValueAsListOfDefs("Classes");
330 const Record
*SchedModel
= Def
->getValueAsDef("SchedModel");
331 unsigned ProcIndex
= ProcModelMap
.find(SchedModel
)->second
;
332 APInt
ProcMask(ProcModelMap
.size(), 0);
333 ProcMask
.setBit(ProcIndex
);
335 for (const Record
*EC
: Classes
) {
336 RecVec Opcodes
= EC
->getValueAsListOfDefs("Opcodes");
338 std::vector
<int64_t> OpIndices
=
339 EC
->getValueAsListOfInts("OperandIndices");
340 APInt OperandMask
= constructOperandMask(OpIndices
);
342 const Record
*Pred
= EC
->getValueAsDef("Predicate");
343 APInt
PredMask(NumUniquePredicates
, 0);
344 PredMask
.setBit(Predicate2Index
[Pred
]);
346 for (const Record
*Opcode
: Opcodes
) {
347 unsigned OpcodeIdx
= Opcode2Index
[Opcode
];
348 if (OpcodeMasks
[OpcodeIdx
].first
[ProcIndex
]) {
349 std::string Message
=
350 "Opcode " + Opcode
->getName().str() +
351 " used by multiple InstructionEquivalenceClass definitions.";
352 PrintFatalError(EC
->getLoc(), Message
);
354 OpcodeMasks
[OpcodeIdx
].first
|= ProcMask
;
355 OpcodeMasks
[OpcodeIdx
].second
|= PredMask
;
356 OpcodeInfo
&OI
= OpcodeMappings
[OpcodeIdx
].second
;
358 OI
.addPredicateForProcModel(ProcMask
, OperandMask
, Pred
);
363 // Sort OpcodeMappings elements based on their CPU and predicate masks.
364 // As a last resort, order elements by opcode identifier.
365 llvm::sort(OpcodeMappings
,
366 [&](const OpcodeMapPair
&Lhs
, const OpcodeMapPair
&Rhs
) {
367 unsigned LhsIdx
= Opcode2Index
[Lhs
.first
];
368 unsigned RhsIdx
= Opcode2Index
[Rhs
.first
];
369 const std::pair
<APInt
, APInt
> &LhsMasks
= OpcodeMasks
[LhsIdx
];
370 const std::pair
<APInt
, APInt
> &RhsMasks
= OpcodeMasks
[RhsIdx
];
372 auto PopulationCountAndLeftBit
=
373 [](const APInt
&Other
) -> std::pair
<int, int> {
374 return std::pair
<int, int>(Other
.popcount(),
375 -Other
.countl_zero());
377 auto lhsmask_first
= PopulationCountAndLeftBit(LhsMasks
.first
);
378 auto rhsmask_first
= PopulationCountAndLeftBit(RhsMasks
.first
);
379 if (lhsmask_first
!= rhsmask_first
)
380 return lhsmask_first
< rhsmask_first
;
382 auto lhsmask_second
= PopulationCountAndLeftBit(LhsMasks
.second
);
383 auto rhsmask_second
= PopulationCountAndLeftBit(RhsMasks
.second
);
384 if (lhsmask_second
!= rhsmask_second
)
385 return lhsmask_second
< rhsmask_second
;
387 return LhsIdx
< RhsIdx
;
390 // Now construct opcode groups. Groups are used by the SubtargetEmitter when
391 // expanding the body of a STIPredicate function. In particular, each opcode
392 // group is expanded into a sequence of labels in a switch statement.
393 // It identifies opcodes for which different processors define same predicates
394 // and same opcode masks.
395 for (OpcodeMapPair
&Info
: OpcodeMappings
)
396 Fn
.addOpcode(Info
.first
, std::move(Info
.second
));
399 void CodeGenSchedModels::collectSTIPredicates() {
400 // Map STIPredicateDecl records to elements of vector
401 // CodeGenSchedModels::STIPredicates.
402 DenseMap
<const Record
*, unsigned> Decl2Index
;
404 RecVec RV
= Records
.getAllDerivedDefinitions("STIPredicate");
405 for (const Record
*R
: RV
) {
406 const Record
*Decl
= R
->getValueAsDef("Declaration");
408 const auto It
= Decl2Index
.find(Decl
);
409 if (It
== Decl2Index
.end()) {
410 Decl2Index
[Decl
] = STIPredicates
.size();
411 STIPredicateFunction
Predicate(Decl
);
412 Predicate
.addDefinition(R
);
413 STIPredicates
.emplace_back(std::move(Predicate
));
417 STIPredicateFunction
&PreviousDef
= STIPredicates
[It
->second
];
418 PreviousDef
.addDefinition(R
);
421 for (STIPredicateFunction
&Fn
: STIPredicates
)
422 processSTIPredicate(Fn
, ProcModelMap
);
425 void OpcodeInfo::addPredicateForProcModel(const llvm::APInt
&CpuMask
,
426 const llvm::APInt
&OperandMask
,
427 const Record
*Predicate
) {
428 auto It
= llvm::find_if(
429 Predicates
, [&OperandMask
, &Predicate
](const PredicateInfo
&P
) {
430 return P
.Predicate
== Predicate
&& P
.OperandMask
== OperandMask
;
432 if (It
== Predicates
.end()) {
433 Predicates
.emplace_back(CpuMask
, OperandMask
, Predicate
);
436 It
->ProcModelMask
|= CpuMask
;
439 void CodeGenSchedModels::checkMCInstPredicates() const {
440 RecVec MCPredicates
= Records
.getAllDerivedDefinitions("TIIPredicate");
441 if (MCPredicates
.empty())
444 // A target cannot have multiple TIIPredicate definitions with a same name.
445 llvm::StringMap
<const Record
*> TIIPredicates(MCPredicates
.size());
446 for (const Record
*TIIPred
: MCPredicates
) {
447 StringRef Name
= TIIPred
->getValueAsString("FunctionName");
448 StringMap
<const Record
*>::const_iterator It
= TIIPredicates
.find(Name
);
449 if (It
== TIIPredicates
.end()) {
450 TIIPredicates
[Name
] = TIIPred
;
454 PrintError(TIIPred
->getLoc(),
455 "TIIPredicate " + Name
+ " is multiply defined.");
456 PrintFatalNote(It
->second
->getLoc(),
457 " Previous definition of " + Name
+ " was here.");
461 void CodeGenSchedModels::collectRetireControlUnits() {
462 RecVec Units
= Records
.getAllDerivedDefinitions("RetireControlUnit");
464 for (Record
*RCU
: Units
) {
465 CodeGenProcModel
&PM
= getProcModel(RCU
->getValueAsDef("SchedModel"));
466 if (PM
.RetireControlUnit
) {
467 PrintError(RCU
->getLoc(),
468 "Expected a single RetireControlUnit definition");
469 PrintNote(PM
.RetireControlUnit
->getLoc(),
470 "Previous definition of RetireControlUnit was here");
472 PM
.RetireControlUnit
= RCU
;
476 void CodeGenSchedModels::collectLoadStoreQueueInfo() {
477 RecVec Queues
= Records
.getAllDerivedDefinitions("MemoryQueue");
479 for (Record
*Queue
: Queues
) {
480 CodeGenProcModel
&PM
= getProcModel(Queue
->getValueAsDef("SchedModel"));
481 if (Queue
->isSubClassOf("LoadQueue")) {
483 PrintError(Queue
->getLoc(),
484 "Expected a single LoadQueue definition");
485 PrintNote(PM
.LoadQueue
->getLoc(),
486 "Previous definition of LoadQueue was here");
489 PM
.LoadQueue
= Queue
;
492 if (Queue
->isSubClassOf("StoreQueue")) {
494 PrintError(Queue
->getLoc(),
495 "Expected a single StoreQueue definition");
496 PrintNote(PM
.StoreQueue
->getLoc(),
497 "Previous definition of StoreQueue was here");
500 PM
.StoreQueue
= Queue
;
505 /// Collect optional processor information.
506 void CodeGenSchedModels::collectOptionalProcessorInfo() {
507 // Find register file definitions for each processor.
508 collectRegisterFiles();
510 // Collect processor RetireControlUnit descriptors if available.
511 collectRetireControlUnits();
513 // Collect information about load/store queues.
514 collectLoadStoreQueueInfo();
519 /// Gather all processor models.
520 void CodeGenSchedModels::collectProcModels() {
521 RecVec ProcRecords
= Records
.getAllDerivedDefinitions("Processor");
522 llvm::sort(ProcRecords
, LessRecordFieldName());
524 // Check for duplicated names.
525 auto I
= std::adjacent_find(ProcRecords
.begin(), ProcRecords
.end(),
526 [](const Record
*Rec1
, const Record
*Rec2
) {
527 return Rec1
->getValueAsString("Name") == Rec2
->getValueAsString("Name");
529 if (I
!= ProcRecords
.end())
530 PrintFatalError((*I
)->getLoc(), "Duplicate processor name " +
531 (*I
)->getValueAsString("Name"));
533 // Reserve space because we can. Reallocation would be ok.
534 ProcModels
.reserve(ProcRecords
.size()+1);
536 // Use idx=0 for NoModel/NoItineraries.
537 Record
*NoModelDef
= Records
.getDef("NoSchedModel");
538 Record
*NoItinsDef
= Records
.getDef("NoItineraries");
539 ProcModels
.emplace_back(0, "NoSchedModel", NoModelDef
, NoItinsDef
);
540 ProcModelMap
[NoModelDef
] = 0;
542 // For each processor, find a unique machine model.
543 LLVM_DEBUG(dbgs() << "+++ PROCESSOR MODELs (addProcModel) +++\n");
544 for (Record
*ProcRecord
: ProcRecords
)
545 addProcModel(ProcRecord
);
548 /// Get a unique processor model based on the defined MachineModel and
549 /// ProcessorItineraries.
550 void CodeGenSchedModels::addProcModel(Record
*ProcDef
) {
551 Record
*ModelKey
= getModelOrItinDef(ProcDef
);
552 if (!ProcModelMap
.insert(std::make_pair(ModelKey
, ProcModels
.size())).second
)
555 std::string Name
= std::string(ModelKey
->getName());
556 if (ModelKey
->isSubClassOf("SchedMachineModel")) {
557 Record
*ItinsDef
= ModelKey
->getValueAsDef("Itineraries");
558 ProcModels
.emplace_back(ProcModels
.size(), Name
, ModelKey
, ItinsDef
);
561 // An itinerary is defined without a machine model. Infer a new model.
562 if (!ModelKey
->getValueAsListOfDefs("IID").empty())
563 Name
= Name
+ "Model";
564 ProcModels
.emplace_back(ProcModels
.size(), Name
,
565 ProcDef
->getValueAsDef("SchedModel"), ModelKey
);
567 LLVM_DEBUG(ProcModels
.back().dump());
570 // Recursively find all reachable SchedReadWrite records.
571 static void scanSchedRW(Record
*RWDef
, RecVec
&RWDefs
,
572 SmallPtrSet
<Record
*, 16> &RWSet
) {
573 if (!RWSet
.insert(RWDef
).second
)
575 RWDefs
.push_back(RWDef
);
576 // Reads don't currently have sequence records, but it can be added later.
577 if (RWDef
->isSubClassOf("WriteSequence")) {
578 RecVec Seq
= RWDef
->getValueAsListOfDefs("Writes");
579 for (Record
*WSRec
: Seq
)
580 scanSchedRW(WSRec
, RWDefs
, RWSet
);
582 else if (RWDef
->isSubClassOf("SchedVariant")) {
583 // Visit each variant (guarded by a different predicate).
584 RecVec Vars
= RWDef
->getValueAsListOfDefs("Variants");
585 for (Record
*Variant
: Vars
) {
586 // Visit each RW in the sequence selected by the current variant.
587 RecVec Selected
= Variant
->getValueAsListOfDefs("Selected");
588 for (Record
*SelDef
: Selected
)
589 scanSchedRW(SelDef
, RWDefs
, RWSet
);
594 // Collect and sort all SchedReadWrites reachable via tablegen records.
595 // More may be inferred later when inferring new SchedClasses from variants.
596 void CodeGenSchedModels::collectSchedRW() {
597 // Reserve idx=0 for invalid writes/reads.
598 SchedWrites
.resize(1);
599 SchedReads
.resize(1);
601 SmallPtrSet
<Record
*, 16> RWSet
;
603 // Find all SchedReadWrites referenced by instruction defs.
604 RecVec SWDefs
, SRDefs
;
605 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
606 Record
*SchedDef
= Inst
->TheDef
;
607 if (SchedDef
->isValueUnset("SchedRW"))
609 RecVec RWs
= SchedDef
->getValueAsListOfDefs("SchedRW");
610 for (Record
*RW
: RWs
) {
611 if (RW
->isSubClassOf("SchedWrite"))
612 scanSchedRW(RW
, SWDefs
, RWSet
);
614 assert(RW
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
615 scanSchedRW(RW
, SRDefs
, RWSet
);
619 // Find all ReadWrites referenced by InstRW.
620 RecVec InstRWDefs
= Records
.getAllDerivedDefinitions("InstRW");
621 for (Record
*InstRWDef
: InstRWDefs
) {
622 // For all OperandReadWrites.
623 RecVec RWDefs
= InstRWDef
->getValueAsListOfDefs("OperandReadWrites");
624 for (Record
*RWDef
: RWDefs
) {
625 if (RWDef
->isSubClassOf("SchedWrite"))
626 scanSchedRW(RWDef
, SWDefs
, RWSet
);
628 assert(RWDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
629 scanSchedRW(RWDef
, SRDefs
, RWSet
);
633 // Find all ReadWrites referenced by ItinRW.
634 RecVec ItinRWDefs
= Records
.getAllDerivedDefinitions("ItinRW");
635 for (Record
*ItinRWDef
: ItinRWDefs
) {
636 // For all OperandReadWrites.
637 RecVec RWDefs
= ItinRWDef
->getValueAsListOfDefs("OperandReadWrites");
638 for (Record
*RWDef
: RWDefs
) {
639 if (RWDef
->isSubClassOf("SchedWrite"))
640 scanSchedRW(RWDef
, SWDefs
, RWSet
);
642 assert(RWDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
643 scanSchedRW(RWDef
, SRDefs
, RWSet
);
647 // Find all ReadWrites referenced by SchedAlias. AliasDefs needs to be sorted
648 // for the loop below that initializes Alias vectors.
649 RecVec AliasDefs
= Records
.getAllDerivedDefinitions("SchedAlias");
650 llvm::sort(AliasDefs
, LessRecord());
651 for (Record
*ADef
: AliasDefs
) {
652 Record
*MatchDef
= ADef
->getValueAsDef("MatchRW");
653 Record
*AliasDef
= ADef
->getValueAsDef("AliasRW");
654 if (MatchDef
->isSubClassOf("SchedWrite")) {
655 if (!AliasDef
->isSubClassOf("SchedWrite"))
656 PrintFatalError(ADef
->getLoc(), "SchedWrite Alias must be SchedWrite");
657 scanSchedRW(AliasDef
, SWDefs
, RWSet
);
660 assert(MatchDef
->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
661 if (!AliasDef
->isSubClassOf("SchedRead"))
662 PrintFatalError(ADef
->getLoc(), "SchedRead Alias must be SchedRead");
663 scanSchedRW(AliasDef
, SRDefs
, RWSet
);
666 // Sort and add the SchedReadWrites directly referenced by instructions or
667 // itinerary resources. Index reads and writes in separate domains.
668 llvm::sort(SWDefs
, LessRecord());
669 for (Record
*SWDef
: SWDefs
) {
670 assert(!getSchedRWIdx(SWDef
, /*IsRead=*/false) && "duplicate SchedWrite");
671 SchedWrites
.emplace_back(SchedWrites
.size(), SWDef
);
673 llvm::sort(SRDefs
, LessRecord());
674 for (Record
*SRDef
: SRDefs
) {
675 assert(!getSchedRWIdx(SRDef
, /*IsRead-*/true) && "duplicate SchedWrite");
676 SchedReads
.emplace_back(SchedReads
.size(), SRDef
);
678 // Initialize WriteSequence vectors.
679 for (CodeGenSchedRW
&CGRW
: SchedWrites
) {
680 if (!CGRW
.IsSequence
)
682 findRWs(CGRW
.TheDef
->getValueAsListOfDefs("Writes"), CGRW
.Sequence
,
685 // Initialize Aliases vectors.
686 for (Record
*ADef
: AliasDefs
) {
687 Record
*AliasDef
= ADef
->getValueAsDef("AliasRW");
688 getSchedRW(AliasDef
).IsAlias
= true;
689 Record
*MatchDef
= ADef
->getValueAsDef("MatchRW");
690 CodeGenSchedRW
&RW
= getSchedRW(MatchDef
);
692 PrintFatalError(ADef
->getLoc(), "Cannot Alias an Alias");
693 RW
.Aliases
.push_back(ADef
);
696 dbgs() << "\n+++ SCHED READS and WRITES (collectSchedRW) +++\n";
697 for (unsigned WIdx
= 0, WEnd
= SchedWrites
.size(); WIdx
!= WEnd
; ++WIdx
) {
698 dbgs() << WIdx
<< ": ";
699 SchedWrites
[WIdx
].dump();
701 } for (unsigned RIdx
= 0, REnd
= SchedReads
.size(); RIdx
!= REnd
;
703 dbgs() << RIdx
<< ": ";
704 SchedReads
[RIdx
].dump();
706 } RecVec RWDefs
= Records
.getAllDerivedDefinitions("SchedReadWrite");
709 if (!getSchedRWIdx(RWDef
, RWDef
->isSubClassOf("SchedRead"))) {
710 StringRef Name
= RWDef
->getName();
711 if (Name
!= "NoWrite" && Name
!= "ReadDefault")
712 dbgs() << "Unused SchedReadWrite " << Name
<< '\n';
717 /// Compute a SchedWrite name from a sequence of writes.
718 std::string
CodeGenSchedModels::genRWName(ArrayRef
<unsigned> Seq
, bool IsRead
) {
719 std::string
Name("(");
720 ListSeparator
LS("_");
721 for (unsigned I
: Seq
) {
723 Name
+= getSchedRW(I
, IsRead
).Name
;
729 unsigned CodeGenSchedModels::getSchedRWIdx(const Record
*Def
,
731 const std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
732 const auto I
= find_if(
733 RWVec
, [Def
](const CodeGenSchedRW
&RW
) { return RW
.TheDef
== Def
; });
734 return I
== RWVec
.end() ? 0 : std::distance(RWVec
.begin(), I
);
737 bool CodeGenSchedModels::hasReadOfWrite(Record
*WriteDef
) const {
738 for (auto& ProcModel
: ProcModels
) {
739 const RecVec
&RADefs
= ProcModel
.ReadAdvanceDefs
;
740 for (auto& RADef
: RADefs
) {
741 RecVec ValidWrites
= RADef
->getValueAsListOfDefs("ValidWrites");
742 if (is_contained(ValidWrites
, WriteDef
))
749 static void splitSchedReadWrites(const RecVec
&RWDefs
,
750 RecVec
&WriteDefs
, RecVec
&ReadDefs
) {
751 for (Record
*RWDef
: RWDefs
) {
752 if (RWDef
->isSubClassOf("SchedWrite"))
753 WriteDefs
.push_back(RWDef
);
755 assert(RWDef
->isSubClassOf("SchedRead") && "unknown SchedReadWrite");
756 ReadDefs
.push_back(RWDef
);
761 // Split the SchedReadWrites defs and call findRWs for each list.
762 void CodeGenSchedModels::findRWs(const RecVec
&RWDefs
,
763 IdxVec
&Writes
, IdxVec
&Reads
) const {
766 splitSchedReadWrites(RWDefs
, WriteDefs
, ReadDefs
);
767 findRWs(WriteDefs
, Writes
, false);
768 findRWs(ReadDefs
, Reads
, true);
771 // Call getSchedRWIdx for all elements in a sequence of SchedRW defs.
772 void CodeGenSchedModels::findRWs(const RecVec
&RWDefs
, IdxVec
&RWs
,
774 for (Record
*RWDef
: RWDefs
) {
775 unsigned Idx
= getSchedRWIdx(RWDef
, IsRead
);
776 assert(Idx
&& "failed to collect SchedReadWrite");
781 void CodeGenSchedModels::expandRWSequence(unsigned RWIdx
, IdxVec
&RWSeq
,
783 const CodeGenSchedRW
&SchedRW
= getSchedRW(RWIdx
, IsRead
);
784 if (!SchedRW
.IsSequence
) {
785 RWSeq
.push_back(RWIdx
);
789 SchedRW
.TheDef
? SchedRW
.TheDef
->getValueAsInt("Repeat") : 1;
790 for (int i
= 0; i
< Repeat
; ++i
) {
791 for (unsigned I
: SchedRW
.Sequence
) {
792 expandRWSequence(I
, RWSeq
, IsRead
);
797 // Expand a SchedWrite as a sequence following any aliases that coincide with
798 // the given processor model.
799 void CodeGenSchedModels::expandRWSeqForProc(
800 unsigned RWIdx
, IdxVec
&RWSeq
, bool IsRead
,
801 const CodeGenProcModel
&ProcModel
) const {
803 const CodeGenSchedRW
&SchedWrite
= getSchedRW(RWIdx
, IsRead
);
804 Record
*AliasDef
= nullptr;
805 for (const Record
*Rec
: SchedWrite
.Aliases
) {
806 const CodeGenSchedRW
&AliasRW
= getSchedRW(Rec
->getValueAsDef("AliasRW"));
807 if (Rec
->getValueInit("SchedModel")->isComplete()) {
808 Record
*ModelDef
= Rec
->getValueAsDef("SchedModel");
809 if (&getProcModel(ModelDef
) != &ProcModel
)
813 PrintFatalError(AliasRW
.TheDef
->getLoc(), "Multiple aliases "
814 "defined for processor " + ProcModel
.ModelName
+
815 " Ensure only one SchedAlias exists per RW.");
816 AliasDef
= AliasRW
.TheDef
;
819 expandRWSeqForProc(getSchedRWIdx(AliasDef
, IsRead
),
820 RWSeq
, IsRead
,ProcModel
);
823 if (!SchedWrite
.IsSequence
) {
824 RWSeq
.push_back(RWIdx
);
828 SchedWrite
.TheDef
? SchedWrite
.TheDef
->getValueAsInt("Repeat") : 1;
829 for (int I
= 0, E
= Repeat
; I
< E
; ++I
) {
830 for (unsigned Idx
: SchedWrite
.Sequence
) {
831 expandRWSeqForProc(Idx
, RWSeq
, IsRead
, ProcModel
);
836 // Find the existing SchedWrite that models this sequence of writes.
837 unsigned CodeGenSchedModels::findRWForSequence(ArrayRef
<unsigned> Seq
,
839 std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
841 auto I
= find_if(RWVec
, [Seq
](CodeGenSchedRW
&RW
) {
842 return ArrayRef(RW
.Sequence
) == Seq
;
844 // Index zero reserved for invalid RW.
845 return I
== RWVec
.end() ? 0 : std::distance(RWVec
.begin(), I
);
848 /// Add this ReadWrite if it doesn't already exist.
849 unsigned CodeGenSchedModels::findOrInsertRW(ArrayRef
<unsigned> Seq
,
851 assert(!Seq
.empty() && "cannot insert empty sequence");
855 unsigned Idx
= findRWForSequence(Seq
, IsRead
);
859 std::vector
<CodeGenSchedRW
> &RWVec
= IsRead
? SchedReads
: SchedWrites
;
860 unsigned RWIdx
= RWVec
.size();
861 CodeGenSchedRW
SchedRW(RWIdx
, IsRead
, Seq
, genRWName(Seq
, IsRead
));
862 RWVec
.push_back(SchedRW
);
866 /// Visit all the instruction definitions for this target to gather and
867 /// enumerate the itinerary classes. These are the explicitly specified
868 /// SchedClasses. More SchedClasses may be inferred.
869 void CodeGenSchedModels::collectSchedClasses() {
871 // NoItinerary is always the first class at Idx=0
872 assert(SchedClasses
.empty() && "Expected empty sched class");
873 SchedClasses
.emplace_back(0, "NoInstrModel",
874 Records
.getDef("NoItinerary"));
875 SchedClasses
.back().ProcIndices
.push_back(0);
877 // Create a SchedClass for each unique combination of itinerary class and
879 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
880 Record
*ItinDef
= Inst
->TheDef
->getValueAsDef("Itinerary");
881 IdxVec Writes
, Reads
;
882 if (!Inst
->TheDef
->isValueUnset("SchedRW"))
883 findRWs(Inst
->TheDef
->getValueAsListOfDefs("SchedRW"), Writes
, Reads
);
885 // ProcIdx == 0 indicates the class applies to all processors.
886 unsigned SCIdx
= addSchedClass(ItinDef
, Writes
, Reads
, /*ProcIndices*/{0});
887 InstrClassMap
[Inst
->TheDef
] = SCIdx
;
889 // Create classes for InstRW defs.
890 RecVec InstRWDefs
= Records
.getAllDerivedDefinitions("InstRW");
891 llvm::sort(InstRWDefs
, LessRecord());
892 LLVM_DEBUG(dbgs() << "\n+++ SCHED CLASSES (createInstRWClass) +++\n");
893 for (Record
*RWDef
: InstRWDefs
)
894 createInstRWClass(RWDef
);
896 NumInstrSchedClasses
= SchedClasses
.size();
898 bool EnableDump
= false;
899 LLVM_DEBUG(EnableDump
= true);
905 << "\n+++ ITINERARIES and/or MACHINE MODELS (collectSchedClasses) +++\n");
906 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
907 StringRef InstName
= Inst
->TheDef
->getName();
908 unsigned SCIdx
= getSchedClassIdx(*Inst
);
911 if (!Inst
->hasNoSchedulingInfo
)
912 dbgs() << "No machine model for " << Inst
->TheDef
->getName() << '\n';
916 CodeGenSchedClass
&SC
= getSchedClass(SCIdx
);
917 if (SC
.ProcIndices
[0] != 0)
918 PrintFatalError(Inst
->TheDef
->getLoc(), "Instruction's sched class "
919 "must not be subtarget specific.");
922 if (SC
.ItinClassDef
->getName() != "NoItinerary") {
923 ProcIndices
.push_back(0);
924 dbgs() << "Itinerary for " << InstName
<< ": "
925 << SC
.ItinClassDef
->getName() << '\n';
927 if (!SC
.Writes
.empty()) {
928 ProcIndices
.push_back(0);
930 dbgs() << "SchedRW machine model for " << InstName
;
931 for (unsigned int Write
: SC
.Writes
)
932 dbgs() << " " << SchedWrites
[Write
].Name
;
933 for (unsigned int Read
: SC
.Reads
)
934 dbgs() << " " << SchedReads
[Read
].Name
;
938 const RecVec
&RWDefs
= SchedClasses
[SCIdx
].InstRWs
;
939 for (Record
*RWDef
: RWDefs
) {
940 const CodeGenProcModel
&ProcModel
=
941 getProcModel(RWDef
->getValueAsDef("SchedModel"));
942 ProcIndices
.push_back(ProcModel
.Index
);
943 LLVM_DEBUG(dbgs() << "InstRW on " << ProcModel
.ModelName
<< " for "
947 findRWs(RWDef
->getValueAsListOfDefs("OperandReadWrites"),
950 for (unsigned WIdx
: Writes
)
951 dbgs() << " " << SchedWrites
[WIdx
].Name
;
952 for (unsigned RIdx
: Reads
)
953 dbgs() << " " << SchedReads
[RIdx
].Name
;
957 // If ProcIndices contains zero, the class applies to all processors.
959 if (!llvm::is_contained(ProcIndices
, 0)) {
960 for (const CodeGenProcModel
&PM
: ProcModels
) {
961 if (!llvm::is_contained(ProcIndices
, PM
.Index
))
962 dbgs() << "No machine model for " << Inst
->TheDef
->getName()
963 << " on processor " << PM
.ModelName
<< '\n';
970 // Get the SchedClass index for an instruction.
972 CodeGenSchedModels::getSchedClassIdx(const CodeGenInstruction
&Inst
) const {
973 return InstrClassMap
.lookup(Inst
.TheDef
);
977 CodeGenSchedModels::createSchedClassName(Record
*ItinClassDef
,
978 ArrayRef
<unsigned> OperWrites
,
979 ArrayRef
<unsigned> OperReads
) {
982 if (ItinClassDef
&& ItinClassDef
->getName() != "NoItinerary")
983 Name
= std::string(ItinClassDef
->getName());
984 for (unsigned Idx
: OperWrites
) {
987 Name
+= SchedWrites
[Idx
].Name
;
989 for (unsigned Idx
: OperReads
) {
991 Name
+= SchedReads
[Idx
].Name
;
996 std::string
CodeGenSchedModels::createSchedClassName(const RecVec
&InstDefs
) {
999 ListSeparator
LS("_");
1000 for (const Record
*InstDef
: InstDefs
) {
1002 Name
+= InstDef
->getName();
1007 /// Add an inferred sched class from an itinerary class and per-operand list of
1008 /// SchedWrites and SchedReads. ProcIndices contains the set of IDs of
1009 /// processors that may utilize this class.
1010 unsigned CodeGenSchedModels::addSchedClass(Record
*ItinClassDef
,
1011 ArrayRef
<unsigned> OperWrites
,
1012 ArrayRef
<unsigned> OperReads
,
1013 ArrayRef
<unsigned> ProcIndices
) {
1014 assert(!ProcIndices
.empty() && "expect at least one ProcIdx");
1016 auto IsKeyEqual
= [=](const CodeGenSchedClass
&SC
) {
1017 return SC
.isKeyEqual(ItinClassDef
, OperWrites
, OperReads
);
1020 auto I
= find_if(make_range(schedClassBegin(), schedClassEnd()), IsKeyEqual
);
1021 unsigned Idx
= I
== schedClassEnd() ? 0 : std::distance(schedClassBegin(), I
);
1022 if (Idx
|| SchedClasses
[0].isKeyEqual(ItinClassDef
, OperWrites
, OperReads
)) {
1024 std::set_union(SchedClasses
[Idx
].ProcIndices
.begin(),
1025 SchedClasses
[Idx
].ProcIndices
.end(),
1026 ProcIndices
.begin(), ProcIndices
.end(),
1027 std::back_inserter(PI
));
1028 SchedClasses
[Idx
].ProcIndices
= std::move(PI
);
1031 Idx
= SchedClasses
.size();
1032 SchedClasses
.emplace_back(Idx
,
1033 createSchedClassName(ItinClassDef
, OperWrites
,
1036 CodeGenSchedClass
&SC
= SchedClasses
.back();
1037 SC
.Writes
= OperWrites
;
1038 SC
.Reads
= OperReads
;
1039 SC
.ProcIndices
= ProcIndices
;
1044 // Create classes for each set of opcodes that are in the same InstReadWrite
1045 // definition across all processors.
1046 void CodeGenSchedModels::createInstRWClass(Record
*InstRWDef
) {
1047 // ClassInstrs will hold an entry for each subset of Instrs in InstRWDef that
1048 // intersects with an existing class via a previous InstRWDef. Instrs that do
1049 // not intersect with an existing class refer back to their former class as
1050 // determined from ItinDef or SchedRW.
1051 SmallMapVector
<unsigned, SmallVector
<Record
*, 8>, 4> ClassInstrs
;
1052 // Sort Instrs into sets.
1053 const RecVec
*InstDefs
= Sets
.expand(InstRWDef
);
1054 if (InstDefs
->empty())
1055 PrintFatalError(InstRWDef
->getLoc(), "No matching instruction opcodes");
1057 for (Record
*InstDef
: *InstDefs
) {
1058 InstClassMapTy::const_iterator Pos
= InstrClassMap
.find(InstDef
);
1059 if (Pos
== InstrClassMap
.end())
1060 PrintFatalError(InstDef
->getLoc(), "No sched class for instruction.");
1061 unsigned SCIdx
= Pos
->second
;
1062 ClassInstrs
[SCIdx
].push_back(InstDef
);
1064 // For each set of Instrs, create a new class if necessary, and map or remap
1065 // the Instrs to it.
1066 for (auto &Entry
: ClassInstrs
) {
1067 unsigned OldSCIdx
= Entry
.first
;
1068 ArrayRef
<Record
*> InstDefs
= Entry
.second
;
1069 // If the all instrs in the current class are accounted for, then leave
1070 // them mapped to their old class.
1072 const RecVec
&RWDefs
= SchedClasses
[OldSCIdx
].InstRWs
;
1073 if (!RWDefs
.empty()) {
1074 const RecVec
*OrigInstDefs
= Sets
.expand(RWDefs
[0]);
1075 unsigned OrigNumInstrs
=
1076 count_if(*OrigInstDefs
, [&](Record
*OIDef
) {
1077 return InstrClassMap
[OIDef
] == OldSCIdx
;
1079 if (OrigNumInstrs
== InstDefs
.size()) {
1080 assert(SchedClasses
[OldSCIdx
].ProcIndices
[0] == 0 &&
1081 "expected a generic SchedClass");
1082 Record
*RWModelDef
= InstRWDef
->getValueAsDef("SchedModel");
1083 // Make sure we didn't already have a InstRW containing this
1084 // instruction on this model.
1085 for (Record
*RWD
: RWDefs
) {
1086 if (RWD
->getValueAsDef("SchedModel") == RWModelDef
&&
1087 RWModelDef
->getValueAsBit("FullInstRWOverlapCheck")) {
1088 assert(!InstDefs
.empty()); // Checked at function start.
1090 InstRWDef
->getLoc(),
1091 "Overlapping InstRW definition for \"" +
1092 InstDefs
.front()->getName() +
1093 "\" also matches previous \"" +
1094 RWD
->getValue("Instrs")->getValue()->getAsString() +
1096 PrintFatalNote(RWD
->getLoc(), "Previous match was here.");
1099 LLVM_DEBUG(dbgs() << "InstRW: Reuse SC " << OldSCIdx
<< ":"
1100 << SchedClasses
[OldSCIdx
].Name
<< " on "
1101 << RWModelDef
->getName() << "\n");
1102 SchedClasses
[OldSCIdx
].InstRWs
.push_back(InstRWDef
);
1107 unsigned SCIdx
= SchedClasses
.size();
1108 SchedClasses
.emplace_back(SCIdx
, createSchedClassName(InstDefs
), nullptr);
1109 CodeGenSchedClass
&SC
= SchedClasses
.back();
1110 LLVM_DEBUG(dbgs() << "InstRW: New SC " << SCIdx
<< ":" << SC
.Name
<< " on "
1111 << InstRWDef
->getValueAsDef("SchedModel")->getName()
1114 // Preserve ItinDef and Writes/Reads for processors without an InstRW entry.
1115 SC
.ItinClassDef
= SchedClasses
[OldSCIdx
].ItinClassDef
;
1116 SC
.Writes
= SchedClasses
[OldSCIdx
].Writes
;
1117 SC
.Reads
= SchedClasses
[OldSCIdx
].Reads
;
1118 SC
.ProcIndices
.push_back(0);
1119 // If we had an old class, copy it's InstRWs to this new class.
1121 Record
*RWModelDef
= InstRWDef
->getValueAsDef("SchedModel");
1122 for (Record
*OldRWDef
: SchedClasses
[OldSCIdx
].InstRWs
) {
1123 if (OldRWDef
->getValueAsDef("SchedModel") == RWModelDef
) {
1124 assert(!InstDefs
.empty()); // Checked at function start.
1126 InstRWDef
->getLoc(),
1127 "Overlapping InstRW definition for \"" +
1128 InstDefs
.front()->getName() + "\" also matches previous \"" +
1129 OldRWDef
->getValue("Instrs")->getValue()->getAsString() +
1131 PrintFatalNote(OldRWDef
->getLoc(), "Previous match was here.");
1133 assert(OldRWDef
!= InstRWDef
&&
1134 "SchedClass has duplicate InstRW def");
1135 SC
.InstRWs
.push_back(OldRWDef
);
1138 // Map each Instr to this new class.
1139 for (Record
*InstDef
: InstDefs
)
1140 InstrClassMap
[InstDef
] = SCIdx
;
1141 SC
.InstRWs
.push_back(InstRWDef
);
1145 // True if collectProcItins found anything.
1146 bool CodeGenSchedModels::hasItineraries() const {
1147 for (const CodeGenProcModel
&PM
: make_range(procModelBegin(),procModelEnd()))
1148 if (PM
.hasItineraries())
1153 // Gather the processor itineraries.
1154 void CodeGenSchedModels::collectProcItins() {
1155 LLVM_DEBUG(dbgs() << "\n+++ PROBLEM ITINERARIES (collectProcItins) +++\n");
1156 for (CodeGenProcModel
&ProcModel
: ProcModels
) {
1157 if (!ProcModel
.hasItineraries())
1160 RecVec ItinRecords
= ProcModel
.ItinsDef
->getValueAsListOfDefs("IID");
1161 assert(!ItinRecords
.empty() && "ProcModel.hasItineraries is incorrect");
1163 // Populate ItinDefList with Itinerary records.
1164 ProcModel
.ItinDefList
.resize(NumInstrSchedClasses
);
1166 // Insert each itinerary data record in the correct position within
1167 // the processor model's ItinDefList.
1168 for (Record
*ItinData
: ItinRecords
) {
1169 const Record
*ItinDef
= ItinData
->getValueAsDef("TheClass");
1170 bool FoundClass
= false;
1172 for (const CodeGenSchedClass
&SC
:
1173 make_range(schedClassBegin(), schedClassEnd())) {
1174 // Multiple SchedClasses may share an itinerary. Update all of them.
1175 if (SC
.ItinClassDef
== ItinDef
) {
1176 ProcModel
.ItinDefList
[SC
.Index
] = ItinData
;
1181 LLVM_DEBUG(dbgs() << ProcModel
.ItinsDef
->getName()
1182 << " missing class for itinerary "
1183 << ItinDef
->getName() << '\n');
1186 // Check for missing itinerary entries.
1187 assert(!ProcModel
.ItinDefList
[0] && "NoItinerary class can't have rec");
1189 for (unsigned i
= 1, N
= ProcModel
.ItinDefList
.size(); i
< N
; ++i
) {
1190 if (!ProcModel
.ItinDefList
[i
])
1191 dbgs() << ProcModel
.ItinsDef
->getName()
1192 << " missing itinerary for class " << SchedClasses
[i
].Name
1198 // Gather the read/write types for each itinerary class.
1199 void CodeGenSchedModels::collectProcItinRW() {
1200 RecVec ItinRWDefs
= Records
.getAllDerivedDefinitions("ItinRW");
1201 llvm::sort(ItinRWDefs
, LessRecord());
1202 for (Record
*RWDef
: ItinRWDefs
) {
1203 if (!RWDef
->getValueInit("SchedModel")->isComplete())
1204 PrintFatalError(RWDef
->getLoc(), "SchedModel is undefined");
1205 Record
*ModelDef
= RWDef
->getValueAsDef("SchedModel");
1206 ProcModelMapTy::const_iterator I
= ProcModelMap
.find(ModelDef
);
1207 if (I
== ProcModelMap
.end()) {
1208 PrintFatalError(RWDef
->getLoc(), "Undefined SchedMachineModel "
1209 + ModelDef
->getName());
1211 ProcModels
[I
->second
].ItinRWDefs
.push_back(RWDef
);
1215 // Gather the unsupported features for processor models.
1216 void CodeGenSchedModels::collectProcUnsupportedFeatures() {
1217 for (CodeGenProcModel
&ProcModel
: ProcModels
)
1219 ProcModel
.UnsupportedFeaturesDefs
,
1220 ProcModel
.ModelDef
->getValueAsListOfDefs("UnsupportedFeatures"));
1223 /// Infer new classes from existing classes. In the process, this may create new
1224 /// SchedWrites from sequences of existing SchedWrites.
1225 void CodeGenSchedModels::inferSchedClasses() {
1227 dbgs() << "\n+++ INFERRING SCHED CLASSES (inferSchedClasses) +++\n");
1228 LLVM_DEBUG(dbgs() << NumInstrSchedClasses
<< " instr sched classes.\n");
1230 // Visit all existing classes and newly created classes.
1231 for (unsigned Idx
= 0; Idx
!= SchedClasses
.size(); ++Idx
) {
1232 assert(SchedClasses
[Idx
].Index
== Idx
&& "bad SCIdx");
1234 if (SchedClasses
[Idx
].ItinClassDef
)
1235 inferFromItinClass(SchedClasses
[Idx
].ItinClassDef
, Idx
);
1236 if (!SchedClasses
[Idx
].InstRWs
.empty())
1237 inferFromInstRWs(Idx
);
1238 if (!SchedClasses
[Idx
].Writes
.empty()) {
1239 inferFromRW(SchedClasses
[Idx
].Writes
, SchedClasses
[Idx
].Reads
,
1240 Idx
, SchedClasses
[Idx
].ProcIndices
);
1242 assert(SchedClasses
.size() < (NumInstrSchedClasses
*6) &&
1243 "too many SchedVariants");
1247 /// Infer classes from per-processor itinerary resources.
1248 void CodeGenSchedModels::inferFromItinClass(Record
*ItinClassDef
,
1249 unsigned FromClassIdx
) {
1250 for (unsigned PIdx
= 0, PEnd
= ProcModels
.size(); PIdx
!= PEnd
; ++PIdx
) {
1251 const CodeGenProcModel
&PM
= ProcModels
[PIdx
];
1252 // For all ItinRW entries.
1253 bool HasMatch
= false;
1254 for (const Record
*Rec
: PM
.ItinRWDefs
) {
1255 RecVec Matched
= Rec
->getValueAsListOfDefs("MatchedItinClasses");
1256 if (!llvm::is_contained(Matched
, ItinClassDef
))
1259 PrintFatalError(Rec
->getLoc(), "Duplicate itinerary class "
1260 + ItinClassDef
->getName()
1261 + " in ItinResources for " + PM
.ModelName
);
1263 IdxVec Writes
, Reads
;
1264 findRWs(Rec
->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1265 inferFromRW(Writes
, Reads
, FromClassIdx
, PIdx
);
1270 /// Infer classes from per-processor InstReadWrite definitions.
1271 void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx
) {
1272 for (unsigned I
= 0, E
= SchedClasses
[SCIdx
].InstRWs
.size(); I
!= E
; ++I
) {
1273 assert(SchedClasses
[SCIdx
].InstRWs
.size() == E
&& "InstrRWs was mutated!");
1274 Record
*Rec
= SchedClasses
[SCIdx
].InstRWs
[I
];
1275 const RecVec
*InstDefs
= Sets
.expand(Rec
);
1276 RecIter II
= InstDefs
->begin(), IE
= InstDefs
->end();
1277 for (; II
!= IE
; ++II
) {
1278 if (InstrClassMap
[*II
] == SCIdx
)
1281 // If this class no longer has any instructions mapped to it, it has become
1285 IdxVec Writes
, Reads
;
1286 findRWs(Rec
->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1287 unsigned PIdx
= getProcModel(Rec
->getValueAsDef("SchedModel")).Index
;
1288 inferFromRW(Writes
, Reads
, SCIdx
, PIdx
); // May mutate SchedClasses.
1289 SchedClasses
[SCIdx
].InstRWProcIndices
.insert(PIdx
);
1295 // Helper for substituteVariantOperand.
1296 struct TransVariant
{
1297 Record
*VarOrSeqDef
; // Variant or sequence.
1298 unsigned RWIdx
; // Index of this variant or sequence's matched type.
1299 unsigned ProcIdx
; // Processor model index or zero for any.
1300 unsigned TransVecIdx
; // Index into PredTransitions::TransVec.
1302 TransVariant(Record
*def
, unsigned rwi
, unsigned pi
, unsigned ti
):
1303 VarOrSeqDef(def
), RWIdx(rwi
), ProcIdx(pi
), TransVecIdx(ti
) {}
1306 // Associate a predicate with the SchedReadWrite that it guards.
1307 // RWIdx is the index of the read/write variant.
1313 PredCheck(bool r
, unsigned w
, Record
*p
): IsRead(r
), RWIdx(w
), Predicate(p
) {}
1316 // A Predicate transition is a list of RW sequences guarded by a PredTerm.
1317 struct PredTransition
{
1318 // A predicate term is a conjunction of PredChecks.
1319 SmallVector
<PredCheck
, 4> PredTerm
;
1320 SmallVector
<SmallVector
<unsigned,4>, 16> WriteSequences
;
1321 SmallVector
<SmallVector
<unsigned,4>, 16> ReadSequences
;
1322 unsigned ProcIndex
= 0;
1324 PredTransition() = default;
1325 PredTransition(ArrayRef
<PredCheck
> PT
, unsigned ProcId
) {
1326 PredTerm
.assign(PT
.begin(), PT
.end());
1331 // Encapsulate a set of partially constructed transitions.
1332 // The results are built by repeated calls to substituteVariants.
1333 class PredTransitions
{
1334 CodeGenSchedModels
&SchedModels
;
1337 std::vector
<PredTransition
> TransVec
;
1339 PredTransitions(CodeGenSchedModels
&sm
): SchedModels(sm
) {}
1341 bool substituteVariantOperand(const SmallVectorImpl
<unsigned> &RWSeq
,
1342 bool IsRead
, unsigned StartIdx
);
1344 bool substituteVariants(const PredTransition
&Trans
);
1351 bool mutuallyExclusive(Record
*PredDef
, ArrayRef
<Record
*> Preds
,
1352 ArrayRef
<PredCheck
> Term
);
1353 void getIntersectingVariants(
1354 const CodeGenSchedRW
&SchedRW
, unsigned TransIdx
,
1355 std::vector
<TransVariant
> &IntersectingVariants
);
1356 void pushVariant(const TransVariant
&VInfo
, bool IsRead
);
1359 } // end anonymous namespace
1361 // Return true if this predicate is mutually exclusive with a PredTerm. This
1362 // degenerates into checking if the predicate is mutually exclusive with any
1363 // predicate in the Term's conjunction.
1365 // All predicates associated with a given SchedRW are considered mutually
1366 // exclusive. This should work even if the conditions expressed by the
1367 // predicates are not exclusive because the predicates for a given SchedWrite
1368 // are always checked in the order they are defined in the .td file. Later
1369 // conditions implicitly negate any prior condition.
1370 bool PredTransitions::mutuallyExclusive(Record
*PredDef
,
1371 ArrayRef
<Record
*> Preds
,
1372 ArrayRef
<PredCheck
> Term
) {
1373 for (const PredCheck
&PC
: Term
) {
1374 if (PC
.Predicate
== PredDef
)
1377 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(PC
.RWIdx
, PC
.IsRead
);
1378 assert(SchedRW
.HasVariants
&& "PredCheck must refer to a SchedVariant");
1379 RecVec Variants
= SchedRW
.TheDef
->getValueAsListOfDefs("Variants");
1380 if (any_of(Variants
, [PredDef
](const Record
*R
) {
1381 return R
->getValueAsDef("Predicate") == PredDef
;
1383 // To check if PredDef is mutually exclusive with PC we also need to
1384 // check that PC.Predicate is exclusive with all predicates from variant
1385 // we're expanding. Consider following RW sequence with two variants
1386 // (1 & 2), where A, B and C are predicates from corresponding SchedVars:
1390 // Here C is not mutually exclusive with variant (1), because A doesn't
1391 // exist in variant (2). This means we have possible transitions from A
1392 // to C and from A to B, and fully expanded sequence would look like:
1394 // if (A & C) return ...;
1395 // if (A & B) return ...;
1396 // if (B) return ...;
1398 // Now let's consider another sequence:
1402 // Here A in variant (2) is mutually exclusive with variant (1), because
1403 // A also exists in (2). This means A->B transition is impossible and
1404 // expanded sequence would look like:
1406 // if (A) return ...;
1407 // if (B) return ...;
1408 if (!llvm::is_contained(Preds
, PC
.Predicate
))
1416 static std::vector
<Record
*> getAllPredicates(ArrayRef
<TransVariant
> Variants
,
1418 std::vector
<Record
*> Preds
;
1419 for (auto &Variant
: Variants
) {
1420 if (!Variant
.VarOrSeqDef
->isSubClassOf("SchedVar"))
1422 Preds
.push_back(Variant
.VarOrSeqDef
->getValueAsDef("Predicate"));
1427 // Populate IntersectingVariants with any variants or aliased sequences of the
1428 // given SchedRW whose processor indices and predicates are not mutually
1429 // exclusive with the given transition.
1430 void PredTransitions::getIntersectingVariants(
1431 const CodeGenSchedRW
&SchedRW
, unsigned TransIdx
,
1432 std::vector
<TransVariant
> &IntersectingVariants
) {
1434 bool GenericRW
= false;
1436 std::vector
<TransVariant
> Variants
;
1437 if (SchedRW
.HasVariants
) {
1438 unsigned VarProcIdx
= 0;
1439 if (SchedRW
.TheDef
->getValueInit("SchedModel")->isComplete()) {
1440 Record
*ModelDef
= SchedRW
.TheDef
->getValueAsDef("SchedModel");
1441 VarProcIdx
= SchedModels
.getProcModel(ModelDef
).Index
;
1443 if (VarProcIdx
== 0 || VarProcIdx
== TransVec
[TransIdx
].ProcIndex
) {
1444 // Push each variant. Assign TransVecIdx later.
1445 const RecVec VarDefs
= SchedRW
.TheDef
->getValueAsListOfDefs("Variants");
1446 for (Record
*VarDef
: VarDefs
)
1447 Variants
.emplace_back(VarDef
, SchedRW
.Index
, VarProcIdx
, 0);
1448 if (VarProcIdx
== 0)
1452 for (RecIter AI
= SchedRW
.Aliases
.begin(), AE
= SchedRW
.Aliases
.end();
1454 // If either the SchedAlias itself or the SchedReadWrite that it aliases
1455 // to is defined within a processor model, constrain all variants to
1457 unsigned AliasProcIdx
= 0;
1458 if ((*AI
)->getValueInit("SchedModel")->isComplete()) {
1459 Record
*ModelDef
= (*AI
)->getValueAsDef("SchedModel");
1460 AliasProcIdx
= SchedModels
.getProcModel(ModelDef
).Index
;
1462 if (AliasProcIdx
&& AliasProcIdx
!= TransVec
[TransIdx
].ProcIndex
)
1464 if (!Variants
.empty()) {
1465 const CodeGenProcModel
&PM
=
1466 *(SchedModels
.procModelBegin() + AliasProcIdx
);
1467 PrintFatalError((*AI
)->getLoc(),
1468 "Multiple variants defined for processor " +
1470 " Ensure only one SchedAlias exists per RW.");
1473 const CodeGenSchedRW
&AliasRW
=
1474 SchedModels
.getSchedRW((*AI
)->getValueAsDef("AliasRW"));
1476 if (AliasRW
.HasVariants
) {
1477 const RecVec VarDefs
= AliasRW
.TheDef
->getValueAsListOfDefs("Variants");
1478 for (Record
*VD
: VarDefs
)
1479 Variants
.emplace_back(VD
, AliasRW
.Index
, AliasProcIdx
, 0);
1481 if (AliasRW
.IsSequence
)
1482 Variants
.emplace_back(AliasRW
.TheDef
, SchedRW
.Index
, AliasProcIdx
, 0);
1483 if (AliasProcIdx
== 0)
1486 std::vector
<Record
*> AllPreds
=
1487 getAllPredicates(Variants
, TransVec
[TransIdx
].ProcIndex
);
1488 for (TransVariant
&Variant
: Variants
) {
1489 // Don't expand variants if the processor models don't intersect.
1490 // A zero processor index means any processor.
1491 if (Variant
.VarOrSeqDef
->isSubClassOf("SchedVar")) {
1492 Record
*PredDef
= Variant
.VarOrSeqDef
->getValueAsDef("Predicate");
1493 if (mutuallyExclusive(PredDef
, AllPreds
, TransVec
[TransIdx
].PredTerm
))
1497 if (IntersectingVariants
.empty()) {
1498 // The first variant builds on the existing transition.
1499 Variant
.TransVecIdx
= TransIdx
;
1500 IntersectingVariants
.push_back(Variant
);
1503 // Push another copy of the current transition for more variants.
1504 Variant
.TransVecIdx
= TransVec
.size();
1505 IntersectingVariants
.push_back(Variant
);
1506 TransVec
.push_back(TransVec
[TransIdx
]);
1509 if (GenericRW
&& IntersectingVariants
.empty()) {
1510 PrintFatalError(SchedRW
.TheDef
->getLoc(), "No variant of this type has "
1511 "a matching predicate on any processor");
1515 // Push the Reads/Writes selected by this variant onto the PredTransition
1516 // specified by VInfo.
1517 void PredTransitions::
1518 pushVariant(const TransVariant
&VInfo
, bool IsRead
) {
1519 PredTransition
&Trans
= TransVec
[VInfo
.TransVecIdx
];
1521 // If this operand transition is reached through a processor-specific alias,
1522 // then the whole transition is specific to this processor.
1524 if (VInfo
.VarOrSeqDef
->isSubClassOf("SchedVar")) {
1525 Record
*PredDef
= VInfo
.VarOrSeqDef
->getValueAsDef("Predicate");
1526 Trans
.PredTerm
.emplace_back(IsRead
, VInfo
.RWIdx
,PredDef
);
1527 RecVec SelectedDefs
= VInfo
.VarOrSeqDef
->getValueAsListOfDefs("Selected");
1528 SchedModels
.findRWs(SelectedDefs
, SelectedRWs
, IsRead
);
1531 assert(VInfo
.VarOrSeqDef
->isSubClassOf("WriteSequence") &&
1532 "variant must be a SchedVariant or aliased WriteSequence");
1533 SelectedRWs
.push_back(SchedModels
.getSchedRWIdx(VInfo
.VarOrSeqDef
, IsRead
));
1536 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(VInfo
.RWIdx
, IsRead
);
1538 SmallVectorImpl
<SmallVector
<unsigned,4>> &RWSequences
= IsRead
1539 ? Trans
.ReadSequences
: Trans
.WriteSequences
;
1540 if (SchedRW
.IsVariadic
) {
1541 unsigned OperIdx
= RWSequences
.size()-1;
1542 // Make N-1 copies of this transition's last sequence.
1543 RWSequences
.reserve(RWSequences
.size() + SelectedRWs
.size() - 1);
1544 RWSequences
.insert(RWSequences
.end(), SelectedRWs
.size() - 1,
1545 RWSequences
[OperIdx
]);
1546 // Push each of the N elements of the SelectedRWs onto a copy of the last
1547 // sequence (split the current operand into N operands).
1548 // Note that write sequences should be expanded within this loop--the entire
1549 // sequence belongs to a single operand.
1550 for (IdxIter RWI
= SelectedRWs
.begin(), RWE
= SelectedRWs
.end();
1551 RWI
!= RWE
; ++RWI
, ++OperIdx
) {
1554 ExpandedRWs
.push_back(*RWI
);
1556 SchedModels
.expandRWSequence(*RWI
, ExpandedRWs
, IsRead
);
1557 llvm::append_range(RWSequences
[OperIdx
], ExpandedRWs
);
1559 assert(OperIdx
== RWSequences
.size() && "missed a sequence");
1562 // Push this transition's expanded sequence onto this transition's last
1563 // sequence (add to the current operand's sequence).
1564 SmallVectorImpl
<unsigned> &Seq
= RWSequences
.back();
1566 for (unsigned int SelectedRW
: SelectedRWs
) {
1568 ExpandedRWs
.push_back(SelectedRW
);
1570 SchedModels
.expandRWSequence(SelectedRW
, ExpandedRWs
, IsRead
);
1572 llvm::append_range(Seq
, ExpandedRWs
);
1576 // RWSeq is a sequence of all Reads or all Writes for the next read or write
1577 // operand. StartIdx is an index into TransVec where partial results
1578 // starts. RWSeq must be applied to all transitions between StartIdx and the end
1580 bool PredTransitions::substituteVariantOperand(
1581 const SmallVectorImpl
<unsigned> &RWSeq
, bool IsRead
, unsigned StartIdx
) {
1583 // Visit each original RW within the current sequence.
1584 for (unsigned int RWI
: RWSeq
) {
1585 const CodeGenSchedRW
&SchedRW
= SchedModels
.getSchedRW(RWI
, IsRead
);
1586 // Push this RW on all partial PredTransitions or distribute variants.
1587 // New PredTransitions may be pushed within this loop which should not be
1588 // revisited (TransEnd must be loop invariant).
1589 for (unsigned TransIdx
= StartIdx
, TransEnd
= TransVec
.size();
1590 TransIdx
!= TransEnd
; ++TransIdx
) {
1591 // Distribute this partial PredTransition across intersecting variants.
1592 // This will push a copies of TransVec[TransIdx] on the back of TransVec.
1593 std::vector
<TransVariant
> IntersectingVariants
;
1594 getIntersectingVariants(SchedRW
, TransIdx
, IntersectingVariants
);
1595 // Now expand each variant on top of its copy of the transition.
1596 for (const TransVariant
&IV
: IntersectingVariants
)
1597 pushVariant(IV
, IsRead
);
1598 if (IntersectingVariants
.empty()) {
1600 TransVec
[TransIdx
].ReadSequences
.back().push_back(RWI
);
1602 TransVec
[TransIdx
].WriteSequences
.back().push_back(RWI
);
1612 // For each variant of a Read/Write in Trans, substitute the sequence of
1613 // Read/Writes guarded by the variant. This is exponential in the number of
1614 // variant Read/Writes, but in practice detection of mutually exclusive
1615 // predicates should result in linear growth in the total number variants.
1617 // This is one step in a breadth-first search of nested variants.
1618 bool PredTransitions::substituteVariants(const PredTransition
&Trans
) {
1619 // Build up a set of partial results starting at the back of
1620 // PredTransitions. Remember the first new transition.
1621 unsigned StartIdx
= TransVec
.size();
1623 assert(Trans
.ProcIndex
!= 0);
1624 TransVec
.emplace_back(Trans
.PredTerm
, Trans
.ProcIndex
);
1626 // Visit each original write sequence.
1627 for (const auto &WriteSequence
: Trans
.WriteSequences
) {
1628 // Push a new (empty) write sequence onto all partial Transitions.
1629 for (std::vector
<PredTransition
>::iterator I
=
1630 TransVec
.begin() + StartIdx
, E
= TransVec
.end(); I
!= E
; ++I
) {
1631 I
->WriteSequences
.emplace_back();
1634 substituteVariantOperand(WriteSequence
, /*IsRead=*/false, StartIdx
);
1636 // Visit each original read sequence.
1637 for (const auto &ReadSequence
: Trans
.ReadSequences
) {
1638 // Push a new (empty) read sequence onto all partial Transitions.
1639 for (std::vector
<PredTransition
>::iterator I
=
1640 TransVec
.begin() + StartIdx
, E
= TransVec
.end(); I
!= E
; ++I
) {
1641 I
->ReadSequences
.emplace_back();
1643 Subst
|= substituteVariantOperand(ReadSequence
, /*IsRead=*/true, StartIdx
);
1648 static void addSequences(CodeGenSchedModels
&SchedModels
,
1649 const SmallVectorImpl
<SmallVector
<unsigned, 4>> &Seqs
,
1650 IdxVec
&Result
, bool IsRead
) {
1651 for (const auto &S
: Seqs
)
1653 Result
.push_back(SchedModels
.findOrInsertRW(S
, IsRead
));
1657 static void dumpRecVec(const RecVec
&RV
) {
1658 for (const Record
*R
: RV
)
1659 dbgs() << R
->getName() << ", ";
1663 static void dumpTransition(const CodeGenSchedModels
&SchedModels
,
1664 const CodeGenSchedClass
&FromSC
,
1665 const CodeGenSchedTransition
&SCTrans
,
1666 const RecVec
&Preds
) {
1667 LLVM_DEBUG(dbgs() << "Adding transition from " << FromSC
.Name
<< "("
1668 << FromSC
.Index
<< ") to "
1669 << SchedModels
.getSchedClass(SCTrans
.ToClassIdx
).Name
<< "("
1670 << SCTrans
.ToClassIdx
<< ") on pred term: (";
1672 dbgs() << ") on processor (" << SCTrans
.ProcIndex
<< ")\n");
1674 // Create a new SchedClass for each variant found by inferFromRW. Pass
1675 static void inferFromTransitions(ArrayRef
<PredTransition
> LastTransitions
,
1676 unsigned FromClassIdx
,
1677 CodeGenSchedModels
&SchedModels
) {
1678 // For each PredTransition, create a new CodeGenSchedTransition, which usually
1679 // requires creating a new SchedClass.
1680 for (const auto &LastTransition
: LastTransitions
) {
1681 // Variant expansion (substituteVariants) may create unconditional
1682 // transitions. We don't need to build sched classes for them.
1683 if (LastTransition
.PredTerm
.empty())
1685 IdxVec OperWritesVariant
, OperReadsVariant
;
1686 addSequences(SchedModels
, LastTransition
.WriteSequences
, OperWritesVariant
,
1688 addSequences(SchedModels
, LastTransition
.ReadSequences
, OperReadsVariant
,
1690 CodeGenSchedTransition SCTrans
;
1692 // Transition should not contain processor indices already assigned to
1693 // InstRWs in this scheduling class.
1694 const CodeGenSchedClass
&FromSC
= SchedModels
.getSchedClass(FromClassIdx
);
1695 if (FromSC
.InstRWProcIndices
.count(LastTransition
.ProcIndex
))
1697 SCTrans
.ProcIndex
= LastTransition
.ProcIndex
;
1698 SCTrans
.ToClassIdx
=
1699 SchedModels
.addSchedClass(/*ItinClassDef=*/nullptr, OperWritesVariant
,
1700 OperReadsVariant
, LastTransition
.ProcIndex
);
1702 // The final PredTerm is unique set of predicates guarding the transition.
1704 transform(LastTransition
.PredTerm
, std::back_inserter(Preds
),
1705 [](const PredCheck
&P
) { return P
.Predicate
; });
1706 Preds
.erase(std::unique(Preds
.begin(), Preds
.end()), Preds
.end());
1707 dumpTransition(SchedModels
, FromSC
, SCTrans
, Preds
);
1708 SCTrans
.PredTerm
= std::move(Preds
);
1709 SchedModels
.getSchedClass(FromClassIdx
)
1710 .Transitions
.push_back(std::move(SCTrans
));
1714 std::vector
<unsigned> CodeGenSchedModels::getAllProcIndices() const {
1715 std::vector
<unsigned> ProcIdVec
;
1716 for (const auto &PM
: ProcModelMap
)
1718 ProcIdVec
.push_back(PM
.second
);
1719 // The order of the keys (Record pointers) of ProcModelMap are not stable.
1720 // Sort to stabalize the values.
1721 llvm::sort(ProcIdVec
);
1725 static std::vector
<PredTransition
>
1726 makePerProcessorTransitions(const PredTransition
&Trans
,
1727 ArrayRef
<unsigned> ProcIndices
) {
1728 std::vector
<PredTransition
> PerCpuTransVec
;
1729 for (unsigned ProcId
: ProcIndices
) {
1730 assert(ProcId
!= 0);
1731 PerCpuTransVec
.push_back(Trans
);
1732 PerCpuTransVec
.back().ProcIndex
= ProcId
;
1734 return PerCpuTransVec
;
1737 // Create new SchedClasses for the given ReadWrite list. If any of the
1738 // ReadWrites refers to a SchedVariant, create a new SchedClass for each variant
1739 // of the ReadWrite list, following Aliases if necessary.
1740 void CodeGenSchedModels::inferFromRW(ArrayRef
<unsigned> OperWrites
,
1741 ArrayRef
<unsigned> OperReads
,
1742 unsigned FromClassIdx
,
1743 ArrayRef
<unsigned> ProcIndices
) {
1744 LLVM_DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices
);
1746 // Create a seed transition with an empty PredTerm and the expanded sequences
1747 // of SchedWrites for the current SchedClass.
1748 std::vector
<PredTransition
> LastTransitions
;
1749 LastTransitions
.emplace_back();
1751 for (unsigned WriteIdx
: OperWrites
) {
1753 expandRWSequence(WriteIdx
, WriteSeq
, /*IsRead=*/false);
1754 LastTransitions
[0].WriteSequences
.emplace_back();
1755 SmallVectorImpl
<unsigned> &Seq
= LastTransitions
[0].WriteSequences
.back();
1756 Seq
.append(WriteSeq
.begin(), WriteSeq
.end());
1757 LLVM_DEBUG(dbgs() << "("; dumpIdxVec(Seq
); dbgs() << ") ");
1759 LLVM_DEBUG(dbgs() << " Reads: ");
1760 for (unsigned ReadIdx
: OperReads
) {
1762 expandRWSequence(ReadIdx
, ReadSeq
, /*IsRead=*/true);
1763 LastTransitions
[0].ReadSequences
.emplace_back();
1764 SmallVectorImpl
<unsigned> &Seq
= LastTransitions
[0].ReadSequences
.back();
1765 Seq
.append(ReadSeq
.begin(), ReadSeq
.end());
1766 LLVM_DEBUG(dbgs() << "("; dumpIdxVec(Seq
); dbgs() << ") ");
1768 LLVM_DEBUG(dbgs() << '\n');
1770 LastTransitions
= makePerProcessorTransitions(
1771 LastTransitions
[0], llvm::is_contained(ProcIndices
, 0)
1772 ? ArrayRef
<unsigned>(getAllProcIndices())
1774 // Collect all PredTransitions for individual operands.
1775 // Iterate until no variant writes remain.
1776 bool SubstitutedAny
;
1778 SubstitutedAny
= false;
1779 PredTransitions
Transitions(*this);
1780 for (const PredTransition
&Trans
: LastTransitions
)
1781 SubstitutedAny
|= Transitions
.substituteVariants(Trans
);
1782 LLVM_DEBUG(Transitions
.dump());
1783 LastTransitions
.swap(Transitions
.TransVec
);
1784 } while (SubstitutedAny
);
1786 // WARNING: We are about to mutate the SchedClasses vector. Do not refer to
1787 // OperWrites, OperReads, or ProcIndices after calling inferFromTransitions.
1788 inferFromTransitions(LastTransitions
, FromClassIdx
, *this);
1791 // Check if any processor resource group contains all resource records in
1793 bool CodeGenSchedModels::hasSuperGroup(RecVec
&SubUnits
, CodeGenProcModel
&PM
) {
1794 for (Record
*ProcResourceDef
: PM
.ProcResourceDefs
) {
1795 if (!ProcResourceDef
->isSubClassOf("ProcResGroup"))
1797 RecVec SuperUnits
= ProcResourceDef
->getValueAsListOfDefs("Resources");
1798 RecIter RI
= SubUnits
.begin(), RE
= SubUnits
.end();
1799 for ( ; RI
!= RE
; ++RI
) {
1800 if (!is_contained(SuperUnits
, *RI
)) {
1810 // Verify that overlapping groups have a common supergroup.
1811 void CodeGenSchedModels::verifyProcResourceGroups(CodeGenProcModel
&PM
) {
1812 for (unsigned i
= 0, e
= PM
.ProcResourceDefs
.size(); i
< e
; ++i
) {
1813 if (!PM
.ProcResourceDefs
[i
]->isSubClassOf("ProcResGroup"))
1816 PM
.ProcResourceDefs
[i
]->getValueAsListOfDefs("Resources");
1817 for (unsigned j
= i
+1; j
< e
; ++j
) {
1818 if (!PM
.ProcResourceDefs
[j
]->isSubClassOf("ProcResGroup"))
1821 PM
.ProcResourceDefs
[j
]->getValueAsListOfDefs("Resources");
1822 if (std::find_first_of(CheckUnits
.begin(), CheckUnits
.end(),
1823 OtherUnits
.begin(), OtherUnits
.end())
1824 != CheckUnits
.end()) {
1825 // CheckUnits and OtherUnits overlap
1826 llvm::append_range(OtherUnits
, CheckUnits
);
1827 if (!hasSuperGroup(OtherUnits
, PM
)) {
1828 PrintFatalError((PM
.ProcResourceDefs
[i
])->getLoc(),
1829 "proc resource group overlaps with "
1830 + PM
.ProcResourceDefs
[j
]->getName()
1831 + " but no supergroup contains both.");
1838 // Collect all the RegisterFile definitions available in this target.
1839 void CodeGenSchedModels::collectRegisterFiles() {
1840 RecVec RegisterFileDefs
= Records
.getAllDerivedDefinitions("RegisterFile");
1842 // RegisterFiles is the vector of CodeGenRegisterFile.
1843 for (Record
*RF
: RegisterFileDefs
) {
1844 // For each register file definition, construct a CodeGenRegisterFile object
1845 // and add it to the appropriate scheduling model.
1846 CodeGenProcModel
&PM
= getProcModel(RF
->getValueAsDef("SchedModel"));
1847 PM
.RegisterFiles
.emplace_back(CodeGenRegisterFile(RF
->getName(),RF
));
1848 CodeGenRegisterFile
&CGRF
= PM
.RegisterFiles
.back();
1849 CGRF
.MaxMovesEliminatedPerCycle
=
1850 RF
->getValueAsInt("MaxMovesEliminatedPerCycle");
1851 CGRF
.AllowZeroMoveEliminationOnly
=
1852 RF
->getValueAsBit("AllowZeroMoveEliminationOnly");
1854 // Now set the number of physical registers as well as the cost of registers
1855 // in each register class.
1856 CGRF
.NumPhysRegs
= RF
->getValueAsInt("NumPhysRegs");
1857 if (!CGRF
.NumPhysRegs
) {
1858 PrintFatalError(RF
->getLoc(),
1859 "Invalid RegisterFile with zero physical registers");
1862 RecVec RegisterClasses
= RF
->getValueAsListOfDefs("RegClasses");
1863 std::vector
<int64_t> RegisterCosts
= RF
->getValueAsListOfInts("RegCosts");
1864 ListInit
*MoveElimInfo
= RF
->getValueAsListInit("AllowMoveElimination");
1865 for (unsigned I
= 0, E
= RegisterClasses
.size(); I
< E
; ++I
) {
1866 int Cost
= RegisterCosts
.size() > I
? RegisterCosts
[I
] : 1;
1868 bool AllowMoveElim
= false;
1869 if (MoveElimInfo
->size() > I
) {
1870 BitInit
*Val
= cast
<BitInit
>(MoveElimInfo
->getElement(I
));
1871 AllowMoveElim
= Val
->getValue();
1874 CGRF
.Costs
.emplace_back(RegisterClasses
[I
], Cost
, AllowMoveElim
);
1879 // Collect and sort WriteRes, ReadAdvance, and ProcResources.
1880 void CodeGenSchedModels::collectProcResources() {
1881 ProcResourceDefs
= Records
.getAllDerivedDefinitions("ProcResourceUnits");
1882 ProcResGroups
= Records
.getAllDerivedDefinitions("ProcResGroup");
1884 // Add any subtarget-specific SchedReadWrites that are directly associated
1885 // with processor resources. Refer to the parent SchedClass's ProcIndices to
1886 // determine which processors they apply to.
1887 for (const CodeGenSchedClass
&SC
:
1888 make_range(schedClassBegin(), schedClassEnd())) {
1889 if (SC
.ItinClassDef
) {
1890 collectItinProcResources(SC
.ItinClassDef
);
1894 // This class may have a default ReadWrite list which can be overriden by
1895 // InstRW definitions.
1896 for (Record
*RW
: SC
.InstRWs
) {
1897 Record
*RWModelDef
= RW
->getValueAsDef("SchedModel");
1898 unsigned PIdx
= getProcModel(RWModelDef
).Index
;
1899 IdxVec Writes
, Reads
;
1900 findRWs(RW
->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
1901 collectRWResources(Writes
, Reads
, PIdx
);
1904 collectRWResources(SC
.Writes
, SC
.Reads
, SC
.ProcIndices
);
1906 // Add resources separately defined by each subtarget.
1907 RecVec WRDefs
= Records
.getAllDerivedDefinitions("WriteRes");
1908 for (Record
*WR
: WRDefs
) {
1909 Record
*ModelDef
= WR
->getValueAsDef("SchedModel");
1910 addWriteRes(WR
, getProcModel(ModelDef
).Index
);
1912 RecVec SWRDefs
= Records
.getAllDerivedDefinitions("SchedWriteRes");
1913 for (Record
*SWR
: SWRDefs
) {
1914 Record
*ModelDef
= SWR
->getValueAsDef("SchedModel");
1915 addWriteRes(SWR
, getProcModel(ModelDef
).Index
);
1917 RecVec RADefs
= Records
.getAllDerivedDefinitions("ReadAdvance");
1918 for (Record
*RA
: RADefs
) {
1919 Record
*ModelDef
= RA
->getValueAsDef("SchedModel");
1920 addReadAdvance(RA
, getProcModel(ModelDef
).Index
);
1922 RecVec SRADefs
= Records
.getAllDerivedDefinitions("SchedReadAdvance");
1923 for (Record
*SRA
: SRADefs
) {
1924 if (SRA
->getValueInit("SchedModel")->isComplete()) {
1925 Record
*ModelDef
= SRA
->getValueAsDef("SchedModel");
1926 addReadAdvance(SRA
, getProcModel(ModelDef
).Index
);
1929 // Add ProcResGroups that are defined within this processor model, which may
1930 // not be directly referenced but may directly specify a buffer size.
1931 RecVec ProcResGroups
= Records
.getAllDerivedDefinitions("ProcResGroup");
1932 for (Record
*PRG
: ProcResGroups
) {
1933 if (!PRG
->getValueInit("SchedModel")->isComplete())
1935 CodeGenProcModel
&PM
= getProcModel(PRG
->getValueAsDef("SchedModel"));
1936 if (!is_contained(PM
.ProcResourceDefs
, PRG
))
1937 PM
.ProcResourceDefs
.push_back(PRG
);
1939 // Add ProcResourceUnits unconditionally.
1940 for (Record
*PRU
: Records
.getAllDerivedDefinitions("ProcResourceUnits")) {
1941 if (!PRU
->getValueInit("SchedModel")->isComplete())
1943 CodeGenProcModel
&PM
= getProcModel(PRU
->getValueAsDef("SchedModel"));
1944 if (!is_contained(PM
.ProcResourceDefs
, PRU
))
1945 PM
.ProcResourceDefs
.push_back(PRU
);
1947 // Finalize each ProcModel by sorting the record arrays.
1948 for (CodeGenProcModel
&PM
: ProcModels
) {
1949 llvm::sort(PM
.WriteResDefs
, LessRecord());
1950 llvm::sort(PM
.ReadAdvanceDefs
, LessRecord());
1951 llvm::sort(PM
.ProcResourceDefs
, LessRecord());
1953 PM
.dump(); dbgs() << "WriteResDefs: "; for (auto WriteResDef
1954 : PM
.WriteResDefs
) {
1955 if (WriteResDef
->isSubClassOf("WriteRes"))
1956 dbgs() << WriteResDef
->getValueAsDef("WriteType")->getName() << " ";
1958 dbgs() << WriteResDef
->getName() << " ";
1959 } dbgs() << "\nReadAdvanceDefs: ";
1960 for (Record
*ReadAdvanceDef
1961 : PM
.ReadAdvanceDefs
) {
1962 if (ReadAdvanceDef
->isSubClassOf("ReadAdvance"))
1963 dbgs() << ReadAdvanceDef
->getValueAsDef("ReadType")->getName()
1966 dbgs() << ReadAdvanceDef
->getName() << " ";
1968 << "\nProcResourceDefs: ";
1969 for (Record
*ProcResourceDef
1970 : PM
.ProcResourceDefs
) {
1971 dbgs() << ProcResourceDef
->getName() << " ";
1974 verifyProcResourceGroups(PM
);
1977 ProcResourceDefs
.clear();
1978 ProcResGroups
.clear();
1981 void CodeGenSchedModels::checkCompleteness() {
1982 bool Complete
= true;
1983 for (const CodeGenProcModel
&ProcModel
: procModels()) {
1984 const bool HasItineraries
= ProcModel
.hasItineraries();
1985 if (!ProcModel
.ModelDef
->getValueAsBit("CompleteModel"))
1987 for (const CodeGenInstruction
*Inst
: Target
.getInstructionsByEnumValue()) {
1988 if (Inst
->hasNoSchedulingInfo
)
1990 if (ProcModel
.isUnsupported(*Inst
))
1992 unsigned SCIdx
= getSchedClassIdx(*Inst
);
1994 if (Inst
->TheDef
->isValueUnset("SchedRW")) {
1995 PrintError(Inst
->TheDef
->getLoc(),
1996 "No schedule information for instruction '" +
1997 Inst
->TheDef
->getName() + "' in SchedMachineModel '" +
1998 ProcModel
.ModelDef
->getName() + "'");
2004 const CodeGenSchedClass
&SC
= getSchedClass(SCIdx
);
2005 if (!SC
.Writes
.empty())
2007 if (HasItineraries
&& SC
.ItinClassDef
!= nullptr &&
2008 SC
.ItinClassDef
->getName() != "NoItinerary")
2011 const RecVec
&InstRWs
= SC
.InstRWs
;
2012 auto I
= find_if(InstRWs
, [&ProcModel
](const Record
*R
) {
2013 return R
->getValueAsDef("SchedModel") == ProcModel
.ModelDef
;
2015 if (I
== InstRWs
.end()) {
2016 PrintError(Inst
->TheDef
->getLoc(), "'" + ProcModel
.ModelName
+
2017 "' lacks information for '" +
2018 Inst
->TheDef
->getName() + "'");
2024 errs() << "\n\nIncomplete schedule models found.\n"
2025 << "- Consider setting 'CompleteModel = 0' while developing new models.\n"
2026 << "- Pseudo instructions can be marked with 'hasNoSchedulingInfo = 1'.\n"
2027 << "- Instructions should usually have Sched<[...]> as a superclass, "
2028 "you may temporarily use an empty list.\n"
2029 << "- Instructions related to unsupported features can be excluded with "
2030 "list<Predicate> UnsupportedFeatures = [HasA,..,HasY]; in the "
2031 "processor model.\n\n";
2032 PrintFatalError("Incomplete schedule model");
2036 // Collect itinerary class resources for each processor.
2037 void CodeGenSchedModels::collectItinProcResources(Record
*ItinClassDef
) {
2038 for (unsigned PIdx
= 0, PEnd
= ProcModels
.size(); PIdx
!= PEnd
; ++PIdx
) {
2039 const CodeGenProcModel
&PM
= ProcModels
[PIdx
];
2040 // For all ItinRW entries.
2041 bool HasMatch
= false;
2042 for (RecIter II
= PM
.ItinRWDefs
.begin(), IE
= PM
.ItinRWDefs
.end();
2044 RecVec Matched
= (*II
)->getValueAsListOfDefs("MatchedItinClasses");
2045 if (!llvm::is_contained(Matched
, ItinClassDef
))
2048 PrintFatalError((*II
)->getLoc(), "Duplicate itinerary class "
2049 + ItinClassDef
->getName()
2050 + " in ItinResources for " + PM
.ModelName
);
2052 IdxVec Writes
, Reads
;
2053 findRWs((*II
)->getValueAsListOfDefs("OperandReadWrites"), Writes
, Reads
);
2054 collectRWResources(Writes
, Reads
, PIdx
);
2059 void CodeGenSchedModels::collectRWResources(unsigned RWIdx
, bool IsRead
,
2060 ArrayRef
<unsigned> ProcIndices
) {
2061 const CodeGenSchedRW
&SchedRW
= getSchedRW(RWIdx
, IsRead
);
2062 if (SchedRW
.TheDef
) {
2063 if (!IsRead
&& SchedRW
.TheDef
->isSubClassOf("SchedWriteRes")) {
2064 for (unsigned Idx
: ProcIndices
)
2065 addWriteRes(SchedRW
.TheDef
, Idx
);
2067 else if (IsRead
&& SchedRW
.TheDef
->isSubClassOf("SchedReadAdvance")) {
2068 for (unsigned Idx
: ProcIndices
)
2069 addReadAdvance(SchedRW
.TheDef
, Idx
);
2072 for (auto *Alias
: SchedRW
.Aliases
) {
2073 IdxVec AliasProcIndices
;
2074 if (Alias
->getValueInit("SchedModel")->isComplete()) {
2075 AliasProcIndices
.push_back(
2076 getProcModel(Alias
->getValueAsDef("SchedModel")).Index
);
2078 AliasProcIndices
= ProcIndices
;
2079 const CodeGenSchedRW
&AliasRW
= getSchedRW(Alias
->getValueAsDef("AliasRW"));
2080 assert(AliasRW
.IsRead
== IsRead
&& "cannot alias reads to writes");
2083 expandRWSequence(AliasRW
.Index
, ExpandedRWs
, IsRead
);
2084 for (unsigned int ExpandedRW
: ExpandedRWs
) {
2085 collectRWResources(ExpandedRW
, IsRead
, AliasProcIndices
);
2090 // Collect resources for a set of read/write types and processor indices.
2091 void CodeGenSchedModels::collectRWResources(ArrayRef
<unsigned> Writes
,
2092 ArrayRef
<unsigned> Reads
,
2093 ArrayRef
<unsigned> ProcIndices
) {
2094 for (unsigned Idx
: Writes
)
2095 collectRWResources(Idx
, /*IsRead=*/false, ProcIndices
);
2097 for (unsigned Idx
: Reads
)
2098 collectRWResources(Idx
, /*IsRead=*/true, ProcIndices
);
2101 // Find the processor's resource units for this kind of resource.
2102 Record
*CodeGenSchedModels::findProcResUnits(Record
*ProcResKind
,
2103 const CodeGenProcModel
&PM
,
2104 ArrayRef
<SMLoc
> Loc
) const {
2105 if (ProcResKind
->isSubClassOf("ProcResourceUnits"))
2108 Record
*ProcUnitDef
= nullptr;
2109 assert(!ProcResourceDefs
.empty());
2110 assert(!ProcResGroups
.empty());
2112 for (Record
*ProcResDef
: ProcResourceDefs
) {
2113 if (ProcResDef
->getValueAsDef("Kind") == ProcResKind
2114 && ProcResDef
->getValueAsDef("SchedModel") == PM
.ModelDef
) {
2116 PrintFatalError(Loc
,
2117 "Multiple ProcessorResourceUnits associated with "
2118 + ProcResKind
->getName());
2120 ProcUnitDef
= ProcResDef
;
2123 for (Record
*ProcResGroup
: ProcResGroups
) {
2124 if (ProcResGroup
== ProcResKind
2125 && ProcResGroup
->getValueAsDef("SchedModel") == PM
.ModelDef
) {
2127 PrintFatalError(Loc
,
2128 "Multiple ProcessorResourceUnits associated with "
2129 + ProcResKind
->getName());
2131 ProcUnitDef
= ProcResGroup
;
2135 PrintFatalError(Loc
,
2136 "No ProcessorResources associated with "
2137 + ProcResKind
->getName());
2142 // Iteratively add a resource and its super resources.
2143 void CodeGenSchedModels::addProcResource(Record
*ProcResKind
,
2144 CodeGenProcModel
&PM
,
2145 ArrayRef
<SMLoc
> Loc
) {
2147 Record
*ProcResUnits
= findProcResUnits(ProcResKind
, PM
, Loc
);
2149 // See if this ProcResource is already associated with this processor.
2150 if (is_contained(PM
.ProcResourceDefs
, ProcResUnits
))
2153 PM
.ProcResourceDefs
.push_back(ProcResUnits
);
2154 if (ProcResUnits
->isSubClassOf("ProcResGroup"))
2157 if (!ProcResUnits
->getValueInit("Super")->isComplete())
2160 ProcResKind
= ProcResUnits
->getValueAsDef("Super");
2164 // Add resources for a SchedWrite to this processor if they don't exist.
2165 void CodeGenSchedModels::addWriteRes(Record
*ProcWriteResDef
, unsigned PIdx
) {
2166 assert(PIdx
&& "don't add resources to an invalid Processor model");
2168 RecVec
&WRDefs
= ProcModels
[PIdx
].WriteResDefs
;
2169 if (is_contained(WRDefs
, ProcWriteResDef
))
2171 WRDefs
.push_back(ProcWriteResDef
);
2173 // Visit ProcResourceKinds referenced by the newly discovered WriteRes.
2174 RecVec ProcResDefs
= ProcWriteResDef
->getValueAsListOfDefs("ProcResources");
2175 for (auto *ProcResDef
: ProcResDefs
) {
2176 addProcResource(ProcResDef
, ProcModels
[PIdx
], ProcWriteResDef
->getLoc());
2180 // Add resources for a ReadAdvance to this processor if they don't exist.
2181 void CodeGenSchedModels::addReadAdvance(Record
*ProcReadAdvanceDef
,
2183 RecVec
&RADefs
= ProcModels
[PIdx
].ReadAdvanceDefs
;
2184 if (is_contained(RADefs
, ProcReadAdvanceDef
))
2186 RADefs
.push_back(ProcReadAdvanceDef
);
2189 unsigned CodeGenProcModel::getProcResourceIdx(Record
*PRDef
) const {
2190 RecIter PRPos
= find(ProcResourceDefs
, PRDef
);
2191 if (PRPos
== ProcResourceDefs
.end())
2192 PrintFatalError(PRDef
->getLoc(), "ProcResource def is not included in "
2193 "the ProcResources list for " + ModelName
);
2194 // Idx=0 is reserved for invalid.
2195 return 1 + (PRPos
- ProcResourceDefs
.begin());
2198 bool CodeGenProcModel::isUnsupported(const CodeGenInstruction
&Inst
) const {
2199 for (const Record
*TheDef
: UnsupportedFeaturesDefs
) {
2200 for (const Record
*PredDef
: Inst
.TheDef
->getValueAsListOfDefs("Predicates")) {
2201 if (TheDef
->getName() == PredDef
->getName())
2209 void CodeGenProcModel::dump() const {
2210 dbgs() << Index
<< ": " << ModelName
<< " "
2211 << (ModelDef
? ModelDef
->getName() : "inferred") << " "
2212 << (ItinsDef
? ItinsDef
->getName() : "no itinerary") << '\n';
2215 void CodeGenSchedRW::dump() const {
2216 dbgs() << Name
<< (IsVariadic
? " (V) " : " ");
2219 dumpIdxVec(Sequence
);
2224 void CodeGenSchedClass::dump(const CodeGenSchedModels
* SchedModels
) const {
2225 dbgs() << "SCHEDCLASS " << Index
<< ":" << Name
<< '\n'
2227 for (unsigned i
= 0, N
= Writes
.size(); i
< N
; ++i
) {
2228 SchedModels
->getSchedWrite(Writes
[i
]).dump();
2234 dbgs() << "\n Reads: ";
2235 for (unsigned i
= 0, N
= Reads
.size(); i
< N
; ++i
) {
2236 SchedModels
->getSchedRead(Reads
[i
]).dump();
2242 dbgs() << "\n ProcIdx: "; dumpIdxVec(ProcIndices
);
2243 if (!Transitions
.empty()) {
2244 dbgs() << "\n Transitions for Proc ";
2245 for (const CodeGenSchedTransition
&Transition
: Transitions
) {
2246 dbgs() << Transition
.ProcIndex
<< ", ";
2252 void PredTransitions::dump() const {
2253 dbgs() << "Expanded Variants:\n";
2254 for (const auto &TI
: TransVec
) {
2257 for (const PredCheck
&PC
: TI
.PredTerm
)
2258 dbgs() << LS
<< SchedModels
.getSchedRW(PC
.RWIdx
, PC
.IsRead
).Name
<< ":"
2259 << PC
.Predicate
->getName();
2260 dbgs() << "},\n => {";
2261 for (SmallVectorImpl
<SmallVector
<unsigned, 4>>::const_iterator
2262 WSI
= TI
.WriteSequences
.begin(),
2263 WSE
= TI
.WriteSequences
.end();
2264 WSI
!= WSE
; ++WSI
) {
2267 for (unsigned N
: *WSI
)
2268 dbgs() << LS
<< SchedModels
.getSchedWrite(N
).Name
;