1 //===- CodeGenSchedule.cpp - Scheduling MachineModels ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines structures to encapsulate the machine model as described in
11 // the target description.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "CodeGenInstruction.h"
16 #include "CodeGenSchedule.h"
17 #include "CodeGenTarget.h"
18 #include "llvm/ADT/SmallPtrSet.h"
19 #include "llvm/ADT/SmallSet.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/Support/Regex.h"
26 #include "llvm/TableGen/Error.h"
27 #include <algorithm>
28 #include <iterator>
29 #include <utility>
30 
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "subtarget-emitter"
34 
35 #ifndef NDEBUG
36 static void dumpIdxVec(ArrayRef<unsigned> V) {
37   for (unsigned Idx : V)
38     dbgs() << Idx << ", ";
39 }
40 #endif
41 
42 namespace {
43 
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);
49   }
50 };
51 
52 // (instregex "OpcPat",...) Find all instructions matching an opcode pattern.
53 //
54 // TODO: Since this is a prefix match, perform a binary search over the
55 // instruction names using lower_bound. Note that the predefined instrs must be
56 // scanned linearly first. However, this is only safe if the regex pattern has
57 // no top-level bars. The DAG already has a list of patterns, so there's no
58 // reason to use top-level bars, but we need a way to verify they don't exist
59 // before implementing the optimization.
60 struct InstRegexOp : public SetTheory::Operator {
61   const CodeGenTarget &Target;
62   InstRegexOp(const CodeGenTarget &t): Target(t) {}
63 
64   void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
65              ArrayRef<SMLoc> Loc) override {
66     SmallVector<Regex, 4> RegexList;
67     for (Init *Arg : make_range(Expr->arg_begin(), Expr->arg_end())) {
68       StringInit *SI = dyn_cast<StringInit>(Arg);
69       if (!SI)
70         PrintFatalError(Loc, "instregex requires pattern string: "
71           + Expr->getAsString());
72       std::string pat = SI->getValue();
73       // Implement a python-style prefix match.
74       if (pat[0] != '^') {
75         pat.insert(0, "^(");
76         pat.insert(pat.end(), ')');
77       }
78       RegexList.push_back(Regex(pat));
79     }
80     for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
81       for (auto &R : RegexList) {
82         if (R.match(Inst->TheDef->getName()))
83           Elts.insert(Inst->TheDef);
84       }
85     }
86   }
87 };
88 
89 } // end anonymous namespace
90 
91 /// CodeGenModels ctor interprets machine model records and populates maps.
92 CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
93                                        const CodeGenTarget &TGT):
94   Records(RK), Target(TGT) {
95 
96   Sets.addFieldExpander("InstRW", "Instrs");
97 
98   // Allow Set evaluation to recognize the dags used in InstRW records:
99   // (instrs Op1, Op1...)
100   Sets.addOperator("instrs", llvm::make_unique<InstrsOp>());
101   Sets.addOperator("instregex", llvm::make_unique<InstRegexOp>(Target));
102 
103   // Instantiate a CodeGenProcModel for each SchedMachineModel with the values
104   // that are explicitly referenced in tablegen records. Resources associated
105   // with each processor will be derived later. Populate ProcModelMap with the
106   // CodeGenProcModel instances.
107   collectProcModels();
108 
109   // Instantiate a CodeGenSchedRW for each SchedReadWrite record explicitly
110   // defined, and populate SchedReads and SchedWrites vectors. Implicit
111   // SchedReadWrites that represent sequences derived from expanded variant will
112   // be inferred later.
113   collectSchedRW();
114 
115   // Instantiate a CodeGenSchedClass for each unique SchedRW signature directly
116   // required by an instruction definition, and populate SchedClassIdxMap. Set
117   // NumItineraryClasses to the number of explicit itinerary classes referenced
118   // by instructions. Set NumInstrSchedClasses to the number of itinerary
119   // classes plus any classes implied by instructions that derive from class
120   // Sched and provide SchedRW list. This does not infer any new classes from
121   // SchedVariant.
122   collectSchedClasses();
123 
124   // Find instruction itineraries for each processor. Sort and populate
125   // CodeGenProcModel::ItinDefList. (Cycle-to-cycle itineraries). This requires
126   // all itinerary classes to be discovered.
127   collectProcItins();
128 
129   // Find ItinRW records for each processor and itinerary class.
130   // (For per-operand resources mapped to itinerary classes).
131   collectProcItinRW();
132 
133   // Find UnsupportedFeatures records for each processor.
134   // (For per-operand resources mapped to itinerary classes).
135   collectProcUnsupportedFeatures();
136 
137   // Infer new SchedClasses from SchedVariant.
138   inferSchedClasses();
139 
140   // Populate each CodeGenProcModel's WriteResDefs, ReadAdvanceDefs, and
141   // ProcResourceDefs.
142   DEBUG(dbgs() << "\n+++ RESOURCE DEFINITIONS (collectProcResources) +++\n");
143   collectProcResources();
144 
145   checkCompleteness();
146 }
147 
148 /// Gather all processor models.
149 void CodeGenSchedModels::collectProcModels() {
150   RecVec ProcRecords = Records.getAllDerivedDefinitions("Processor");
151   std::sort(ProcRecords.begin(), ProcRecords.end(), LessRecordFieldName());
152 
153   // Reserve space because we can. Reallocation would be ok.
154   ProcModels.reserve(ProcRecords.size()+1);
155 
156   // Use idx=0 for NoModel/NoItineraries.
157   Record *NoModelDef = Records.getDef("NoSchedModel");
158   Record *NoItinsDef = Records.getDef("NoItineraries");
159   ProcModels.emplace_back(0, "NoSchedModel", NoModelDef, NoItinsDef);
160   ProcModelMap[NoModelDef] = 0;
161 
162   // For each processor, find a unique machine model.
163   DEBUG(dbgs() << "+++ PROCESSOR MODELs (addProcModel) +++\n");
164   for (Record *ProcRecord : ProcRecords)
165     addProcModel(ProcRecord);
166 }
167 
168 /// Get a unique processor model based on the defined MachineModel and
169 /// ProcessorItineraries.
170 void CodeGenSchedModels::addProcModel(Record *ProcDef) {
171   Record *ModelKey = getModelOrItinDef(ProcDef);
172   if (!ProcModelMap.insert(std::make_pair(ModelKey, ProcModels.size())).second)
173     return;
174 
175   std::string Name = ModelKey->getName();
176   if (ModelKey->isSubClassOf("SchedMachineModel")) {
177     Record *ItinsDef = ModelKey->getValueAsDef("Itineraries");
178     ProcModels.emplace_back(ProcModels.size(), Name, ModelKey, ItinsDef);
179   }
180   else {
181     // An itinerary is defined without a machine model. Infer a new model.
182     if (!ModelKey->getValueAsListOfDefs("IID").empty())
183       Name = Name + "Model";
184     ProcModels.emplace_back(ProcModels.size(), Name,
185                             ProcDef->getValueAsDef("SchedModel"), ModelKey);
186   }
187   DEBUG(ProcModels.back().dump());
188 }
189 
190 // Recursively find all reachable SchedReadWrite records.
191 static void scanSchedRW(Record *RWDef, RecVec &RWDefs,
192                         SmallPtrSet<Record*, 16> &RWSet) {
193   if (!RWSet.insert(RWDef).second)
194     return;
195   RWDefs.push_back(RWDef);
196   // Reads don't currently have sequence records, but it can be added later.
197   if (RWDef->isSubClassOf("WriteSequence")) {
198     RecVec Seq = RWDef->getValueAsListOfDefs("Writes");
199     for (Record *WSRec : Seq)
200       scanSchedRW(WSRec, RWDefs, RWSet);
201   }
202   else if (RWDef->isSubClassOf("SchedVariant")) {
203     // Visit each variant (guarded by a different predicate).
204     RecVec Vars = RWDef->getValueAsListOfDefs("Variants");
205     for (Record *Variant : Vars) {
206       // Visit each RW in the sequence selected by the current variant.
207       RecVec Selected = Variant->getValueAsListOfDefs("Selected");
208       for (Record *SelDef : Selected)
209         scanSchedRW(SelDef, RWDefs, RWSet);
210     }
211   }
212 }
213 
214 // Collect and sort all SchedReadWrites reachable via tablegen records.
215 // More may be inferred later when inferring new SchedClasses from variants.
216 void CodeGenSchedModels::collectSchedRW() {
217   // Reserve idx=0 for invalid writes/reads.
218   SchedWrites.resize(1);
219   SchedReads.resize(1);
220 
221   SmallPtrSet<Record*, 16> RWSet;
222 
223   // Find all SchedReadWrites referenced by instruction defs.
224   RecVec SWDefs, SRDefs;
225   for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
226     Record *SchedDef = Inst->TheDef;
227     if (SchedDef->isValueUnset("SchedRW"))
228       continue;
229     RecVec RWs = SchedDef->getValueAsListOfDefs("SchedRW");
230     for (Record *RW : RWs) {
231       if (RW->isSubClassOf("SchedWrite"))
232         scanSchedRW(RW, SWDefs, RWSet);
233       else {
234         assert(RW->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
235         scanSchedRW(RW, SRDefs, RWSet);
236       }
237     }
238   }
239   // Find all ReadWrites referenced by InstRW.
240   RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");
241   for (Record *InstRWDef : InstRWDefs) {
242     // For all OperandReadWrites.
243     RecVec RWDefs = InstRWDef->getValueAsListOfDefs("OperandReadWrites");
244     for (Record *RWDef : RWDefs) {
245       if (RWDef->isSubClassOf("SchedWrite"))
246         scanSchedRW(RWDef, SWDefs, RWSet);
247       else {
248         assert(RWDef->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
249         scanSchedRW(RWDef, SRDefs, RWSet);
250       }
251     }
252   }
253   // Find all ReadWrites referenced by ItinRW.
254   RecVec ItinRWDefs = Records.getAllDerivedDefinitions("ItinRW");
255   for (Record *ItinRWDef : ItinRWDefs) {
256     // For all OperandReadWrites.
257     RecVec RWDefs = ItinRWDef->getValueAsListOfDefs("OperandReadWrites");
258     for (Record *RWDef : RWDefs) {
259       if (RWDef->isSubClassOf("SchedWrite"))
260         scanSchedRW(RWDef, SWDefs, RWSet);
261       else {
262         assert(RWDef->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
263         scanSchedRW(RWDef, SRDefs, RWSet);
264       }
265     }
266   }
267   // Find all ReadWrites referenced by SchedAlias. AliasDefs needs to be sorted
268   // for the loop below that initializes Alias vectors.
269   RecVec AliasDefs = Records.getAllDerivedDefinitions("SchedAlias");
270   std::sort(AliasDefs.begin(), AliasDefs.end(), LessRecord());
271   for (Record *ADef : AliasDefs) {
272     Record *MatchDef = ADef->getValueAsDef("MatchRW");
273     Record *AliasDef = ADef->getValueAsDef("AliasRW");
274     if (MatchDef->isSubClassOf("SchedWrite")) {
275       if (!AliasDef->isSubClassOf("SchedWrite"))
276         PrintFatalError(ADef->getLoc(), "SchedWrite Alias must be SchedWrite");
277       scanSchedRW(AliasDef, SWDefs, RWSet);
278     }
279     else {
280       assert(MatchDef->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
281       if (!AliasDef->isSubClassOf("SchedRead"))
282         PrintFatalError(ADef->getLoc(), "SchedRead Alias must be SchedRead");
283       scanSchedRW(AliasDef, SRDefs, RWSet);
284     }
285   }
286   // Sort and add the SchedReadWrites directly referenced by instructions or
287   // itinerary resources. Index reads and writes in separate domains.
288   std::sort(SWDefs.begin(), SWDefs.end(), LessRecord());
289   for (Record *SWDef : SWDefs) {
290     assert(!getSchedRWIdx(SWDef, /*IsRead=*/false) && "duplicate SchedWrite");
291     SchedWrites.emplace_back(SchedWrites.size(), SWDef);
292   }
293   std::sort(SRDefs.begin(), SRDefs.end(), LessRecord());
294   for (Record *SRDef : SRDefs) {
295     assert(!getSchedRWIdx(SRDef, /*IsRead-*/true) && "duplicate SchedWrite");
296     SchedReads.emplace_back(SchedReads.size(), SRDef);
297   }
298   // Initialize WriteSequence vectors.
299   for (CodeGenSchedRW &CGRW : SchedWrites) {
300     if (!CGRW.IsSequence)
301       continue;
302     findRWs(CGRW.TheDef->getValueAsListOfDefs("Writes"), CGRW.Sequence,
303             /*IsRead=*/false);
304   }
305   // Initialize Aliases vectors.
306   for (Record *ADef : AliasDefs) {
307     Record *AliasDef = ADef->getValueAsDef("AliasRW");
308     getSchedRW(AliasDef).IsAlias = true;
309     Record *MatchDef = ADef->getValueAsDef("MatchRW");
310     CodeGenSchedRW &RW = getSchedRW(MatchDef);
311     if (RW.IsAlias)
312       PrintFatalError(ADef->getLoc(), "Cannot Alias an Alias");
313     RW.Aliases.push_back(ADef);
314   }
315   DEBUG(
316     dbgs() << "\n+++ SCHED READS and WRITES (collectSchedRW) +++\n";
317     for (unsigned WIdx = 0, WEnd = SchedWrites.size(); WIdx != WEnd; ++WIdx) {
318       dbgs() << WIdx << ": ";
319       SchedWrites[WIdx].dump();
320       dbgs() << '\n';
321     }
322     for (unsigned RIdx = 0, REnd = SchedReads.size(); RIdx != REnd; ++RIdx) {
323       dbgs() << RIdx << ": ";
324       SchedReads[RIdx].dump();
325       dbgs() << '\n';
326     }
327     RecVec RWDefs = Records.getAllDerivedDefinitions("SchedReadWrite");
328     for (Record *RWDef : RWDefs) {
329       if (!getSchedRWIdx(RWDef, RWDef->isSubClassOf("SchedRead"))) {
330         const std::string &Name = RWDef->getName();
331         if (Name != "NoWrite" && Name != "ReadDefault")
332           dbgs() << "Unused SchedReadWrite " << RWDef->getName() << '\n';
333       }
334     });
335 }
336 
337 /// Compute a SchedWrite name from a sequence of writes.
338 std::string CodeGenSchedModels::genRWName(ArrayRef<unsigned> Seq, bool IsRead) {
339   std::string Name("(");
340   for (auto I = Seq.begin(), E = Seq.end(); I != E; ++I) {
341     if (I != Seq.begin())
342       Name += '_';
343     Name += getSchedRW(*I, IsRead).Name;
344   }
345   Name += ')';
346   return Name;
347 }
348 
349 unsigned CodeGenSchedModels::getSchedRWIdx(Record *Def, bool IsRead,
350                                            unsigned After) const {
351   const std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites;
352   assert(After < RWVec.size() && "start position out of bounds");
353   for (std::vector<CodeGenSchedRW>::const_iterator I = RWVec.begin() + After,
354          E = RWVec.end(); I != E; ++I) {
355     if (I->TheDef == Def)
356       return I - RWVec.begin();
357   }
358   return 0;
359 }
360 
361 bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const {
362   for (const CodeGenSchedRW &Read : SchedReads) {
363     Record *ReadDef = Read.TheDef;
364     if (!ReadDef || !ReadDef->isSubClassOf("ProcReadAdvance"))
365       continue;
366 
367     RecVec ValidWrites = ReadDef->getValueAsListOfDefs("ValidWrites");
368     if (is_contained(ValidWrites, WriteDef)) {
369       return true;
370     }
371   }
372   return false;
373 }
374 
375 namespace llvm {
376 
377 void splitSchedReadWrites(const RecVec &RWDefs,
378                           RecVec &WriteDefs, RecVec &ReadDefs) {
379   for (Record *RWDef : RWDefs) {
380     if (RWDef->isSubClassOf("SchedWrite"))
381       WriteDefs.push_back(RWDef);
382     else {
383       assert(RWDef->isSubClassOf("SchedRead") && "unknown SchedReadWrite");
384       ReadDefs.push_back(RWDef);
385     }
386   }
387 }
388 
389 } // end namespace llvm
390 
391 // Split the SchedReadWrites defs and call findRWs for each list.
392 void CodeGenSchedModels::findRWs(const RecVec &RWDefs,
393                                  IdxVec &Writes, IdxVec &Reads) const {
394     RecVec WriteDefs;
395     RecVec ReadDefs;
396     splitSchedReadWrites(RWDefs, WriteDefs, ReadDefs);
397     findRWs(WriteDefs, Writes, false);
398     findRWs(ReadDefs, Reads, true);
399 }
400 
401 // Call getSchedRWIdx for all elements in a sequence of SchedRW defs.
402 void CodeGenSchedModels::findRWs(const RecVec &RWDefs, IdxVec &RWs,
403                                  bool IsRead) const {
404   for (Record *RWDef : RWDefs) {
405     unsigned Idx = getSchedRWIdx(RWDef, IsRead);
406     assert(Idx && "failed to collect SchedReadWrite");
407     RWs.push_back(Idx);
408   }
409 }
410 
411 void CodeGenSchedModels::expandRWSequence(unsigned RWIdx, IdxVec &RWSeq,
412                                           bool IsRead) const {
413   const CodeGenSchedRW &SchedRW = getSchedRW(RWIdx, IsRead);
414   if (!SchedRW.IsSequence) {
415     RWSeq.push_back(RWIdx);
416     return;
417   }
418   int Repeat =
419     SchedRW.TheDef ? SchedRW.TheDef->getValueAsInt("Repeat") : 1;
420   for (int i = 0; i < Repeat; ++i) {
421     for (unsigned I : SchedRW.Sequence) {
422       expandRWSequence(I, RWSeq, IsRead);
423     }
424   }
425 }
426 
427 // Expand a SchedWrite as a sequence following any aliases that coincide with
428 // the given processor model.
429 void CodeGenSchedModels::expandRWSeqForProc(
430   unsigned RWIdx, IdxVec &RWSeq, bool IsRead,
431   const CodeGenProcModel &ProcModel) const {
432 
433   const CodeGenSchedRW &SchedWrite = getSchedRW(RWIdx, IsRead);
434   Record *AliasDef = nullptr;
435   for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
436        AI != AE; ++AI) {
437     const CodeGenSchedRW &AliasRW = getSchedRW((*AI)->getValueAsDef("AliasRW"));
438     if ((*AI)->getValueInit("SchedModel")->isComplete()) {
439       Record *ModelDef = (*AI)->getValueAsDef("SchedModel");
440       if (&getProcModel(ModelDef) != &ProcModel)
441         continue;
442     }
443     if (AliasDef)
444       PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
445                       "defined for processor " + ProcModel.ModelName +
446                       " Ensure only one SchedAlias exists per RW.");
447     AliasDef = AliasRW.TheDef;
448   }
449   if (AliasDef) {
450     expandRWSeqForProc(getSchedRWIdx(AliasDef, IsRead),
451                        RWSeq, IsRead,ProcModel);
452     return;
453   }
454   if (!SchedWrite.IsSequence) {
455     RWSeq.push_back(RWIdx);
456     return;
457   }
458   int Repeat =
459     SchedWrite.TheDef ? SchedWrite.TheDef->getValueAsInt("Repeat") : 1;
460   for (int i = 0; i < Repeat; ++i) {
461     for (unsigned I : SchedWrite.Sequence) {
462       expandRWSeqForProc(I, RWSeq, IsRead, ProcModel);
463     }
464   }
465 }
466 
467 // Find the existing SchedWrite that models this sequence of writes.
468 unsigned CodeGenSchedModels::findRWForSequence(ArrayRef<unsigned> Seq,
469                                                bool IsRead) {
470   std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites;
471 
472   for (std::vector<CodeGenSchedRW>::iterator I = RWVec.begin(), E = RWVec.end();
473        I != E; ++I) {
474     if (makeArrayRef(I->Sequence) == Seq)
475       return I - RWVec.begin();
476   }
477   // Index zero reserved for invalid RW.
478   return 0;
479 }
480 
481 /// Add this ReadWrite if it doesn't already exist.
482 unsigned CodeGenSchedModels::findOrInsertRW(ArrayRef<unsigned> Seq,
483                                             bool IsRead) {
484   assert(!Seq.empty() && "cannot insert empty sequence");
485   if (Seq.size() == 1)
486     return Seq.back();
487 
488   unsigned Idx = findRWForSequence(Seq, IsRead);
489   if (Idx)
490     return Idx;
491 
492   unsigned RWIdx = IsRead ? SchedReads.size() : SchedWrites.size();
493   CodeGenSchedRW SchedRW(RWIdx, IsRead, Seq, genRWName(Seq, IsRead));
494   if (IsRead)
495     SchedReads.push_back(SchedRW);
496   else
497     SchedWrites.push_back(SchedRW);
498   return RWIdx;
499 }
500 
501 /// Visit all the instruction definitions for this target to gather and
502 /// enumerate the itinerary classes. These are the explicitly specified
503 /// SchedClasses. More SchedClasses may be inferred.
504 void CodeGenSchedModels::collectSchedClasses() {
505 
506   // NoItinerary is always the first class at Idx=0
507   SchedClasses.resize(1);
508   SchedClasses.back().Index = 0;
509   SchedClasses.back().Name = "NoInstrModel";
510   SchedClasses.back().ItinClassDef = Records.getDef("NoItinerary");
511   SchedClasses.back().ProcIndices.push_back(0);
512 
513   // Create a SchedClass for each unique combination of itinerary class and
514   // SchedRW list.
515   for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
516     Record *ItinDef = Inst->TheDef->getValueAsDef("Itinerary");
517     IdxVec Writes, Reads;
518     if (!Inst->TheDef->isValueUnset("SchedRW"))
519       findRWs(Inst->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads);
520 
521     // ProcIdx == 0 indicates the class applies to all processors.
522     IdxVec ProcIndices(1, 0);
523 
524     unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, ProcIndices);
525     InstrClassMap[Inst->TheDef] = SCIdx;
526   }
527   // Create classes for InstRW defs.
528   RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");
529   std::sort(InstRWDefs.begin(), InstRWDefs.end(), LessRecord());
530   DEBUG(dbgs() << "\n+++ SCHED CLASSES (createInstRWClass) +++\n");
531   for (Record *RWDef : InstRWDefs)
532     createInstRWClass(RWDef);
533 
534   NumInstrSchedClasses = SchedClasses.size();
535 
536   bool EnableDump = false;
537   DEBUG(EnableDump = true);
538   if (!EnableDump)
539     return;
540 
541   dbgs() << "\n+++ ITINERARIES and/or MACHINE MODELS (collectSchedClasses) +++\n";
542   for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
543     StringRef InstName = Inst->TheDef->getName();
544     unsigned SCIdx = InstrClassMap.lookup(Inst->TheDef);
545     if (!SCIdx) {
546       if (!Inst->hasNoSchedulingInfo)
547         dbgs() << "No machine model for " << Inst->TheDef->getName() << '\n';
548       continue;
549     }
550     CodeGenSchedClass &SC = getSchedClass(SCIdx);
551     if (SC.ProcIndices[0] != 0)
552       PrintFatalError(Inst->TheDef->getLoc(), "Instruction's sched class "
553                       "must not be subtarget specific.");
554 
555     IdxVec ProcIndices;
556     if (SC.ItinClassDef->getName() != "NoItinerary") {
557       ProcIndices.push_back(0);
558       dbgs() << "Itinerary for " << InstName << ": "
559              << SC.ItinClassDef->getName() << '\n';
560     }
561     if (!SC.Writes.empty()) {
562       ProcIndices.push_back(0);
563       dbgs() << "SchedRW machine model for " << InstName;
564       for (IdxIter WI = SC.Writes.begin(), WE = SC.Writes.end(); WI != WE; ++WI)
565         dbgs() << " " << SchedWrites[*WI].Name;
566       for (IdxIter RI = SC.Reads.begin(), RE = SC.Reads.end(); RI != RE; ++RI)
567         dbgs() << " " << SchedReads[*RI].Name;
568       dbgs() << '\n';
569     }
570     const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs;
571     for (Record *RWDef : RWDefs) {
572       const CodeGenProcModel &ProcModel =
573         getProcModel(RWDef->getValueAsDef("SchedModel"));
574       ProcIndices.push_back(ProcModel.Index);
575       dbgs() << "InstRW on " << ProcModel.ModelName << " for " << InstName;
576       IdxVec Writes;
577       IdxVec Reads;
578       findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
579               Writes, Reads);
580       for (unsigned WIdx : Writes)
581         dbgs() << " " << SchedWrites[WIdx].Name;
582       for (unsigned RIdx : Reads)
583         dbgs() << " " << SchedReads[RIdx].Name;
584       dbgs() << '\n';
585     }
586     // If ProcIndices contains zero, the class applies to all processors.
587     if (!std::count(ProcIndices.begin(), ProcIndices.end(), 0)) {
588       for (const CodeGenProcModel &PM :
589            make_range(ProcModels.begin(), ProcModels.end())) {
590         if (!std::count(ProcIndices.begin(), ProcIndices.end(), PM.Index))
591           dbgs() << "No machine model for " << Inst->TheDef->getName()
592                  << " on processor " << PM.ModelName << '\n';
593       }
594     }
595   }
596 }
597 
598 /// Find an SchedClass that has been inferred from a per-operand list of
599 /// SchedWrites and SchedReads.
600 unsigned CodeGenSchedModels::findSchedClassIdx(Record *ItinClassDef,
601                                                ArrayRef<unsigned> Writes,
602                                                ArrayRef<unsigned> Reads) const {
603   for (SchedClassIter I = schedClassBegin(), E = schedClassEnd(); I != E; ++I) {
604     if (I->ItinClassDef == ItinClassDef && makeArrayRef(I->Writes) == Writes &&
605         makeArrayRef(I->Reads) == Reads) {
606       return I - schedClassBegin();
607     }
608   }
609   return 0;
610 }
611 
612 // Get the SchedClass index for an instruction.
613 unsigned CodeGenSchedModels::getSchedClassIdx(
614   const CodeGenInstruction &Inst) const {
615 
616   return InstrClassMap.lookup(Inst.TheDef);
617 }
618 
619 std::string
620 CodeGenSchedModels::createSchedClassName(Record *ItinClassDef,
621                                          ArrayRef<unsigned> OperWrites,
622                                          ArrayRef<unsigned> OperReads) {
623 
624   std::string Name;
625   if (ItinClassDef && ItinClassDef->getName() != "NoItinerary")
626     Name = ItinClassDef->getName();
627   for (unsigned Idx : OperWrites) {
628     if (!Name.empty())
629       Name += '_';
630     Name += SchedWrites[Idx].Name;
631   }
632   for (unsigned Idx : OperReads) {
633     Name += '_';
634     Name += SchedReads[Idx].Name;
635   }
636   return Name;
637 }
638 
639 std::string CodeGenSchedModels::createSchedClassName(const RecVec &InstDefs) {
640 
641   std::string Name;
642   for (RecIter I = InstDefs.begin(), E = InstDefs.end(); I != E; ++I) {
643     if (I != InstDefs.begin())
644       Name += '_';
645     Name += (*I)->getName();
646   }
647   return Name;
648 }
649 
650 /// Add an inferred sched class from an itinerary class and per-operand list of
651 /// SchedWrites and SchedReads. ProcIndices contains the set of IDs of
652 /// processors that may utilize this class.
653 unsigned CodeGenSchedModels::addSchedClass(Record *ItinClassDef,
654                                            ArrayRef<unsigned> OperWrites,
655                                            ArrayRef<unsigned> OperReads,
656                                            ArrayRef<unsigned> ProcIndices) {
657   assert(!ProcIndices.empty() && "expect at least one ProcIdx");
658 
659   unsigned Idx = findSchedClassIdx(ItinClassDef, OperWrites, OperReads);
660   if (Idx || SchedClasses[0].isKeyEqual(ItinClassDef, OperWrites, OperReads)) {
661     IdxVec PI;
662     std::set_union(SchedClasses[Idx].ProcIndices.begin(),
663                    SchedClasses[Idx].ProcIndices.end(),
664                    ProcIndices.begin(), ProcIndices.end(),
665                    std::back_inserter(PI));
666     SchedClasses[Idx].ProcIndices.swap(PI);
667     return Idx;
668   }
669   Idx = SchedClasses.size();
670   SchedClasses.resize(Idx+1);
671   CodeGenSchedClass &SC = SchedClasses.back();
672   SC.Index = Idx;
673   SC.Name = createSchedClassName(ItinClassDef, OperWrites, OperReads);
674   SC.ItinClassDef = ItinClassDef;
675   SC.Writes = OperWrites;
676   SC.Reads = OperReads;
677   SC.ProcIndices = ProcIndices;
678 
679   return Idx;
680 }
681 
682 // Create classes for each set of opcodes that are in the same InstReadWrite
683 // definition across all processors.
684 void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
685   // ClassInstrs will hold an entry for each subset of Instrs in InstRWDef that
686   // intersects with an existing class via a previous InstRWDef. Instrs that do
687   // not intersect with an existing class refer back to their former class as
688   // determined from ItinDef or SchedRW.
689   SmallVector<std::pair<unsigned, SmallVector<Record *, 8>>, 4> ClassInstrs;
690   // Sort Instrs into sets.
691   const RecVec *InstDefs = Sets.expand(InstRWDef);
692   if (InstDefs->empty())
693     PrintFatalError(InstRWDef->getLoc(), "No matching instruction opcodes");
694 
695   for (Record *InstDef : make_range(InstDefs->begin(), InstDefs->end())) {
696     InstClassMapTy::const_iterator Pos = InstrClassMap.find(InstDef);
697     if (Pos == InstrClassMap.end())
698       PrintFatalError(InstDef->getLoc(), "No sched class for instruction.");
699     unsigned SCIdx = Pos->second;
700     unsigned CIdx = 0, CEnd = ClassInstrs.size();
701     for (; CIdx != CEnd; ++CIdx) {
702       if (ClassInstrs[CIdx].first == SCIdx)
703         break;
704     }
705     if (CIdx == CEnd) {
706       ClassInstrs.resize(CEnd + 1);
707       ClassInstrs[CIdx].first = SCIdx;
708     }
709     ClassInstrs[CIdx].second.push_back(InstDef);
710   }
711   // For each set of Instrs, create a new class if necessary, and map or remap
712   // the Instrs to it.
713   unsigned CIdx = 0, CEnd = ClassInstrs.size();
714   for (; CIdx != CEnd; ++CIdx) {
715     unsigned OldSCIdx = ClassInstrs[CIdx].first;
716     ArrayRef<Record*> InstDefs = ClassInstrs[CIdx].second;
717     // If the all instrs in the current class are accounted for, then leave
718     // them mapped to their old class.
719     if (OldSCIdx) {
720       const RecVec &RWDefs = SchedClasses[OldSCIdx].InstRWs;
721       if (!RWDefs.empty()) {
722         const RecVec *OrigInstDefs = Sets.expand(RWDefs[0]);
723         unsigned OrigNumInstrs = 0;
724         for (Record *OIDef : make_range(OrigInstDefs->begin(), OrigInstDefs->end())) {
725           if (InstrClassMap[OIDef] == OldSCIdx)
726             ++OrigNumInstrs;
727         }
728         if (OrigNumInstrs == InstDefs.size()) {
729           assert(SchedClasses[OldSCIdx].ProcIndices[0] == 0 &&
730                  "expected a generic SchedClass");
731           DEBUG(dbgs() << "InstRW: Reuse SC " << OldSCIdx << ":"
732                 << SchedClasses[OldSCIdx].Name << " on "
733                 << InstRWDef->getValueAsDef("SchedModel")->getName() << "\n");
734           SchedClasses[OldSCIdx].InstRWs.push_back(InstRWDef);
735           continue;
736         }
737       }
738     }
739     unsigned SCIdx = SchedClasses.size();
740     SchedClasses.resize(SCIdx+1);
741     CodeGenSchedClass &SC = SchedClasses.back();
742     SC.Index = SCIdx;
743     SC.Name = createSchedClassName(InstDefs);
744     DEBUG(dbgs() << "InstRW: New SC " << SCIdx << ":" << SC.Name << " on "
745           << InstRWDef->getValueAsDef("SchedModel")->getName() << "\n");
746 
747     // Preserve ItinDef and Writes/Reads for processors without an InstRW entry.
748     SC.ItinClassDef = SchedClasses[OldSCIdx].ItinClassDef;
749     SC.Writes = SchedClasses[OldSCIdx].Writes;
750     SC.Reads = SchedClasses[OldSCIdx].Reads;
751     SC.ProcIndices.push_back(0);
752     // Map each Instr to this new class.
753     // Note that InstDefs may be a smaller list than InstRWDef's "Instrs".
754     Record *RWModelDef = InstRWDef->getValueAsDef("SchedModel");
755     SmallSet<unsigned, 4> RemappedClassIDs;
756     for (ArrayRef<Record*>::const_iterator
757            II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) {
758       unsigned OldSCIdx = InstrClassMap[*II];
759       if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx).second) {
760         for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(),
761                RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) {
762           if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) {
763             PrintFatalError(InstRWDef->getLoc(), "Overlapping InstRW def " +
764                           (*II)->getName() + " also matches " +
765                           (*RI)->getValue("Instrs")->getValue()->getAsString());
766           }
767           assert(*RI != InstRWDef && "SchedClass has duplicate InstRW def");
768           SC.InstRWs.push_back(*RI);
769         }
770       }
771       InstrClassMap[*II] = SCIdx;
772     }
773     SC.InstRWs.push_back(InstRWDef);
774   }
775 }
776 
777 // True if collectProcItins found anything.
778 bool CodeGenSchedModels::hasItineraries() const {
779   for (const CodeGenProcModel &PM : make_range(procModelBegin(),procModelEnd())) {
780     if (PM.hasItineraries())
781       return true;
782   }
783   return false;
784 }
785 
786 // Gather the processor itineraries.
787 void CodeGenSchedModels::collectProcItins() {
788   DEBUG(dbgs() << "\n+++ PROBLEM ITINERARIES (collectProcItins) +++\n");
789   for (CodeGenProcModel &ProcModel : ProcModels) {
790     if (!ProcModel.hasItineraries())
791       continue;
792 
793     RecVec ItinRecords = ProcModel.ItinsDef->getValueAsListOfDefs("IID");
794     assert(!ItinRecords.empty() && "ProcModel.hasItineraries is incorrect");
795 
796     // Populate ItinDefList with Itinerary records.
797     ProcModel.ItinDefList.resize(NumInstrSchedClasses);
798 
799     // Insert each itinerary data record in the correct position within
800     // the processor model's ItinDefList.
801     for (Record *ItinData : ItinRecords) {
802       Record *ItinDef = ItinData->getValueAsDef("TheClass");
803       bool FoundClass = false;
804       for (SchedClassIter SCI = schedClassBegin(), SCE = schedClassEnd();
805            SCI != SCE; ++SCI) {
806         // Multiple SchedClasses may share an itinerary. Update all of them.
807         if (SCI->ItinClassDef == ItinDef) {
808           ProcModel.ItinDefList[SCI->Index] = ItinData;
809           FoundClass = true;
810         }
811       }
812       if (!FoundClass) {
813         DEBUG(dbgs() << ProcModel.ItinsDef->getName()
814               << " missing class for itinerary " << ItinDef->getName() << '\n');
815       }
816     }
817     // Check for missing itinerary entries.
818     assert(!ProcModel.ItinDefList[0] && "NoItinerary class can't have rec");
819     DEBUG(
820       for (unsigned i = 1, N = ProcModel.ItinDefList.size(); i < N; ++i) {
821         if (!ProcModel.ItinDefList[i])
822           dbgs() << ProcModel.ItinsDef->getName()
823                  << " missing itinerary for class "
824                  << SchedClasses[i].Name << '\n';
825       });
826   }
827 }
828 
829 // Gather the read/write types for each itinerary class.
830 void CodeGenSchedModels::collectProcItinRW() {
831   RecVec ItinRWDefs = Records.getAllDerivedDefinitions("ItinRW");
832   std::sort(ItinRWDefs.begin(), ItinRWDefs.end(), LessRecord());
833   for (Record *RWDef  : make_range(ItinRWDefs.begin(), ItinRWDefs.end())) {
834     if (!RWDef->getValueInit("SchedModel")->isComplete())
835       PrintFatalError(RWDef->getLoc(), "SchedModel is undefined");
836     Record *ModelDef = RWDef->getValueAsDef("SchedModel");
837     ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
838     if (I == ProcModelMap.end()) {
839       PrintFatalError(RWDef->getLoc(), "Undefined SchedMachineModel "
840                     + ModelDef->getName());
841     }
842     ProcModels[I->second].ItinRWDefs.push_back(RWDef);
843   }
844 }
845 
846 // Gather the unsupported features for processor models.
847 void CodeGenSchedModels::collectProcUnsupportedFeatures() {
848   for (CodeGenProcModel &ProcModel : ProcModels) {
849     for (Record *Pred : ProcModel.ModelDef->getValueAsListOfDefs("UnsupportedFeatures")) {
850        ProcModel.UnsupportedFeaturesDefs.push_back(Pred);
851     }
852   }
853 }
854 
855 /// Infer new classes from existing classes. In the process, this may create new
856 /// SchedWrites from sequences of existing SchedWrites.
857 void CodeGenSchedModels::inferSchedClasses() {
858   DEBUG(dbgs() << "\n+++ INFERRING SCHED CLASSES (inferSchedClasses) +++\n");
859   DEBUG(dbgs() << NumInstrSchedClasses << " instr sched classes.\n");
860 
861   // Visit all existing classes and newly created classes.
862   for (unsigned Idx = 0; Idx != SchedClasses.size(); ++Idx) {
863     assert(SchedClasses[Idx].Index == Idx && "bad SCIdx");
864 
865     if (SchedClasses[Idx].ItinClassDef)
866       inferFromItinClass(SchedClasses[Idx].ItinClassDef, Idx);
867     if (!SchedClasses[Idx].InstRWs.empty())
868       inferFromInstRWs(Idx);
869     if (!SchedClasses[Idx].Writes.empty()) {
870       inferFromRW(SchedClasses[Idx].Writes, SchedClasses[Idx].Reads,
871                   Idx, SchedClasses[Idx].ProcIndices);
872     }
873     assert(SchedClasses.size() < (NumInstrSchedClasses*6) &&
874            "too many SchedVariants");
875   }
876 }
877 
878 /// Infer classes from per-processor itinerary resources.
879 void CodeGenSchedModels::inferFromItinClass(Record *ItinClassDef,
880                                             unsigned FromClassIdx) {
881   for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) {
882     const CodeGenProcModel &PM = ProcModels[PIdx];
883     // For all ItinRW entries.
884     bool HasMatch = false;
885     for (RecIter II = PM.ItinRWDefs.begin(), IE = PM.ItinRWDefs.end();
886          II != IE; ++II) {
887       RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
888       if (!std::count(Matched.begin(), Matched.end(), ItinClassDef))
889         continue;
890       if (HasMatch)
891         PrintFatalError((*II)->getLoc(), "Duplicate itinerary class "
892                       + ItinClassDef->getName()
893                       + " in ItinResources for " + PM.ModelName);
894       HasMatch = true;
895       IdxVec Writes, Reads;
896       findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
897       IdxVec ProcIndices(1, PIdx);
898       inferFromRW(Writes, Reads, FromClassIdx, ProcIndices);
899     }
900   }
901 }
902 
903 /// Infer classes from per-processor InstReadWrite definitions.
904 void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) {
905   for (unsigned I = 0, E = SchedClasses[SCIdx].InstRWs.size(); I != E; ++I) {
906     assert(SchedClasses[SCIdx].InstRWs.size() == E && "InstrRWs was mutated!");
907     Record *Rec = SchedClasses[SCIdx].InstRWs[I];
908     const RecVec *InstDefs = Sets.expand(Rec);
909     RecIter II = InstDefs->begin(), IE = InstDefs->end();
910     for (; II != IE; ++II) {
911       if (InstrClassMap[*II] == SCIdx)
912         break;
913     }
914     // If this class no longer has any instructions mapped to it, it has become
915     // irrelevant.
916     if (II == IE)
917       continue;
918     IdxVec Writes, Reads;
919     findRWs(Rec->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
920     unsigned PIdx = getProcModel(Rec->getValueAsDef("SchedModel")).Index;
921     IdxVec ProcIndices(1, PIdx);
922     inferFromRW(Writes, Reads, SCIdx, ProcIndices); // May mutate SchedClasses.
923   }
924 }
925 
926 namespace {
927 
928 // Helper for substituteVariantOperand.
929 struct TransVariant {
930   Record *VarOrSeqDef;  // Variant or sequence.
931   unsigned RWIdx;       // Index of this variant or sequence's matched type.
932   unsigned ProcIdx;     // Processor model index or zero for any.
933   unsigned TransVecIdx; // Index into PredTransitions::TransVec.
934 
935   TransVariant(Record *def, unsigned rwi, unsigned pi, unsigned ti):
936     VarOrSeqDef(def), RWIdx(rwi), ProcIdx(pi), TransVecIdx(ti) {}
937 };
938 
939 // Associate a predicate with the SchedReadWrite that it guards.
940 // RWIdx is the index of the read/write variant.
941 struct PredCheck {
942   bool IsRead;
943   unsigned RWIdx;
944   Record *Predicate;
945 
946   PredCheck(bool r, unsigned w, Record *p): IsRead(r), RWIdx(w), Predicate(p) {}
947 };
948 
949 // A Predicate transition is a list of RW sequences guarded by a PredTerm.
950 struct PredTransition {
951   // A predicate term is a conjunction of PredChecks.
952   SmallVector<PredCheck, 4> PredTerm;
953   SmallVector<SmallVector<unsigned,4>, 16> WriteSequences;
954   SmallVector<SmallVector<unsigned,4>, 16> ReadSequences;
955   SmallVector<unsigned, 4> ProcIndices;
956 };
957 
958 // Encapsulate a set of partially constructed transitions.
959 // The results are built by repeated calls to substituteVariants.
960 class PredTransitions {
961   CodeGenSchedModels &SchedModels;
962 
963 public:
964   std::vector<PredTransition> TransVec;
965 
966   PredTransitions(CodeGenSchedModels &sm): SchedModels(sm) {}
967 
968   void substituteVariantOperand(const SmallVectorImpl<unsigned> &RWSeq,
969                                 bool IsRead, unsigned StartIdx);
970 
971   void substituteVariants(const PredTransition &Trans);
972 
973 #ifndef NDEBUG
974   void dump() const;
975 #endif
976 
977 private:
978   bool mutuallyExclusive(Record *PredDef, ArrayRef<PredCheck> Term);
979   void getIntersectingVariants(
980     const CodeGenSchedRW &SchedRW, unsigned TransIdx,
981     std::vector<TransVariant> &IntersectingVariants);
982   void pushVariant(const TransVariant &VInfo, bool IsRead);
983 };
984 
985 } // end anonymous namespace
986 
987 // Return true if this predicate is mutually exclusive with a PredTerm. This
988 // degenerates into checking if the predicate is mutually exclusive with any
989 // predicate in the Term's conjunction.
990 //
991 // All predicates associated with a given SchedRW are considered mutually
992 // exclusive. This should work even if the conditions expressed by the
993 // predicates are not exclusive because the predicates for a given SchedWrite
994 // are always checked in the order they are defined in the .td file. Later
995 // conditions implicitly negate any prior condition.
996 bool PredTransitions::mutuallyExclusive(Record *PredDef,
997                                         ArrayRef<PredCheck> Term) {
998   for (const PredCheck &PC: make_range(Term.begin(), Term.end())) {
999     if (PC.Predicate == PredDef)
1000       return false;
1001 
1002     const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(PC.RWIdx, PC.IsRead);
1003     assert(SchedRW.HasVariants && "PredCheck must refer to a SchedVariant");
1004     RecVec Variants = SchedRW.TheDef->getValueAsListOfDefs("Variants");
1005     for (RecIter VI = Variants.begin(), VE = Variants.end(); VI != VE; ++VI) {
1006       if ((*VI)->getValueAsDef("Predicate") == PredDef)
1007         return true;
1008     }
1009   }
1010   return false;
1011 }
1012 
1013 static bool hasAliasedVariants(const CodeGenSchedRW &RW,
1014                                CodeGenSchedModels &SchedModels) {
1015   if (RW.HasVariants)
1016     return true;
1017 
1018   for (Record *Alias : make_range(RW.Aliases.begin(), RW.Aliases.end())) {
1019     const CodeGenSchedRW &AliasRW =
1020       SchedModels.getSchedRW(Alias->getValueAsDef("AliasRW"));
1021     if (AliasRW.HasVariants)
1022       return true;
1023     if (AliasRW.IsSequence) {
1024       IdxVec ExpandedRWs;
1025       SchedModels.expandRWSequence(AliasRW.Index, ExpandedRWs, AliasRW.IsRead);
1026       for (IdxIter SI = ExpandedRWs.begin(), SE = ExpandedRWs.end();
1027            SI != SE; ++SI) {
1028         if (hasAliasedVariants(SchedModels.getSchedRW(*SI, AliasRW.IsRead),
1029                                SchedModels)) {
1030           return true;
1031         }
1032       }
1033     }
1034   }
1035   return false;
1036 }
1037 
1038 static bool hasVariant(ArrayRef<PredTransition> Transitions,
1039                        CodeGenSchedModels &SchedModels) {
1040   for (ArrayRef<PredTransition>::iterator
1041          PTI = Transitions.begin(), PTE = Transitions.end();
1042        PTI != PTE; ++PTI) {
1043     for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
1044            WSI = PTI->WriteSequences.begin(), WSE = PTI->WriteSequences.end();
1045          WSI != WSE; ++WSI) {
1046       for (SmallVectorImpl<unsigned>::const_iterator
1047              WI = WSI->begin(), WE = WSI->end(); WI != WE; ++WI) {
1048         if (hasAliasedVariants(SchedModels.getSchedWrite(*WI), SchedModels))
1049           return true;
1050       }
1051     }
1052     for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
1053            RSI = PTI->ReadSequences.begin(), RSE = PTI->ReadSequences.end();
1054          RSI != RSE; ++RSI) {
1055       for (SmallVectorImpl<unsigned>::const_iterator
1056              RI = RSI->begin(), RE = RSI->end(); RI != RE; ++RI) {
1057         if (hasAliasedVariants(SchedModels.getSchedRead(*RI), SchedModels))
1058           return true;
1059       }
1060     }
1061   }
1062   return false;
1063 }
1064 
1065 // Populate IntersectingVariants with any variants or aliased sequences of the
1066 // given SchedRW whose processor indices and predicates are not mutually
1067 // exclusive with the given transition.
1068 void PredTransitions::getIntersectingVariants(
1069   const CodeGenSchedRW &SchedRW, unsigned TransIdx,
1070   std::vector<TransVariant> &IntersectingVariants) {
1071 
1072   bool GenericRW = false;
1073 
1074   std::vector<TransVariant> Variants;
1075   if (SchedRW.HasVariants) {
1076     unsigned VarProcIdx = 0;
1077     if (SchedRW.TheDef->getValueInit("SchedModel")->isComplete()) {
1078       Record *ModelDef = SchedRW.TheDef->getValueAsDef("SchedModel");
1079       VarProcIdx = SchedModels.getProcModel(ModelDef).Index;
1080     }
1081     // Push each variant. Assign TransVecIdx later.
1082     const RecVec VarDefs = SchedRW.TheDef->getValueAsListOfDefs("Variants");
1083     for (Record *VarDef : VarDefs)
1084       Variants.push_back(TransVariant(VarDef, SchedRW.Index, VarProcIdx, 0));
1085     if (VarProcIdx == 0)
1086       GenericRW = true;
1087   }
1088   for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
1089        AI != AE; ++AI) {
1090     // If either the SchedAlias itself or the SchedReadWrite that it aliases
1091     // to is defined within a processor model, constrain all variants to
1092     // that processor.
1093     unsigned AliasProcIdx = 0;
1094     if ((*AI)->getValueInit("SchedModel")->isComplete()) {
1095       Record *ModelDef = (*AI)->getValueAsDef("SchedModel");
1096       AliasProcIdx = SchedModels.getProcModel(ModelDef).Index;
1097     }
1098     const CodeGenSchedRW &AliasRW =
1099       SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
1100 
1101     if (AliasRW.HasVariants) {
1102       const RecVec VarDefs = AliasRW.TheDef->getValueAsListOfDefs("Variants");
1103       for (RecIter RI = VarDefs.begin(), RE = VarDefs.end(); RI != RE; ++RI)
1104         Variants.push_back(TransVariant(*RI, AliasRW.Index, AliasProcIdx, 0));
1105     }
1106     if (AliasRW.IsSequence) {
1107       Variants.push_back(
1108         TransVariant(AliasRW.TheDef, SchedRW.Index, AliasProcIdx, 0));
1109     }
1110     if (AliasProcIdx == 0)
1111       GenericRW = true;
1112   }
1113   for (TransVariant &Variant : Variants) {
1114     // Don't expand variants if the processor models don't intersect.
1115     // A zero processor index means any processor.
1116     SmallVectorImpl<unsigned> &ProcIndices = TransVec[TransIdx].ProcIndices;
1117     if (ProcIndices[0] && Variant.ProcIdx) {
1118       unsigned Cnt = std::count(ProcIndices.begin(), ProcIndices.end(),
1119                                 Variant.ProcIdx);
1120       if (!Cnt)
1121         continue;
1122       if (Cnt > 1) {
1123         const CodeGenProcModel &PM =
1124           *(SchedModels.procModelBegin() + Variant.ProcIdx);
1125         PrintFatalError(Variant.VarOrSeqDef->getLoc(),
1126                         "Multiple variants defined for processor " +
1127                         PM.ModelName +
1128                         " Ensure only one SchedAlias exists per RW.");
1129       }
1130     }
1131     if (Variant.VarOrSeqDef->isSubClassOf("SchedVar")) {
1132       Record *PredDef = Variant.VarOrSeqDef->getValueAsDef("Predicate");
1133       if (mutuallyExclusive(PredDef, TransVec[TransIdx].PredTerm))
1134         continue;
1135     }
1136     if (IntersectingVariants.empty()) {
1137       // The first variant builds on the existing transition.
1138       Variant.TransVecIdx = TransIdx;
1139       IntersectingVariants.push_back(Variant);
1140     }
1141     else {
1142       // Push another copy of the current transition for more variants.
1143       Variant.TransVecIdx = TransVec.size();
1144       IntersectingVariants.push_back(Variant);
1145       TransVec.push_back(TransVec[TransIdx]);
1146     }
1147   }
1148   if (GenericRW && IntersectingVariants.empty()) {
1149     PrintFatalError(SchedRW.TheDef->getLoc(), "No variant of this type has "
1150                     "a matching predicate on any processor");
1151   }
1152 }
1153 
1154 // Push the Reads/Writes selected by this variant onto the PredTransition
1155 // specified by VInfo.
1156 void PredTransitions::
1157 pushVariant(const TransVariant &VInfo, bool IsRead) {
1158   PredTransition &Trans = TransVec[VInfo.TransVecIdx];
1159 
1160   // If this operand transition is reached through a processor-specific alias,
1161   // then the whole transition is specific to this processor.
1162   if (VInfo.ProcIdx != 0)
1163     Trans.ProcIndices.assign(1, VInfo.ProcIdx);
1164 
1165   IdxVec SelectedRWs;
1166   if (VInfo.VarOrSeqDef->isSubClassOf("SchedVar")) {
1167     Record *PredDef = VInfo.VarOrSeqDef->getValueAsDef("Predicate");
1168     Trans.PredTerm.push_back(PredCheck(IsRead, VInfo.RWIdx,PredDef));
1169     RecVec SelectedDefs = VInfo.VarOrSeqDef->getValueAsListOfDefs("Selected");
1170     SchedModels.findRWs(SelectedDefs, SelectedRWs, IsRead);
1171   }
1172   else {
1173     assert(VInfo.VarOrSeqDef->isSubClassOf("WriteSequence") &&
1174            "variant must be a SchedVariant or aliased WriteSequence");
1175     SelectedRWs.push_back(SchedModels.getSchedRWIdx(VInfo.VarOrSeqDef, IsRead));
1176   }
1177 
1178   const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(VInfo.RWIdx, IsRead);
1179 
1180   SmallVectorImpl<SmallVector<unsigned,4>> &RWSequences = IsRead
1181     ? Trans.ReadSequences : Trans.WriteSequences;
1182   if (SchedRW.IsVariadic) {
1183     unsigned OperIdx = RWSequences.size()-1;
1184     // Make N-1 copies of this transition's last sequence.
1185     for (unsigned i = 1, e = SelectedRWs.size(); i != e; ++i) {
1186       // Create a temporary copy the vector could reallocate.
1187       RWSequences.reserve(RWSequences.size() + 1);
1188       RWSequences.push_back(RWSequences[OperIdx]);
1189     }
1190     // Push each of the N elements of the SelectedRWs onto a copy of the last
1191     // sequence (split the current operand into N operands).
1192     // Note that write sequences should be expanded within this loop--the entire
1193     // sequence belongs to a single operand.
1194     for (IdxIter RWI = SelectedRWs.begin(), RWE = SelectedRWs.end();
1195          RWI != RWE; ++RWI, ++OperIdx) {
1196       IdxVec ExpandedRWs;
1197       if (IsRead)
1198         ExpandedRWs.push_back(*RWI);
1199       else
1200         SchedModels.expandRWSequence(*RWI, ExpandedRWs, IsRead);
1201       RWSequences[OperIdx].insert(RWSequences[OperIdx].end(),
1202                                   ExpandedRWs.begin(), ExpandedRWs.end());
1203     }
1204     assert(OperIdx == RWSequences.size() && "missed a sequence");
1205   }
1206   else {
1207     // Push this transition's expanded sequence onto this transition's last
1208     // sequence (add to the current operand's sequence).
1209     SmallVectorImpl<unsigned> &Seq = RWSequences.back();
1210     IdxVec ExpandedRWs;
1211     for (IdxIter RWI = SelectedRWs.begin(), RWE = SelectedRWs.end();
1212          RWI != RWE; ++RWI) {
1213       if (IsRead)
1214         ExpandedRWs.push_back(*RWI);
1215       else
1216         SchedModels.expandRWSequence(*RWI, ExpandedRWs, IsRead);
1217     }
1218     Seq.insert(Seq.end(), ExpandedRWs.begin(), ExpandedRWs.end());
1219   }
1220 }
1221 
1222 // RWSeq is a sequence of all Reads or all Writes for the next read or write
1223 // operand. StartIdx is an index into TransVec where partial results
1224 // starts. RWSeq must be applied to all transitions between StartIdx and the end
1225 // of TransVec.
1226 void PredTransitions::substituteVariantOperand(
1227   const SmallVectorImpl<unsigned> &RWSeq, bool IsRead, unsigned StartIdx) {
1228 
1229   // Visit each original RW within the current sequence.
1230   for (SmallVectorImpl<unsigned>::const_iterator
1231          RWI = RWSeq.begin(), RWE = RWSeq.end(); RWI != RWE; ++RWI) {
1232     const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(*RWI, IsRead);
1233     // Push this RW on all partial PredTransitions or distribute variants.
1234     // New PredTransitions may be pushed within this loop which should not be
1235     // revisited (TransEnd must be loop invariant).
1236     for (unsigned TransIdx = StartIdx, TransEnd = TransVec.size();
1237          TransIdx != TransEnd; ++TransIdx) {
1238       // In the common case, push RW onto the current operand's sequence.
1239       if (!hasAliasedVariants(SchedRW, SchedModels)) {
1240         if (IsRead)
1241           TransVec[TransIdx].ReadSequences.back().push_back(*RWI);
1242         else
1243           TransVec[TransIdx].WriteSequences.back().push_back(*RWI);
1244         continue;
1245       }
1246       // Distribute this partial PredTransition across intersecting variants.
1247       // This will push a copies of TransVec[TransIdx] on the back of TransVec.
1248       std::vector<TransVariant> IntersectingVariants;
1249       getIntersectingVariants(SchedRW, TransIdx, IntersectingVariants);
1250       // Now expand each variant on top of its copy of the transition.
1251       for (std::vector<TransVariant>::const_iterator
1252              IVI = IntersectingVariants.begin(),
1253              IVE = IntersectingVariants.end();
1254            IVI != IVE; ++IVI) {
1255         pushVariant(*IVI, IsRead);
1256       }
1257     }
1258   }
1259 }
1260 
1261 // For each variant of a Read/Write in Trans, substitute the sequence of
1262 // Read/Writes guarded by the variant. This is exponential in the number of
1263 // variant Read/Writes, but in practice detection of mutually exclusive
1264 // predicates should result in linear growth in the total number variants.
1265 //
1266 // This is one step in a breadth-first search of nested variants.
1267 void PredTransitions::substituteVariants(const PredTransition &Trans) {
1268   // Build up a set of partial results starting at the back of
1269   // PredTransitions. Remember the first new transition.
1270   unsigned StartIdx = TransVec.size();
1271   TransVec.resize(TransVec.size() + 1);
1272   TransVec.back().PredTerm = Trans.PredTerm;
1273   TransVec.back().ProcIndices = Trans.ProcIndices;
1274 
1275   // Visit each original write sequence.
1276   for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
1277          WSI = Trans.WriteSequences.begin(), WSE = Trans.WriteSequences.end();
1278        WSI != WSE; ++WSI) {
1279     // Push a new (empty) write sequence onto all partial Transitions.
1280     for (std::vector<PredTransition>::iterator I =
1281            TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) {
1282       I->WriteSequences.resize(I->WriteSequences.size() + 1);
1283     }
1284     substituteVariantOperand(*WSI, /*IsRead=*/false, StartIdx);
1285   }
1286   // Visit each original read sequence.
1287   for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
1288          RSI = Trans.ReadSequences.begin(), RSE = Trans.ReadSequences.end();
1289        RSI != RSE; ++RSI) {
1290     // Push a new (empty) read sequence onto all partial Transitions.
1291     for (std::vector<PredTransition>::iterator I =
1292            TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) {
1293       I->ReadSequences.resize(I->ReadSequences.size() + 1);
1294     }
1295     substituteVariantOperand(*RSI, /*IsRead=*/true, StartIdx);
1296   }
1297 }
1298 
1299 // Create a new SchedClass for each variant found by inferFromRW. Pass
1300 static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions,
1301                                  unsigned FromClassIdx,
1302                                  CodeGenSchedModels &SchedModels) {
1303   // For each PredTransition, create a new CodeGenSchedTransition, which usually
1304   // requires creating a new SchedClass.
1305   for (ArrayRef<PredTransition>::iterator
1306          I = LastTransitions.begin(), E = LastTransitions.end(); I != E; ++I) {
1307     IdxVec OperWritesVariant;
1308     for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
1309            WSI = I->WriteSequences.begin(), WSE = I->WriteSequences.end();
1310          WSI != WSE; ++WSI) {
1311       // Create a new write representing the expanded sequence.
1312       OperWritesVariant.push_back(
1313         SchedModels.findOrInsertRW(*WSI, /*IsRead=*/false));
1314     }
1315     IdxVec OperReadsVariant;
1316     for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
1317            RSI = I->ReadSequences.begin(), RSE = I->ReadSequences.end();
1318          RSI != RSE; ++RSI) {
1319       // Create a new read representing the expanded sequence.
1320       OperReadsVariant.push_back(
1321         SchedModels.findOrInsertRW(*RSI, /*IsRead=*/true));
1322     }
1323     IdxVec ProcIndices(I->ProcIndices.begin(), I->ProcIndices.end());
1324     CodeGenSchedTransition SCTrans;
1325     SCTrans.ToClassIdx =
1326       SchedModels.addSchedClass(/*ItinClassDef=*/nullptr, OperWritesVariant,
1327                                 OperReadsVariant, ProcIndices);
1328     SCTrans.ProcIndices = ProcIndices;
1329     // The final PredTerm is unique set of predicates guarding the transition.
1330     RecVec Preds;
1331     for (SmallVectorImpl<PredCheck>::const_iterator
1332            PI = I->PredTerm.begin(), PE = I->PredTerm.end(); PI != PE; ++PI) {
1333       Preds.push_back(PI->Predicate);
1334     }
1335     RecIter PredsEnd = std::unique(Preds.begin(), Preds.end());
1336     Preds.resize(PredsEnd - Preds.begin());
1337     SCTrans.PredTerm = Preds;
1338     SchedModels.getSchedClass(FromClassIdx).Transitions.push_back(SCTrans);
1339   }
1340 }
1341 
1342 // Create new SchedClasses for the given ReadWrite list. If any of the
1343 // ReadWrites refers to a SchedVariant, create a new SchedClass for each variant
1344 // of the ReadWrite list, following Aliases if necessary.
1345 void CodeGenSchedModels::inferFromRW(ArrayRef<unsigned> OperWrites,
1346                                      ArrayRef<unsigned> OperReads,
1347                                      unsigned FromClassIdx,
1348                                      ArrayRef<unsigned> ProcIndices) {
1349   DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices); dbgs() << ") ");
1350 
1351   // Create a seed transition with an empty PredTerm and the expanded sequences
1352   // of SchedWrites for the current SchedClass.
1353   std::vector<PredTransition> LastTransitions;
1354   LastTransitions.resize(1);
1355   LastTransitions.back().ProcIndices.append(ProcIndices.begin(),
1356                                             ProcIndices.end());
1357 
1358   for (unsigned WriteIdx : OperWrites) {
1359     IdxVec WriteSeq;
1360     expandRWSequence(WriteIdx, WriteSeq, /*IsRead=*/false);
1361     unsigned Idx = LastTransitions[0].WriteSequences.size();
1362     LastTransitions[0].WriteSequences.resize(Idx + 1);
1363     SmallVectorImpl<unsigned> &Seq = LastTransitions[0].WriteSequences[Idx];
1364     for (IdxIter WI = WriteSeq.begin(), WE = WriteSeq.end(); WI != WE; ++WI)
1365       Seq.push_back(*WI);
1366     DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") ");
1367   }
1368   DEBUG(dbgs() << " Reads: ");
1369   for (unsigned ReadIdx : OperReads) {
1370     IdxVec ReadSeq;
1371     expandRWSequence(ReadIdx, ReadSeq, /*IsRead=*/true);
1372     unsigned Idx = LastTransitions[0].ReadSequences.size();
1373     LastTransitions[0].ReadSequences.resize(Idx + 1);
1374     SmallVectorImpl<unsigned> &Seq = LastTransitions[0].ReadSequences[Idx];
1375     for (IdxIter RI = ReadSeq.begin(), RE = ReadSeq.end(); RI != RE; ++RI)
1376       Seq.push_back(*RI);
1377     DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") ");
1378   }
1379   DEBUG(dbgs() << '\n');
1380 
1381   // Collect all PredTransitions for individual operands.
1382   // Iterate until no variant writes remain.
1383   while (hasVariant(LastTransitions, *this)) {
1384     PredTransitions Transitions(*this);
1385     for (std::vector<PredTransition>::const_iterator
1386            I = LastTransitions.begin(), E = LastTransitions.end();
1387          I != E; ++I) {
1388       Transitions.substituteVariants(*I);
1389     }
1390     DEBUG(Transitions.dump());
1391     LastTransitions.swap(Transitions.TransVec);
1392   }
1393   // If the first transition has no variants, nothing to do.
1394   if (LastTransitions[0].PredTerm.empty())
1395     return;
1396 
1397   // WARNING: We are about to mutate the SchedClasses vector. Do not refer to
1398   // OperWrites, OperReads, or ProcIndices after calling inferFromTransitions.
1399   inferFromTransitions(LastTransitions, FromClassIdx, *this);
1400 }
1401 
1402 // Check if any processor resource group contains all resource records in
1403 // SubUnits.
1404 bool CodeGenSchedModels::hasSuperGroup(RecVec &SubUnits, CodeGenProcModel &PM) {
1405   for (unsigned i = 0, e = PM.ProcResourceDefs.size(); i < e; ++i) {
1406     if (!PM.ProcResourceDefs[i]->isSubClassOf("ProcResGroup"))
1407       continue;
1408     RecVec SuperUnits =
1409       PM.ProcResourceDefs[i]->getValueAsListOfDefs("Resources");
1410     RecIter RI = SubUnits.begin(), RE = SubUnits.end();
1411     for ( ; RI != RE; ++RI) {
1412       if (!is_contained(SuperUnits, *RI)) {
1413         break;
1414       }
1415     }
1416     if (RI == RE)
1417       return true;
1418   }
1419   return false;
1420 }
1421 
1422 // Verify that overlapping groups have a common supergroup.
1423 void CodeGenSchedModels::verifyProcResourceGroups(CodeGenProcModel &PM) {
1424   for (unsigned i = 0, e = PM.ProcResourceDefs.size(); i < e; ++i) {
1425     if (!PM.ProcResourceDefs[i]->isSubClassOf("ProcResGroup"))
1426       continue;
1427     RecVec CheckUnits =
1428       PM.ProcResourceDefs[i]->getValueAsListOfDefs("Resources");
1429     for (unsigned j = i+1; j < e; ++j) {
1430       if (!PM.ProcResourceDefs[j]->isSubClassOf("ProcResGroup"))
1431         continue;
1432       RecVec OtherUnits =
1433         PM.ProcResourceDefs[j]->getValueAsListOfDefs("Resources");
1434       if (std::find_first_of(CheckUnits.begin(), CheckUnits.end(),
1435                              OtherUnits.begin(), OtherUnits.end())
1436           != CheckUnits.end()) {
1437         // CheckUnits and OtherUnits overlap
1438         OtherUnits.insert(OtherUnits.end(), CheckUnits.begin(),
1439                           CheckUnits.end());
1440         if (!hasSuperGroup(OtherUnits, PM)) {
1441           PrintFatalError((PM.ProcResourceDefs[i])->getLoc(),
1442                           "proc resource group overlaps with "
1443                           + PM.ProcResourceDefs[j]->getName()
1444                           + " but no supergroup contains both.");
1445         }
1446       }
1447     }
1448   }
1449 }
1450 
1451 // Collect and sort WriteRes, ReadAdvance, and ProcResources.
1452 void CodeGenSchedModels::collectProcResources() {
1453   ProcResourceDefs = Records.getAllDerivedDefinitions("ProcResourceUnits");
1454   ProcResGroups = Records.getAllDerivedDefinitions("ProcResGroup");
1455 
1456   // Add any subtarget-specific SchedReadWrites that are directly associated
1457   // with processor resources. Refer to the parent SchedClass's ProcIndices to
1458   // determine which processors they apply to.
1459   for (SchedClassIter SCI = schedClassBegin(), SCE = schedClassEnd();
1460        SCI != SCE; ++SCI) {
1461     if (SCI->ItinClassDef)
1462       collectItinProcResources(SCI->ItinClassDef);
1463     else {
1464       // This class may have a default ReadWrite list which can be overriden by
1465       // InstRW definitions.
1466       if (!SCI->InstRWs.empty()) {
1467         for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
1468              RWI != RWE; ++RWI) {
1469           Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
1470           IdxVec ProcIndices(1, getProcModel(RWModelDef).Index);
1471           IdxVec Writes, Reads;
1472           findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"),
1473                   Writes, Reads);
1474           collectRWResources(Writes, Reads, ProcIndices);
1475         }
1476       }
1477       collectRWResources(SCI->Writes, SCI->Reads, SCI->ProcIndices);
1478     }
1479   }
1480   // Add resources separately defined by each subtarget.
1481   RecVec WRDefs = Records.getAllDerivedDefinitions("WriteRes");
1482   for (RecIter WRI = WRDefs.begin(), WRE = WRDefs.end(); WRI != WRE; ++WRI) {
1483     Record *ModelDef = (*WRI)->getValueAsDef("SchedModel");
1484     addWriteRes(*WRI, getProcModel(ModelDef).Index);
1485   }
1486   RecVec SWRDefs = Records.getAllDerivedDefinitions("SchedWriteRes");
1487   for (RecIter WRI = SWRDefs.begin(), WRE = SWRDefs.end(); WRI != WRE; ++WRI) {
1488     Record *ModelDef = (*WRI)->getValueAsDef("SchedModel");
1489     addWriteRes(*WRI, getProcModel(ModelDef).Index);
1490   }
1491   RecVec RADefs = Records.getAllDerivedDefinitions("ReadAdvance");
1492   for (RecIter RAI = RADefs.begin(), RAE = RADefs.end(); RAI != RAE; ++RAI) {
1493     Record *ModelDef = (*RAI)->getValueAsDef("SchedModel");
1494     addReadAdvance(*RAI, getProcModel(ModelDef).Index);
1495   }
1496   RecVec SRADefs = Records.getAllDerivedDefinitions("SchedReadAdvance");
1497   for (RecIter RAI = SRADefs.begin(), RAE = SRADefs.end(); RAI != RAE; ++RAI) {
1498     if ((*RAI)->getValueInit("SchedModel")->isComplete()) {
1499       Record *ModelDef = (*RAI)->getValueAsDef("SchedModel");
1500       addReadAdvance(*RAI, getProcModel(ModelDef).Index);
1501     }
1502   }
1503   // Add ProcResGroups that are defined within this processor model, which may
1504   // not be directly referenced but may directly specify a buffer size.
1505   RecVec ProcResGroups = Records.getAllDerivedDefinitions("ProcResGroup");
1506   for (Record *PRG : make_range(ProcResGroups.begin(), ProcResGroups.end())) {
1507     if (!PRG->getValueInit("SchedModel")->isComplete())
1508       continue;
1509     CodeGenProcModel &PM = getProcModel(PRG->getValueAsDef("SchedModel"));
1510     if (!is_contained(PM.ProcResourceDefs, PRG))
1511       PM.ProcResourceDefs.push_back(PRG);
1512   }
1513   // Finalize each ProcModel by sorting the record arrays.
1514   for (CodeGenProcModel &PM : ProcModels) {
1515     std::sort(PM.WriteResDefs.begin(), PM.WriteResDefs.end(),
1516               LessRecord());
1517     std::sort(PM.ReadAdvanceDefs.begin(), PM.ReadAdvanceDefs.end(),
1518               LessRecord());
1519     std::sort(PM.ProcResourceDefs.begin(), PM.ProcResourceDefs.end(),
1520               LessRecord());
1521     DEBUG(
1522       PM.dump();
1523       dbgs() << "WriteResDefs: ";
1524       for (RecIter RI = PM.WriteResDefs.begin(),
1525              RE = PM.WriteResDefs.end(); RI != RE; ++RI) {
1526         if ((*RI)->isSubClassOf("WriteRes"))
1527           dbgs() << (*RI)->getValueAsDef("WriteType")->getName() << " ";
1528         else
1529           dbgs() << (*RI)->getName() << " ";
1530       }
1531       dbgs() << "\nReadAdvanceDefs: ";
1532       for (RecIter RI = PM.ReadAdvanceDefs.begin(),
1533              RE = PM.ReadAdvanceDefs.end(); RI != RE; ++RI) {
1534         if ((*RI)->isSubClassOf("ReadAdvance"))
1535           dbgs() << (*RI)->getValueAsDef("ReadType")->getName() << " ";
1536         else
1537           dbgs() << (*RI)->getName() << " ";
1538       }
1539       dbgs() << "\nProcResourceDefs: ";
1540       for (RecIter RI = PM.ProcResourceDefs.begin(),
1541              RE = PM.ProcResourceDefs.end(); RI != RE; ++RI) {
1542         dbgs() << (*RI)->getName() << " ";
1543       }
1544       dbgs() << '\n');
1545     verifyProcResourceGroups(PM);
1546   }
1547 
1548   ProcResourceDefs.clear();
1549   ProcResGroups.clear();
1550 }
1551 
1552 void CodeGenSchedModels::checkCompleteness() {
1553   bool Complete = true;
1554   bool HadCompleteModel = false;
1555   for (const CodeGenProcModel &ProcModel : procModels()) {
1556     if (!ProcModel.ModelDef->getValueAsBit("CompleteModel"))
1557       continue;
1558     for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
1559       if (Inst->hasNoSchedulingInfo)
1560         continue;
1561       if (ProcModel.isUnsupported(*Inst))
1562         continue;
1563       unsigned SCIdx = getSchedClassIdx(*Inst);
1564       if (!SCIdx) {
1565         if (Inst->TheDef->isValueUnset("SchedRW") && !HadCompleteModel) {
1566           PrintError("No schedule information for instruction '"
1567                      + Inst->TheDef->getName() + "'");
1568           Complete = false;
1569         }
1570         continue;
1571       }
1572 
1573       const CodeGenSchedClass &SC = getSchedClass(SCIdx);
1574       if (!SC.Writes.empty())
1575         continue;
1576       if (SC.ItinClassDef != nullptr &&
1577           SC.ItinClassDef->getName() != "NoItinerary")
1578         continue;
1579 
1580       const RecVec &InstRWs = SC.InstRWs;
1581       auto I = find_if(InstRWs, [&ProcModel](const Record *R) {
1582         return R->getValueAsDef("SchedModel") == ProcModel.ModelDef;
1583       });
1584       if (I == InstRWs.end()) {
1585         PrintError("'" + ProcModel.ModelName + "' lacks information for '" +
1586                    Inst->TheDef->getName() + "'");
1587         Complete = false;
1588       }
1589     }
1590     HadCompleteModel = true;
1591   }
1592   if (!Complete) {
1593     errs() << "\n\nIncomplete schedule models found.\n"
1594       << "- Consider setting 'CompleteModel = 0' while developing new models.\n"
1595       << "- Pseudo instructions can be marked with 'hasNoSchedulingInfo = 1'.\n"
1596       << "- Instructions should usually have Sched<[...]> as a superclass, "
1597          "you may temporarily use an empty list.\n"
1598       << "- Instructions related to unsupported features can be excluded with "
1599          "list<Predicate> UnsupportedFeatures = [HasA,..,HasY]; in the "
1600          "processor model.\n\n";
1601     PrintFatalError("Incomplete schedule model");
1602   }
1603 }
1604 
1605 // Collect itinerary class resources for each processor.
1606 void CodeGenSchedModels::collectItinProcResources(Record *ItinClassDef) {
1607   for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) {
1608     const CodeGenProcModel &PM = ProcModels[PIdx];
1609     // For all ItinRW entries.
1610     bool HasMatch = false;
1611     for (RecIter II = PM.ItinRWDefs.begin(), IE = PM.ItinRWDefs.end();
1612          II != IE; ++II) {
1613       RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
1614       if (!std::count(Matched.begin(), Matched.end(), ItinClassDef))
1615         continue;
1616       if (HasMatch)
1617         PrintFatalError((*II)->getLoc(), "Duplicate itinerary class "
1618                         + ItinClassDef->getName()
1619                         + " in ItinResources for " + PM.ModelName);
1620       HasMatch = true;
1621       IdxVec Writes, Reads;
1622       findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
1623       IdxVec ProcIndices(1, PIdx);
1624       collectRWResources(Writes, Reads, ProcIndices);
1625     }
1626   }
1627 }
1628 
1629 void CodeGenSchedModels::collectRWResources(unsigned RWIdx, bool IsRead,
1630                                             ArrayRef<unsigned> ProcIndices) {
1631   const CodeGenSchedRW &SchedRW = getSchedRW(RWIdx, IsRead);
1632   if (SchedRW.TheDef) {
1633     if (!IsRead && SchedRW.TheDef->isSubClassOf("SchedWriteRes")) {
1634       for (unsigned Idx : ProcIndices)
1635         addWriteRes(SchedRW.TheDef, Idx);
1636     }
1637     else if (IsRead && SchedRW.TheDef->isSubClassOf("SchedReadAdvance")) {
1638       for (unsigned Idx : ProcIndices)
1639         addReadAdvance(SchedRW.TheDef, Idx);
1640     }
1641   }
1642   for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
1643        AI != AE; ++AI) {
1644     IdxVec AliasProcIndices;
1645     if ((*AI)->getValueInit("SchedModel")->isComplete()) {
1646       AliasProcIndices.push_back(
1647         getProcModel((*AI)->getValueAsDef("SchedModel")).Index);
1648     }
1649     else
1650       AliasProcIndices = ProcIndices;
1651     const CodeGenSchedRW &AliasRW = getSchedRW((*AI)->getValueAsDef("AliasRW"));
1652     assert(AliasRW.IsRead == IsRead && "cannot alias reads to writes");
1653 
1654     IdxVec ExpandedRWs;
1655     expandRWSequence(AliasRW.Index, ExpandedRWs, IsRead);
1656     for (IdxIter SI = ExpandedRWs.begin(), SE = ExpandedRWs.end();
1657          SI != SE; ++SI) {
1658       collectRWResources(*SI, IsRead, AliasProcIndices);
1659     }
1660   }
1661 }
1662 
1663 // Collect resources for a set of read/write types and processor indices.
1664 void CodeGenSchedModels::collectRWResources(ArrayRef<unsigned> Writes,
1665                                             ArrayRef<unsigned> Reads,
1666                                             ArrayRef<unsigned> ProcIndices) {
1667   for (unsigned Idx : Writes)
1668     collectRWResources(Idx, /*IsRead=*/false, ProcIndices);
1669 
1670   for (unsigned Idx : Reads)
1671     collectRWResources(Idx, /*IsRead=*/true, ProcIndices);
1672 }
1673 
1674 // Find the processor's resource units for this kind of resource.
1675 Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind,
1676                                              const CodeGenProcModel &PM) const {
1677   if (ProcResKind->isSubClassOf("ProcResourceUnits"))
1678     return ProcResKind;
1679 
1680   Record *ProcUnitDef = nullptr;
1681   assert(!ProcResourceDefs.empty());
1682   assert(!ProcResGroups.empty());
1683 
1684   for (Record *ProcResDef : ProcResourceDefs) {
1685     if (ProcResDef->getValueAsDef("Kind") == ProcResKind
1686         && ProcResDef->getValueAsDef("SchedModel") == PM.ModelDef) {
1687       if (ProcUnitDef) {
1688         PrintFatalError(ProcResDef->getLoc(),
1689                         "Multiple ProcessorResourceUnits associated with "
1690                         + ProcResKind->getName());
1691       }
1692       ProcUnitDef = ProcResDef;
1693     }
1694   }
1695   for (Record *ProcResGroup : ProcResGroups) {
1696     if (ProcResGroup == ProcResKind
1697         && ProcResGroup->getValueAsDef("SchedModel") == PM.ModelDef) {
1698       if (ProcUnitDef) {
1699         PrintFatalError((ProcResGroup)->getLoc(),
1700                         "Multiple ProcessorResourceUnits associated with "
1701                         + ProcResKind->getName());
1702       }
1703       ProcUnitDef = ProcResGroup;
1704     }
1705   }
1706   if (!ProcUnitDef) {
1707     PrintFatalError(ProcResKind->getLoc(),
1708                     "No ProcessorResources associated with "
1709                     + ProcResKind->getName());
1710   }
1711   return ProcUnitDef;
1712 }
1713 
1714 // Iteratively add a resource and its super resources.
1715 void CodeGenSchedModels::addProcResource(Record *ProcResKind,
1716                                          CodeGenProcModel &PM) {
1717   while (true) {
1718     Record *ProcResUnits = findProcResUnits(ProcResKind, PM);
1719 
1720     // See if this ProcResource is already associated with this processor.
1721     if (is_contained(PM.ProcResourceDefs, ProcResUnits))
1722       return;
1723 
1724     PM.ProcResourceDefs.push_back(ProcResUnits);
1725     if (ProcResUnits->isSubClassOf("ProcResGroup"))
1726       return;
1727 
1728     if (!ProcResUnits->getValueInit("Super")->isComplete())
1729       return;
1730 
1731     ProcResKind = ProcResUnits->getValueAsDef("Super");
1732   }
1733 }
1734 
1735 // Add resources for a SchedWrite to this processor if they don't exist.
1736 void CodeGenSchedModels::addWriteRes(Record *ProcWriteResDef, unsigned PIdx) {
1737   assert(PIdx && "don't add resources to an invalid Processor model");
1738 
1739   RecVec &WRDefs = ProcModels[PIdx].WriteResDefs;
1740   if (is_contained(WRDefs, ProcWriteResDef))
1741     return;
1742   WRDefs.push_back(ProcWriteResDef);
1743 
1744   // Visit ProcResourceKinds referenced by the newly discovered WriteRes.
1745   RecVec ProcResDefs = ProcWriteResDef->getValueAsListOfDefs("ProcResources");
1746   for (RecIter WritePRI = ProcResDefs.begin(), WritePRE = ProcResDefs.end();
1747        WritePRI != WritePRE; ++WritePRI) {
1748     addProcResource(*WritePRI, ProcModels[PIdx]);
1749   }
1750 }
1751 
1752 // Add resources for a ReadAdvance to this processor if they don't exist.
1753 void CodeGenSchedModels::addReadAdvance(Record *ProcReadAdvanceDef,
1754                                         unsigned PIdx) {
1755   RecVec &RADefs = ProcModels[PIdx].ReadAdvanceDefs;
1756   if (is_contained(RADefs, ProcReadAdvanceDef))
1757     return;
1758   RADefs.push_back(ProcReadAdvanceDef);
1759 }
1760 
1761 unsigned CodeGenProcModel::getProcResourceIdx(Record *PRDef) const {
1762   RecIter PRPos = find(ProcResourceDefs, PRDef);
1763   if (PRPos == ProcResourceDefs.end())
1764     PrintFatalError(PRDef->getLoc(), "ProcResource def is not included in "
1765                     "the ProcResources list for " + ModelName);
1766   // Idx=0 is reserved for invalid.
1767   return 1 + (PRPos - ProcResourceDefs.begin());
1768 }
1769 
1770 bool CodeGenProcModel::isUnsupported(const CodeGenInstruction &Inst) const {
1771   for (const Record *TheDef : UnsupportedFeaturesDefs) {
1772     for (const Record *PredDef : Inst.TheDef->getValueAsListOfDefs("Predicates")) {
1773       if (TheDef->getName() == PredDef->getName())
1774         return true;
1775     }
1776   }
1777   return false;
1778 }
1779 
1780 #ifndef NDEBUG
1781 void CodeGenProcModel::dump() const {
1782   dbgs() << Index << ": " << ModelName << " "
1783          << (ModelDef ? ModelDef->getName() : "inferred") << " "
1784          << (ItinsDef ? ItinsDef->getName() : "no itinerary") << '\n';
1785 }
1786 
1787 void CodeGenSchedRW::dump() const {
1788   dbgs() << Name << (IsVariadic ? " (V) " : " ");
1789   if (IsSequence) {
1790     dbgs() << "(";
1791     dumpIdxVec(Sequence);
1792     dbgs() << ")";
1793   }
1794 }
1795 
1796 void CodeGenSchedClass::dump(const CodeGenSchedModels* SchedModels) const {
1797   dbgs() << "SCHEDCLASS " << Index << ":" << Name << '\n'
1798          << "  Writes: ";
1799   for (unsigned i = 0, N = Writes.size(); i < N; ++i) {
1800     SchedModels->getSchedWrite(Writes[i]).dump();
1801     if (i < N-1) {
1802       dbgs() << '\n';
1803       dbgs().indent(10);
1804     }
1805   }
1806   dbgs() << "\n  Reads: ";
1807   for (unsigned i = 0, N = Reads.size(); i < N; ++i) {
1808     SchedModels->getSchedRead(Reads[i]).dump();
1809     if (i < N-1) {
1810       dbgs() << '\n';
1811       dbgs().indent(10);
1812     }
1813   }
1814   dbgs() << "\n  ProcIdx: "; dumpIdxVec(ProcIndices); dbgs() << '\n';
1815   if (!Transitions.empty()) {
1816     dbgs() << "\n Transitions for Proc ";
1817     for (const CodeGenSchedTransition &Transition : Transitions) {
1818       dumpIdxVec(Transition.ProcIndices);
1819     }
1820   }
1821 }
1822 
1823 void PredTransitions::dump() const {
1824   dbgs() << "Expanded Variants:\n";
1825   for (std::vector<PredTransition>::const_iterator
1826          TI = TransVec.begin(), TE = TransVec.end(); TI != TE; ++TI) {
1827     dbgs() << "{";
1828     for (SmallVectorImpl<PredCheck>::const_iterator
1829            PCI = TI->PredTerm.begin(), PCE = TI->PredTerm.end();
1830          PCI != PCE; ++PCI) {
1831       if (PCI != TI->PredTerm.begin())
1832         dbgs() << ", ";
1833       dbgs() << SchedModels.getSchedRW(PCI->RWIdx, PCI->IsRead).Name
1834              << ":" << PCI->Predicate->getName();
1835     }
1836     dbgs() << "},\n  => {";
1837     for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
1838            WSI = TI->WriteSequences.begin(), WSE = TI->WriteSequences.end();
1839          WSI != WSE; ++WSI) {
1840       dbgs() << "(";
1841       for (SmallVectorImpl<unsigned>::const_iterator
1842              WI = WSI->begin(), WE = WSI->end(); WI != WE; ++WI) {
1843         if (WI != WSI->begin())
1844           dbgs() << ", ";
1845         dbgs() << SchedModels.getSchedWrite(*WI).Name;
1846       }
1847       dbgs() << "),";
1848     }
1849     dbgs() << "}\n";
1850   }
1851 }
1852 #endif // NDEBUG
1853