CodeGenSchedule.cpp revision 3cbd1786ac06fe751dc4b5ad55e75115cb1d51ce
12661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick//===- CodeGenSchedule.cpp - Scheduling MachineModels ---------------------===//
22661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick//
32661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick//                     The LLVM Compiler Infrastructure
42661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick//
52661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// This file is distributed under the University of Illinois Open Source
62661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// License. See LICENSE.TXT for details.
72661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick//
82661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick//===----------------------------------------------------------------------===//
92661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick//
102661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// This file defines structures to encapsulate the machine model as decribed in
112661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// the target description.
122661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick//
132661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick//===----------------------------------------------------------------------===//
142661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
152661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick#define DEBUG_TYPE "subtarget-emitter"
162661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
172661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick#include "CodeGenSchedule.h"
182661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick#include "CodeGenTarget.h"
1948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick#include "llvm/TableGen/Error.h"
202661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick#include "llvm/Support/Debug.h"
212661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
222661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickusing namespace llvm;
232661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
2448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick#ifndef NDEBUG
2548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickstatic void dumpIdxVec(const IdxVec &V) {
2648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (unsigned i = 0, e = V.size(); i < e; ++i) {
2748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    dbgs() << V[i] << ", ";
2848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
2948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
305e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickstatic void dumpIdxVec(const SmallVectorImpl<unsigned> &V) {
315e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (unsigned i = 0, e = V.size(); i < e; ++i) {
325e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    dbgs() << V[i] << ", ";
335e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
345e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
3548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick#endif
3648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
3748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// CodeGenModels ctor interprets machine model records and populates maps.
382661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew TrickCodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
392661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                       const CodeGenTarget &TGT):
4048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  Records(RK), Target(TGT), NumItineraryClasses(0) {
4148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
4248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Instantiate a CodeGenProcModel for each SchedMachineModel with the values
4348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // that are explicitly referenced in tablegen records. Resources associated
4448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // with each processor will be derived later. Populate ProcModelMap with the
4548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // CodeGenProcModel instances.
4648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  collectProcModels();
4748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
4848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Instantiate a CodeGenSchedRW for each SchedReadWrite record explicitly
4948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // defined, and populate SchedReads and SchedWrites vectors. Implicit
5048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // SchedReadWrites that represent sequences derived from expanded variant will
5148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // be inferred later.
5248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  collectSchedRW();
5348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
5448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Instantiate a CodeGenSchedClass for each unique SchedRW signature directly
5548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // required by an instruction definition, and populate SchedClassIdxMap. Set
5648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // NumItineraryClasses to the number of explicit itinerary classes referenced
5748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // by instructions. Set NumInstrSchedClasses to the number of itinerary
5848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // classes plus any classes implied by instructions that derive from class
5948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Sched and provide SchedRW list. This does not infer any new classes from
6048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // SchedVariant.
6148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  collectSchedClasses();
6248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
6348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Find instruction itineraries for each processor. Sort and populate
6448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // CodeGenProcMode::ItinDefList. (Cycle-to-cycle itineraries). This requires
6548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // all itinerary classes to be discovered.
6648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  collectProcItins();
6748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
6848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Find ItinRW records for each processor and itinerary class.
6948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // (For per-operand resources mapped to itinerary classes).
7048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  collectProcItinRW();
715e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
725e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // Infer new SchedClasses from SchedVariant.
735e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  inferSchedClasses();
745e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
755e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  DEBUG(for (unsigned i = 0; i < SchedClasses.size(); ++i)
765e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          SchedClasses[i].dump(this));
773cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
783cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  // Populate each CodeGenProcModel's WriteResDefs, ReadAdvanceDefs, and
793cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  // ProcResourceDefs.
803cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  collectProcResources();
8148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
8248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
8348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// Gather all processor models.
8448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenSchedModels::collectProcModels() {
8548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  RecVec ProcRecords = Records.getAllDerivedDefinitions("Processor");
8648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  std::sort(ProcRecords.begin(), ProcRecords.end(), LessRecordFieldName());
8748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
8848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Reserve space because we can. Reallocation would be ok.
8948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  ProcModels.reserve(ProcRecords.size()+1);
9048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
9148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Use idx=0 for NoModel/NoItineraries.
9248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  Record *NoModelDef = Records.getDef("NoSchedModel");
9348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  Record *NoItinsDef = Records.getDef("NoItineraries");
9448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  ProcModels.push_back(CodeGenProcModel(0, "NoSchedModel",
9548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                                        NoModelDef, NoItinsDef));
9648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  ProcModelMap[NoModelDef] = 0;
9748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
9848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // For each processor, find a unique machine model.
9948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (unsigned i = 0, N = ProcRecords.size(); i < N; ++i)
10048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    addProcModel(ProcRecords[i]);
10148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
10248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
10348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// Get a unique processor model based on the defined MachineModel and
10448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// ProcessorItineraries.
10548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenSchedModels::addProcModel(Record *ProcDef) {
10648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  Record *ModelKey = getModelOrItinDef(ProcDef);
10748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  if (!ProcModelMap.insert(std::make_pair(ModelKey, ProcModels.size())).second)
10848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    return;
10948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
11048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  std::string Name = ModelKey->getName();
11148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  if (ModelKey->isSubClassOf("SchedMachineModel")) {
11248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    Record *ItinsDef = ModelKey->getValueAsDef("Itineraries");
11348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    ProcModels.push_back(
11448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      CodeGenProcModel(ProcModels.size(), Name, ModelKey, ItinsDef));
11548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
11648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  else {
11748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // An itinerary is defined without a machine model. Infer a new model.
11848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (!ModelKey->getValueAsListOfDefs("IID").empty())
11948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      Name = Name + "Model";
12048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    ProcModels.push_back(
12148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      CodeGenProcModel(ProcModels.size(), Name,
12248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                       ProcDef->getValueAsDef("SchedModel"), ModelKey));
12348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
12448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  DEBUG(ProcModels.back().dump());
12548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
12648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
12748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick// Recursively find all reachable SchedReadWrite records.
12848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickstatic void scanSchedRW(Record *RWDef, RecVec &RWDefs,
12948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                        SmallPtrSet<Record*, 16> &RWSet) {
13048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  if (!RWSet.insert(RWDef))
13148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    return;
13248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  RWDefs.push_back(RWDef);
13348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Reads don't current have sequence records, but it can be added later.
13448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  if (RWDef->isSubClassOf("WriteSequence")) {
13548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    RecVec Seq = RWDef->getValueAsListOfDefs("Writes");
13648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    for (RecIter I = Seq.begin(), E = Seq.end(); I != E; ++I)
13748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      scanSchedRW(*I, RWDefs, RWSet);
13848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
13948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  else if (RWDef->isSubClassOf("SchedVariant")) {
14048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // Visit each variant (guarded by a different predicate).
14148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    RecVec Vars = RWDef->getValueAsListOfDefs("Variants");
14248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    for (RecIter VI = Vars.begin(), VE = Vars.end(); VI != VE; ++VI) {
14348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      // Visit each RW in the sequence selected by the current variant.
14448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      RecVec Selected = (*VI)->getValueAsListOfDefs("Selected");
14548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      for (RecIter I = Selected.begin(), E = Selected.end(); I != E; ++I)
14648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        scanSchedRW(*I, RWDefs, RWSet);
14748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
14848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
14948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
15048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
15148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick// Collect and sort all SchedReadWrites reachable via tablegen records.
15248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick// More may be inferred later when inferring new SchedClasses from variants.
15348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenSchedModels::collectSchedRW() {
15448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Reserve idx=0 for invalid writes/reads.
15548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  SchedWrites.resize(1);
15648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  SchedReads.resize(1);
1572661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
15848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  SmallPtrSet<Record*, 16> RWSet;
1592661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
16048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Find all SchedReadWrites referenced by instruction defs.
16148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  RecVec SWDefs, SRDefs;
16248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
16348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         E = Target.inst_end(); I != E; ++I) {
16448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    Record *SchedDef = (*I)->TheDef;
16548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (!SchedDef->isSubClassOf("Sched"))
16648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      continue;
16748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    RecVec RWs = SchedDef->getValueAsListOfDefs("SchedRW");
16848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    for (RecIter RWI = RWs.begin(), RWE = RWs.end(); RWI != RWE; ++RWI) {
16948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      if ((*RWI)->isSubClassOf("SchedWrite"))
17048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        scanSchedRW(*RWI, SWDefs, RWSet);
17148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      else {
17248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        assert((*RWI)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
17348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        scanSchedRW(*RWI, SRDefs, RWSet);
17448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      }
17548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
17648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
17748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Find all ReadWrites referenced by InstRW.
17848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");
17948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (RecIter OI = InstRWDefs.begin(), OE = InstRWDefs.end(); OI != OE; ++OI) {
18048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // For all OperandReadWrites.
18148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    RecVec RWDefs = (*OI)->getValueAsListOfDefs("OperandReadWrites");
18248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end();
18348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         RWI != RWE; ++RWI) {
18448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      if ((*RWI)->isSubClassOf("SchedWrite"))
18548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        scanSchedRW(*RWI, SWDefs, RWSet);
18648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      else {
18748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        assert((*RWI)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
18848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        scanSchedRW(*RWI, SRDefs, RWSet);
18948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      }
19048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
19148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
19248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Find all ReadWrites referenced by ItinRW.
19348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  RecVec ItinRWDefs = Records.getAllDerivedDefinitions("ItinRW");
19448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (RecIter II = ItinRWDefs.begin(), IE = ItinRWDefs.end(); II != IE; ++II) {
19548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // For all OperandReadWrites.
19648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    RecVec RWDefs = (*II)->getValueAsListOfDefs("OperandReadWrites");
19748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end();
19848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         RWI != RWE; ++RWI) {
19948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      if ((*RWI)->isSubClassOf("SchedWrite"))
20048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        scanSchedRW(*RWI, SWDefs, RWSet);
20148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      else {
20248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        assert((*RWI)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
20348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        scanSchedRW(*RWI, SRDefs, RWSet);
20448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      }
20548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
20648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
20748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Sort and add the SchedReadWrites directly referenced by instructions or
20848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // itinerary resources. Index reads and writes in separate domains.
20948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  std::sort(SWDefs.begin(), SWDefs.end(), LessRecord());
21048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (RecIter SWI = SWDefs.begin(), SWE = SWDefs.end(); SWI != SWE; ++SWI) {
21148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    assert(!getSchedRWIdx(*SWI, /*IsRead=*/false) && "duplicate SchedWrite");
21248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SchedWrites.push_back(CodeGenSchedRW(*SWI));
21348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
21448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  std::sort(SRDefs.begin(), SRDefs.end(), LessRecord());
21548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (RecIter SRI = SRDefs.begin(), SRE = SRDefs.end(); SRI != SRE; ++SRI) {
21648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    assert(!getSchedRWIdx(*SRI, /*IsRead-*/true) && "duplicate SchedWrite");
21748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SchedReads.push_back(CodeGenSchedRW(*SRI));
21848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
21948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Initialize WriteSequence vectors.
22048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (std::vector<CodeGenSchedRW>::iterator WI = SchedWrites.begin(),
22148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         WE = SchedWrites.end(); WI != WE; ++WI) {
22248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (!WI->IsSequence)
22348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      continue;
22448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    findRWs(WI->TheDef->getValueAsListOfDefs("Writes"), WI->Sequence,
22548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick            /*IsRead=*/false);
22648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
22748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  DEBUG(
22848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    for (unsigned WIdx = 0, WEnd = SchedWrites.size(); WIdx != WEnd; ++WIdx) {
22948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      dbgs() << WIdx << ": ";
23048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      SchedWrites[WIdx].dump();
23148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      dbgs() << '\n';
23248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
23348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    for (unsigned RIdx = 0, REnd = SchedReads.size(); RIdx != REnd; ++RIdx) {
23448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      dbgs() << RIdx << ": ";
23548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      SchedReads[RIdx].dump();
23648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      dbgs() << '\n';
23748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
23848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    RecVec RWDefs = Records.getAllDerivedDefinitions("SchedReadWrite");
23948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    for (RecIter RI = RWDefs.begin(), RE = RWDefs.end();
24048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         RI != RE; ++RI) {
24148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      if (!getSchedRWIdx(*RI, (*RI)->isSubClassOf("SchedRead"))) {
24248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        const std::string &Name = (*RI)->getName();
24348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        if (Name != "NoWrite" && Name != "ReadDefault")
24448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick          dbgs() << "Unused SchedReadWrite " << (*RI)->getName() << '\n';
24548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      }
24648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    });
24748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
24848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
24948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// Compute a SchedWrite name from a sequence of writes.
25048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickstd::string CodeGenSchedModels::genRWName(const IdxVec& Seq, bool IsRead) {
25148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  std::string Name("(");
25248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (IdxIter I = Seq.begin(), E = Seq.end(); I != E; ++I) {
25348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (I != Seq.begin())
25448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      Name += '_';
25548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    Name += getSchedRW(*I, IsRead).Name;
25648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
25748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  Name += ')';
25848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  return Name;
25948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
26048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
26148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickunsigned CodeGenSchedModels::getSchedRWIdx(Record *Def, bool IsRead,
26248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                                           unsigned After) const {
26348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  const std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites;
26448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  assert(After < RWVec.size() && "start position out of bounds");
26548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (std::vector<CodeGenSchedRW>::const_iterator I = RWVec.begin() + After,
26648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         E = RWVec.end(); I != E; ++I) {
26748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (I->TheDef == Def)
26848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      return I - RWVec.begin();
26948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
27048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  return 0;
27148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
27248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
27348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Tricknamespace llvm {
27448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid splitSchedReadWrites(const RecVec &RWDefs,
27548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                          RecVec &WriteDefs, RecVec &ReadDefs) {
27648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); RWI != RWE; ++RWI) {
27748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if ((*RWI)->isSubClassOf("SchedWrite"))
27848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      WriteDefs.push_back(*RWI);
27948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    else {
28048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      assert((*RWI)->isSubClassOf("SchedRead") && "unknown SchedReadWrite");
28148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      ReadDefs.push_back(*RWI);
28248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
28348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
28448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
28548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick} // namespace llvm
28648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
28748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick// Split the SchedReadWrites defs and call findRWs for each list.
28848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenSchedModels::findRWs(const RecVec &RWDefs,
28948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                                 IdxVec &Writes, IdxVec &Reads) const {
29048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    RecVec WriteDefs;
29148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    RecVec ReadDefs;
29248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    splitSchedReadWrites(RWDefs, WriteDefs, ReadDefs);
29348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    findRWs(WriteDefs, Writes, false);
29448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    findRWs(ReadDefs, Reads, true);
29548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
29648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
29748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick// Call getSchedRWIdx for all elements in a sequence of SchedRW defs.
29848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenSchedModels::findRWs(const RecVec &RWDefs, IdxVec &RWs,
29948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                                 bool IsRead) const {
30048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (RecIter RI = RWDefs.begin(), RE = RWDefs.end(); RI != RE; ++RI) {
30148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    unsigned Idx = getSchedRWIdx(*RI, IsRead);
30248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    assert(Idx && "failed to collect SchedReadWrite");
30348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    RWs.push_back(Idx);
30448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
3052661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick}
3062661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
3075e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickvoid CodeGenSchedModels::expandRWSequence(unsigned RWIdx, IdxVec &RWSeq,
3085e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                          bool IsRead) const {
3095e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  const CodeGenSchedRW &SchedRW = getSchedRW(RWIdx, IsRead);
3105e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  if (!SchedRW.IsSequence) {
3115e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    RWSeq.push_back(RWIdx);
3125e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    return;
3135e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
3145e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  int Repeat =
3155e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    SchedRW.TheDef ? SchedRW.TheDef->getValueAsInt("Repeat") : 1;
3165e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (int i = 0; i < Repeat; ++i) {
3175e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (IdxIter I = SchedRW.Sequence.begin(), E = SchedRW.Sequence.end();
3185e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         I != E; ++I) {
3195e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      expandRWSequence(*I, RWSeq, IsRead);
3205e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
3215e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
3225e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
3235e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
3245e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// Find the existing SchedWrite that models this sequence of writes.
3255e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickunsigned CodeGenSchedModels::findRWForSequence(const IdxVec &Seq,
3265e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                               bool IsRead) {
3275e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites;
3285e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
3295e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (std::vector<CodeGenSchedRW>::iterator I = RWVec.begin(), E = RWVec.end();
3305e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick       I != E; ++I) {
3315e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    if (I->Sequence == Seq)
3325e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      return I - RWVec.begin();
3335e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
3345e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // Index zero reserved for invalid RW.
3355e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  return 0;
3365e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
3375e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
3385e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick/// Add this ReadWrite if it doesn't already exist.
3395e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickunsigned CodeGenSchedModels::findOrInsertRW(ArrayRef<unsigned> Seq,
3405e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                            bool IsRead) {
3415e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  assert(!Seq.empty() && "cannot insert empty sequence");
3425e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  if (Seq.size() == 1)
3435e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    return Seq.back();
3445e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
3455e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  unsigned Idx = findRWForSequence(Seq, IsRead);
3465e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  if (Idx)
3475e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    return Idx;
3485e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
3495e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  CodeGenSchedRW SchedRW(Seq, genRWName(Seq, IsRead));
3505e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  if (IsRead) {
3515e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    SchedReads.push_back(SchedRW);
3525e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    return SchedReads.size() - 1;
3535e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
3545e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  SchedWrites.push_back(SchedRW);
3555e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  return SchedWrites.size() - 1;
3565e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
3575e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
35848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// Visit all the instruction definitions for this target to gather and
35948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// enumerate the itinerary classes. These are the explicitly specified
36048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// SchedClasses. More SchedClasses may be inferred.
36148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenSchedModels::collectSchedClasses() {
3622661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
36348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // NoItinerary is always the first class at Idx=0
3642661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  SchedClasses.resize(1);
3652661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  SchedClasses.back().Name = "NoItinerary";
36648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  SchedClasses.back().ProcIndices.push_back(0);
3672661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  SchedClassIdxMap[SchedClasses.back().Name] = 0;
3682661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
3692661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // Gather and sort all itinerary classes used by instruction descriptions.
37048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  RecVec ItinClassList;
3712661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
3722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         E = Target.inst_end(); I != E; ++I) {
37348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    Record *ItinDef = (*I)->TheDef->getValueAsDef("Itinerary");
3742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Map a new SchedClass with no index.
37548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (!SchedClassIdxMap.count(ItinDef->getName())) {
37648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      SchedClassIdxMap[ItinDef->getName()] = 0;
37748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      ItinClassList.push_back(ItinDef);
3782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    }
3792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  }
3802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // Assign each itinerary class unique number, skipping NoItinerary==0
3812661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  NumItineraryClasses = ItinClassList.size();
3822661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord());
3832661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (unsigned i = 0, N = NumItineraryClasses; i < N; i++) {
3842661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    Record *ItinDef = ItinClassList[i];
3852661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    SchedClassIdxMap[ItinDef->getName()] = SchedClasses.size();
3862661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    SchedClasses.push_back(CodeGenSchedClass(ItinDef));
3872661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  }
38848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Infer classes from SchedReadWrite resources listed for each
38948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // instruction definition that inherits from class Sched.
39048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
39148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         E = Target.inst_end(); I != E; ++I) {
39248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (!(*I)->TheDef->isSubClassOf("Sched"))
39348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      continue;
39448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    IdxVec Writes, Reads;
39548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads);
39648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // ProcIdx == 0 indicates the class applies to all processors.
39748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    IdxVec ProcIndices(1, 0);
39848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    addSchedClass(Writes, Reads, ProcIndices);
39948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
40048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Create classes for InstReadWrite defs.
40148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");
40248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  std::sort(InstRWDefs.begin(), InstRWDefs.end(), LessRecord());
40348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (RecIter OI = InstRWDefs.begin(), OE = InstRWDefs.end(); OI != OE; ++OI)
40448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    createInstRWClass(*OI);
4052661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
40648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  NumInstrSchedClasses = SchedClasses.size();
40748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
40848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  bool EnableDump = false;
40948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  DEBUG(EnableDump = true);
41048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  if (!EnableDump)
41148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    return;
41248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
41348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         E = Target.inst_end(); I != E; ++I) {
41448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    Record *SchedDef = (*I)->TheDef;
41548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    std::string InstName = (*I)->TheDef->getName();
41648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (SchedDef->isSubClassOf("Sched")) {
41748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      IdxVec Writes;
41848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      IdxVec Reads;
41948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads);
42048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      dbgs() << "SchedRW machine model for " << InstName;
42148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI)
42248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        dbgs() << " " << SchedWrites[*WI].Name;
42348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI)
42448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        dbgs() << " " << SchedReads[*RI].Name;
42548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      dbgs() << '\n';
42648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
42748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    unsigned SCIdx = InstrClassMap.lookup((*I)->TheDef);
42848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (SCIdx) {
42948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs;
43048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end();
43148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick           RWI != RWE; ++RWI) {
43248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        const CodeGenProcModel &ProcModel =
43348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick          getProcModel((*RWI)->getValueAsDef("SchedModel"));
43448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        dbgs() << "InstrRW on " << ProcModel.ModelName << " for " << InstName;
43548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        IdxVec Writes;
43648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        IdxVec Reads;
43748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"),
43848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                Writes, Reads);
43948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI)
44048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick          dbgs() << " " << SchedWrites[*WI].Name;
44148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI)
44248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick          dbgs() << " " << SchedReads[*RI].Name;
44348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        dbgs() << '\n';
44448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      }
44548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      continue;
44648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
44748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (!SchedDef->isSubClassOf("Sched")
44848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        && (SchedDef->getValueAsDef("Itinerary")->getName() == "NoItinerary")) {
44948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      dbgs() << "No machine model for " << (*I)->TheDef->getName() << '\n';
45048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
45148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
4522661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick}
4532661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
45448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickunsigned CodeGenSchedModels::getSchedClassIdx(
45548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  const RecVec &RWDefs) const {
4562661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
45748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  IdxVec Writes, Reads;
45848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  findRWs(RWDefs, Writes, Reads);
45948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  return findSchedClassIdx(Writes, Reads);
46048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
4612661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
46248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// Find an SchedClass that has been inferred from a per-operand list of
46348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// SchedWrites and SchedReads.
46448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickunsigned CodeGenSchedModels::findSchedClassIdx(const IdxVec &Writes,
46548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                                               const IdxVec &Reads) const {
46648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (SchedClassIter I = schedClassBegin(), E = schedClassEnd(); I != E; ++I) {
46748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // Classes with InstRWs may have the same Writes/Reads as a class originally
46848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // produced by a SchedRW definition. We need to be able to recover the
46948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // original class index for processors that don't match any InstRWs.
47048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (I->ItinClassDef || !I->InstRWs.empty())
47148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      continue;
47248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
47348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (I->Writes == Writes && I->Reads == Reads) {
47448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      return I - schedClassBegin();
47548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
47648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
47748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  return 0;
4782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick}
4792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
48048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick// Get the SchedClass index for an instruction.
48148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickunsigned CodeGenSchedModels::getSchedClassIdx(
48248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  const CodeGenInstruction &Inst) const {
4832661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
48448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  unsigned SCIdx = InstrClassMap.lookup(Inst.TheDef);
48548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  if (SCIdx)
48648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    return SCIdx;
4872661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
48848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // If this opcode isn't mapped by the subtarget fallback to the instruction
48948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // definition's SchedRW or ItinDef values.
49048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  if (Inst.TheDef->isSubClassOf("Sched")) {
49148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    RecVec RWs = Inst.TheDef->getValueAsListOfDefs("SchedRW");
49248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    return getSchedClassIdx(RWs);
49348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
49448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  Record *ItinDef = Inst.TheDef->getValueAsDef("Itinerary");
49548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  assert(SchedClassIdxMap.count(ItinDef->getName()) && "missing ItinClass");
49648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  unsigned Idx = SchedClassIdxMap.lookup(ItinDef->getName());
49748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  assert(Idx <= NumItineraryClasses && "bad ItinClass index");
49848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  return Idx;
49948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
5002661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
50148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickstd::string CodeGenSchedModels::createSchedClassName(
50248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  const IdxVec &OperWrites, const IdxVec &OperReads) {
50348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
50448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  std::string Name;
50548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (IdxIter WI = OperWrites.begin(), WE = OperWrites.end(); WI != WE; ++WI) {
50648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (WI != OperWrites.begin())
50748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      Name += '_';
50848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    Name += SchedWrites[*WI].Name;
5092661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  }
51048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (IdxIter RI = OperReads.begin(), RE = OperReads.end(); RI != RE; ++RI) {
51148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    Name += '_';
51248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    Name += SchedReads[*RI].Name;
5132661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  }
51448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  return Name;
51548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
5162661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
51748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickstd::string CodeGenSchedModels::createSchedClassName(const RecVec &InstDefs) {
5182661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
51948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  std::string Name;
52048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (RecIter I = InstDefs.begin(), E = InstDefs.end(); I != E; ++I) {
52148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (I != InstDefs.begin())
52248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      Name += '_';
52348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    Name += (*I)->getName();
52448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
52548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  return Name;
52648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
52748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
52848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// Add an inferred sched class from a per-operand list of SchedWrites and
52948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// SchedReads. ProcIndices contains the set of IDs of processors that may
53048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick/// utilize this class.
53148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickunsigned CodeGenSchedModels::addSchedClass(const IdxVec &OperWrites,
53248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                                           const IdxVec &OperReads,
53348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                                           const IdxVec &ProcIndices)
53448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick{
53548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  assert(!ProcIndices.empty() && "expect at least one ProcIdx");
53648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
53748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  unsigned Idx = findSchedClassIdx(OperWrites, OperReads);
53848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  if (Idx) {
53948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    IdxVec PI;
54048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    std::set_union(SchedClasses[Idx].ProcIndices.begin(),
54148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                   SchedClasses[Idx].ProcIndices.end(),
54248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                   ProcIndices.begin(), ProcIndices.end(),
54348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                   std::back_inserter(PI));
54448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SchedClasses[Idx].ProcIndices.swap(PI);
54548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    return Idx;
54648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
54748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  Idx = SchedClasses.size();
54848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  SchedClasses.resize(Idx+1);
54948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  CodeGenSchedClass &SC = SchedClasses.back();
55048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  SC.Name = createSchedClassName(OperWrites, OperReads);
55148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  SC.Writes = OperWrites;
55248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  SC.Reads = OperReads;
55348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  SC.ProcIndices = ProcIndices;
5542661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
55548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  return Idx;
55648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
55748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
55848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick// Create classes for each set of opcodes that are in the same InstReadWrite
55948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick// definition across all processors.
56048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
56148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // ClassInstrs will hold an entry for each subset of Instrs in InstRWDef that
56248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // intersects with an existing class via a previous InstRWDef. Instrs that do
56348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // not intersect with an existing class refer back to their former class as
56448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // determined from ItinDef or SchedRW.
56548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  SmallVector<std::pair<unsigned, SmallVector<Record *, 8> >, 4> ClassInstrs;
56648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // Sort Instrs into sets.
56748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  RecVec InstDefs = InstRWDef->getValueAsListOfDefs("Instrs");
56848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  std::sort(InstDefs.begin(), InstDefs.end(), LessRecord());
56948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (RecIter I = InstDefs.begin(), E = InstDefs.end(); I != E; ++I) {
57048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    unsigned SCIdx = 0;
57148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    InstClassMapTy::const_iterator Pos = InstrClassMap.find(*I);
57248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (Pos != InstrClassMap.end())
57348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      SCIdx = Pos->second;
57448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    else {
57548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      // This instruction has not been mapped yet. Get the original class. All
57648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      // instructions in the same InstrRW class must be from the same original
57748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      // class because that is the fall-back class for other processors.
57848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      Record *ItinDef = (*I)->getValueAsDef("Itinerary");
57948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      SCIdx = SchedClassIdxMap.lookup(ItinDef->getName());
58048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      if (!SCIdx && (*I)->isSubClassOf("Sched"))
58148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        SCIdx = getSchedClassIdx((*I)->getValueAsListOfDefs("SchedRW"));
58248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
58348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    unsigned CIdx = 0, CEnd = ClassInstrs.size();
58448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    for (; CIdx != CEnd; ++CIdx) {
58548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      if (ClassInstrs[CIdx].first == SCIdx)
58648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        break;
58748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
58848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (CIdx == CEnd) {
58948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      ClassInstrs.resize(CEnd + 1);
59048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      ClassInstrs[CIdx].first = SCIdx;
59148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
59248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    ClassInstrs[CIdx].second.push_back(*I);
59348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
59448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // For each set of Instrs, create a new class if necessary, and map or remap
59548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  // the Instrs to it.
59648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  unsigned CIdx = 0, CEnd = ClassInstrs.size();
59748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (; CIdx != CEnd; ++CIdx) {
59848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    unsigned OldSCIdx = ClassInstrs[CIdx].first;
59948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    ArrayRef<Record*> InstDefs = ClassInstrs[CIdx].second;
60048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // If the all instrs in the current class are accounted for, then leave
60148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // them mapped to their old class.
60248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (SchedClasses[OldSCIdx].InstRWs.size() == InstDefs.size()) {
60348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      assert(SchedClasses[OldSCIdx].ProcIndices[0] == 0 &&
60448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick             "expected a generic SchedClass");
60548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      continue;
60648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
60748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    unsigned SCIdx = SchedClasses.size();
60848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SchedClasses.resize(SCIdx+1);
60948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    CodeGenSchedClass &SC = SchedClasses.back();
61048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SC.Name = createSchedClassName(InstDefs);
61148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // Preserve ItinDef and Writes/Reads for processors without an InstRW entry.
61248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SC.ItinClassDef = SchedClasses[OldSCIdx].ItinClassDef;
61348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SC.Writes = SchedClasses[OldSCIdx].Writes;
61448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SC.Reads = SchedClasses[OldSCIdx].Reads;
61548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SC.ProcIndices.push_back(0);
61648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // Map each Instr to this new class.
61748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // Note that InstDefs may be a smaller list than InstRWDef's "Instrs".
61848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    for (ArrayRef<Record*>::const_iterator
61948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick           II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) {
62048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      unsigned OldSCIdx = InstrClassMap[*II];
62148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      if (OldSCIdx) {
62248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        SC.InstRWs.insert(SC.InstRWs.end(),
62348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                          SchedClasses[OldSCIdx].InstRWs.begin(),
62448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                          SchedClasses[OldSCIdx].InstRWs.end());
62548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      }
62648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      InstrClassMap[*II] = SCIdx;
62748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
62848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SC.InstRWs.push_back(InstRWDef);
62948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
6302661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick}
6312661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
6322661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// Gather the processor itineraries.
63348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenSchedModels::collectProcItins() {
63448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(),
63548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         PE = ProcModels.end(); PI != PE; ++PI) {
63648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    CodeGenProcModel &ProcModel = *PI;
63748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    RecVec ItinRecords = ProcModel.ItinsDef->getValueAsListOfDefs("IID");
63848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // Skip empty itinerary.
63948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (ItinRecords.empty())
64048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      continue;
6412661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
64248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    ProcModel.ItinDefList.resize(NumItineraryClasses+1);
6432661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
64448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // Insert each itinerary data record in the correct position within
64548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // the processor model's ItinDefList.
64648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    for (unsigned i = 0, N = ItinRecords.size(); i < N; i++) {
64748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      Record *ItinData = ItinRecords[i];
64848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      Record *ItinDef = ItinData->getValueAsDef("TheClass");
64948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      if (!SchedClassIdxMap.count(ItinDef->getName())) {
65048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        DEBUG(dbgs() << ProcModel.ItinsDef->getName()
65148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick              << " has unused itinerary class " << ItinDef->getName() << '\n');
65248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        continue;
65348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      }
65448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      assert(SchedClassIdxMap.count(ItinDef->getName()) && "missing ItinClass");
65548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      unsigned Idx = SchedClassIdxMap.lookup(ItinDef->getName());
65648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      assert(Idx <= NumItineraryClasses && "bad ItinClass index");
65748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      ProcModel.ItinDefList[Idx] = ItinData;
65848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
65948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    // Check for missing itinerary entries.
66048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    assert(!ProcModel.ItinDefList[0] && "NoItinerary class can't have rec");
66148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    DEBUG(
66248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      for (unsigned i = 1, N = ProcModel.ItinDefList.size(); i < N; ++i) {
66348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick        if (!ProcModel.ItinDefList[i])
66448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick          dbgs() << ProcModel.ItinsDef->getName()
66548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                 << " missing itinerary for class "
66648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                 << SchedClasses[i].Name << '\n';
66748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      });
66848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
66948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
6702661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
67148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick// Gather the read/write types for each itinerary class.
67248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenSchedModels::collectProcItinRW() {
67348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  RecVec ItinRWDefs = Records.getAllDerivedDefinitions("ItinRW");
67448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  std::sort(ItinRWDefs.begin(), ItinRWDefs.end(), LessRecord());
67548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (RecIter II = ItinRWDefs.begin(), IE = ItinRWDefs.end(); II != IE; ++II) {
67648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (!(*II)->getValueInit("SchedModel")->isComplete())
67748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      throw TGError((*II)->getLoc(), "SchedModel is undefined");
67848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    Record *ModelDef = (*II)->getValueAsDef("SchedModel");
67948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
68048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (I == ProcModelMap.end()) {
68148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      throw TGError((*II)->getLoc(), "Undefined SchedMachineModel "
68248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick                    + ModelDef->getName());
6832661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    }
68448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    ProcModels[I->second].ItinRWDefs.push_back(*II);
6852661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  }
68648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
68748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
6885e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick/// Infer new classes from existing classes. In the process, this may create new
6895e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick/// SchedWrites from sequences of existing SchedWrites.
6905e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickvoid CodeGenSchedModels::inferSchedClasses() {
6915e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // Visit all existing classes and newly created classes.
6925e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (unsigned Idx = 0; Idx != SchedClasses.size(); ++Idx) {
6935e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    if (SchedClasses[Idx].ItinClassDef)
6945e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      inferFromItinClass(SchedClasses[Idx].ItinClassDef, Idx);
6955e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    else if (!SchedClasses[Idx].InstRWs.empty())
6965e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      inferFromInstRWs(Idx);
6975e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    else {
6985e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      inferFromRW(SchedClasses[Idx].Writes, SchedClasses[Idx].Reads,
6995e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                  Idx, SchedClasses[Idx].ProcIndices);
7005e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
7015e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    assert(SchedClasses.size() < (NumInstrSchedClasses*6) &&
7025e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           "too many SchedVariants");
7035e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
7045e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
7055e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7065e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick/// Infer classes from per-processor itinerary resources.
7075e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickvoid CodeGenSchedModels::inferFromItinClass(Record *ItinClassDef,
7085e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                            unsigned FromClassIdx) {
7095e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) {
7105e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    const CodeGenProcModel &PM = ProcModels[PIdx];
7115e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // For all ItinRW entries.
7125e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    bool HasMatch = false;
7135e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (RecIter II = PM.ItinRWDefs.begin(), IE = PM.ItinRWDefs.end();
7145e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         II != IE; ++II) {
7155e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
7165e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      if (!std::count(Matched.begin(), Matched.end(), ItinClassDef))
7175e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        continue;
7185e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      if (HasMatch)
7195e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        throw TGError((*II)->getLoc(), "Duplicate itinerary class "
7205e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                      + ItinClassDef->getName()
7215e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                      + " in ItinResources for " + PM.ModelName);
7225e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      HasMatch = true;
7235e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      IdxVec Writes, Reads;
7245e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
7255e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      IdxVec ProcIndices(1, PIdx);
7265e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      inferFromRW(Writes, Reads, FromClassIdx, ProcIndices);
7275e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
7285e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
7295e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
7305e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7315e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick/// Infer classes from per-processor InstReadWrite definitions.
7325e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickvoid CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) {
7335e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs;
7345e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); RWI != RWE; ++RWI) {
7355e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    RecVec Instrs = (*RWI)->getValueAsListOfDefs("Instrs");
7365e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    RecIter II = Instrs.begin(), IE = Instrs.end();
7375e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (; II != IE; ++II) {
7385e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      if (InstrClassMap[*II] == SCIdx)
7395e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        break;
7405e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
7415e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // If this class no longer has any instructions mapped to it, it has become
7425e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // irrelevant.
7435e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    if (II == IE)
7445e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      continue;
7455e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    IdxVec Writes, Reads;
7465e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
7475e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    unsigned PIdx = getProcModel((*RWI)->getValueAsDef("SchedModel")).Index;
7485e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    IdxVec ProcIndices(1, PIdx);
7495e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    inferFromRW(Writes, Reads, SCIdx, ProcIndices);
7505e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
7515e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
7525e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7535e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Tricknamespace {
7545e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// Associate a predicate with the SchedReadWrite that it guards.
7555e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// RWIdx is the index of the read/write variant.
7565e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickstruct PredCheck {
7575e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  bool IsRead;
7585e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  unsigned RWIdx;
7595e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  Record *Predicate;
7605e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7615e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  PredCheck(bool r, unsigned w, Record *p): IsRead(r), RWIdx(w), Predicate(p) {}
7625e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick};
7635e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7645e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// A Predicate transition is a list of RW sequences guarded by a PredTerm.
7655e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickstruct PredTransition {
7665e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // A predicate term is a conjunction of PredChecks.
7675e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  SmallVector<PredCheck, 4> PredTerm;
7685e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  SmallVector<SmallVector<unsigned,4>, 16> WriteSequences;
7695e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  SmallVector<SmallVector<unsigned,4>, 16> ReadSequences;
7705e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick};
7715e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7725e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// Encapsulate a set of partially constructed transitions.
7735e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// The results are built by repeated calls to substituteVariants.
7745e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickclass PredTransitions {
7755e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  CodeGenSchedModels &SchedModels;
7765e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7775e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickpublic:
7785e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  std::vector<PredTransition> TransVec;
7795e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7805e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  PredTransitions(CodeGenSchedModels &sm): SchedModels(sm) {}
7815e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7825e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  void substituteVariantOperand(const SmallVectorImpl<unsigned> &RWSeq,
7835e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                bool IsRead, unsigned StartIdx);
7845e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7855e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  void substituteVariants(const PredTransition &Trans);
7865e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7875e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick#ifndef NDEBUG
7885e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  void dump() const;
7895e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick#endif
7905e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7915e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickprivate:
7925e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  bool mutuallyExclusive(Record *PredDef, ArrayRef<PredCheck> Term);
7935e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  void pushVariant(unsigned SchedRW, Record *Variant, PredTransition &Trans,
7945e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                   bool IsRead);
7955e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick};
7965e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick} // anonymous
7975e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
7985e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// Return true if this predicate is mutually exclusive with a PredTerm. This
7995e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// degenerates into checking if the predicate is mutually exclusive with any
8005e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// predicate in the Term's conjunction.
8015e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick//
8025e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// All predicates associated with a given SchedRW are considered mutually
8035e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// exclusive. This should work even if the conditions expressed by the
8045e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// predicates are not exclusive because the predicates for a given SchedWrite
8055e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// are always checked in the order they are defined in the .td file. Later
8065e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// conditions implicitly negate any prior condition.
8075e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickbool PredTransitions::mutuallyExclusive(Record *PredDef,
8085e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                        ArrayRef<PredCheck> Term) {
8095e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
8105e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (ArrayRef<PredCheck>::iterator I = Term.begin(), E = Term.end();
8115e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick       I != E; ++I) {
8125e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    if (I->Predicate == PredDef)
8135e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      return false;
8145e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
8155e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(I->RWIdx, I->IsRead);
8165e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    assert(SchedRW.HasVariants && "PredCheck must refer to a SchedVariant");
8175e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    RecVec Variants = SchedRW.TheDef->getValueAsListOfDefs("Variants");
8185e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (RecIter VI = Variants.begin(), VE = Variants.end(); VI != VE; ++VI) {
8195e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      if ((*VI)->getValueAsDef("Predicate") == PredDef)
8205e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        return true;
8215e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
8225e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
8235e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  return false;
8245e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
8255e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
8265e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// Push the Reads/Writes selected by this variant onto the given PredTransition.
8275e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickvoid PredTransitions::pushVariant(unsigned RWIdx, Record *Variant,
8285e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                  PredTransition &Trans, bool IsRead) {
8295e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  Trans.PredTerm.push_back(
8305e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    PredCheck(IsRead, RWIdx, Variant->getValueAsDef("Predicate")));
8315e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  RecVec SelectedDefs = Variant->getValueAsListOfDefs("Selected");
8325e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  IdxVec SelectedRWs;
8335e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  SchedModels.findRWs(SelectedDefs, SelectedRWs, IsRead);
8345e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
8355e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(RWIdx, IsRead);
8365e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
8375e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  SmallVectorImpl<SmallVector<unsigned,4> > &RWSequences = IsRead
8385e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    ? Trans.ReadSequences : Trans.WriteSequences;
8395e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  if (SchedRW.IsVariadic) {
8405e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    unsigned OperIdx = RWSequences.size()-1;
8415e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // Make N-1 copies of this transition's last sequence.
8425e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (unsigned i = 1, e = SelectedRWs.size(); i != e; ++i) {
8435e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      RWSequences.push_back(RWSequences[OperIdx]);
8445e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
8455e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // Push each of the N elements of the SelectedRWs onto a copy of the last
8465e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // sequence (split the current operand into N operands).
8475e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // Note that write sequences should be expanded within this loop--the entire
8485e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // sequence belongs to a single operand.
8495e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (IdxIter RWI = SelectedRWs.begin(), RWE = SelectedRWs.end();
8505e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         RWI != RWE; ++RWI, ++OperIdx) {
8515e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      IdxVec ExpandedRWs;
8525e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      if (IsRead)
8535e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        ExpandedRWs.push_back(*RWI);
8545e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      else
8555e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        SchedModels.expandRWSequence(*RWI, ExpandedRWs, IsRead);
8565e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      RWSequences[OperIdx].insert(RWSequences[OperIdx].end(),
8575e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                  ExpandedRWs.begin(), ExpandedRWs.end());
8585e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
8595e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    assert(OperIdx == RWSequences.size() && "missed a sequence");
8605e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
8615e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  else {
8625e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // Push this transition's expanded sequence onto this transition's last
8635e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // sequence (add to the current operand's sequence).
8645e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    SmallVectorImpl<unsigned> &Seq = RWSequences.back();
8655e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    IdxVec ExpandedRWs;
8665e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (IdxIter RWI = SelectedRWs.begin(), RWE = SelectedRWs.end();
8675e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         RWI != RWE; ++RWI) {
8685e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      if (IsRead)
8695e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        ExpandedRWs.push_back(*RWI);
8705e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      else
8715e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        SchedModels.expandRWSequence(*RWI, ExpandedRWs, IsRead);
8725e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
8735e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    Seq.insert(Seq.end(), ExpandedRWs.begin(), ExpandedRWs.end());
8745e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
8755e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
8765e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
8775e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// RWSeq is a sequence of all Reads or all Writes for the next read or write
8785e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// operand. StartIdx is an index into TransVec where partial results
8795e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// starts. RWSeq must be applied to all tranistions between StartIdx and the end
8805e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// of TransVec.
8815e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickvoid PredTransitions::substituteVariantOperand(
8825e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  const SmallVectorImpl<unsigned> &RWSeq, bool IsRead, unsigned StartIdx) {
8835e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
8845e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // Visit each original RW within the current sequence.
8855e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (SmallVectorImpl<unsigned>::const_iterator
8865e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         RWI = RWSeq.begin(), RWE = RWSeq.end(); RWI != RWE; ++RWI) {
8875e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(*RWI, IsRead);
8885e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // Push this RW on all partial PredTransitions or distribute variants.
8895e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // New PredTransitions may be pushed within this loop which should not be
8905e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // revisited (TransEnd must be loop invariant).
8915e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (unsigned TransIdx = StartIdx, TransEnd = TransVec.size();
8925e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         TransIdx != TransEnd; ++TransIdx) {
8935e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      // In the common case, push RW onto the current operand's sequence.
8945e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      if (!SchedRW.HasVariants) {
8955e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        if (IsRead)
8965e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          TransVec[TransIdx].ReadSequences.back().push_back(*RWI);
8975e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        else
8985e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          TransVec[TransIdx].WriteSequences.back().push_back(*RWI);
8995e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        continue;
9005e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      }
9015e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      // Distribute this partial PredTransition across intersecting variants.
9025e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      RecVec Variants = SchedRW.TheDef->getValueAsListOfDefs("Variants");
9035e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      std::vector<std::pair<Record*,unsigned> > IntersectingVariants;
9045e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      for (RecIter VI = Variants.begin(), VE = Variants.end(); VI != VE; ++VI) {
9055e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        Record *PredDef = (*VI)->getValueAsDef("Predicate");
9065e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        if (mutuallyExclusive(PredDef, TransVec[TransIdx].PredTerm))
9075e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          continue;
9085e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        if (IntersectingVariants.empty())
9095e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          // The first variant builds on the existing transition.
9105e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          IntersectingVariants.push_back(std::make_pair(*VI, TransIdx));
9115e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        else {
9125e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          // Push another copy of the current transition for more variants.
9135e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          IntersectingVariants.push_back(
9145e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick            std::make_pair(*VI, TransVec.size()));
9155e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          TransVec.push_back(TransVec[TransIdx]);
9165e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        }
9175e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      }
9185e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      // Now expand each variant on top of its copy of the transition.
9195e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      for (std::vector<std::pair<Record*, unsigned> >::const_iterator
9205e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick             IVI = IntersectingVariants.begin(),
9215e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick             IVE = IntersectingVariants.end();
9225e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           IVI != IVE; ++IVI)
9235e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        pushVariant(*RWI, IVI->first, TransVec[IVI->second], IsRead);
9245e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
9255e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
9265e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
9275e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
9285e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// For each variant of a Read/Write in Trans, substitute the sequence of
9295e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// Read/Writes guarded by the variant. This is exponential in the number of
9305e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// variant Read/Writes, but in practice detection of mutually exclusive
9315e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// predicates should result in linear growth in the total number variants.
9325e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick//
9335e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// This is one step in a breadth-first search of nested variants.
9345e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickvoid PredTransitions::substituteVariants(const PredTransition &Trans) {
9355e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // Build up a set of partial results starting at the back of
9365e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // PredTransitions. Remember the first new transition.
9375e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  unsigned StartIdx = TransVec.size();
9385e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  TransVec.resize(TransVec.size() + 1);
9395e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  TransVec.back().PredTerm = Trans.PredTerm;
9405e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
9415e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // Visit each original write sequence.
9425e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
9435e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         WSI = Trans.WriteSequences.begin(), WSE = Trans.WriteSequences.end();
9445e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick       WSI != WSE; ++WSI) {
9455e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // Push a new (empty) write sequence onto all partial Transitions.
9465e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (std::vector<PredTransition>::iterator I =
9475e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) {
9485e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      I->WriteSequences.resize(I->WriteSequences.size() + 1);
9495e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
9505e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    substituteVariantOperand(*WSI, /*IsRead=*/false, StartIdx);
9515e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
9525e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // Visit each original read sequence.
9535e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
9545e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         RSI = Trans.ReadSequences.begin(), RSE = Trans.ReadSequences.end();
9555e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick       RSI != RSE; ++RSI) {
9565e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // Push a new (empty) read sequence onto all partial Transitions.
9575e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (std::vector<PredTransition>::iterator I =
9585e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) {
9595e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      I->ReadSequences.resize(I->ReadSequences.size() + 1);
9605e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
9615e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    substituteVariantOperand(*RSI, /*IsRead=*/true, StartIdx);
9625e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
9635e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
9645e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
9655e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickstatic bool hasVariant(ArrayRef<PredTransition> Transitions,
9665e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                       CodeGenSchedModels &SchedModels) {
9675e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (ArrayRef<PredTransition>::iterator
9685e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         PTI = Transitions.begin(), PTE = Transitions.end();
9695e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick       PTI != PTE; ++PTI) {
9705e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
9715e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           WSI = PTI->WriteSequences.begin(), WSE = PTI->WriteSequences.end();
9725e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         WSI != WSE; ++WSI) {
9735e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      for (SmallVectorImpl<unsigned>::const_iterator
9745e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick             WI = WSI->begin(), WE = WSI->end(); WI != WE; ++WI) {
9755e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        if (SchedModels.getSchedWrite(*WI).HasVariants)
9765e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          return true;
9775e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      }
9785e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
9795e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
9805e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           RSI = PTI->ReadSequences.begin(), RSE = PTI->ReadSequences.end();
9815e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         RSI != RSE; ++RSI) {
9825e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      for (SmallVectorImpl<unsigned>::const_iterator
9835e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick             RI = RSI->begin(), RE = RSI->end(); RI != RE; ++RI) {
9845e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        if (SchedModels.getSchedRead(*RI).HasVariants)
9855e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          return true;
9865e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      }
9875e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
9885e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
9895e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  return false;
9905e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
9915e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
9925e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// Create a new SchedClass for each variant found by inferFromRW. Pass
9935e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick// ProcIndices by copy to avoid referencing anything from SchedClasses.
9945e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickstatic void inferFromTransitions(ArrayRef<PredTransition> LastTransitions,
9955e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                 unsigned FromClassIdx, IdxVec ProcIndices,
9965e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                 CodeGenSchedModels &SchedModels) {
9975e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // For each PredTransition, create a new CodeGenSchedTransition, which usually
9985e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // requires creating a new SchedClass.
9995e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (ArrayRef<PredTransition>::iterator
10005e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         I = LastTransitions.begin(), E = LastTransitions.end(); I != E; ++I) {
10015e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    IdxVec OperWritesVariant;
10025e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
10035e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           WSI = I->WriteSequences.begin(), WSE = I->WriteSequences.end();
10045e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         WSI != WSE; ++WSI) {
10055e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      // Create a new write representing the expanded sequence.
10065e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      OperWritesVariant.push_back(
10075e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        SchedModels.findOrInsertRW(*WSI, /*IsRead=*/false));
10085e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
10095e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    IdxVec OperReadsVariant;
10105e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
10115e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           RSI = I->ReadSequences.begin(), RSE = I->ReadSequences.end();
10125e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         RSI != RSE; ++RSI) {
10135e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      // Create a new write representing the expanded sequence.
10145e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      OperReadsVariant.push_back(
10155e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        SchedModels.findOrInsertRW(*RSI, /*IsRead=*/true));
10165e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
10175e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    CodeGenSchedTransition SCTrans;
10185e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    SCTrans.ToClassIdx =
10195e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      SchedModels.addSchedClass(OperWritesVariant, OperReadsVariant,
10205e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                ProcIndices);
10215e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    SCTrans.ProcIndices = ProcIndices;
10225e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    // The final PredTerm is unique set of predicates guarding the transition.
10235e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    RecVec Preds;
10245e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (SmallVectorImpl<PredCheck>::const_iterator
10255e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           PI = I->PredTerm.begin(), PE = I->PredTerm.end(); PI != PE; ++PI) {
10265e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      Preds.push_back(PI->Predicate);
10275e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
10285e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    RecIter PredsEnd = std::unique(Preds.begin(), Preds.end());
10295e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    Preds.resize(PredsEnd - Preds.begin());
10305e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    SCTrans.PredTerm = Preds;
10315e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    SchedModels.getSchedClass(FromClassIdx).Transitions.push_back(SCTrans);
10325e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
10335e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
10345e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
10355e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick/// Find each variant write that OperWrites or OperaReads refers to and create a
10365e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick/// new SchedClass for each variant.
10375e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickvoid CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites,
10385e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                     const IdxVec &OperReads,
10395e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                     unsigned FromClassIdx,
10405e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick                                     const IdxVec &ProcIndices) {
10415e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  DEBUG(dbgs() << "INFERRW Writes: ");
10425e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
10435e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // Create a seed transition with an empty PredTerm and the expanded sequences
10445e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // of SchedWrites for the current SchedClass.
10455e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  std::vector<PredTransition> LastTransitions;
10465e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  LastTransitions.resize(1);
10475e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (IdxIter I = OperWrites.begin(), E = OperWrites.end(); I != E; ++I) {
10485e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    IdxVec WriteSeq;
10495e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    expandRWSequence(*I, WriteSeq, /*IsRead=*/false);
10505e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    unsigned Idx = LastTransitions[0].WriteSequences.size();
10515e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    LastTransitions[0].WriteSequences.resize(Idx + 1);
10525e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    SmallVectorImpl<unsigned> &Seq = LastTransitions[0].WriteSequences[Idx];
10535e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (IdxIter WI = WriteSeq.begin(), WE = WriteSeq.end(); WI != WE; ++WI)
10545e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      Seq.push_back(*WI);
10555e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") ");
10565e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
10575e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  DEBUG(dbgs() << " Reads: ");
10585e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (IdxIter I = OperReads.begin(), E = OperReads.end(); I != E; ++I) {
10595e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    IdxVec ReadSeq;
10605e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    expandRWSequence(*I, ReadSeq, /*IsRead=*/true);
10615e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    unsigned Idx = LastTransitions[0].ReadSequences.size();
10625e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    LastTransitions[0].ReadSequences.resize(Idx + 1);
10635e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    SmallVectorImpl<unsigned> &Seq = LastTransitions[0].ReadSequences[Idx];
10645e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (IdxIter RI = ReadSeq.begin(), RE = ReadSeq.end(); RI != RE; ++RI)
10655e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      Seq.push_back(*RI);
10665e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") ");
10675e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
10685e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  DEBUG(dbgs() << '\n');
10695e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
10705e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // Collect all PredTransitions for individual operands.
10715e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // Iterate until no variant writes remain.
10725e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  while (hasVariant(LastTransitions, *this)) {
10735e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    PredTransitions Transitions(*this);
10745e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (std::vector<PredTransition>::const_iterator
10755e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           I = LastTransitions.begin(), E = LastTransitions.end();
10765e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         I != E; ++I) {
10775e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      Transitions.substituteVariants(*I);
10785e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
10795e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    DEBUG(Transitions.dump());
10805e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    LastTransitions.swap(Transitions.TransVec);
10815e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
10825e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // If the first transition has no variants, nothing to do.
10835e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  if (LastTransitions[0].PredTerm.empty())
10845e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    return;
10855e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
10865e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // WARNING: We are about to mutate the SchedClasses vector. Do not refer to
10875e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  // OperWrites, OperReads, or ProcIndices after calling inferFromTransitions.
10885e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  inferFromTransitions(LastTransitions, FromClassIdx, ProcIndices, *this);
10895e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
10905e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
10913cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick// Collect and sort WriteRes, ReadAdvance, and ProcResources.
10923cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trickvoid CodeGenSchedModels::collectProcResources() {
10933cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  // Add any subtarget-specific SchedReadWrites that are directly associated
10943cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  // with processor resources. Refer to the parent SchedClass's ProcIndices to
10953cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  // determine which processors they apply to.
10963cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  for (SchedClassIter SCI = schedClassBegin(), SCE = schedClassEnd();
10973cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick       SCI != SCE; ++SCI) {
10983cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    if (SCI->ItinClassDef)
10993cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      collectItinProcResources(SCI->ItinClassDef);
11003cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    else
11013cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      collectRWResources(SCI->Writes, SCI->Reads, SCI->ProcIndices);
11023cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  }
11033cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  // Add resources separately defined by each subtarget.
11043cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  RecVec WRDefs = Records.getAllDerivedDefinitions("WriteRes");
11053cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  for (RecIter WRI = WRDefs.begin(), WRE = WRDefs.end(); WRI != WRE; ++WRI) {
11063cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    Record *ModelDef = (*WRI)->getValueAsDef("SchedModel");
11073cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    addWriteRes(*WRI, getProcModel(ModelDef).Index);
11083cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  }
11093cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  RecVec RADefs = Records.getAllDerivedDefinitions("ReadAdvance");
11103cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  for (RecIter RAI = RADefs.begin(), RAE = RADefs.end(); RAI != RAE; ++RAI) {
11113cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    Record *ModelDef = (*RAI)->getValueAsDef("SchedModel");
11123cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    addReadAdvance(*RAI, getProcModel(ModelDef).Index);
11133cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  }
11143cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  // Finalize each ProcModel by sorting the record arrays.
11153cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) {
11163cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    CodeGenProcModel &PM = ProcModels[PIdx];
11173cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    std::sort(PM.WriteResDefs.begin(), PM.WriteResDefs.end(),
11183cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick              LessRecord());
11193cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    std::sort(PM.ReadAdvanceDefs.begin(), PM.ReadAdvanceDefs.end(),
11203cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick              LessRecord());
11213cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    std::sort(PM.ProcResourceDefs.begin(), PM.ProcResourceDefs.end(),
11223cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick              LessRecord());
11233cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    DEBUG(
11243cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      PM.dump();
11253cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      dbgs() << "WriteResDefs: ";
11263cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      for (RecIter RI = PM.WriteResDefs.begin(),
11273cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick             RE = PM.WriteResDefs.end(); RI != RE; ++RI) {
11283cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick        if ((*RI)->isSubClassOf("WriteRes"))
11293cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick          dbgs() << (*RI)->getValueAsDef("WriteType")->getName() << " ";
11303cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick        else
11313cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick          dbgs() << (*RI)->getName() << " ";
11323cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      }
11333cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      dbgs() << "\nReadAdvanceDefs: ";
11343cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      for (RecIter RI = PM.ReadAdvanceDefs.begin(),
11353cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick             RE = PM.ReadAdvanceDefs.end(); RI != RE; ++RI) {
11363cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick        if ((*RI)->isSubClassOf("ReadAdvance"))
11373cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick          dbgs() << (*RI)->getValueAsDef("ReadType")->getName() << " ";
11383cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick        else
11393cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick          dbgs() << (*RI)->getName() << " ";
11403cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      }
11413cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      dbgs() << "\nProcResourceDefs: ";
11423cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      for (RecIter RI = PM.ProcResourceDefs.begin(),
11433cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick             RE = PM.ProcResourceDefs.end(); RI != RE; ++RI) {
11443cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick        dbgs() << (*RI)->getName() << " ";
11453cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      }
11463cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      dbgs() << '\n');
11473cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  }
11483cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick}
11493cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
11503cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick// Collect itinerary class resources for each processor.
11513cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trickvoid CodeGenSchedModels::collectItinProcResources(Record *ItinClassDef) {
11523cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) {
11533cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    const CodeGenProcModel &PM = ProcModels[PIdx];
11543cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    // For all ItinRW entries.
11553cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    bool HasMatch = false;
11563cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    for (RecIter II = PM.ItinRWDefs.begin(), IE = PM.ItinRWDefs.end();
11573cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick         II != IE; ++II) {
11583cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
11593cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      if (!std::count(Matched.begin(), Matched.end(), ItinClassDef))
11603cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick        continue;
11613cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      if (HasMatch)
11623cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick        throw TGError((*II)->getLoc(), "Duplicate itinerary class "
11633cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                      + ItinClassDef->getName()
11643cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                      + " in ItinResources for " + PM.ModelName);
11653cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      HasMatch = true;
11663cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      IdxVec Writes, Reads;
11673cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
11683cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      IdxVec ProcIndices(1, PIdx);
11693cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      collectRWResources(Writes, Reads, ProcIndices);
11703cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    }
11713cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  }
11723cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick}
11733cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
11743cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
11753cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick// Collect resources for a set of read/write types and processor indices.
11763cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trickvoid CodeGenSchedModels::collectRWResources(const IdxVec &Writes,
11773cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                                            const IdxVec &Reads,
11783cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                                            const IdxVec &ProcIndices) {
11793cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
11803cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
11813cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    const CodeGenSchedRW &SchedRW = getSchedRW(*WI, /*IsRead=*/false);
11823cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    if (SchedRW.TheDef && SchedRW.TheDef->isSubClassOf("SchedWriteRes")) {
11833cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
11843cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick           PI != PE; ++PI) {
11853cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick        addWriteRes(SchedRW.TheDef, *PI);
11863cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      }
11873cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    }
11883cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  }
11893cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI) {
11903cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    const CodeGenSchedRW &SchedRW = getSchedRW(*RI, /*IsRead=*/true);
11913cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    if (SchedRW.TheDef && SchedRW.TheDef->isSubClassOf("SchedReadAdvance")) {
11923cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
11933cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick           PI != PE; ++PI) {
11943cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick        addReadAdvance(SchedRW.TheDef, *PI);
11953cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      }
11963cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    }
11973cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  }
11983cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick}
11993cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12003cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick// Find the processor's resource units for this kind of resource.
12013cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew TrickRecord *CodeGenSchedModels::findProcResUnits(Record *ProcResKind,
12023cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                                             const CodeGenProcModel &PM) const {
12033cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  if (ProcResKind->isSubClassOf("ProcResourceUnits"))
12043cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    return ProcResKind;
12053cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12063cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  Record *ProcUnitDef = 0;
12073cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  RecVec ProcResourceDefs =
12083cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    Records.getAllDerivedDefinitions("ProcResourceUnits");
12093cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12103cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  for (RecIter RI = ProcResourceDefs.begin(), RE = ProcResourceDefs.end();
12113cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick       RI != RE; ++RI) {
12123cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12133cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    if ((*RI)->getValueAsDef("Kind") == ProcResKind
12143cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick        && (*RI)->getValueAsDef("SchedModel") == PM.ModelDef) {
12153cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      if (ProcUnitDef) {
12163cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick        throw TGError((*RI)->getLoc(),
12173cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                      "Multiple ProcessorResourceUnits associated with "
12183cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                      + ProcResKind->getName());
12193cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      }
12203cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      ProcUnitDef = *RI;
12213cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    }
12223cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  }
12233cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  if (!ProcUnitDef) {
12243cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    throw TGError(ProcResKind->getLoc(),
12253cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                  "No ProcessorResources associated with "
12263cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                  + ProcResKind->getName());
12273cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  }
12283cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  return ProcUnitDef;
12293cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick}
12303cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12313cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick// Iteratively add a resource and its super resources.
12323cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trickvoid CodeGenSchedModels::addProcResource(Record *ProcResKind,
12333cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                                         CodeGenProcModel &PM) {
12343cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  for (;;) {
12353cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    Record *ProcResUnits = findProcResUnits(ProcResKind, PM);
12363cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12373cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    // See if this ProcResource is already associated with this processor.
12383cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    RecIter I = std::find(PM.ProcResourceDefs.begin(),
12393cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                          PM.ProcResourceDefs.end(), ProcResUnits);
12403cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    if (I != PM.ProcResourceDefs.end())
12413cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      return;
12423cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12433cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    PM.ProcResourceDefs.push_back(ProcResUnits);
12443cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    if (!ProcResUnits->getValueInit("Super")->isComplete())
12453cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick      return;
12463cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12473cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    ProcResKind = ProcResUnits->getValueAsDef("Super");
12483cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  }
12493cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick}
12503cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12513cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick// Add resources for a SchedWrite to this processor if they don't exist.
12523cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trickvoid CodeGenSchedModels::addWriteRes(Record *ProcWriteResDef, unsigned PIdx) {
12533cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  RecVec &WRDefs = ProcModels[PIdx].WriteResDefs;
12543cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  RecIter WRI = std::find(WRDefs.begin(), WRDefs.end(), ProcWriteResDef);
12553cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  if (WRI != WRDefs.end())
12563cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    return;
12573cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  WRDefs.push_back(ProcWriteResDef);
12583cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12593cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  // Visit ProcResourceKinds referenced by the newly discovered WriteRes.
12603cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  RecVec ProcResDefs = ProcWriteResDef->getValueAsListOfDefs("ProcResources");
12613cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  for (RecIter WritePRI = ProcResDefs.begin(), WritePRE = ProcResDefs.end();
12623cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick       WritePRI != WritePRE; ++WritePRI) {
12633cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    addProcResource(*WritePRI, ProcModels[PIdx]);
12643cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  }
12653cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick}
12663cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12673cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick// Add resources for a ReadAdvance to this processor if they don't exist.
12683cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trickvoid CodeGenSchedModels::addReadAdvance(Record *ProcReadAdvanceDef,
12693cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick                                        unsigned PIdx) {
12703cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  RecVec &RADefs = ProcModels[PIdx].ReadAdvanceDefs;
12713cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  RecIter I = std::find(RADefs.begin(), RADefs.end(), ProcReadAdvanceDef);
12723cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  if (I != RADefs.end())
12733cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick    return;
12743cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick  RADefs.push_back(ProcReadAdvanceDef);
12753cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick}
12763cbd1786ac06fe751dc4b5ad55e75115cb1d51ceAndrew Trick
12772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick#ifndef NDEBUG
127848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenProcModel::dump() const {
127948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  dbgs() << Index << ": " << ModelName << " "
128048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         << (ModelDef ? ModelDef->getName() : "inferred") << " "
128148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         << (ItinsDef ? ItinsDef->getName() : "no itinerary") << '\n';
128248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
128348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
128448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenSchedRW::dump() const {
128548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  dbgs() << Name << (IsVariadic ? " (V) " : " ");
128648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  if (IsSequence) {
128748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    dbgs() << "(";
128848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    dumpIdxVec(Sequence);
128948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    dbgs() << ")";
12902661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  }
12912661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick}
129248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick
129348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trickvoid CodeGenSchedClass::dump(const CodeGenSchedModels* SchedModels) const {
129448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  dbgs() << "SCHEDCLASS " << Name << '\n'
129548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         << "  Writes: ";
129648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (unsigned i = 0, N = Writes.size(); i < N; ++i) {
129748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SchedModels->getSchedWrite(Writes[i]).dump();
129848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (i < N-1) {
129948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      dbgs() << '\n';
130048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      dbgs().indent(10);
130148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
130248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
130348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  dbgs() << "\n  Reads: ";
130448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  for (unsigned i = 0, N = Reads.size(); i < N; ++i) {
130548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    SchedModels->getSchedRead(Reads[i]).dump();
130648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    if (i < N-1) {
130748605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      dbgs() << '\n';
130848605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      dbgs().indent(10);
130948605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    }
131048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  }
131148605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick  dbgs() << "\n  ProcIdx: "; dumpIdxVec(ProcIndices); dbgs() << '\n';
131248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick}
13135e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick
13145e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trickvoid PredTransitions::dump() const {
13155e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  dbgs() << "Expanded Variants:\n";
13165e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  for (std::vector<PredTransition>::const_iterator
13175e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         TI = TransVec.begin(), TE = TransVec.end(); TI != TE; ++TI) {
13185e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    dbgs() << "{";
13195e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (SmallVectorImpl<PredCheck>::const_iterator
13205e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           PCI = TI->PredTerm.begin(), PCE = TI->PredTerm.end();
13215e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         PCI != PCE; ++PCI) {
13225e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      if (PCI != TI->PredTerm.begin())
13235e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        dbgs() << ", ";
13245e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      dbgs() << SchedModels.getSchedRW(PCI->RWIdx, PCI->IsRead).Name
13255e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick             << ":" << PCI->Predicate->getName();
13265e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
13275e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    dbgs() << "},\n  => {";
13285e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
13295e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick           WSI = TI->WriteSequences.begin(), WSE = TI->WriteSequences.end();
13305e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick         WSI != WSE; ++WSI) {
13315e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      dbgs() << "(";
13325e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      for (SmallVectorImpl<unsigned>::const_iterator
13335e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick             WI = WSI->begin(), WE = WSI->end(); WI != WE; ++WI) {
13345e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        if (WI != WSI->begin())
13355e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick          dbgs() << ", ";
13365e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick        dbgs() << SchedModels.getSchedWrite(*WI).Name;
13375e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      }
13385e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick      dbgs() << "),";
13395e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    }
13405e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick    dbgs() << "}\n";
13415e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick  }
13425e613c260bb3044eb059dea74cd6bccfa9b85bddAndrew Trick}
134348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick#endif // NDEBUG
1344