//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "subtarget-emitter"
-
#include "CodeGenSchedule.h"
#include "CodeGenTarget.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;
+#define DEBUG_TYPE "subtarget-emitter"
+
#ifndef NDEBUG
-static void dumpIdxVec(const IdxVec &V) {
- for (unsigned i = 0, e = V.size(); i < e; ++i) {
- dbgs() << V[i] << ", ";
- }
-}
-static void dumpIdxVec(const SmallVectorImpl<unsigned> &V) {
- for (unsigned i = 0, e = V.size(); i < e; ++i) {
- dbgs() << V[i] << ", ";
- }
+static void dumpIdxVec(ArrayRef<unsigned> V) {
+ for (unsigned Idx : V)
+ dbgs() << Idx << ", ";
}
#endif
void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
ArrayRef<SMLoc> Loc) override {
- SmallVector<Regex*, 4> RegexList;
+ SmallVector<Regex, 4> RegexList;
for (DagInit::const_arg_iterator
AI = Expr->arg_begin(), AE = Expr->arg_end(); AI != AE; ++AI) {
StringInit *SI = dyn_cast<StringInit>(*AI);
pat.insert(0, "^(");
pat.insert(pat.end(), ')');
}
- RegexList.push_back(new Regex(pat));
- }
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end(); I != E; ++I) {
- for (SmallVectorImpl<Regex*>::iterator
- RI = RegexList.begin(), RE = RegexList.end(); RI != RE; ++RI) {
- if ((*RI)->match((*I)->TheDef->getName()))
- Elts.insert((*I)->TheDef);
+ RegexList.push_back(Regex(pat));
+ }
+ for (const CodeGenInstruction *Inst : Target.instructions()) {
+ for (auto &R : RegexList) {
+ if (R.match(Inst->TheDef->getName()))
+ Elts.insert(Inst->TheDef);
}
}
- DeleteContainerPointers(RegexList);
}
};
} // end anonymous namespace
// Allow Set evaluation to recognize the dags used in InstRW records:
// (instrs Op1, Op1...)
- Sets.addOperator("instrs", new InstrsOp);
- Sets.addOperator("instregex", new InstRegexOp(Target));
+ Sets.addOperator("instrs", llvm::make_unique<InstrsOp>());
+ Sets.addOperator("instregex", llvm::make_unique<InstRegexOp>(Target));
// Instantiate a CodeGenProcModel for each SchedMachineModel with the values
// that are explicitly referenced in tablegen records. Resources associated
// Use idx=0 for NoModel/NoItineraries.
Record *NoModelDef = Records.getDef("NoSchedModel");
Record *NoItinsDef = Records.getDef("NoItineraries");
- ProcModels.push_back(CodeGenProcModel(0, "NoSchedModel",
- NoModelDef, NoItinsDef));
+ ProcModels.emplace_back(0, "NoSchedModel", NoModelDef, NoItinsDef);
ProcModelMap[NoModelDef] = 0;
// For each processor, find a unique machine model.
std::string Name = ModelKey->getName();
if (ModelKey->isSubClassOf("SchedMachineModel")) {
Record *ItinsDef = ModelKey->getValueAsDef("Itineraries");
- ProcModels.push_back(
- CodeGenProcModel(ProcModels.size(), Name, ModelKey, ItinsDef));
+ ProcModels.emplace_back(ProcModels.size(), Name, ModelKey, ItinsDef);
}
else {
// An itinerary is defined without a machine model. Infer a new model.
if (!ModelKey->getValueAsListOfDefs("IID").empty())
Name = Name + "Model";
- ProcModels.push_back(
- CodeGenProcModel(ProcModels.size(), Name,
- ProcDef->getValueAsDef("SchedModel"), ModelKey));
+ ProcModels.emplace_back(ProcModels.size(), Name,
+ ProcDef->getValueAsDef("SchedModel"), ModelKey);
}
DEBUG(ProcModels.back().dump());
}
// Recursively find all reachable SchedReadWrite records.
static void scanSchedRW(Record *RWDef, RecVec &RWDefs,
SmallPtrSet<Record*, 16> &RWSet) {
- if (!RWSet.insert(RWDef))
+ if (!RWSet.insert(RWDef).second)
return;
RWDefs.push_back(RWDef);
// Reads don't current have sequence records, but it can be added later.
// Find all SchedReadWrites referenced by instruction defs.
RecVec SWDefs, SRDefs;
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end(); I != E; ++I) {
- Record *SchedDef = (*I)->TheDef;
+ for (const CodeGenInstruction *Inst : Target.instructions()) {
+ Record *SchedDef = Inst->TheDef;
if (SchedDef->isValueUnset("SchedRW"))
continue;
RecVec RWs = SchedDef->getValueAsListOfDefs("SchedRW");
std::sort(SWDefs.begin(), SWDefs.end(), LessRecord());
for (RecIter SWI = SWDefs.begin(), SWE = SWDefs.end(); SWI != SWE; ++SWI) {
assert(!getSchedRWIdx(*SWI, /*IsRead=*/false) && "duplicate SchedWrite");
- SchedWrites.push_back(CodeGenSchedRW(SchedWrites.size(), *SWI));
+ SchedWrites.emplace_back(SchedWrites.size(), *SWI);
}
std::sort(SRDefs.begin(), SRDefs.end(), LessRecord());
for (RecIter SRI = SRDefs.begin(), SRE = SRDefs.end(); SRI != SRE; ++SRI) {
assert(!getSchedRWIdx(*SRI, /*IsRead-*/true) && "duplicate SchedWrite");
- SchedReads.push_back(CodeGenSchedRW(SchedReads.size(), *SRI));
+ SchedReads.emplace_back(SchedReads.size(), *SRI);
}
// Initialize WriteSequence vectors.
for (std::vector<CodeGenSchedRW>::iterator WI = SchedWrites.begin(),
}
/// Compute a SchedWrite name from a sequence of writes.
-std::string CodeGenSchedModels::genRWName(const IdxVec& Seq, bool IsRead) {
+std::string CodeGenSchedModels::genRWName(ArrayRef<unsigned> Seq, bool IsRead) {
std::string Name("(");
- for (IdxIter I = Seq.begin(), E = Seq.end(); I != E; ++I) {
+ for (auto I = Seq.begin(), E = Seq.end(); I != E; ++I) {
if (I != Seq.begin())
Name += '_';
Name += getSchedRW(*I, IsRead).Name;
const CodeGenProcModel &ProcModel) const {
const CodeGenSchedRW &SchedWrite = getSchedRW(RWIdx, IsRead);
- Record *AliasDef = 0;
+ Record *AliasDef = nullptr;
for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
AI != AE; ++AI) {
const CodeGenSchedRW &AliasRW = getSchedRW((*AI)->getValueAsDef("AliasRW"));
}
// Find the existing SchedWrite that models this sequence of writes.
-unsigned CodeGenSchedModels::findRWForSequence(const IdxVec &Seq,
+unsigned CodeGenSchedModels::findRWForSequence(ArrayRef<unsigned> Seq,
bool IsRead) {
std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites;
for (std::vector<CodeGenSchedRW>::iterator I = RWVec.begin(), E = RWVec.end();
I != E; ++I) {
- if (I->Sequence == Seq)
+ if (makeArrayRef(I->Sequence) == Seq)
return I - RWVec.begin();
}
// Index zero reserved for invalid RW.
// Create a SchedClass for each unique combination of itinerary class and
// SchedRW list.
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end(); I != E; ++I) {
- Record *ItinDef = (*I)->TheDef->getValueAsDef("Itinerary");
+ for (const CodeGenInstruction *Inst : Target.instructions()) {
+ Record *ItinDef = Inst->TheDef->getValueAsDef("Itinerary");
IdxVec Writes, Reads;
- if (!(*I)->TheDef->isValueUnset("SchedRW"))
- findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads);
+ if (!Inst->TheDef->isValueUnset("SchedRW"))
+ findRWs(Inst->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads);
// ProcIdx == 0 indicates the class applies to all processors.
IdxVec ProcIndices(1, 0);
unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, ProcIndices);
- InstrClassMap[(*I)->TheDef] = SCIdx;
+ InstrClassMap[Inst->TheDef] = SCIdx;
}
// Create classes for InstRW defs.
RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");
if (!EnableDump)
return;
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end(); I != E; ++I) {
-
- std::string InstName = (*I)->TheDef->getName();
- unsigned SCIdx = InstrClassMap.lookup((*I)->TheDef);
+ for (const CodeGenInstruction *Inst : Target.instructions()) {
+ std::string InstName = Inst->TheDef->getName();
+ unsigned SCIdx = InstrClassMap.lookup(Inst->TheDef);
if (!SCIdx) {
- dbgs() << "No machine model for " << (*I)->TheDef->getName() << '\n';
+ dbgs() << "No machine model for " << Inst->TheDef->getName() << '\n';
continue;
}
CodeGenSchedClass &SC = getSchedClass(SCIdx);
if (SC.ProcIndices[0] != 0)
- PrintFatalError((*I)->TheDef->getLoc(), "Instruction's sched class "
+ PrintFatalError(Inst->TheDef->getLoc(), "Instruction's sched class "
"must not be subtarget specific.");
IdxVec ProcIndices;
for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(),
PE = ProcModels.end(); PI != PE; ++PI) {
if (!std::count(ProcIndices.begin(), ProcIndices.end(), PI->Index))
- dbgs() << "No machine model for " << (*I)->TheDef->getName()
+ dbgs() << "No machine model for " << Inst->TheDef->getName()
<< " on processor " << PI->ModelName << '\n';
}
}
/// Find an SchedClass that has been inferred from a per-operand list of
/// SchedWrites and SchedReads.
unsigned CodeGenSchedModels::findSchedClassIdx(Record *ItinClassDef,
- const IdxVec &Writes,
- const IdxVec &Reads) const {
+ ArrayRef<unsigned> Writes,
+ ArrayRef<unsigned> Reads) const {
for (SchedClassIter I = schedClassBegin(), E = schedClassEnd(); I != E; ++I) {
- if (I->ItinClassDef == ItinClassDef
- && I->Writes == Writes && I->Reads == Reads) {
+ if (I->ItinClassDef == ItinClassDef && makeArrayRef(I->Writes) == Writes &&
+ makeArrayRef(I->Reads) == Reads) {
return I - schedClassBegin();
}
}
return InstrClassMap.lookup(Inst.TheDef);
}
-std::string CodeGenSchedModels::createSchedClassName(
- Record *ItinClassDef, const IdxVec &OperWrites, const IdxVec &OperReads) {
+std::string
+CodeGenSchedModels::createSchedClassName(Record *ItinClassDef,
+ ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads) {
std::string Name;
if (ItinClassDef && ItinClassDef->getName() != "NoItinerary")
Name = ItinClassDef->getName();
- for (IdxIter WI = OperWrites.begin(), WE = OperWrites.end(); WI != WE; ++WI) {
+ for (unsigned Idx : OperWrites) {
if (!Name.empty())
Name += '_';
- Name += SchedWrites[*WI].Name;
+ Name += SchedWrites[Idx].Name;
}
- for (IdxIter RI = OperReads.begin(), RE = OperReads.end(); RI != RE; ++RI) {
+ for (unsigned Idx : OperReads) {
Name += '_';
- Name += SchedReads[*RI].Name;
+ Name += SchedReads[Idx].Name;
}
return Name;
}
/// SchedWrites and SchedReads. ProcIndices contains the set of IDs of
/// processors that may utilize this class.
unsigned CodeGenSchedModels::addSchedClass(Record *ItinClassDef,
- const IdxVec &OperWrites,
- const IdxVec &OperReads,
- const IdxVec &ProcIndices)
-{
+ ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads,
+ ArrayRef<unsigned> ProcIndices) {
assert(!ProcIndices.empty() && "expect at least one ProcIdx");
unsigned Idx = findSchedClassIdx(ItinClassDef, OperWrites, OperReads);
for (ArrayRef<Record*>::const_iterator
II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) {
unsigned OldSCIdx = InstrClassMap[*II];
- if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx)) {
+ if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx).second) {
for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(),
RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) {
if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) {
// Gather the processor itineraries.
void CodeGenSchedModels::collectProcItins() {
- for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(),
- PE = ProcModels.end(); PI != PE; ++PI) {
- CodeGenProcModel &ProcModel = *PI;
+ for (CodeGenProcModel &ProcModel : ProcModels) {
if (!ProcModel.hasItineraries())
continue;
IdxVec ProcIndices(I->ProcIndices.begin(), I->ProcIndices.end());
CodeGenSchedTransition SCTrans;
SCTrans.ToClassIdx =
- SchedModels.addSchedClass(/*ItinClassDef=*/0, OperWritesVariant,
+ SchedModels.addSchedClass(/*ItinClassDef=*/nullptr, OperWritesVariant,
OperReadsVariant, ProcIndices);
SCTrans.ProcIndices = ProcIndices;
// The final PredTerm is unique set of predicates guarding the transition.
// Create new SchedClasses for the given ReadWrite list. If any of the
// ReadWrites refers to a SchedVariant, create a new SchedClass for each variant
// of the ReadWrite list, following Aliases if necessary.
-void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites,
- const IdxVec &OperReads,
+void CodeGenSchedModels::inferFromRW(ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads,
unsigned FromClassIdx,
- const IdxVec &ProcIndices) {
+ ArrayRef<unsigned> ProcIndices) {
DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices); dbgs() << ") ");
// Create a seed transition with an empty PredTerm and the expanded sequences
LastTransitions.back().ProcIndices.append(ProcIndices.begin(),
ProcIndices.end());
- for (IdxIter I = OperWrites.begin(), E = OperWrites.end(); I != E; ++I) {
+ for (unsigned WriteIdx : OperWrites) {
IdxVec WriteSeq;
- expandRWSequence(*I, WriteSeq, /*IsRead=*/false);
+ expandRWSequence(WriteIdx, WriteSeq, /*IsRead=*/false);
unsigned Idx = LastTransitions[0].WriteSequences.size();
LastTransitions[0].WriteSequences.resize(Idx + 1);
SmallVectorImpl<unsigned> &Seq = LastTransitions[0].WriteSequences[Idx];
DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") ");
}
DEBUG(dbgs() << " Reads: ");
- for (IdxIter I = OperReads.begin(), E = OperReads.end(); I != E; ++I) {
+ for (unsigned ReadIdx : OperReads) {
IdxVec ReadSeq;
- expandRWSequence(*I, ReadSeq, /*IsRead=*/true);
+ expandRWSequence(ReadIdx, ReadSeq, /*IsRead=*/true);
unsigned Idx = LastTransitions[0].ReadSequences.size();
LastTransitions[0].ReadSequences.resize(Idx + 1);
SmallVectorImpl<unsigned> &Seq = LastTransitions[0].ReadSequences[Idx];
Record *ModelDef = (*WRI)->getValueAsDef("SchedModel");
addWriteRes(*WRI, getProcModel(ModelDef).Index);
}
+ RecVec SWRDefs = Records.getAllDerivedDefinitions("SchedWriteRes");
+ for (RecIter WRI = SWRDefs.begin(), WRE = SWRDefs.end(); WRI != WRE; ++WRI) {
+ Record *ModelDef = (*WRI)->getValueAsDef("SchedModel");
+ addWriteRes(*WRI, getProcModel(ModelDef).Index);
+ }
RecVec RADefs = Records.getAllDerivedDefinitions("ReadAdvance");
for (RecIter RAI = RADefs.begin(), RAE = RADefs.end(); RAI != RAE; ++RAI) {
Record *ModelDef = (*RAI)->getValueAsDef("SchedModel");
addReadAdvance(*RAI, getProcModel(ModelDef).Index);
}
+ RecVec SRADefs = Records.getAllDerivedDefinitions("SchedReadAdvance");
+ for (RecIter RAI = SRADefs.begin(), RAE = SRADefs.end(); RAI != RAE; ++RAI) {
+ if ((*RAI)->getValueInit("SchedModel")->isComplete()) {
+ Record *ModelDef = (*RAI)->getValueAsDef("SchedModel");
+ addReadAdvance(*RAI, getProcModel(ModelDef).Index);
+ }
+ }
// Add ProcResGroups that are defined within this processor model, which may
// not be directly referenced but may directly specify a buffer size.
RecVec ProcResGroups = Records.getAllDerivedDefinitions("ProcResGroup");
PM.ProcResourceDefs.push_back(*RI);
}
// Finalize each ProcModel by sorting the record arrays.
- for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) {
- CodeGenProcModel &PM = ProcModels[PIdx];
+ for (CodeGenProcModel &PM : ProcModels) {
std::sort(PM.WriteResDefs.begin(), PM.WriteResDefs.end(),
LessRecord());
std::sort(PM.ReadAdvanceDefs.begin(), PM.ReadAdvanceDefs.end(),
}
void CodeGenSchedModels::collectRWResources(unsigned RWIdx, bool IsRead,
- const IdxVec &ProcIndices) {
+ ArrayRef<unsigned> ProcIndices) {
const CodeGenSchedRW &SchedRW = getSchedRW(RWIdx, IsRead);
if (SchedRW.TheDef) {
if (!IsRead && SchedRW.TheDef->isSubClassOf("SchedWriteRes")) {
- for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
- PI != PE; ++PI) {
- addWriteRes(SchedRW.TheDef, *PI);
- }
+ for (unsigned Idx : ProcIndices)
+ addWriteRes(SchedRW.TheDef, Idx);
}
else if (IsRead && SchedRW.TheDef->isSubClassOf("SchedReadAdvance")) {
- for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
- PI != PE; ++PI) {
- addReadAdvance(SchedRW.TheDef, *PI);
- }
+ for (unsigned Idx : ProcIndices)
+ addReadAdvance(SchedRW.TheDef, Idx);
}
}
for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
}
// Collect resources for a set of read/write types and processor indices.
-void CodeGenSchedModels::collectRWResources(const IdxVec &Writes,
- const IdxVec &Reads,
- const IdxVec &ProcIndices) {
+void CodeGenSchedModels::collectRWResources(ArrayRef<unsigned> Writes,
+ ArrayRef<unsigned> Reads,
+ ArrayRef<unsigned> ProcIndices) {
- for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI)
- collectRWResources(*WI, /*IsRead=*/false, ProcIndices);
+ for (unsigned Idx : Writes)
+ collectRWResources(Idx, /*IsRead=*/false, ProcIndices);
- for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI)
- collectRWResources(*RI, /*IsRead=*/true, ProcIndices);
+ for (unsigned Idx : Reads)
+ collectRWResources(Idx, /*IsRead=*/true, ProcIndices);
}
if (ProcResKind->isSubClassOf("ProcResourceUnits"))
return ProcResKind;
- Record *ProcUnitDef = 0;
+ Record *ProcUnitDef = nullptr;
RecVec ProcResourceDefs =
Records.getAllDerivedDefinitions("ProcResourceUnits");