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