diff options
| author | 2019-01-27 16:42:12 +0000 | |
|---|---|---|
| committer | 2019-01-27 16:42:12 +0000 | |
| commit | b773203fb58f3ef282fb69c832d8710cab5bc82d (patch) | |
| tree | e75913f147570fbd75169647b144df85b88a038c /gnu/llvm/utils/TableGen/CodeGenSchedule.cpp | |
| parent | tweak errno in previous (diff) | |
| download | wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip | |
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/utils/TableGen/CodeGenSchedule.cpp')
| -rw-r--r-- | gnu/llvm/utils/TableGen/CodeGenSchedule.cpp | 834 |
1 files changed, 471 insertions, 363 deletions
diff --git a/gnu/llvm/utils/TableGen/CodeGenSchedule.cpp b/gnu/llvm/utils/TableGen/CodeGenSchedule.cpp index b753e19a544..9331fadf409 100644 --- a/gnu/llvm/utils/TableGen/CodeGenSchedule.cpp +++ b/gnu/llvm/utils/TableGen/CodeGenSchedule.cpp @@ -12,17 +12,18 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenInstruction.h" #include "CodeGenSchedule.h" +#include "CodeGenInstruction.h" #include "CodeGenTarget.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Regex.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include <algorithm> #include <iterator> @@ -50,38 +51,113 @@ struct InstrsOp : public SetTheory::Operator { }; // (instregex "OpcPat",...) Find all instructions matching an opcode pattern. -// -// TODO: Since this is a prefix match, perform a binary search over the -// instruction names using lower_bound. Note that the predefined instrs must be -// scanned linearly first. However, this is only safe if the regex pattern has -// no top-level bars. The DAG already has a list of patterns, so there's no -// reason to use top-level bars, but we need a way to verify they don't exist -// before implementing the optimization. struct InstRegexOp : public SetTheory::Operator { const CodeGenTarget &Target; InstRegexOp(const CodeGenTarget &t): Target(t) {} + /// Remove any text inside of parentheses from S. + static std::string removeParens(llvm::StringRef S) { + std::string Result; + unsigned Paren = 0; + // NB: We don't care about escaped parens here. + for (char C : S) { + switch (C) { + case '(': + ++Paren; + break; + case ')': + --Paren; + break; + default: + if (Paren == 0) + Result += C; + } + } + return Result; + } + void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, ArrayRef<SMLoc> Loc) override { - SmallVector<Regex, 4> RegexList; + ArrayRef<const CodeGenInstruction *> Instructions = + Target.getInstructionsByEnumValue(); + + unsigned NumGeneric = Target.getNumFixedInstructions(); + unsigned NumPseudos = Target.getNumPseudoInstructions(); + auto Generics = Instructions.slice(0, NumGeneric); + auto Pseudos = Instructions.slice(NumGeneric, NumPseudos); + auto NonPseudos = Instructions.slice(NumGeneric + NumPseudos); + for (Init *Arg : make_range(Expr->arg_begin(), Expr->arg_end())) { StringInit *SI = dyn_cast<StringInit>(Arg); if (!SI) - PrintFatalError(Loc, "instregex requires pattern string: " - + Expr->getAsString()); - std::string pat = SI->getValue(); - // Implement a python-style prefix match. - if (pat[0] != '^') { - pat.insert(0, "^("); - pat.insert(pat.end(), ')'); + PrintFatalError(Loc, "instregex requires pattern string: " + + Expr->getAsString()); + StringRef Original = SI->getValue(); + + // Extract a prefix that we can binary search on. + static const char RegexMetachars[] = "()^$|*+?.[]\\{}"; + auto FirstMeta = Original.find_first_of(RegexMetachars); + + // Look for top-level | or ?. We cannot optimize them to binary search. + if (removeParens(Original).find_first_of("|?") != std::string::npos) + FirstMeta = 0; + + Optional<Regex> Regexpr = None; + StringRef Prefix = Original.substr(0, FirstMeta); + StringRef PatStr = Original.substr(FirstMeta); + if (!PatStr.empty()) { + // For the rest use a python-style prefix match. + std::string pat = PatStr; + if (pat[0] != '^') { + pat.insert(0, "^("); + pat.insert(pat.end(), ')'); + } + Regexpr = Regex(pat); } - RegexList.push_back(Regex(pat)); - } - for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { - for (auto &R : RegexList) { - if (R.match(Inst->TheDef->getName())) + + int NumMatches = 0; + + // The generic opcodes are unsorted, handle them manually. + for (auto *Inst : Generics) { + StringRef InstName = Inst->TheDef->getName(); + if (InstName.startswith(Prefix) && + (!Regexpr || Regexpr->match(InstName.substr(Prefix.size())))) { Elts.insert(Inst->TheDef); + NumMatches++; + } } + + // Target instructions are split into two ranges: pseudo instructions + // first, than non-pseudos. Each range is in lexicographical order + // sorted by name. Find the sub-ranges that start with our prefix. + struct Comp { + bool operator()(const CodeGenInstruction *LHS, StringRef RHS) { + return LHS->TheDef->getName() < RHS; + } + bool operator()(StringRef LHS, const CodeGenInstruction *RHS) { + return LHS < RHS->TheDef->getName() && + !RHS->TheDef->getName().startswith(LHS); + } + }; + auto Range1 = + std::equal_range(Pseudos.begin(), Pseudos.end(), Prefix, Comp()); + auto Range2 = std::equal_range(NonPseudos.begin(), NonPseudos.end(), + Prefix, Comp()); + + // For these ranges we know that instruction names start with the prefix. + // Check if there's a regex that needs to be checked. + const auto HandleNonGeneric = [&](const CodeGenInstruction *Inst) { + StringRef InstName = Inst->TheDef->getName(); + if (!Regexpr || Regexpr->match(InstName.substr(Prefix.size()))) { + Elts.insert(Inst->TheDef); + NumMatches++; + } + }; + std::for_each(Range1.first, Range1.second, HandleNonGeneric); + std::for_each(Range2.first, Range2.second, HandleNonGeneric); + + if (0 == NumMatches) + PrintFatalError(Loc, "instregex has no matches: " + Original); } } }; @@ -139,16 +215,49 @@ CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK, // Populate each CodeGenProcModel's WriteResDefs, ReadAdvanceDefs, and // ProcResourceDefs. - DEBUG(dbgs() << "\n+++ RESOURCE DEFINITIONS (collectProcResources) +++\n"); + LLVM_DEBUG( + dbgs() << "\n+++ RESOURCE DEFINITIONS (collectProcResources) +++\n"); collectProcResources(); + // Collect optional processor description. + collectOptionalProcessorInfo(); + + checkCompleteness(); +} + +void CodeGenSchedModels::collectRetireControlUnits() { + RecVec Units = Records.getAllDerivedDefinitions("RetireControlUnit"); + + for (Record *RCU : Units) { + CodeGenProcModel &PM = getProcModel(RCU->getValueAsDef("SchedModel")); + if (PM.RetireControlUnit) { + PrintError(RCU->getLoc(), + "Expected a single RetireControlUnit definition"); + PrintNote(PM.RetireControlUnit->getLoc(), + "Previous definition of RetireControlUnit was here"); + } + PM.RetireControlUnit = RCU; + } +} + +/// Collect optional processor information. +void CodeGenSchedModels::collectOptionalProcessorInfo() { + // Find register file definitions for each processor. + collectRegisterFiles(); + + // Collect processor RetireControlUnit descriptors if available. + collectRetireControlUnits(); + + // Find pfm counter definitions for each processor. + collectPfmCounters(); + checkCompleteness(); } /// Gather all processor models. void CodeGenSchedModels::collectProcModels() { RecVec ProcRecords = Records.getAllDerivedDefinitions("Processor"); - std::sort(ProcRecords.begin(), ProcRecords.end(), LessRecordFieldName()); + llvm::sort(ProcRecords.begin(), ProcRecords.end(), LessRecordFieldName()); // Reserve space because we can. Reallocation would be ok. ProcModels.reserve(ProcRecords.size()+1); @@ -160,7 +269,7 @@ void CodeGenSchedModels::collectProcModels() { ProcModelMap[NoModelDef] = 0; // For each processor, find a unique machine model. - DEBUG(dbgs() << "+++ PROCESSOR MODELs (addProcModel) +++\n"); + LLVM_DEBUG(dbgs() << "+++ PROCESSOR MODELs (addProcModel) +++\n"); for (Record *ProcRecord : ProcRecords) addProcModel(ProcRecord); } @@ -184,7 +293,7 @@ void CodeGenSchedModels::addProcModel(Record *ProcDef) { ProcModels.emplace_back(ProcModels.size(), Name, ProcDef->getValueAsDef("SchedModel"), ModelKey); } - DEBUG(ProcModels.back().dump()); + LLVM_DEBUG(ProcModels.back().dump()); } // Recursively find all reachable SchedReadWrite records. @@ -267,7 +376,7 @@ void CodeGenSchedModels::collectSchedRW() { // Find all ReadWrites referenced by SchedAlias. AliasDefs needs to be sorted // for the loop below that initializes Alias vectors. RecVec AliasDefs = Records.getAllDerivedDefinitions("SchedAlias"); - std::sort(AliasDefs.begin(), AliasDefs.end(), LessRecord()); + llvm::sort(AliasDefs.begin(), AliasDefs.end(), LessRecord()); for (Record *ADef : AliasDefs) { Record *MatchDef = ADef->getValueAsDef("MatchRW"); Record *AliasDef = ADef->getValueAsDef("AliasRW"); @@ -285,12 +394,12 @@ void CodeGenSchedModels::collectSchedRW() { } // Sort and add the SchedReadWrites directly referenced by instructions or // itinerary resources. Index reads and writes in separate domains. - std::sort(SWDefs.begin(), SWDefs.end(), LessRecord()); + llvm::sort(SWDefs.begin(), SWDefs.end(), LessRecord()); for (Record *SWDef : SWDefs) { assert(!getSchedRWIdx(SWDef, /*IsRead=*/false) && "duplicate SchedWrite"); SchedWrites.emplace_back(SchedWrites.size(), SWDef); } - std::sort(SRDefs.begin(), SRDefs.end(), LessRecord()); + llvm::sort(SRDefs.begin(), SRDefs.end(), LessRecord()); for (Record *SRDef : SRDefs) { assert(!getSchedRWIdx(SRDef, /*IsRead-*/true) && "duplicate SchedWrite"); SchedReads.emplace_back(SchedReads.size(), SRDef); @@ -312,26 +421,26 @@ void CodeGenSchedModels::collectSchedRW() { PrintFatalError(ADef->getLoc(), "Cannot Alias an Alias"); RW.Aliases.push_back(ADef); } - DEBUG( - dbgs() << "\n+++ SCHED READS and WRITES (collectSchedRW) +++\n"; - for (unsigned WIdx = 0, WEnd = SchedWrites.size(); WIdx != WEnd; ++WIdx) { - dbgs() << WIdx << ": "; - SchedWrites[WIdx].dump(); - dbgs() << '\n'; - } - for (unsigned RIdx = 0, REnd = SchedReads.size(); RIdx != REnd; ++RIdx) { - dbgs() << RIdx << ": "; - SchedReads[RIdx].dump(); - dbgs() << '\n'; - } - RecVec RWDefs = Records.getAllDerivedDefinitions("SchedReadWrite"); - for (Record *RWDef : RWDefs) { - if (!getSchedRWIdx(RWDef, RWDef->isSubClassOf("SchedRead"))) { - const std::string &Name = RWDef->getName(); - if (Name != "NoWrite" && Name != "ReadDefault") - dbgs() << "Unused SchedReadWrite " << RWDef->getName() << '\n'; - } - }); + LLVM_DEBUG( + dbgs() << "\n+++ SCHED READS and WRITES (collectSchedRW) +++\n"; + for (unsigned WIdx = 0, WEnd = SchedWrites.size(); WIdx != WEnd; ++WIdx) { + dbgs() << WIdx << ": "; + SchedWrites[WIdx].dump(); + dbgs() << '\n'; + } for (unsigned RIdx = 0, REnd = SchedReads.size(); RIdx != REnd; + ++RIdx) { + dbgs() << RIdx << ": "; + SchedReads[RIdx].dump(); + dbgs() << '\n'; + } RecVec RWDefs = Records.getAllDerivedDefinitions("SchedReadWrite"); + for (Record *RWDef + : RWDefs) { + if (!getSchedRWIdx(RWDef, RWDef->isSubClassOf("SchedRead"))) { + StringRef Name = RWDef->getName(); + if (Name != "NoWrite" && Name != "ReadDefault") + dbgs() << "Unused SchedReadWrite " << Name << '\n'; + } + }); } /// Compute a SchedWrite name from a sequence of writes. @@ -346,16 +455,12 @@ std::string CodeGenSchedModels::genRWName(ArrayRef<unsigned> Seq, bool IsRead) { return Name; } -unsigned CodeGenSchedModels::getSchedRWIdx(Record *Def, bool IsRead, - unsigned After) const { +unsigned CodeGenSchedModels::getSchedRWIdx(const Record *Def, + bool IsRead) const { const std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites; - assert(After < RWVec.size() && "start position out of bounds"); - for (std::vector<CodeGenSchedRW>::const_iterator I = RWVec.begin() + After, - E = RWVec.end(); I != E; ++I) { - if (I->TheDef == Def) - return I - RWVec.begin(); - } - return 0; + const auto I = find_if( + RWVec, [Def](const CodeGenSchedRW &RW) { return RW.TheDef == Def; }); + return I == RWVec.end() ? 0 : std::distance(RWVec.begin(), I); } bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const { @@ -372,10 +477,8 @@ bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const { return false; } -namespace llvm { - -void splitSchedReadWrites(const RecVec &RWDefs, - RecVec &WriteDefs, RecVec &ReadDefs) { +static void splitSchedReadWrites(const RecVec &RWDefs, + RecVec &WriteDefs, RecVec &ReadDefs) { for (Record *RWDef : RWDefs) { if (RWDef->isSubClassOf("SchedWrite")) WriteDefs.push_back(RWDef); @@ -386,16 +489,14 @@ void splitSchedReadWrites(const RecVec &RWDefs, } } -} // end namespace llvm - // Split the SchedReadWrites defs and call findRWs for each list. void CodeGenSchedModels::findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const { - RecVec WriteDefs; - RecVec ReadDefs; - splitSchedReadWrites(RWDefs, WriteDefs, ReadDefs); - findRWs(WriteDefs, Writes, false); - findRWs(ReadDefs, Reads, true); + RecVec WriteDefs; + RecVec ReadDefs; + splitSchedReadWrites(RWDefs, WriteDefs, ReadDefs); + findRWs(WriteDefs, Writes, false); + findRWs(ReadDefs, Reads, true); } // Call getSchedRWIdx for all elements in a sequence of SchedRW defs. @@ -432,11 +533,10 @@ void CodeGenSchedModels::expandRWSeqForProc( const CodeGenSchedRW &SchedWrite = getSchedRW(RWIdx, IsRead); Record *AliasDef = nullptr; - for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end(); - AI != AE; ++AI) { - const CodeGenSchedRW &AliasRW = getSchedRW((*AI)->getValueAsDef("AliasRW")); - if ((*AI)->getValueInit("SchedModel")->isComplete()) { - Record *ModelDef = (*AI)->getValueAsDef("SchedModel"); + for (const Record *Rec : SchedWrite.Aliases) { + const CodeGenSchedRW &AliasRW = getSchedRW(Rec->getValueAsDef("AliasRW")); + if (Rec->getValueInit("SchedModel")->isComplete()) { + Record *ModelDef = Rec->getValueAsDef("SchedModel"); if (&getProcModel(ModelDef) != &ProcModel) continue; } @@ -457,9 +557,9 @@ void CodeGenSchedModels::expandRWSeqForProc( } int Repeat = SchedWrite.TheDef ? SchedWrite.TheDef->getValueAsInt("Repeat") : 1; - for (int i = 0; i < Repeat; ++i) { - for (unsigned I : SchedWrite.Sequence) { - expandRWSeqForProc(I, RWSeq, IsRead, ProcModel); + for (int I = 0, E = Repeat; I < E; ++I) { + for (unsigned Idx : SchedWrite.Sequence) { + expandRWSeqForProc(Idx, RWSeq, IsRead, ProcModel); } } } @@ -469,13 +569,11 @@ 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 (makeArrayRef(I->Sequence) == Seq) - return I - RWVec.begin(); - } + auto I = find_if(RWVec, [Seq](CodeGenSchedRW &RW) { + return makeArrayRef(RW.Sequence) == Seq; + }); // Index zero reserved for invalid RW. - return 0; + return I == RWVec.end() ? 0 : std::distance(RWVec.begin(), I); } /// Add this ReadWrite if it doesn't already exist. @@ -489,12 +587,10 @@ unsigned CodeGenSchedModels::findOrInsertRW(ArrayRef<unsigned> Seq, if (Idx) return Idx; - unsigned RWIdx = IsRead ? SchedReads.size() : SchedWrites.size(); + std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites; + unsigned RWIdx = RWVec.size(); CodeGenSchedRW SchedRW(RWIdx, IsRead, Seq, genRWName(Seq, IsRead)); - if (IsRead) - SchedReads.push_back(SchedRW); - else - SchedWrites.push_back(SchedRW); + RWVec.push_back(SchedRW); return RWIdx; } @@ -504,10 +600,9 @@ unsigned CodeGenSchedModels::findOrInsertRW(ArrayRef<unsigned> Seq, void CodeGenSchedModels::collectSchedClasses() { // NoItinerary is always the first class at Idx=0 - SchedClasses.resize(1); - SchedClasses.back().Index = 0; - SchedClasses.back().Name = "NoInstrModel"; - SchedClasses.back().ItinClassDef = Records.getDef("NoItinerary"); + assert(SchedClasses.empty() && "Expected empty sched class"); + SchedClasses.emplace_back(0, "NoInstrModel", + Records.getDef("NoItinerary")); SchedClasses.back().ProcIndices.push_back(0); // Create a SchedClass for each unique combination of itinerary class and @@ -519,32 +614,34 @@ void CodeGenSchedModels::collectSchedClasses() { 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); + unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, /*ProcIndices*/{0}); InstrClassMap[Inst->TheDef] = SCIdx; } // Create classes for InstRW defs. RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW"); - std::sort(InstRWDefs.begin(), InstRWDefs.end(), LessRecord()); - DEBUG(dbgs() << "\n+++ SCHED CLASSES (createInstRWClass) +++\n"); + llvm::sort(InstRWDefs.begin(), InstRWDefs.end(), LessRecord()); + LLVM_DEBUG(dbgs() << "\n+++ SCHED CLASSES (createInstRWClass) +++\n"); for (Record *RWDef : InstRWDefs) createInstRWClass(RWDef); NumInstrSchedClasses = SchedClasses.size(); bool EnableDump = false; - DEBUG(EnableDump = true); + LLVM_DEBUG(EnableDump = true); if (!EnableDump) return; - dbgs() << "\n+++ ITINERARIES and/or MACHINE MODELS (collectSchedClasses) +++\n"; + LLVM_DEBUG( + dbgs() + << "\n+++ ITINERARIES and/or MACHINE MODELS (collectSchedClasses) +++\n"); for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { StringRef InstName = Inst->TheDef->getName(); - unsigned SCIdx = InstrClassMap.lookup(Inst->TheDef); + unsigned SCIdx = getSchedClassIdx(*Inst); if (!SCIdx) { - if (!Inst->hasNoSchedulingInfo) - dbgs() << "No machine model for " << Inst->TheDef->getName() << '\n'; + LLVM_DEBUG({ + if (!Inst->hasNoSchedulingInfo) + dbgs() << "No machine model for " << Inst->TheDef->getName() << '\n'; + }); continue; } CodeGenSchedClass &SC = getSchedClass(SCIdx); @@ -560,58 +657,51 @@ void CodeGenSchedModels::collectSchedClasses() { } if (!SC.Writes.empty()) { ProcIndices.push_back(0); - dbgs() << "SchedRW machine model for " << InstName; - for (IdxIter WI = SC.Writes.begin(), WE = SC.Writes.end(); WI != WE; ++WI) - dbgs() << " " << SchedWrites[*WI].Name; - for (IdxIter RI = SC.Reads.begin(), RE = SC.Reads.end(); RI != RE; ++RI) - dbgs() << " " << SchedReads[*RI].Name; - dbgs() << '\n'; + LLVM_DEBUG({ + dbgs() << "SchedRW machine model for " << InstName; + for (IdxIter WI = SC.Writes.begin(), WE = SC.Writes.end(); WI != WE; + ++WI) + dbgs() << " " << SchedWrites[*WI].Name; + for (IdxIter RI = SC.Reads.begin(), RE = SC.Reads.end(); RI != RE; ++RI) + dbgs() << " " << SchedReads[*RI].Name; + dbgs() << '\n'; + }); } const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs; for (Record *RWDef : RWDefs) { const CodeGenProcModel &ProcModel = - getProcModel(RWDef->getValueAsDef("SchedModel")); + getProcModel(RWDef->getValueAsDef("SchedModel")); ProcIndices.push_back(ProcModel.Index); - dbgs() << "InstRW on " << ProcModel.ModelName << " for " << InstName; + LLVM_DEBUG(dbgs() << "InstRW on " << ProcModel.ModelName << " for " + << InstName); IdxVec Writes; IdxVec Reads; findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads); - for (unsigned WIdx : Writes) - dbgs() << " " << SchedWrites[WIdx].Name; - for (unsigned RIdx : Reads) - dbgs() << " " << SchedReads[RIdx].Name; - dbgs() << '\n'; + LLVM_DEBUG({ + for (unsigned WIdx : Writes) + dbgs() << " " << SchedWrites[WIdx].Name; + for (unsigned RIdx : Reads) + dbgs() << " " << SchedReads[RIdx].Name; + dbgs() << '\n'; + }); } // If ProcIndices contains zero, the class applies to all processors. - if (!std::count(ProcIndices.begin(), ProcIndices.end(), 0)) { - for (const CodeGenProcModel &PM : ProcModels) { - if (!std::count(ProcIndices.begin(), ProcIndices.end(), PM.Index)) - dbgs() << "No machine model for " << Inst->TheDef->getName() - << " on processor " << PM.ModelName << '\n'; + LLVM_DEBUG({ + if (!std::count(ProcIndices.begin(), ProcIndices.end(), 0)) { + for (const CodeGenProcModel &PM : ProcModels) { + if (!std::count(ProcIndices.begin(), ProcIndices.end(), PM.Index)) + dbgs() << "No machine model for " << Inst->TheDef->getName() + << " on processor " << PM.ModelName << '\n'; + } } - } - } -} - -/// Find an SchedClass that has been inferred from a per-operand list of -/// SchedWrites and SchedReads. -unsigned CodeGenSchedModels::findSchedClassIdx(Record *ItinClassDef, - ArrayRef<unsigned> Writes, - ArrayRef<unsigned> Reads) const { - for (SchedClassIter I = schedClassBegin(), E = schedClassEnd(); I != E; ++I) { - if (I->ItinClassDef == ItinClassDef && makeArrayRef(I->Writes) == Writes && - makeArrayRef(I->Reads) == Reads) { - return I - schedClassBegin(); - } + }); } - return 0; } // Get the SchedClass index for an instruction. -unsigned CodeGenSchedModels::getSchedClassIdx( - const CodeGenInstruction &Inst) const { - +unsigned +CodeGenSchedModels::getSchedClassIdx(const CodeGenInstruction &Inst) const { return InstrClassMap.lookup(Inst.TheDef); } @@ -655,22 +745,27 @@ unsigned CodeGenSchedModels::addSchedClass(Record *ItinClassDef, ArrayRef<unsigned> ProcIndices) { assert(!ProcIndices.empty() && "expect at least one ProcIdx"); - unsigned Idx = findSchedClassIdx(ItinClassDef, OperWrites, OperReads); + auto IsKeyEqual = [=](const CodeGenSchedClass &SC) { + return SC.isKeyEqual(ItinClassDef, OperWrites, OperReads); + }; + + auto I = find_if(make_range(schedClassBegin(), schedClassEnd()), IsKeyEqual); + unsigned Idx = I == schedClassEnd() ? 0 : std::distance(schedClassBegin(), I); if (Idx || SchedClasses[0].isKeyEqual(ItinClassDef, OperWrites, OperReads)) { IdxVec PI; std::set_union(SchedClasses[Idx].ProcIndices.begin(), SchedClasses[Idx].ProcIndices.end(), ProcIndices.begin(), ProcIndices.end(), std::back_inserter(PI)); - SchedClasses[Idx].ProcIndices.swap(PI); + SchedClasses[Idx].ProcIndices = std::move(PI); return Idx; } Idx = SchedClasses.size(); - SchedClasses.resize(Idx+1); + SchedClasses.emplace_back(Idx, + createSchedClassName(ItinClassDef, OperWrites, + OperReads), + ItinClassDef); CodeGenSchedClass &SC = SchedClasses.back(); - SC.Index = Idx; - SC.Name = createSchedClassName(ItinClassDef, OperWrites, OperReads); - SC.ItinClassDef = ItinClassDef; SC.Writes = OperWrites; SC.Reads = OperReads; SC.ProcIndices = ProcIndices; @@ -685,106 +780,104 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { // intersects with an existing class via a previous InstRWDef. Instrs that do // not intersect with an existing class refer back to their former class as // determined from ItinDef or SchedRW. - SmallVector<std::pair<unsigned, SmallVector<Record *, 8>>, 4> ClassInstrs; + SmallMapVector<unsigned, SmallVector<Record *, 8>, 4> ClassInstrs; // Sort Instrs into sets. const RecVec *InstDefs = Sets.expand(InstRWDef); if (InstDefs->empty()) PrintFatalError(InstRWDef->getLoc(), "No matching instruction opcodes"); - for (Record *InstDef : make_range(InstDefs->begin(), InstDefs->end())) { + for (Record *InstDef : *InstDefs) { InstClassMapTy::const_iterator Pos = InstrClassMap.find(InstDef); if (Pos == InstrClassMap.end()) PrintFatalError(InstDef->getLoc(), "No sched class for instruction."); unsigned SCIdx = Pos->second; - unsigned CIdx = 0, CEnd = ClassInstrs.size(); - for (; CIdx != CEnd; ++CIdx) { - if (ClassInstrs[CIdx].first == SCIdx) - break; - } - if (CIdx == CEnd) { - ClassInstrs.resize(CEnd + 1); - ClassInstrs[CIdx].first = SCIdx; - } - ClassInstrs[CIdx].second.push_back(InstDef); + ClassInstrs[SCIdx].push_back(InstDef); } // For each set of Instrs, create a new class if necessary, and map or remap // the Instrs to it. - unsigned CIdx = 0, CEnd = ClassInstrs.size(); - for (; CIdx != CEnd; ++CIdx) { - unsigned OldSCIdx = ClassInstrs[CIdx].first; - ArrayRef<Record*> InstDefs = ClassInstrs[CIdx].second; + for (auto &Entry : ClassInstrs) { + unsigned OldSCIdx = Entry.first; + ArrayRef<Record*> InstDefs = Entry.second; // If the all instrs in the current class are accounted for, then leave // them mapped to their old class. if (OldSCIdx) { const RecVec &RWDefs = SchedClasses[OldSCIdx].InstRWs; if (!RWDefs.empty()) { const RecVec *OrigInstDefs = Sets.expand(RWDefs[0]); - unsigned OrigNumInstrs = 0; - for (Record *OIDef : make_range(OrigInstDefs->begin(), OrigInstDefs->end())) { - if (InstrClassMap[OIDef] == OldSCIdx) - ++OrigNumInstrs; - } + unsigned OrigNumInstrs = + count_if(*OrigInstDefs, [&](Record *OIDef) { + return InstrClassMap[OIDef] == OldSCIdx; + }); if (OrigNumInstrs == InstDefs.size()) { assert(SchedClasses[OldSCIdx].ProcIndices[0] == 0 && "expected a generic SchedClass"); - DEBUG(dbgs() << "InstRW: Reuse SC " << OldSCIdx << ":" - << SchedClasses[OldSCIdx].Name << " on " - << InstRWDef->getValueAsDef("SchedModel")->getName() << "\n"); + Record *RWModelDef = InstRWDef->getValueAsDef("SchedModel"); + // Make sure we didn't already have a InstRW containing this + // instruction on this model. + for (Record *RWD : RWDefs) { + if (RWD->getValueAsDef("SchedModel") == RWModelDef && + RWModelDef->getValueAsBit("FullInstRWOverlapCheck")) { + for (Record *Inst : InstDefs) { + PrintFatalError(InstRWDef->getLoc(), "Overlapping InstRW def " + + Inst->getName() + " also matches " + + RWD->getValue("Instrs")->getValue()->getAsString()); + } + } + } + LLVM_DEBUG(dbgs() << "InstRW: Reuse SC " << OldSCIdx << ":" + << SchedClasses[OldSCIdx].Name << " on " + << RWModelDef->getName() << "\n"); SchedClasses[OldSCIdx].InstRWs.push_back(InstRWDef); continue; } } } unsigned SCIdx = SchedClasses.size(); - SchedClasses.resize(SCIdx+1); + SchedClasses.emplace_back(SCIdx, createSchedClassName(InstDefs), nullptr); CodeGenSchedClass &SC = SchedClasses.back(); - SC.Index = SCIdx; - SC.Name = createSchedClassName(InstDefs); - DEBUG(dbgs() << "InstRW: New SC " << SCIdx << ":" << SC.Name << " on " - << InstRWDef->getValueAsDef("SchedModel")->getName() << "\n"); + LLVM_DEBUG(dbgs() << "InstRW: New SC " << SCIdx << ":" << SC.Name << " on " + << InstRWDef->getValueAsDef("SchedModel")->getName() + << "\n"); // Preserve ItinDef and Writes/Reads for processors without an InstRW entry. SC.ItinClassDef = SchedClasses[OldSCIdx].ItinClassDef; SC.Writes = SchedClasses[OldSCIdx].Writes; SC.Reads = SchedClasses[OldSCIdx].Reads; SC.ProcIndices.push_back(0); - // Map each Instr to this new class. - // Note that InstDefs may be a smaller list than InstRWDef's "Instrs". - Record *RWModelDef = InstRWDef->getValueAsDef("SchedModel"); - SmallSet<unsigned, 4> RemappedClassIDs; - for (ArrayRef<Record*>::const_iterator - II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) { - unsigned OldSCIdx = InstrClassMap[*II]; - 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) { - PrintFatalError(InstRWDef->getLoc(), "Overlapping InstRW def " + - (*II)->getName() + " also matches " + - (*RI)->getValue("Instrs")->getValue()->getAsString()); + // If we had an old class, copy it's InstRWs to this new class. + if (OldSCIdx) { + Record *RWModelDef = InstRWDef->getValueAsDef("SchedModel"); + for (Record *OldRWDef : SchedClasses[OldSCIdx].InstRWs) { + if (OldRWDef->getValueAsDef("SchedModel") == RWModelDef) { + for (Record *InstDef : InstDefs) { + PrintFatalError(OldRWDef->getLoc(), "Overlapping InstRW def " + + InstDef->getName() + " also matches " + + OldRWDef->getValue("Instrs")->getValue()->getAsString()); } - assert(*RI != InstRWDef && "SchedClass has duplicate InstRW def"); - SC.InstRWs.push_back(*RI); } + assert(OldRWDef != InstRWDef && + "SchedClass has duplicate InstRW def"); + SC.InstRWs.push_back(OldRWDef); } - InstrClassMap[*II] = SCIdx; } + // Map each Instr to this new class. + for (Record *InstDef : InstDefs) + InstrClassMap[InstDef] = SCIdx; SC.InstRWs.push_back(InstRWDef); } } // True if collectProcItins found anything. bool CodeGenSchedModels::hasItineraries() const { - for (const CodeGenProcModel &PM : make_range(procModelBegin(),procModelEnd())) { + for (const CodeGenProcModel &PM : make_range(procModelBegin(),procModelEnd())) if (PM.hasItineraries()) return true; - } return false; } // Gather the processor itineraries. void CodeGenSchedModels::collectProcItins() { - DEBUG(dbgs() << "\n+++ PROBLEM ITINERARIES (collectProcItins) +++\n"); + LLVM_DEBUG(dbgs() << "\n+++ PROBLEM ITINERARIES (collectProcItins) +++\n"); for (CodeGenProcModel &ProcModel : ProcModels) { if (!ProcModel.hasItineraries()) continue; @@ -798,37 +891,39 @@ void CodeGenSchedModels::collectProcItins() { // Insert each itinerary data record in the correct position within // the processor model's ItinDefList. for (Record *ItinData : ItinRecords) { - Record *ItinDef = ItinData->getValueAsDef("TheClass"); + const Record *ItinDef = ItinData->getValueAsDef("TheClass"); bool FoundClass = false; - for (SchedClassIter SCI = schedClassBegin(), SCE = schedClassEnd(); - SCI != SCE; ++SCI) { + + for (const CodeGenSchedClass &SC : + make_range(schedClassBegin(), schedClassEnd())) { // Multiple SchedClasses may share an itinerary. Update all of them. - if (SCI->ItinClassDef == ItinDef) { - ProcModel.ItinDefList[SCI->Index] = ItinData; + if (SC.ItinClassDef == ItinDef) { + ProcModel.ItinDefList[SC.Index] = ItinData; FoundClass = true; } } if (!FoundClass) { - DEBUG(dbgs() << ProcModel.ItinsDef->getName() - << " missing class for itinerary " << ItinDef->getName() << '\n'); + LLVM_DEBUG(dbgs() << ProcModel.ItinsDef->getName() + << " missing class for itinerary " + << ItinDef->getName() << '\n'); } } // Check for missing itinerary entries. assert(!ProcModel.ItinDefList[0] && "NoItinerary class can't have rec"); - DEBUG( - for (unsigned i = 1, N = ProcModel.ItinDefList.size(); i < N; ++i) { - if (!ProcModel.ItinDefList[i]) - dbgs() << ProcModel.ItinsDef->getName() - << " missing itinerary for class " - << SchedClasses[i].Name << '\n'; - }); + LLVM_DEBUG( + for (unsigned i = 1, N = ProcModel.ItinDefList.size(); i < N; ++i) { + if (!ProcModel.ItinDefList[i]) + dbgs() << ProcModel.ItinsDef->getName() + << " missing itinerary for class " << SchedClasses[i].Name + << '\n'; + }); } } // Gather the read/write types for each itinerary class. void CodeGenSchedModels::collectProcItinRW() { RecVec ItinRWDefs = Records.getAllDerivedDefinitions("ItinRW"); - std::sort(ItinRWDefs.begin(), ItinRWDefs.end(), LessRecord()); + llvm::sort(ItinRWDefs.begin(), ItinRWDefs.end(), LessRecord()); for (Record *RWDef : ItinRWDefs) { if (!RWDef->getValueInit("SchedModel")->isComplete()) PrintFatalError(RWDef->getLoc(), "SchedModel is undefined"); @@ -854,8 +949,9 @@ void CodeGenSchedModels::collectProcUnsupportedFeatures() { /// Infer new classes from existing classes. In the process, this may create new /// SchedWrites from sequences of existing SchedWrites. void CodeGenSchedModels::inferSchedClasses() { - DEBUG(dbgs() << "\n+++ INFERRING SCHED CLASSES (inferSchedClasses) +++\n"); - DEBUG(dbgs() << NumInstrSchedClasses << " instr sched classes.\n"); + LLVM_DEBUG( + dbgs() << "\n+++ INFERRING SCHED CLASSES (inferSchedClasses) +++\n"); + LLVM_DEBUG(dbgs() << NumInstrSchedClasses << " instr sched classes.\n"); // Visit all existing classes and newly created classes. for (unsigned Idx = 0; Idx != SchedClasses.size(); ++Idx) { @@ -881,20 +977,18 @@ void CodeGenSchedModels::inferFromItinClass(Record *ItinClassDef, const CodeGenProcModel &PM = ProcModels[PIdx]; // For all ItinRW entries. bool HasMatch = false; - for (RecIter II = PM.ItinRWDefs.begin(), IE = PM.ItinRWDefs.end(); - II != IE; ++II) { - RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses"); + for (const Record *Rec : PM.ItinRWDefs) { + RecVec Matched = Rec->getValueAsListOfDefs("MatchedItinClasses"); if (!std::count(Matched.begin(), Matched.end(), ItinClassDef)) continue; if (HasMatch) - PrintFatalError((*II)->getLoc(), "Duplicate itinerary class " + PrintFatalError(Rec->getLoc(), "Duplicate itinerary class " + ItinClassDef->getName() + " in ItinResources for " + PM.ModelName); HasMatch = true; IdxVec Writes, Reads; - findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads); - IdxVec ProcIndices(1, PIdx); - inferFromRW(Writes, Reads, FromClassIdx, ProcIndices); + findRWs(Rec->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads); + inferFromRW(Writes, Reads, FromClassIdx, PIdx); } } } @@ -917,8 +1011,7 @@ void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) { IdxVec Writes, Reads; findRWs(Rec->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads); unsigned PIdx = getProcModel(Rec->getValueAsDef("SchedModel")).Index; - IdxVec ProcIndices(1, PIdx); - inferFromRW(Writes, Reads, SCIdx, ProcIndices); // May mutate SchedClasses. + inferFromRW(Writes, Reads, SCIdx, PIdx); // May mutate SchedClasses. } } @@ -1001,10 +1094,10 @@ bool PredTransitions::mutuallyExclusive(Record *PredDef, const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(PC.RWIdx, PC.IsRead); assert(SchedRW.HasVariants && "PredCheck must refer to a SchedVariant"); RecVec Variants = SchedRW.TheDef->getValueAsListOfDefs("Variants"); - for (RecIter VI = Variants.begin(), VE = Variants.end(); VI != VE; ++VI) { - if ((*VI)->getValueAsDef("Predicate") == PredDef) - return true; - } + if (any_of(Variants, [PredDef](const Record *R) { + return R->getValueAsDef("Predicate") == PredDef; + })) + return true; } return false; } @@ -1022,12 +1115,10 @@ static bool hasAliasedVariants(const CodeGenSchedRW &RW, if (AliasRW.IsSequence) { IdxVec ExpandedRWs; SchedModels.expandRWSequence(AliasRW.Index, ExpandedRWs, AliasRW.IsRead); - for (IdxIter SI = ExpandedRWs.begin(), SE = ExpandedRWs.end(); - SI != SE; ++SI) { - if (hasAliasedVariants(SchedModels.getSchedRW(*SI, AliasRW.IsRead), - SchedModels)) { + for (unsigned SI : ExpandedRWs) { + if (hasAliasedVariants(SchedModels.getSchedRW(SI, AliasRW.IsRead), + SchedModels)) return true; - } } } } @@ -1036,27 +1127,16 @@ static bool hasAliasedVariants(const CodeGenSchedRW &RW, static bool hasVariant(ArrayRef<PredTransition> Transitions, CodeGenSchedModels &SchedModels) { - for (ArrayRef<PredTransition>::iterator - PTI = Transitions.begin(), PTE = Transitions.end(); - PTI != PTE; ++PTI) { - for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator - WSI = PTI->WriteSequences.begin(), WSE = PTI->WriteSequences.end(); - WSI != WSE; ++WSI) { - for (SmallVectorImpl<unsigned>::const_iterator - WI = WSI->begin(), WE = WSI->end(); WI != WE; ++WI) { - if (hasAliasedVariants(SchedModels.getSchedWrite(*WI), SchedModels)) + for (const PredTransition &PTI : Transitions) { + for (const SmallVectorImpl<unsigned> &WSI : PTI.WriteSequences) + for (unsigned WI : WSI) + if (hasAliasedVariants(SchedModels.getSchedWrite(WI), SchedModels)) return true; - } - } - for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator - RSI = PTI->ReadSequences.begin(), RSE = PTI->ReadSequences.end(); - RSI != RSE; ++RSI) { - for (SmallVectorImpl<unsigned>::const_iterator - RI = RSI->begin(), RE = RSI->end(); RI != RE; ++RI) { - if (hasAliasedVariants(SchedModels.getSchedRead(*RI), SchedModels)) + + for (const SmallVectorImpl<unsigned> &RSI : PTI.ReadSequences) + for (unsigned RI : RSI) + if (hasAliasedVariants(SchedModels.getSchedRead(RI), SchedModels)) return true; - } - } } return false; } @@ -1080,7 +1160,7 @@ void PredTransitions::getIntersectingVariants( // Push each variant. Assign TransVecIdx later. const RecVec VarDefs = SchedRW.TheDef->getValueAsListOfDefs("Variants"); for (Record *VarDef : VarDefs) - Variants.push_back(TransVariant(VarDef, SchedRW.Index, VarProcIdx, 0)); + Variants.emplace_back(VarDef, SchedRW.Index, VarProcIdx, 0); if (VarProcIdx == 0) GenericRW = true; } @@ -1100,12 +1180,10 @@ void PredTransitions::getIntersectingVariants( if (AliasRW.HasVariants) { const RecVec VarDefs = AliasRW.TheDef->getValueAsListOfDefs("Variants"); for (Record *VD : VarDefs) - Variants.push_back(TransVariant(VD, AliasRW.Index, AliasProcIdx, 0)); - } - if (AliasRW.IsSequence) { - Variants.push_back( - TransVariant(AliasRW.TheDef, SchedRW.Index, AliasProcIdx, 0)); + Variants.emplace_back(VD, AliasRW.Index, AliasProcIdx, 0); } + if (AliasRW.IsSequence) + Variants.emplace_back(AliasRW.TheDef, SchedRW.Index, AliasProcIdx, 0); if (AliasProcIdx == 0) GenericRW = true; } @@ -1164,7 +1242,7 @@ pushVariant(const TransVariant &VInfo, bool IsRead) { IdxVec SelectedRWs; if (VInfo.VarOrSeqDef->isSubClassOf("SchedVar")) { Record *PredDef = VInfo.VarOrSeqDef->getValueAsDef("Predicate"); - Trans.PredTerm.push_back(PredCheck(IsRead, VInfo.RWIdx,PredDef)); + Trans.PredTerm.emplace_back(IsRead, VInfo.RWIdx,PredDef); RecVec SelectedDefs = VInfo.VarOrSeqDef->getValueAsListOfDefs("Selected"); SchedModels.findRWs(SelectedDefs, SelectedRWs, IsRead); } @@ -1181,11 +1259,8 @@ pushVariant(const TransVariant &VInfo, bool IsRead) { if (SchedRW.IsVariadic) { unsigned OperIdx = RWSequences.size()-1; // Make N-1 copies of this transition's last sequence. - for (unsigned i = 1, e = SelectedRWs.size(); i != e; ++i) { - // Create a temporary copy the vector could reallocate. - RWSequences.reserve(RWSequences.size() + 1); - RWSequences.push_back(RWSequences[OperIdx]); - } + RWSequences.insert(RWSequences.end(), SelectedRWs.size() - 1, + RWSequences[OperIdx]); // Push each of the N elements of the SelectedRWs onto a copy of the last // sequence (split the current operand into N operands). // Note that write sequences should be expanded within this loop--the entire @@ -1267,7 +1342,7 @@ void PredTransitions::substituteVariants(const PredTransition &Trans) { // Build up a set of partial results starting at the back of // PredTransitions. Remember the first new transition. unsigned StartIdx = TransVec.size(); - TransVec.resize(TransVec.size() + 1); + TransVec.emplace_back(); TransVec.back().PredTerm = Trans.PredTerm; TransVec.back().ProcIndices = Trans.ProcIndices; @@ -1278,7 +1353,7 @@ void PredTransitions::substituteVariants(const PredTransition &Trans) { // Push a new (empty) write sequence onto all partial Transitions. for (std::vector<PredTransition>::iterator I = TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) { - I->WriteSequences.resize(I->WriteSequences.size() + 1); + I->WriteSequences.emplace_back(); } substituteVariantOperand(*WSI, /*IsRead=*/false, StartIdx); } @@ -1289,7 +1364,7 @@ void PredTransitions::substituteVariants(const PredTransition &Trans) { // Push a new (empty) read sequence onto all partial Transitions. for (std::vector<PredTransition>::iterator I = TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) { - I->ReadSequences.resize(I->ReadSequences.size() + 1); + I->ReadSequences.emplace_back(); } substituteVariantOperand(*RSI, /*IsRead=*/true, StartIdx); } @@ -1304,37 +1379,30 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions, for (ArrayRef<PredTransition>::iterator I = LastTransitions.begin(), E = LastTransitions.end(); I != E; ++I) { IdxVec OperWritesVariant; - for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator - WSI = I->WriteSequences.begin(), WSE = I->WriteSequences.end(); - WSI != WSE; ++WSI) { - // Create a new write representing the expanded sequence. - OperWritesVariant.push_back( - SchedModels.findOrInsertRW(*WSI, /*IsRead=*/false)); - } + transform(I->WriteSequences, std::back_inserter(OperWritesVariant), + [&SchedModels](ArrayRef<unsigned> WS) { + return SchedModels.findOrInsertRW(WS, /*IsRead=*/false); + }); IdxVec OperReadsVariant; - for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator - RSI = I->ReadSequences.begin(), RSE = I->ReadSequences.end(); - RSI != RSE; ++RSI) { - // Create a new read representing the expanded sequence. - OperReadsVariant.push_back( - SchedModels.findOrInsertRW(*RSI, /*IsRead=*/true)); - } - IdxVec ProcIndices(I->ProcIndices.begin(), I->ProcIndices.end()); + transform(I->ReadSequences, std::back_inserter(OperReadsVariant), + [&SchedModels](ArrayRef<unsigned> RS) { + return SchedModels.findOrInsertRW(RS, /*IsRead=*/true); + }); CodeGenSchedTransition SCTrans; SCTrans.ToClassIdx = SchedModels.addSchedClass(/*ItinClassDef=*/nullptr, OperWritesVariant, - OperReadsVariant, ProcIndices); - SCTrans.ProcIndices = ProcIndices; + OperReadsVariant, I->ProcIndices); + SCTrans.ProcIndices.assign(I->ProcIndices.begin(), I->ProcIndices.end()); // The final PredTerm is unique set of predicates guarding the transition. RecVec Preds; - for (SmallVectorImpl<PredCheck>::const_iterator - PI = I->PredTerm.begin(), PE = I->PredTerm.end(); PI != PE; ++PI) { - Preds.push_back(PI->Predicate); - } - RecIter PredsEnd = std::unique(Preds.begin(), Preds.end()); - Preds.resize(PredsEnd - Preds.begin()); - SCTrans.PredTerm = Preds; - SchedModels.getSchedClass(FromClassIdx).Transitions.push_back(SCTrans); + transform(I->PredTerm, std::back_inserter(Preds), + [](const PredCheck &P) { + return P.Predicate; + }); + Preds.erase(std::unique(Preds.begin(), Preds.end()), Preds.end()); + SCTrans.PredTerm = std::move(Preds); + SchedModels.getSchedClass(FromClassIdx) + .Transitions.push_back(std::move(SCTrans)); } } @@ -1345,48 +1413,42 @@ void CodeGenSchedModels::inferFromRW(ArrayRef<unsigned> OperWrites, ArrayRef<unsigned> OperReads, unsigned FromClassIdx, ArrayRef<unsigned> ProcIndices) { - DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices); dbgs() << ") "); + LLVM_DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices); + dbgs() << ") "); // Create a seed transition with an empty PredTerm and the expanded sequences // of SchedWrites for the current SchedClass. std::vector<PredTransition> LastTransitions; - LastTransitions.resize(1); + LastTransitions.emplace_back(); LastTransitions.back().ProcIndices.append(ProcIndices.begin(), ProcIndices.end()); for (unsigned WriteIdx : OperWrites) { IdxVec WriteSeq; expandRWSequence(WriteIdx, WriteSeq, /*IsRead=*/false); - unsigned Idx = LastTransitions[0].WriteSequences.size(); - LastTransitions[0].WriteSequences.resize(Idx + 1); - SmallVectorImpl<unsigned> &Seq = LastTransitions[0].WriteSequences[Idx]; - for (IdxIter WI = WriteSeq.begin(), WE = WriteSeq.end(); WI != WE; ++WI) - Seq.push_back(*WI); - DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") "); - } - DEBUG(dbgs() << " Reads: "); + LastTransitions[0].WriteSequences.emplace_back(); + SmallVectorImpl<unsigned> &Seq = LastTransitions[0].WriteSequences.back(); + Seq.append(WriteSeq.begin(), WriteSeq.end()); + LLVM_DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") "); + } + LLVM_DEBUG(dbgs() << " Reads: "); for (unsigned ReadIdx : OperReads) { IdxVec ReadSeq; expandRWSequence(ReadIdx, ReadSeq, /*IsRead=*/true); - unsigned Idx = LastTransitions[0].ReadSequences.size(); - LastTransitions[0].ReadSequences.resize(Idx + 1); - SmallVectorImpl<unsigned> &Seq = LastTransitions[0].ReadSequences[Idx]; - for (IdxIter RI = ReadSeq.begin(), RE = ReadSeq.end(); RI != RE; ++RI) - Seq.push_back(*RI); - DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") "); + LastTransitions[0].ReadSequences.emplace_back(); + SmallVectorImpl<unsigned> &Seq = LastTransitions[0].ReadSequences.back(); + Seq.append(ReadSeq.begin(), ReadSeq.end()); + LLVM_DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") "); } - DEBUG(dbgs() << '\n'); + LLVM_DEBUG(dbgs() << '\n'); // Collect all PredTransitions for individual operands. // Iterate until no variant writes remain. while (hasVariant(LastTransitions, *this)) { PredTransitions Transitions(*this); - for (std::vector<PredTransition>::const_iterator - I = LastTransitions.begin(), E = LastTransitions.end(); - I != E; ++I) { - Transitions.substituteVariants(*I); - } - DEBUG(Transitions.dump()); + for (const PredTransition &Trans : LastTransitions) + Transitions.substituteVariants(Trans); + LLVM_DEBUG(Transitions.dump()); LastTransitions.swap(Transitions.TransVec); } // If the first transition has no variants, nothing to do. @@ -1447,6 +1509,47 @@ void CodeGenSchedModels::verifyProcResourceGroups(CodeGenProcModel &PM) { } } +// Collect all the RegisterFile definitions available in this target. +void CodeGenSchedModels::collectRegisterFiles() { + RecVec RegisterFileDefs = Records.getAllDerivedDefinitions("RegisterFile"); + + // RegisterFiles is the vector of CodeGenRegisterFile. + for (Record *RF : RegisterFileDefs) { + // For each register file definition, construct a CodeGenRegisterFile object + // and add it to the appropriate scheduling model. + CodeGenProcModel &PM = getProcModel(RF->getValueAsDef("SchedModel")); + PM.RegisterFiles.emplace_back(CodeGenRegisterFile(RF->getName(),RF)); + CodeGenRegisterFile &CGRF = PM.RegisterFiles.back(); + + // Now set the number of physical registers as well as the cost of registers + // in each register class. + CGRF.NumPhysRegs = RF->getValueAsInt("NumPhysRegs"); + RecVec RegisterClasses = RF->getValueAsListOfDefs("RegClasses"); + std::vector<int64_t> RegisterCosts = RF->getValueAsListOfInts("RegCosts"); + for (unsigned I = 0, E = RegisterClasses.size(); I < E; ++I) { + int Cost = RegisterCosts.size() > I ? RegisterCosts[I] : 1; + CGRF.Costs.emplace_back(RegisterClasses[I], Cost); + } + } +} + +// Collect all the RegisterFile definitions available in this target. +void CodeGenSchedModels::collectPfmCounters() { + for (Record *Def : Records.getAllDerivedDefinitions("PfmIssueCounter")) { + CodeGenProcModel &PM = getProcModel(Def->getValueAsDef("SchedModel")); + PM.PfmIssueCounterDefs.emplace_back(Def); + } + for (Record *Def : Records.getAllDerivedDefinitions("PfmCycleCounter")) { + CodeGenProcModel &PM = getProcModel(Def->getValueAsDef("SchedModel")); + if (PM.PfmCycleCounterDef) { + PrintFatalError(Def->getLoc(), + "multiple cycle counters for " + + Def->getValueAsDef("SchedModel")->getName()); + } + PM.PfmCycleCounterDef = Def; + } +} + // Collect and sort WriteRes, ReadAdvance, and ProcResources. void CodeGenSchedModels::collectProcResources() { ProcResourceDefs = Records.getAllDerivedDefinitions("ProcResourceUnits"); @@ -1455,26 +1558,24 @@ void CodeGenSchedModels::collectProcResources() { // Add any subtarget-specific SchedReadWrites that are directly associated // with processor resources. Refer to the parent SchedClass's ProcIndices to // determine which processors they apply to. - for (SchedClassIter SCI = schedClassBegin(), SCE = schedClassEnd(); - SCI != SCE; ++SCI) { - if (SCI->ItinClassDef) - collectItinProcResources(SCI->ItinClassDef); - else { - // This class may have a default ReadWrite list which can be overriden by - // InstRW definitions. - if (!SCI->InstRWs.empty()) { - for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end(); - RWI != RWE; ++RWI) { - Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel"); - IdxVec ProcIndices(1, getProcModel(RWModelDef).Index); - IdxVec Writes, Reads; - findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"), - Writes, Reads); - collectRWResources(Writes, Reads, ProcIndices); - } - } - collectRWResources(SCI->Writes, SCI->Reads, SCI->ProcIndices); + for (const CodeGenSchedClass &SC : + make_range(schedClassBegin(), schedClassEnd())) { + if (SC.ItinClassDef) { + collectItinProcResources(SC.ItinClassDef); + continue; + } + + // This class may have a default ReadWrite list which can be overriden by + // InstRW definitions. + for (Record *RW : SC.InstRWs) { + Record *RWModelDef = RW->getValueAsDef("SchedModel"); + unsigned PIdx = getProcModel(RWModelDef).Index; + IdxVec Writes, Reads; + findRWs(RW->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads); + collectRWResources(Writes, Reads, PIdx); } + + collectRWResources(SC.Writes, SC.Reads, SC.ProcIndices); } // Add resources separately defined by each subtarget. RecVec WRDefs = Records.getAllDerivedDefinitions("WriteRes"); @@ -1509,38 +1610,45 @@ void CodeGenSchedModels::collectProcResources() { if (!is_contained(PM.ProcResourceDefs, PRG)) PM.ProcResourceDefs.push_back(PRG); } + // Add ProcResourceUnits unconditionally. + for (Record *PRU : Records.getAllDerivedDefinitions("ProcResourceUnits")) { + if (!PRU->getValueInit("SchedModel")->isComplete()) + continue; + CodeGenProcModel &PM = getProcModel(PRU->getValueAsDef("SchedModel")); + if (!is_contained(PM.ProcResourceDefs, PRU)) + PM.ProcResourceDefs.push_back(PRU); + } // Finalize each ProcModel by sorting the record arrays. for (CodeGenProcModel &PM : ProcModels) { - std::sort(PM.WriteResDefs.begin(), PM.WriteResDefs.end(), - LessRecord()); - std::sort(PM.ReadAdvanceDefs.begin(), PM.ReadAdvanceDefs.end(), - LessRecord()); - std::sort(PM.ProcResourceDefs.begin(), PM.ProcResourceDefs.end(), - LessRecord()); - DEBUG( - PM.dump(); - dbgs() << "WriteResDefs: "; - for (RecIter RI = PM.WriteResDefs.begin(), - RE = PM.WriteResDefs.end(); RI != RE; ++RI) { - if ((*RI)->isSubClassOf("WriteRes")) - dbgs() << (*RI)->getValueAsDef("WriteType")->getName() << " "; - else - dbgs() << (*RI)->getName() << " "; - } - dbgs() << "\nReadAdvanceDefs: "; - for (RecIter RI = PM.ReadAdvanceDefs.begin(), - RE = PM.ReadAdvanceDefs.end(); RI != RE; ++RI) { - if ((*RI)->isSubClassOf("ReadAdvance")) - dbgs() << (*RI)->getValueAsDef("ReadType")->getName() << " "; - else - dbgs() << (*RI)->getName() << " "; - } - dbgs() << "\nProcResourceDefs: "; - for (RecIter RI = PM.ProcResourceDefs.begin(), - RE = PM.ProcResourceDefs.end(); RI != RE; ++RI) { - dbgs() << (*RI)->getName() << " "; - } - dbgs() << '\n'); + llvm::sort(PM.WriteResDefs.begin(), PM.WriteResDefs.end(), + LessRecord()); + llvm::sort(PM.ReadAdvanceDefs.begin(), PM.ReadAdvanceDefs.end(), + LessRecord()); + llvm::sort(PM.ProcResourceDefs.begin(), PM.ProcResourceDefs.end(), + LessRecord()); + LLVM_DEBUG( + PM.dump(); + dbgs() << "WriteResDefs: "; for (RecIter RI = PM.WriteResDefs.begin(), + RE = PM.WriteResDefs.end(); + RI != RE; ++RI) { + if ((*RI)->isSubClassOf("WriteRes")) + dbgs() << (*RI)->getValueAsDef("WriteType")->getName() << " "; + else + dbgs() << (*RI)->getName() << " "; + } dbgs() << "\nReadAdvanceDefs: "; + for (RecIter RI = PM.ReadAdvanceDefs.begin(), + RE = PM.ReadAdvanceDefs.end(); + RI != RE; ++RI) { + if ((*RI)->isSubClassOf("ReadAdvance")) + dbgs() << (*RI)->getValueAsDef("ReadType")->getName() << " "; + else + dbgs() << (*RI)->getName() << " "; + } dbgs() + << "\nProcResourceDefs: "; + for (RecIter RI = PM.ProcResourceDefs.begin(), + RE = PM.ProcResourceDefs.end(); + RI != RE; ++RI) { dbgs() << (*RI)->getName() << " "; } dbgs() + << '\n'); verifyProcResourceGroups(PM); } @@ -1552,6 +1660,7 @@ void CodeGenSchedModels::checkCompleteness() { bool Complete = true; bool HadCompleteModel = false; for (const CodeGenProcModel &ProcModel : procModels()) { + const bool HasItineraries = ProcModel.hasItineraries(); if (!ProcModel.ModelDef->getValueAsBit("CompleteModel")) continue; for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { @@ -1572,7 +1681,7 @@ void CodeGenSchedModels::checkCompleteness() { const CodeGenSchedClass &SC = getSchedClass(SCIdx); if (!SC.Writes.empty()) continue; - if (SC.ItinClassDef != nullptr && + if (HasItineraries && SC.ItinClassDef != nullptr && SC.ItinClassDef->getName() != "NoItinerary") continue; @@ -1619,8 +1728,7 @@ void CodeGenSchedModels::collectItinProcResources(Record *ItinClassDef) { HasMatch = true; IdxVec Writes, Reads; findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads); - IdxVec ProcIndices(1, PIdx); - collectRWResources(Writes, Reads, ProcIndices); + collectRWResources(Writes, Reads, PIdx); } } } |
