summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/utils/TableGen/CodeGenSchedule.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
committerpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
commitb773203fb58f3ef282fb69c832d8710cab5bc82d (patch)
treee75913f147570fbd75169647b144df85b88a038c /gnu/llvm/utils/TableGen/CodeGenSchedule.cpp
parenttweak errno in previous (diff)
downloadwireguard-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.cpp834
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);
}
}
}