summaryrefslogtreecommitdiff
path: root/utils/TableGen
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2012-09-22 02:24:21 +0000
committerAndrew Trick <atrick@apple.com>2012-09-22 02:24:21 +0000
commit92649883119aaa8edd9ccf612eaaff5ccc8fcc77 (patch)
tree7364686dfed0404a7bfb0fd63c895f8886b823c4 /utils/TableGen
parenta2df2ba16a94bf20b9202594d01cfbf370c2091a (diff)
downloadllvm-92649883119aaa8edd9ccf612eaaff5ccc8fcc77.tar.gz
llvm-92649883119aaa8edd9ccf612eaaff5ccc8fcc77.tar.bz2
llvm-92649883119aaa8edd9ccf612eaaff5ccc8fcc77.tar.xz
Machine Model (-schedmodel only). Added SchedAliases.
Allow subtargets to tie SchedReadWrite types to processor specific sequences or variants. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@164451 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp247
-rw-r--r--utils/TableGen/CodeGenSchedule.h31
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp104
3 files changed, 295 insertions, 87 deletions
diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp
index 7946b42b2c..e54202e3f2 100644
--- a/utils/TableGen/CodeGenSchedule.cpp
+++ b/utils/TableGen/CodeGenSchedule.cpp
@@ -61,7 +61,7 @@ CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
collectSchedClasses();
// Find instruction itineraries for each processor. Sort and populate
- // CodeGenProcMode::ItinDefList. (Cycle-to-cycle itineraries). This requires
+ // CodeGenProcModel::ItinDefList. (Cycle-to-cycle itineraries). This requires
// all itinerary classes to be discovered.
collectProcItins();
@@ -204,6 +204,25 @@ 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());
+ for (RecIter AI = AliasDefs.begin(), AE = AliasDefs.end(); AI != AE; ++AI) {
+ Record *MatchDef = (*AI)->getValueAsDef("MatchRW");
+ Record *AliasDef = (*AI)->getValueAsDef("AliasRW");
+ if (MatchDef->isSubClassOf("SchedWrite")) {
+ if (!AliasDef->isSubClassOf("SchedWrite"))
+ throw TGError((*AI)->getLoc(), "SchedWrite Alias must be SchedWrite");
+ scanSchedRW(AliasDef, SWDefs, RWSet);
+ }
+ else {
+ assert(MatchDef->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
+ if (!AliasDef->isSubClassOf("SchedRead"))
+ throw TGError((*AI)->getLoc(), "SchedRead Alias must be SchedRead");
+ scanSchedRW(AliasDef, SRDefs, RWSet);
+ }
+ }
// 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());
@@ -224,6 +243,16 @@ void CodeGenSchedModels::collectSchedRW() {
findRWs(WI->TheDef->getValueAsListOfDefs("Writes"), WI->Sequence,
/*IsRead=*/false);
}
+ // Initialize Aliases vectors.
+ for (RecIter AI = AliasDefs.begin(), AE = AliasDefs.end(); AI != AE; ++AI) {
+ Record *AliasDef = (*AI)->getValueAsDef("AliasRW");
+ getSchedRW(AliasDef).IsAlias = true;
+ Record *MatchDef = (*AI)->getValueAsDef("MatchRW");
+ CodeGenSchedRW &RW = getSchedRW(MatchDef);
+ if (RW.IsAlias)
+ throw TGError((*AI)->getLoc(), "Cannot Alias an Alias");
+ RW.Aliases.push_back(*AI);
+ }
DEBUG(
for (unsigned WIdx = 0, WEnd = SchedWrites.size(); WIdx != WEnd; ++WIdx) {
dbgs() << WIdx << ": ";
@@ -412,7 +441,7 @@ void CodeGenSchedModels::collectSchedClasses() {
IdxVec ProcIndices(1, 0);
addSchedClass(Writes, Reads, ProcIndices);
}
- // Create classes for InstReadWrite defs.
+ // Create classes for InstRW defs.
RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");
std::sort(InstRWDefs.begin(), InstRWDefs.end(), LessRecord());
for (RecIter OI = InstRWDefs.begin(), OE = InstRWDefs.end(); OI != OE; ++OI)
@@ -766,6 +795,17 @@ void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) {
}
namespace {
+// Helper for substituteVariantOperand.
+struct TransVariant {
+ Record *VariantDef;
+ unsigned RWIdx; // Index of this variant's matched type.
+ unsigned ProcIdx; // Processor model index or zero for any.
+ unsigned TransVecIdx; // Index into PredTransitions::TransVec.
+
+ TransVariant(Record *def, unsigned rwi, unsigned pi, unsigned ti):
+ VariantDef(def), RWIdx(rwi), ProcIdx(pi), TransVecIdx(ti) {}
+};
+
// Associate a predicate with the SchedReadWrite that it guards.
// RWIdx is the index of the read/write variant.
struct PredCheck {
@@ -782,6 +822,7 @@ struct PredTransition {
SmallVector<PredCheck, 4> PredTerm;
SmallVector<SmallVector<unsigned,4>, 16> WriteSequences;
SmallVector<SmallVector<unsigned,4>, 16> ReadSequences;
+ SmallVector<unsigned, 4> ProcIndices;
};
// Encapsulate a set of partially constructed transitions.
@@ -805,8 +846,7 @@ public:
private:
bool mutuallyExclusive(Record *PredDef, ArrayRef<PredCheck> Term);
- void pushVariant(unsigned SchedRW, Record *Variant, PredTransition &Trans,
- bool IsRead);
+ void pushVariant(const TransVariant &VInfo, bool IsRead);
};
} // anonymous
@@ -838,16 +878,26 @@ bool PredTransitions::mutuallyExclusive(Record *PredDef,
return false;
}
-// Push the Reads/Writes selected by this variant onto the given PredTransition.
-void PredTransitions::pushVariant(unsigned RWIdx, Record *Variant,
- PredTransition &Trans, bool IsRead) {
- Trans.PredTerm.push_back(
- PredCheck(IsRead, RWIdx, Variant->getValueAsDef("Predicate")));
- RecVec SelectedDefs = Variant->getValueAsListOfDefs("Selected");
+// Push the Reads/Writes selected by this variant onto the PredTransition
+// specified by VInfo.
+void PredTransitions::
+pushVariant(const TransVariant &VInfo, bool IsRead) {
+
+ PredTransition &Trans = TransVec[VInfo.TransVecIdx];
+
+ Record *PredDef = VInfo.VariantDef->getValueAsDef("Predicate");
+ Trans.PredTerm.push_back(PredCheck(IsRead, VInfo.RWIdx,PredDef));
+
+ // If this operand transition is reached through a processor-specific alias,
+ // then the whole transition is specific to this processor.
+ if (VInfo.ProcIdx != 0)
+ Trans.ProcIndices.assign(1, VInfo.ProcIdx);
+
+ RecVec SelectedDefs = VInfo.VariantDef->getValueAsListOfDefs("Selected");
IdxVec SelectedRWs;
SchedModels.findRWs(SelectedDefs, SelectedRWs, IsRead);
- const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(RWIdx, IsRead);
+ const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(VInfo.RWIdx, IsRead);
SmallVectorImpl<SmallVector<unsigned,4> > &RWSequences = IsRead
? Trans.ReadSequences : Trans.WriteSequences;
@@ -889,9 +939,48 @@ void PredTransitions::pushVariant(unsigned RWIdx, Record *Variant,
}
}
+static bool hasAliasedVariants(const CodeGenSchedRW &RW,
+ CodeGenSchedModels &SchedModels) {
+ if (RW.HasVariants)
+ return true;
+
+ for (RecIter I = RW.Aliases.begin(), E = RW.Aliases.end(); I != E; ++I) {
+ if (SchedModels.getSchedRW((*I)->getValueAsDef("AliasRW")).HasVariants)
+ return true;
+ }
+ return false;
+}
+
+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))
+ 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))
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
// RWSeq is a sequence of all Reads or all Writes for the next read or write
// operand. StartIdx is an index into TransVec where partial results
-// starts. RWSeq must be applied to all tranistions between StartIdx and the end
+// starts. RWSeq must be applied to all transitions between StartIdx and the end
// of TransVec.
void PredTransitions::substituteVariantOperand(
const SmallVectorImpl<unsigned> &RWSeq, bool IsRead, unsigned StartIdx) {
@@ -906,7 +995,7 @@ void PredTransitions::substituteVariantOperand(
for (unsigned TransIdx = StartIdx, TransEnd = TransVec.size();
TransIdx != TransEnd; ++TransIdx) {
// In the common case, push RW onto the current operand's sequence.
- if (!SchedRW.HasVariants) {
+ if (!hasAliasedVariants(SchedRW, SchedModels)) {
if (IsRead)
TransVec[TransIdx].ReadSequences.back().push_back(*RWI);
else
@@ -914,28 +1003,74 @@ void PredTransitions::substituteVariantOperand(
continue;
}
// Distribute this partial PredTransition across intersecting variants.
- RecVec Variants = SchedRW.TheDef->getValueAsListOfDefs("Variants");
- std::vector<std::pair<Record*,unsigned> > IntersectingVariants;
- for (RecIter VI = Variants.begin(), VE = Variants.end(); VI != VE; ++VI) {
- Record *PredDef = (*VI)->getValueAsDef("Predicate");
+ RecVec Variants;
+ if (SchedRW.HasVariants)
+ Variants = SchedRW.TheDef->getValueAsListOfDefs("Variants");
+ IdxVec VarRWIds(Variants.size(), *RWI);
+ IdxVec VarProcModels(Variants.size(), 0);
+ for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
+ AI != AE; ++AI) {
+ unsigned AIdx;
+ const CodeGenSchedRW &AliasRW =
+ SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"), AIdx);
+ if (!AliasRW.HasVariants)
+ continue;
+
+ RecVec AliasVars = AliasRW.TheDef->getValueAsListOfDefs("Variants");
+ Variants.insert(Variants.end(), AliasVars.begin(), AliasVars.end());
+
+ VarRWIds.resize(Variants.size(), AIdx);
+
+ Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+ VarProcModels.resize(Variants.size(),
+ SchedModels.getProcModel(ModelDef).Index);
+ }
+ std::vector<TransVariant> IntersectingVariants;
+ for (unsigned VIdx = 0, VEnd = Variants.size(); VIdx != VEnd; ++VIdx) {
+ Record *PredDef = Variants[VIdx]->getValueAsDef("Predicate");
+
+ // Don't expand variants if the processor models don't intersect.
+ // A zero processor index means any processor.
+ SmallVector<unsigned, 4> &ProcIndices = TransVec[TransIdx].ProcIndices;
+ if (ProcIndices[0] != 0 && VarProcModels[VIdx] != 0) {
+ unsigned Cnt = std::count(ProcIndices.begin(), ProcIndices.end(),
+ VarProcModels[VIdx]);
+ if (!Cnt)
+ continue;
+ if (Cnt > 1) {
+ const CodeGenProcModel &PM =
+ *(SchedModels.procModelBegin() + VarProcModels[VIdx]);
+ throw TGError(Variants[VIdx]->getLoc(), "Multiple variants defined "
+ "for processor " + PM.ModelName +
+ " Ensure only one SchedAlias exists per RW.");
+ }
+ }
if (mutuallyExclusive(PredDef, TransVec[TransIdx].PredTerm))
continue;
- if (IntersectingVariants.empty())
+ if (IntersectingVariants.empty()) {
// The first variant builds on the existing transition.
- IntersectingVariants.push_back(std::make_pair(*VI, TransIdx));
+ IntersectingVariants.push_back(
+ TransVariant(Variants[VIdx], VarRWIds[VIdx], VarProcModels[VIdx],
+ TransIdx));
+ }
else {
// Push another copy of the current transition for more variants.
IntersectingVariants.push_back(
- std::make_pair(*VI, TransVec.size()));
+ TransVariant(Variants[VIdx], VarRWIds[VIdx], VarProcModels[VIdx],
+ TransVec.size()));
TransVec.push_back(TransVec[TransIdx]);
}
}
+ if (IntersectingVariants.empty())
+ throw TGError(SchedRW.TheDef->getLoc(), "No variant of this type has a "
+ "matching predicate on any processor ");
// Now expand each variant on top of its copy of the transition.
- for (std::vector<std::pair<Record*, unsigned> >::const_iterator
+ for (std::vector<TransVariant>::const_iterator
IVI = IntersectingVariants.begin(),
IVE = IntersectingVariants.end();
- IVI != IVE; ++IVI)
- pushVariant(*RWI, IVI->first, TransVec[IVI->second], IsRead);
+ IVI != IVE; ++IVI) {
+ pushVariant(*IVI, IsRead);
+ }
}
}
}
@@ -952,6 +1087,7 @@ void PredTransitions::substituteVariants(const PredTransition &Trans) {
unsigned StartIdx = TransVec.size();
TransVec.resize(TransVec.size() + 1);
TransVec.back().PredTerm = Trans.PredTerm;
+ TransVec.back().ProcIndices = Trans.ProcIndices;
// Visit each original write sequence.
for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
@@ -977,37 +1113,9 @@ void PredTransitions::substituteVariants(const PredTransition &Trans) {
}
}
-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 (SchedModels.getSchedWrite(*WI).HasVariants)
- 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 (SchedModels.getSchedRead(*RI).HasVariants)
- return true;
- }
- }
- }
- return false;
-}
-
// Create a new SchedClass for each variant found by inferFromRW. Pass
-// ProcIndices by copy to avoid referencing anything from SchedClasses.
static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions,
- unsigned FromClassIdx, IdxVec ProcIndices,
+ unsigned FromClassIdx,
CodeGenSchedModels &SchedModels) {
// For each PredTransition, create a new CodeGenSchedTransition, which usually
// requires creating a new SchedClass.
@@ -1025,10 +1133,11 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions,
for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
RSI = I->ReadSequences.begin(), RSE = I->ReadSequences.end();
RSI != RSE; ++RSI) {
- // Create a new write representing the expanded sequence.
+ // Create a new read representing the expanded sequence.
OperReadsVariant.push_back(
SchedModels.findOrInsertRW(*RSI, /*IsRead=*/true));
}
+ IdxVec ProcIndices(I->ProcIndices.begin(), I->ProcIndices.end());
CodeGenSchedTransition SCTrans;
SCTrans.ToClassIdx =
SchedModels.addSchedClass(OperWritesVariant, OperReadsVariant,
@@ -1047,18 +1156,22 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions,
}
}
-/// Find each variant write that OperWrites or OperaReads refers to and create a
-/// new SchedClass for each variant.
+// Create new SchedClasses for the given ReadWrite list. If any of the
+// ReadWrites refers to a SchedVariant, create a new SchedClass for each variant
+// of the ReadWrite list, following Aliases if necessary.
void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites,
const IdxVec &OperReads,
unsigned FromClassIdx,
const IdxVec &ProcIndices) {
- DEBUG(dbgs() << "INFERRW Writes: ");
+ DEBUG(dbgs() << "INFER RW: ");
// 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.back().ProcIndices.append(ProcIndices.begin(),
+ ProcIndices.end());
+
for (IdxIter I = OperWrites.begin(), E = OperWrites.end(); I != E; ++I) {
IdxVec WriteSeq;
expandRWSequence(*I, WriteSeq, /*IsRead=*/false);
@@ -1100,7 +1213,7 @@ void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites,
// WARNING: We are about to mutate the SchedClasses vector. Do not refer to
// OperWrites, OperReads, or ProcIndices after calling inferFromTransitions.
- inferFromTransitions(LastTransitions, FromClassIdx, ProcIndices, *this);
+ inferFromTransitions(LastTransitions, FromClassIdx, *this);
}
// Collect and sort WriteRes, ReadAdvance, and ProcResources.
@@ -1200,6 +1313,15 @@ void CodeGenSchedModels::collectRWResources(const IdxVec &Writes,
addWriteRes(SchedRW.TheDef, *PI);
}
}
+ for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
+ AI != AE; ++AI) {
+ const CodeGenSchedRW &AliasRW =
+ getSchedRW((*AI)->getValueAsDef("AliasRW"));
+ if (AliasRW.TheDef && AliasRW.TheDef->isSubClassOf("SchedWriteRes")) {
+ Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+ addWriteRes(AliasRW.TheDef, getProcModel(ModelDef).Index);
+ }
+ }
}
for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI) {
const CodeGenSchedRW &SchedRW = getSchedRW(*RI, /*IsRead=*/true);
@@ -1209,6 +1331,15 @@ void CodeGenSchedModels::collectRWResources(const IdxVec &Writes,
addReadAdvance(SchedRW.TheDef, *PI);
}
}
+ for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
+ AI != AE; ++AI) {
+ const CodeGenSchedRW &AliasRW =
+ getSchedRW((*AI)->getValueAsDef("AliasRW"));
+ if (AliasRW.TheDef && AliasRW.TheDef->isSubClassOf("SchedReadAdvance")) {
+ Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+ addReadAdvance(AliasRW.TheDef, getProcModel(ModelDef).Index);
+ }
+ }
}
}
@@ -1265,6 +1396,8 @@ void CodeGenSchedModels::addProcResource(Record *ProcResKind,
// Add resources for a SchedWrite to this processor if they don't exist.
void CodeGenSchedModels::addWriteRes(Record *ProcWriteResDef, unsigned PIdx) {
+ assert(PIdx && "don't add resources to an invalid Processor model");
+
RecVec &WRDefs = ProcModels[PIdx].WriteResDefs;
RecIter WRI = std::find(WRDefs.begin(), WRDefs.end(), ProcWriteResDef);
if (WRI != WRDefs.end())
diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h
index ec556c2667..226c3aed5c 100644
--- a/utils/TableGen/CodeGenSchedule.h
+++ b/utils/TableGen/CodeGenSchedule.h
@@ -45,14 +45,16 @@ void splitSchedReadWrites(const RecVec &RWDefs,
struct CodeGenSchedRW {
std::string Name;
Record *TheDef;
+ bool IsAlias;
bool HasVariants;
bool IsVariadic;
bool IsSequence;
IdxVec Sequence;
+ RecVec Aliases;
- CodeGenSchedRW(): TheDef(0), HasVariants(false), IsVariadic(false),
- IsSequence(false) {}
- CodeGenSchedRW(Record *Def): TheDef(Def), IsVariadic(false) {
+ CodeGenSchedRW(): TheDef(0), IsAlias(false), HasVariants(false),
+ IsVariadic(false), IsSequence(false) {}
+ CodeGenSchedRW(Record *Def): TheDef(Def), IsAlias(false), IsVariadic(false) {
Name = Def->getName();
HasVariants = Def->isSubClassOf("SchedVariant");
if (HasVariants)
@@ -65,8 +67,8 @@ struct CodeGenSchedRW {
}
CodeGenSchedRW(const IdxVec &Seq, const std::string &Name):
- Name(Name), TheDef(0), HasVariants(false), IsVariadic(false),
- IsSequence(true), Sequence(Seq) {
+ Name(Name), TheDef(0), IsAlias(false), HasVariants(false),
+ IsVariadic(false), IsSequence(true), Sequence(Seq) {
assert(Sequence.size() > 1 && "implied sequence needs >1 RWs");
}
@@ -75,6 +77,7 @@ struct CodeGenSchedRW {
assert((!IsVariadic || HasVariants) && "Variadic write needs variants");
assert((!IsSequence || !HasVariants) && "Sequence can't have variant");
assert((!IsSequence || !Sequence.empty()) && "Sequence should be nonempty");
+ assert((!IsAlias || Aliases.empty()) && "Alias cannot have aliases");
return TheDef || !Sequence.empty();
}
@@ -125,8 +128,10 @@ struct CodeGenSchedClass {
std::vector<CodeGenSchedTransition> Transitions;
- // InstReadWrite records associated with this class. Any Instrs that the
- // definitions refer to that are not mapped to this class should be ignored.
+ // InstRW records associated with this class. These records may refer to an
+ // Instruction no longer mapped to this class by InstrClassMap. These
+ // Instructions should be ignored by this class because they have been split
+ // off to join another inferred class.
RecVec InstRWs;
CodeGenSchedClass(): ItinClassDef(0) {}
@@ -229,7 +234,7 @@ class CodeGenSchedModels {
unsigned NumInstrSchedClasses;
// Map Instruction to SchedClass index. Only for Instructions mentioned in
- // OpReadWrites.
+ // InstRW records.
typedef DenseMap<Record*, unsigned> InstClassMapTy;
InstClassMapTy InstrClassMap;
@@ -281,6 +286,16 @@ public:
const CodeGenSchedRW &getSchedRW(unsigned Idx, bool IsRead) const {
return IsRead ? getSchedRead(Idx) : getSchedWrite(Idx);
}
+ CodeGenSchedRW &getSchedRW(Record *Def, unsigned &Idx) {
+ bool IsRead = Def->isSubClassOf("SchedRead");
+ Idx = getSchedRWIdx(Def, IsRead);
+ return const_cast<CodeGenSchedRW&>(
+ IsRead ? getSchedRead(Idx) : getSchedWrite(Idx));
+ }
+ CodeGenSchedRW &getSchedRW(Record *Def) {
+ unsigned Idx;
+ return getSchedRW(Def, Idx);
+ }
unsigned getSchedRWIdx(Record *Def, bool IsRead, unsigned After = 0) const;
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index e7dc983b6c..4127b379b1 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -81,9 +81,10 @@ class SubtargetEmitter {
char Separator);
void EmitProcessorResources(const CodeGenProcModel &ProcModel,
raw_ostream &OS);
- Record *FindWriteResources(Record *WriteDef,
+ Record *FindWriteResources(const CodeGenSchedRW &SchedWrite,
const CodeGenProcModel &ProcModel);
- Record *FindReadAdvance(Record *ReadDef, const CodeGenProcModel &ProcModel);
+ Record *FindReadAdvance(const CodeGenSchedRW &SchedRead,
+ const CodeGenProcModel &ProcModel);
void GenSchedClassTables(const CodeGenProcModel &ProcModel,
SchedClassTables &SchedTables);
void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
@@ -654,48 +655,107 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
// Find the WriteRes Record that defines processor resources for this
// SchedWrite.
Record *SubtargetEmitter::FindWriteResources(
- Record *WriteDef, const CodeGenProcModel &ProcModel) {
+ const CodeGenSchedRW &SchedWrite, const CodeGenProcModel &ProcModel) {
// Check if the SchedWrite is already subtarget-specific and directly
// specifies a set of processor resources.
- if (WriteDef->isSubClassOf("SchedWriteRes"))
- return WriteDef;
+ if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes"))
+ return SchedWrite.TheDef;
+
+ // Check this processor's list of aliases for SchedWrite.
+ Record *AliasDef = 0;
+ for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
+ AI != AE; ++AI) {
+ const CodeGenSchedRW &AliasRW =
+ SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
+ Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+ if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
+ continue;
+ if (AliasDef)
+ throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
+ "defined for processor " + ProcModel.ModelName +
+ " Ensure only one SchedAlias exists per RW.");
+ AliasDef = AliasRW.TheDef;
+ }
+ if (AliasDef && AliasDef->isSubClassOf("SchedWriteRes"))
+ return AliasDef;
// Check this processor's list of write resources.
+ Record *ResDef = 0;
for (RecIter WRI = ProcModel.WriteResDefs.begin(),
WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
if (!(*WRI)->isSubClassOf("WriteRes"))
continue;
- if (WriteDef == (*WRI)->getValueAsDef("WriteType"))
- return *WRI;
+ if (AliasDef == (*WRI)->getValueAsDef("WriteType")
+ || SchedWrite.TheDef == (*WRI)->getValueAsDef("WriteType")) {
+ if (ResDef) {
+ throw TGError((*WRI)->getLoc(), "Resources are defined for both "
+ "SchedWrite and its alias on processor " +
+ ProcModel.ModelName);
+ }
+ ResDef = *WRI;
+ }
}
- throw TGError(ProcModel.ModelDef->getLoc(),
- std::string("Processor does not define resources for ")
- + WriteDef->getName());
+ // TODO: If ProcModel has a base model (previous generation processor),
+ // then call FindWriteResources recursively with that model here.
+ if (!ResDef) {
+ throw TGError(ProcModel.ModelDef->getLoc(),
+ std::string("Processor does not define resources for ")
+ + SchedWrite.TheDef->getName());
+ }
+ return ResDef;
}
/// Find the ReadAdvance record for the given SchedRead on this processor or
/// return NULL.
-Record *SubtargetEmitter::FindReadAdvance(Record *ReadDef,
+Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
const CodeGenProcModel &ProcModel) {
// Check for SchedReads that directly specify a ReadAdvance.
- if (ReadDef->isSubClassOf("SchedReadAdvance"))
- return ReadDef;
+ if (SchedRead.TheDef->isSubClassOf("SchedReadAdvance"))
+ return SchedRead.TheDef;
+
+ // Check this processor's list of aliases for SchedRead.
+ Record *AliasDef = 0;
+ for (RecIter AI = SchedRead.Aliases.begin(), AE = SchedRead.Aliases.end();
+ AI != AE; ++AI) {
+ const CodeGenSchedRW &AliasRW =
+ SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
+ Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+ if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
+ continue;
+ if (AliasDef)
+ throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
+ "defined for processor " + ProcModel.ModelName +
+ " Ensure only one SchedAlias exists per RW.");
+ AliasDef = AliasRW.TheDef;
+ }
+ if (AliasDef && AliasDef->isSubClassOf("SchedReadAdvance"))
+ return AliasDef;
// Check this processor's ReadAdvanceList.
+ Record *ResDef = 0;
for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
if (!(*RAI)->isSubClassOf("ReadAdvance"))
continue;
- if (ReadDef == (*RAI)->getValueAsDef("ReadType"))
- return *RAI;
+ if (AliasDef == (*RAI)->getValueAsDef("ReadType")
+ || SchedRead.TheDef == (*RAI)->getValueAsDef("ReadType")) {
+ if (ResDef) {
+ throw TGError((*RAI)->getLoc(), "Resources are defined for both "
+ "SchedRead and its alias on processor " +
+ ProcModel.ModelName);
+ }
+ ResDef = *RAI;
+ }
}
- if (ReadDef->getName() != "ReadDefault") {
+ // TODO: If ProcModel has a base model (previous generation processor),
+ // then call FindReadAdvance recursively with that model here.
+ if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") {
throw TGError(ProcModel.ModelDef->getLoc(),
std::string("Processor does not define resources for ")
- + ReadDef->getName());
+ + SchedRead.TheDef->getName());
}
- return NULL;
+ return ResDef;
}
// Generate the SchedClass table for this processor and update global
@@ -797,8 +857,8 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end();
WSI != WSE; ++WSI) {
- Record *WriteDef = SchedModels.getSchedWrite(*WSI).TheDef;
- Record *WriteRes = FindWriteResources(WriteDef, ProcModel);
+ Record *WriteRes =
+ FindWriteResources(SchedModels.getSchedWrite(*WSI), ProcModel);
// Mark the parent class as invalid for unsupported write types.
if (WriteRes->getValueAsBit("Unsupported")) {
@@ -832,8 +892,8 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
// Entries must be sorted first by UseIdx then by WriteResourceID.
for (unsigned UseIdx = 0, EndIdx = Reads.size();
UseIdx != EndIdx; ++UseIdx) {
- Record *ReadDef = SchedModels.getSchedRead(Reads[UseIdx]).TheDef;
- Record *ReadAdvance = FindReadAdvance(ReadDef, ProcModel);
+ Record *ReadAdvance =
+ FindReadAdvance(SchedModels.getSchedRead(Reads[UseIdx]), ProcModel);
if (!ReadAdvance)
continue;