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