mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 16:33:28 +00:00
TableGen subtarget emitter, nearly first class support for SchedAlias.
A processor can now arbitrarily alias one SchedWrite onto another. Only the SchedAlias definition need be within the processor model. The aliased SchedWrite may be a SchedVariant, WriteSequence, or transitively refer to another alias. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165179 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
fe05d98c25
commit
2062b1260f
@ -225,12 +225,12 @@ void CodeGenSchedModels::collectSchedRW() {
|
|||||||
std::sort(SWDefs.begin(), SWDefs.end(), LessRecord());
|
std::sort(SWDefs.begin(), SWDefs.end(), LessRecord());
|
||||||
for (RecIter SWI = SWDefs.begin(), SWE = SWDefs.end(); SWI != SWE; ++SWI) {
|
for (RecIter SWI = SWDefs.begin(), SWE = SWDefs.end(); SWI != SWE; ++SWI) {
|
||||||
assert(!getSchedRWIdx(*SWI, /*IsRead=*/false) && "duplicate SchedWrite");
|
assert(!getSchedRWIdx(*SWI, /*IsRead=*/false) && "duplicate SchedWrite");
|
||||||
SchedWrites.push_back(CodeGenSchedRW(*SWI));
|
SchedWrites.push_back(CodeGenSchedRW(SchedWrites.size(), *SWI));
|
||||||
}
|
}
|
||||||
std::sort(SRDefs.begin(), SRDefs.end(), LessRecord());
|
std::sort(SRDefs.begin(), SRDefs.end(), LessRecord());
|
||||||
for (RecIter SRI = SRDefs.begin(), SRE = SRDefs.end(); SRI != SRE; ++SRI) {
|
for (RecIter SRI = SRDefs.begin(), SRE = SRDefs.end(); SRI != SRE; ++SRI) {
|
||||||
assert(!getSchedRWIdx(*SRI, /*IsRead-*/true) && "duplicate SchedWrite");
|
assert(!getSchedRWIdx(*SRI, /*IsRead-*/true) && "duplicate SchedWrite");
|
||||||
SchedReads.push_back(CodeGenSchedRW(*SRI));
|
SchedReads.push_back(CodeGenSchedRW(SchedReads.size(), *SRI));
|
||||||
}
|
}
|
||||||
// Initialize WriteSequence vectors.
|
// Initialize WriteSequence vectors.
|
||||||
for (std::vector<CodeGenSchedRW>::iterator WI = SchedWrites.begin(),
|
for (std::vector<CodeGenSchedRW>::iterator WI = SchedWrites.begin(),
|
||||||
@ -362,6 +362,47 @@ void CodeGenSchedModels::expandRWSequence(unsigned RWIdx, IdxVec &RWSeq,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expand a SchedWrite as a sequence following any aliases that coincide with
|
||||||
|
// the given processor model.
|
||||||
|
void CodeGenSchedModels::expandRWSeqForProc(
|
||||||
|
unsigned RWIdx, IdxVec &RWSeq, bool IsRead,
|
||||||
|
const CodeGenProcModel &ProcModel) const {
|
||||||
|
|
||||||
|
const CodeGenSchedRW &SchedWrite = getSchedRW(RWIdx, IsRead);
|
||||||
|
Record *AliasDef = 0;
|
||||||
|
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");
|
||||||
|
if (&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) {
|
||||||
|
expandRWSeqForProc(getSchedRWIdx(AliasDef, IsRead),
|
||||||
|
RWSeq, IsRead,ProcModel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!SchedWrite.IsSequence) {
|
||||||
|
RWSeq.push_back(RWIdx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int Repeat =
|
||||||
|
SchedWrite.TheDef ? SchedWrite.TheDef->getValueAsInt("Repeat") : 1;
|
||||||
|
for (int i = 0; i < Repeat; ++i) {
|
||||||
|
for (IdxIter I = SchedWrite.Sequence.begin(), E = SchedWrite.Sequence.end();
|
||||||
|
I != E; ++I) {
|
||||||
|
expandRWSeqForProc(*I, RWSeq, IsRead, ProcModel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Find the existing SchedWrite that models this sequence of writes.
|
// Find the existing SchedWrite that models this sequence of writes.
|
||||||
unsigned CodeGenSchedModels::findRWForSequence(const IdxVec &Seq,
|
unsigned CodeGenSchedModels::findRWForSequence(const IdxVec &Seq,
|
||||||
bool IsRead) {
|
bool IsRead) {
|
||||||
@ -387,13 +428,13 @@ unsigned CodeGenSchedModels::findOrInsertRW(ArrayRef<unsigned> Seq,
|
|||||||
if (Idx)
|
if (Idx)
|
||||||
return Idx;
|
return Idx;
|
||||||
|
|
||||||
CodeGenSchedRW SchedRW(Seq, genRWName(Seq, IsRead));
|
unsigned RWIdx = IsRead ? SchedReads.size() : SchedWrites.size();
|
||||||
if (IsRead) {
|
CodeGenSchedRW SchedRW(RWIdx, IsRead, Seq, genRWName(Seq, IsRead));
|
||||||
|
if (IsRead)
|
||||||
SchedReads.push_back(SchedRW);
|
SchedReads.push_back(SchedRW);
|
||||||
return SchedReads.size() - 1;
|
else
|
||||||
}
|
SchedWrites.push_back(SchedRW);
|
||||||
SchedWrites.push_back(SchedRW);
|
return RWIdx;
|
||||||
return SchedWrites.size() - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Visit all the instruction definitions for this target to gather and
|
/// Visit all the instruction definitions for this target to gather and
|
||||||
@ -794,13 +835,13 @@ void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) {
|
|||||||
namespace {
|
namespace {
|
||||||
// Helper for substituteVariantOperand.
|
// Helper for substituteVariantOperand.
|
||||||
struct TransVariant {
|
struct TransVariant {
|
||||||
Record *VariantDef;
|
Record *VarOrSeqDef; // Variant or sequence.
|
||||||
unsigned RWIdx; // Index of this variant's matched type.
|
unsigned RWIdx; // Index of this variant or sequence's matched type.
|
||||||
unsigned ProcIdx; // Processor model index or zero for any.
|
unsigned ProcIdx; // Processor model index or zero for any.
|
||||||
unsigned TransVecIdx; // Index into PredTransitions::TransVec.
|
unsigned TransVecIdx; // Index into PredTransitions::TransVec.
|
||||||
|
|
||||||
TransVariant(Record *def, unsigned rwi, unsigned pi, unsigned ti):
|
TransVariant(Record *def, unsigned rwi, unsigned pi, unsigned ti):
|
||||||
VariantDef(def), RWIdx(rwi), ProcIdx(pi), TransVecIdx(ti) {}
|
VarOrSeqDef(def), RWIdx(rwi), ProcIdx(pi), TransVecIdx(ti) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Associate a predicate with the SchedReadWrite that it guards.
|
// Associate a predicate with the SchedReadWrite that it guards.
|
||||||
@ -843,6 +884,9 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool mutuallyExclusive(Record *PredDef, ArrayRef<PredCheck> Term);
|
bool mutuallyExclusive(Record *PredDef, ArrayRef<PredCheck> Term);
|
||||||
|
void getIntersectingVariants(
|
||||||
|
const CodeGenSchedRW &SchedRW, unsigned TransIdx,
|
||||||
|
std::vector<TransVariant> &IntersectingVariants);
|
||||||
void pushVariant(const TransVariant &VInfo, bool IsRead);
|
void pushVariant(const TransVariant &VInfo, bool IsRead);
|
||||||
};
|
};
|
||||||
} // anonymous
|
} // anonymous
|
||||||
@ -875,6 +919,137 @@ bool PredTransitions::mutuallyExclusive(Record *PredDef,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
const CodeGenSchedRW &AliasRW =
|
||||||
|
SchedModels.getSchedRW((*I)->getValueAsDef("AliasRW"));
|
||||||
|
if (AliasRW.HasVariants)
|
||||||
|
return true;
|
||||||
|
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)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate IntersectingVariants with any variants or aliased sequences of the
|
||||||
|
// given SchedRW whose processor indices and predicates are not mutually
|
||||||
|
// exclusive with the given transition,
|
||||||
|
void PredTransitions::getIntersectingVariants(
|
||||||
|
const CodeGenSchedRW &SchedRW, unsigned TransIdx,
|
||||||
|
std::vector<TransVariant> &IntersectingVariants) {
|
||||||
|
|
||||||
|
std::vector<TransVariant> Variants;
|
||||||
|
if (SchedRW.HasVariants) {
|
||||||
|
unsigned VarProcIdx = 0;
|
||||||
|
if (SchedRW.TheDef->getValueInit("SchedModel")->isComplete()) {
|
||||||
|
Record *ModelDef = SchedRW.TheDef->getValueAsDef("SchedModel");
|
||||||
|
VarProcIdx = SchedModels.getProcModel(ModelDef).Index;
|
||||||
|
}
|
||||||
|
// Push each variant. Assign TransVecIdx later.
|
||||||
|
const RecVec VarDefs = SchedRW.TheDef->getValueAsListOfDefs("Variants");
|
||||||
|
for (RecIter RI = VarDefs.begin(), RE = VarDefs.end(); RI != RE; ++RI)
|
||||||
|
Variants.push_back(TransVariant(*RI, SchedRW.Index, VarProcIdx, 0));
|
||||||
|
}
|
||||||
|
for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
|
||||||
|
AI != AE; ++AI) {
|
||||||
|
// If either the SchedAlias itself or the SchedReadWrite that it aliases
|
||||||
|
// to is defined within a processor model, constrain all variants to
|
||||||
|
// that processor.
|
||||||
|
unsigned AliasProcIdx = 0;
|
||||||
|
if ((*AI)->getValueInit("SchedModel")->isComplete()) {
|
||||||
|
Record *ModelDef = (*AI)->getValueAsDef("SchedModel");
|
||||||
|
AliasProcIdx = SchedModels.getProcModel(ModelDef).Index;
|
||||||
|
}
|
||||||
|
const CodeGenSchedRW &AliasRW =
|
||||||
|
SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
|
||||||
|
|
||||||
|
if (AliasRW.HasVariants) {
|
||||||
|
const RecVec VarDefs = AliasRW.TheDef->getValueAsListOfDefs("Variants");
|
||||||
|
for (RecIter RI = VarDefs.begin(), RE = VarDefs.end(); RI != RE; ++RI)
|
||||||
|
Variants.push_back(TransVariant(*RI, AliasRW.Index, AliasProcIdx, 0));
|
||||||
|
}
|
||||||
|
if (AliasRW.IsSequence) {
|
||||||
|
Variants.push_back(
|
||||||
|
TransVariant(AliasRW.TheDef, SchedRW.Index, AliasProcIdx, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned VIdx = 0, VEnd = Variants.size(); VIdx != VEnd; ++VIdx) {
|
||||||
|
TransVariant &Variant = Variants[VIdx];
|
||||||
|
// 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] && Variants[VIdx].ProcIdx) {
|
||||||
|
unsigned Cnt = std::count(ProcIndices.begin(), ProcIndices.end(),
|
||||||
|
Variant.ProcIdx);
|
||||||
|
if (!Cnt)
|
||||||
|
continue;
|
||||||
|
if (Cnt > 1) {
|
||||||
|
const CodeGenProcModel &PM =
|
||||||
|
*(SchedModels.procModelBegin() + Variant.ProcIdx);
|
||||||
|
throw TGError(Variant.VarOrSeqDef->getLoc(),
|
||||||
|
"Multiple variants defined for processor " + PM.ModelName +
|
||||||
|
" Ensure only one SchedAlias exists per RW.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Variant.VarOrSeqDef->isSubClassOf("SchedVar")) {
|
||||||
|
Record *PredDef = Variant.VarOrSeqDef->getValueAsDef("Predicate");
|
||||||
|
if (mutuallyExclusive(PredDef, TransVec[TransIdx].PredTerm))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (IntersectingVariants.empty()) {
|
||||||
|
// The first variant builds on the existing transition.
|
||||||
|
Variant.TransVecIdx = TransIdx;
|
||||||
|
IntersectingVariants.push_back(Variant);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Push another copy of the current transition for more variants.
|
||||||
|
Variant.TransVecIdx = TransVec.size();
|
||||||
|
IntersectingVariants.push_back(Variant);
|
||||||
|
TransVec.push_back(TransVec[TransIdx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Push the Reads/Writes selected by this variant onto the PredTransition
|
// Push the Reads/Writes selected by this variant onto the PredTransition
|
||||||
// specified by VInfo.
|
// specified by VInfo.
|
||||||
void PredTransitions::
|
void PredTransitions::
|
||||||
@ -882,17 +1057,23 @@ pushVariant(const TransVariant &VInfo, bool IsRead) {
|
|||||||
|
|
||||||
PredTransition &Trans = TransVec[VInfo.TransVecIdx];
|
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,
|
// If this operand transition is reached through a processor-specific alias,
|
||||||
// then the whole transition is specific to this processor.
|
// then the whole transition is specific to this processor.
|
||||||
if (VInfo.ProcIdx != 0)
|
if (VInfo.ProcIdx != 0)
|
||||||
Trans.ProcIndices.assign(1, VInfo.ProcIdx);
|
Trans.ProcIndices.assign(1, VInfo.ProcIdx);
|
||||||
|
|
||||||
RecVec SelectedDefs = VInfo.VariantDef->getValueAsListOfDefs("Selected");
|
|
||||||
IdxVec SelectedRWs;
|
IdxVec SelectedRWs;
|
||||||
SchedModels.findRWs(SelectedDefs, SelectedRWs, IsRead);
|
if (VInfo.VarOrSeqDef->isSubClassOf("SchedVar")) {
|
||||||
|
Record *PredDef = VInfo.VarOrSeqDef->getValueAsDef("Predicate");
|
||||||
|
Trans.PredTerm.push_back(PredCheck(IsRead, VInfo.RWIdx,PredDef));
|
||||||
|
RecVec SelectedDefs = VInfo.VarOrSeqDef->getValueAsListOfDefs("Selected");
|
||||||
|
SchedModels.findRWs(SelectedDefs, SelectedRWs, IsRead);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(VInfo.VarOrSeqDef->isSubClassOf("WriteSequence") &&
|
||||||
|
"variant must be a SchedVariant or aliased WriteSequence");
|
||||||
|
SelectedRWs.push_back(SchedModels.getSchedRWIdx(VInfo.VarOrSeqDef, IsRead));
|
||||||
|
}
|
||||||
|
|
||||||
const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(VInfo.RWIdx, IsRead);
|
const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(VInfo.RWIdx, IsRead);
|
||||||
|
|
||||||
@ -936,45 +1117,6 @@ pushVariant(const TransVariant &VInfo, bool IsRead) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// 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
|
// operand. StartIdx is an index into TransVec where partial results
|
||||||
// starts. RWSeq must be applied to all transitions between StartIdx and the end
|
// starts. RWSeq must be applied to all transitions between StartIdx and the end
|
||||||
@ -1000,64 +1142,9 @@ void PredTransitions::substituteVariantOperand(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Distribute this partial PredTransition across intersecting variants.
|
// Distribute this partial PredTransition across intersecting variants.
|
||||||
RecVec Variants;
|
// This will push a copies of TransVec[TransIdx] on the back of TransVec.
|
||||||
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;
|
std::vector<TransVariant> IntersectingVariants;
|
||||||
for (unsigned VIdx = 0, VEnd = Variants.size(); VIdx != VEnd; ++VIdx) {
|
getIntersectingVariants(SchedRW, TransIdx, IntersectingVariants);
|
||||||
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()) {
|
|
||||||
// The first variant builds on the existing transition.
|
|
||||||
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(
|
|
||||||
TransVariant(Variants[VIdx], VarRWIds[VIdx], VarProcModels[VIdx],
|
|
||||||
TransVec.size()));
|
|
||||||
TransVec.push_back(TransVec[TransIdx]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (IntersectingVariants.empty())
|
if (IntersectingVariants.empty())
|
||||||
throw TGError(SchedRW.TheDef->getLoc(), "No variant of this type has a "
|
throw TGError(SchedRW.TheDef->getLoc(), "No variant of this type has a "
|
||||||
"matching predicate on any processor ");
|
"matching predicate on any processor ");
|
||||||
|
@ -43,8 +43,10 @@ void splitSchedReadWrites(const RecVec &RWDefs,
|
|||||||
/// IsVariadic controls whether the variants are expanded into multiple operands
|
/// IsVariadic controls whether the variants are expanded into multiple operands
|
||||||
/// or a sequence of writes on one operand.
|
/// or a sequence of writes on one operand.
|
||||||
struct CodeGenSchedRW {
|
struct CodeGenSchedRW {
|
||||||
|
unsigned Index;
|
||||||
std::string Name;
|
std::string Name;
|
||||||
Record *TheDef;
|
Record *TheDef;
|
||||||
|
bool IsRead;
|
||||||
bool IsAlias;
|
bool IsAlias;
|
||||||
bool HasVariants;
|
bool HasVariants;
|
||||||
bool IsVariadic;
|
bool IsVariadic;
|
||||||
@ -52,10 +54,12 @@ struct CodeGenSchedRW {
|
|||||||
IdxVec Sequence;
|
IdxVec Sequence;
|
||||||
RecVec Aliases;
|
RecVec Aliases;
|
||||||
|
|
||||||
CodeGenSchedRW(): TheDef(0), IsAlias(false), HasVariants(false),
|
CodeGenSchedRW(): Index(0), TheDef(0), IsAlias(false), HasVariants(false),
|
||||||
IsVariadic(false), IsSequence(false) {}
|
IsVariadic(false), IsSequence(false) {}
|
||||||
CodeGenSchedRW(Record *Def): TheDef(Def), IsAlias(false), IsVariadic(false) {
|
CodeGenSchedRW(unsigned Idx, Record *Def): Index(Idx), TheDef(Def),
|
||||||
|
IsAlias(false), IsVariadic(false) {
|
||||||
Name = Def->getName();
|
Name = Def->getName();
|
||||||
|
IsRead = Def->isSubClassOf("SchedRead");
|
||||||
HasVariants = Def->isSubClassOf("SchedVariant");
|
HasVariants = Def->isSubClassOf("SchedVariant");
|
||||||
if (HasVariants)
|
if (HasVariants)
|
||||||
IsVariadic = Def->getValueAsBit("Variadic");
|
IsVariadic = Def->getValueAsBit("Variadic");
|
||||||
@ -66,9 +70,10 @@ struct CodeGenSchedRW {
|
|||||||
IsSequence = Def->isSubClassOf("WriteSequence");
|
IsSequence = Def->isSubClassOf("WriteSequence");
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeGenSchedRW(const IdxVec &Seq, const std::string &Name):
|
CodeGenSchedRW(unsigned Idx, bool Read, const IdxVec &Seq,
|
||||||
Name(Name), TheDef(0), IsAlias(false), HasVariants(false),
|
const std::string &Name):
|
||||||
IsVariadic(false), IsSequence(true), Sequence(Seq) {
|
Index(Idx), Name(Name), TheDef(0), IsRead(Read), IsAlias(false),
|
||||||
|
HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) {
|
||||||
assert(Sequence.size() > 1 && "implied sequence needs >1 RWs");
|
assert(Sequence.size() > 1 && "implied sequence needs >1 RWs");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,15 +291,14 @@ public:
|
|||||||
const CodeGenSchedRW &getSchedRW(unsigned Idx, bool IsRead) const {
|
const CodeGenSchedRW &getSchedRW(unsigned Idx, bool IsRead) const {
|
||||||
return IsRead ? getSchedRead(Idx) : getSchedWrite(Idx);
|
return IsRead ? getSchedRead(Idx) : getSchedWrite(Idx);
|
||||||
}
|
}
|
||||||
CodeGenSchedRW &getSchedRW(Record *Def, unsigned &Idx) {
|
CodeGenSchedRW &getSchedRW(Record *Def) {
|
||||||
bool IsRead = Def->isSubClassOf("SchedRead");
|
bool IsRead = Def->isSubClassOf("SchedRead");
|
||||||
Idx = getSchedRWIdx(Def, IsRead);
|
unsigned Idx = getSchedRWIdx(Def, IsRead);
|
||||||
return const_cast<CodeGenSchedRW&>(
|
return const_cast<CodeGenSchedRW&>(
|
||||||
IsRead ? getSchedRead(Idx) : getSchedWrite(Idx));
|
IsRead ? getSchedRead(Idx) : getSchedWrite(Idx));
|
||||||
}
|
}
|
||||||
CodeGenSchedRW &getSchedRW(Record *Def) {
|
const CodeGenSchedRW &getSchedRW(Record*Def) const {
|
||||||
unsigned Idx;
|
return const_cast<CodeGenSchedModels&>(*this).getSchedRW(Def);
|
||||||
return getSchedRW(Def, Idx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned getSchedRWIdx(Record *Def, bool IsRead, unsigned After = 0) const;
|
unsigned getSchedRWIdx(Record *Def, bool IsRead, unsigned After = 0) const;
|
||||||
@ -340,6 +344,8 @@ public:
|
|||||||
void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const;
|
void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const;
|
||||||
void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const;
|
void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const;
|
||||||
void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const;
|
void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const;
|
||||||
|
void expandRWSeqForProc(unsigned RWIdx, IdxVec &RWSeq, bool IsRead,
|
||||||
|
const CodeGenProcModel &ProcModel) const;
|
||||||
|
|
||||||
unsigned addSchedClass(const IdxVec &OperWrites, const IdxVec &OperReads,
|
unsigned addSchedClass(const IdxVec &OperWrites, const IdxVec &OperReads,
|
||||||
const IdxVec &ProcIndices);
|
const IdxVec &ProcIndices);
|
||||||
|
@ -664,15 +664,16 @@ Record *SubtargetEmitter::FindWriteResources(
|
|||||||
if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes"))
|
if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes"))
|
||||||
return SchedWrite.TheDef;
|
return SchedWrite.TheDef;
|
||||||
|
|
||||||
// Check this processor's list of aliases for SchedWrite.
|
|
||||||
Record *AliasDef = 0;
|
Record *AliasDef = 0;
|
||||||
for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
|
for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
|
||||||
AI != AE; ++AI) {
|
AI != AE; ++AI) {
|
||||||
const CodeGenSchedRW &AliasRW =
|
const CodeGenSchedRW &AliasRW =
|
||||||
SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
|
SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
|
||||||
Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
|
if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
|
||||||
if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
|
Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
|
||||||
continue;
|
if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (AliasDef)
|
if (AliasDef)
|
||||||
throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
|
throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
|
||||||
"defined for processor " + ProcModel.ModelName +
|
"defined for processor " + ProcModel.ModelName +
|
||||||
@ -722,9 +723,11 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
|
|||||||
AI != AE; ++AI) {
|
AI != AE; ++AI) {
|
||||||
const CodeGenSchedRW &AliasRW =
|
const CodeGenSchedRW &AliasRW =
|
||||||
SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
|
SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
|
||||||
Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
|
if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
|
||||||
if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
|
Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
|
||||||
continue;
|
if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (AliasDef)
|
if (AliasDef)
|
||||||
throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
|
throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
|
||||||
"defined for processor " + ProcModel.ModelName +
|
"defined for processor " + ProcModel.ModelName +
|
||||||
@ -833,6 +836,8 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (RWDef) {
|
if (RWDef) {
|
||||||
|
Writes.clear();
|
||||||
|
Reads.clear();
|
||||||
SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
|
SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
|
||||||
Writes, Reads);
|
Writes, Reads);
|
||||||
}
|
}
|
||||||
@ -844,7 +849,8 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
|
|||||||
std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
|
std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
|
||||||
for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
|
for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
|
||||||
IdxVec WriteSeq;
|
IdxVec WriteSeq;
|
||||||
SchedModels.expandRWSequence(*WI, WriteSeq, /*IsRead=*/false);
|
SchedModels.expandRWSeqForProc(*WI, WriteSeq, /*IsRead=*/false,
|
||||||
|
ProcModel);
|
||||||
|
|
||||||
// For each operand, create a latency entry.
|
// For each operand, create a latency entry.
|
||||||
MCWriteLatencyEntry WLEntry;
|
MCWriteLatencyEntry WLEntry;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user