mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-22 19:50:55 +00:00
TableGen subtarget parser. Handle new machine model.
Infer SchedClasses from variants defined by the target or subtarget. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163952 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
48605c3406
commit
5e613c260b
@ -27,6 +27,11 @@ static void dumpIdxVec(const IdxVec &V) {
|
||||
dbgs() << V[i] << ", ";
|
||||
}
|
||||
}
|
||||
static void dumpIdxVec(const SmallVectorImpl<unsigned> &V) {
|
||||
for (unsigned i = 0, e = V.size(); i < e; ++i) {
|
||||
dbgs() << V[i] << ", ";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// CodeGenModels ctor interprets machine model records and populates maps.
|
||||
@ -63,6 +68,12 @@ CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
|
||||
// Find ItinRW records for each processor and itinerary class.
|
||||
// (For per-operand resources mapped to itinerary classes).
|
||||
collectProcItinRW();
|
||||
|
||||
// Infer new SchedClasses from SchedVariant.
|
||||
inferSchedClasses();
|
||||
|
||||
DEBUG(for (unsigned i = 0; i < SchedClasses.size(); ++i)
|
||||
SchedClasses[i].dump(this));
|
||||
}
|
||||
|
||||
/// Gather all processor models.
|
||||
@ -289,6 +300,57 @@ void CodeGenSchedModels::findRWs(const RecVec &RWDefs, IdxVec &RWs,
|
||||
}
|
||||
}
|
||||
|
||||
void CodeGenSchedModels::expandRWSequence(unsigned RWIdx, IdxVec &RWSeq,
|
||||
bool IsRead) const {
|
||||
const CodeGenSchedRW &SchedRW = getSchedRW(RWIdx, IsRead);
|
||||
if (!SchedRW.IsSequence) {
|
||||
RWSeq.push_back(RWIdx);
|
||||
return;
|
||||
}
|
||||
int Repeat =
|
||||
SchedRW.TheDef ? SchedRW.TheDef->getValueAsInt("Repeat") : 1;
|
||||
for (int i = 0; i < Repeat; ++i) {
|
||||
for (IdxIter I = SchedRW.Sequence.begin(), E = SchedRW.Sequence.end();
|
||||
I != E; ++I) {
|
||||
expandRWSequence(*I, RWSeq, IsRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find the existing SchedWrite that models this sequence of writes.
|
||||
unsigned CodeGenSchedModels::findRWForSequence(const IdxVec &Seq,
|
||||
bool IsRead) {
|
||||
std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites;
|
||||
|
||||
for (std::vector<CodeGenSchedRW>::iterator I = RWVec.begin(), E = RWVec.end();
|
||||
I != E; ++I) {
|
||||
if (I->Sequence == Seq)
|
||||
return I - RWVec.begin();
|
||||
}
|
||||
// Index zero reserved for invalid RW.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Add this ReadWrite if it doesn't already exist.
|
||||
unsigned CodeGenSchedModels::findOrInsertRW(ArrayRef<unsigned> Seq,
|
||||
bool IsRead) {
|
||||
assert(!Seq.empty() && "cannot insert empty sequence");
|
||||
if (Seq.size() == 1)
|
||||
return Seq.back();
|
||||
|
||||
unsigned Idx = findRWForSequence(Seq, IsRead);
|
||||
if (Idx)
|
||||
return Idx;
|
||||
|
||||
CodeGenSchedRW SchedRW(Seq, genRWName(Seq, IsRead));
|
||||
if (IsRead) {
|
||||
SchedReads.push_back(SchedRW);
|
||||
return SchedReads.size() - 1;
|
||||
}
|
||||
SchedWrites.push_back(SchedRW);
|
||||
return SchedWrites.size() - 1;
|
||||
}
|
||||
|
||||
/// Visit all the instruction definitions for this target to gather and
|
||||
/// enumerate the itinerary classes. These are the explicitly specified
|
||||
/// SchedClasses. More SchedClasses may be inferred.
|
||||
@ -619,6 +681,409 @@ void CodeGenSchedModels::collectProcItinRW() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Infer new classes from existing classes. In the process, this may create new
|
||||
/// SchedWrites from sequences of existing SchedWrites.
|
||||
void CodeGenSchedModels::inferSchedClasses() {
|
||||
// Visit all existing classes and newly created classes.
|
||||
for (unsigned Idx = 0; Idx != SchedClasses.size(); ++Idx) {
|
||||
if (SchedClasses[Idx].ItinClassDef)
|
||||
inferFromItinClass(SchedClasses[Idx].ItinClassDef, Idx);
|
||||
else if (!SchedClasses[Idx].InstRWs.empty())
|
||||
inferFromInstRWs(Idx);
|
||||
else {
|
||||
inferFromRW(SchedClasses[Idx].Writes, SchedClasses[Idx].Reads,
|
||||
Idx, SchedClasses[Idx].ProcIndices);
|
||||
}
|
||||
assert(SchedClasses.size() < (NumInstrSchedClasses*6) &&
|
||||
"too many SchedVariants");
|
||||
}
|
||||
}
|
||||
|
||||
/// Infer classes from per-processor itinerary resources.
|
||||
void CodeGenSchedModels::inferFromItinClass(Record *ItinClassDef,
|
||||
unsigned FromClassIdx) {
|
||||
for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) {
|
||||
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");
|
||||
if (!std::count(Matched.begin(), Matched.end(), ItinClassDef))
|
||||
continue;
|
||||
if (HasMatch)
|
||||
throw TGError((*II)->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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Infer classes from per-processor InstReadWrite definitions.
|
||||
void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) {
|
||||
const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs;
|
||||
for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); RWI != RWE; ++RWI) {
|
||||
RecVec Instrs = (*RWI)->getValueAsListOfDefs("Instrs");
|
||||
RecIter II = Instrs.begin(), IE = Instrs.end();
|
||||
for (; II != IE; ++II) {
|
||||
if (InstrClassMap[*II] == SCIdx)
|
||||
break;
|
||||
}
|
||||
// If this class no longer has any instructions mapped to it, it has become
|
||||
// irrelevant.
|
||||
if (II == IE)
|
||||
continue;
|
||||
IdxVec Writes, Reads;
|
||||
findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
|
||||
unsigned PIdx = getProcModel((*RWI)->getValueAsDef("SchedModel")).Index;
|
||||
IdxVec ProcIndices(1, PIdx);
|
||||
inferFromRW(Writes, Reads, SCIdx, ProcIndices);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Associate a predicate with the SchedReadWrite that it guards.
|
||||
// RWIdx is the index of the read/write variant.
|
||||
struct PredCheck {
|
||||
bool IsRead;
|
||||
unsigned RWIdx;
|
||||
Record *Predicate;
|
||||
|
||||
PredCheck(bool r, unsigned w, Record *p): IsRead(r), RWIdx(w), Predicate(p) {}
|
||||
};
|
||||
|
||||
// A Predicate transition is a list of RW sequences guarded by a PredTerm.
|
||||
struct PredTransition {
|
||||
// A predicate term is a conjunction of PredChecks.
|
||||
SmallVector<PredCheck, 4> PredTerm;
|
||||
SmallVector<SmallVector<unsigned,4>, 16> WriteSequences;
|
||||
SmallVector<SmallVector<unsigned,4>, 16> ReadSequences;
|
||||
};
|
||||
|
||||
// Encapsulate a set of partially constructed transitions.
|
||||
// The results are built by repeated calls to substituteVariants.
|
||||
class PredTransitions {
|
||||
CodeGenSchedModels &SchedModels;
|
||||
|
||||
public:
|
||||
std::vector<PredTransition> TransVec;
|
||||
|
||||
PredTransitions(CodeGenSchedModels &sm): SchedModels(sm) {}
|
||||
|
||||
void substituteVariantOperand(const SmallVectorImpl<unsigned> &RWSeq,
|
||||
bool IsRead, unsigned StartIdx);
|
||||
|
||||
void substituteVariants(const PredTransition &Trans);
|
||||
|
||||
#ifndef NDEBUG
|
||||
void dump() const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool mutuallyExclusive(Record *PredDef, ArrayRef<PredCheck> Term);
|
||||
void pushVariant(unsigned SchedRW, Record *Variant, PredTransition &Trans,
|
||||
bool IsRead);
|
||||
};
|
||||
} // anonymous
|
||||
|
||||
// Return true if this predicate is mutually exclusive with a PredTerm. This
|
||||
// degenerates into checking if the predicate is mutually exclusive with any
|
||||
// predicate in the Term's conjunction.
|
||||
//
|
||||
// All predicates associated with a given SchedRW are considered mutually
|
||||
// exclusive. This should work even if the conditions expressed by the
|
||||
// predicates are not exclusive because the predicates for a given SchedWrite
|
||||
// are always checked in the order they are defined in the .td file. Later
|
||||
// conditions implicitly negate any prior condition.
|
||||
bool PredTransitions::mutuallyExclusive(Record *PredDef,
|
||||
ArrayRef<PredCheck> Term) {
|
||||
|
||||
for (ArrayRef<PredCheck>::iterator I = Term.begin(), E = Term.end();
|
||||
I != E; ++I) {
|
||||
if (I->Predicate == PredDef)
|
||||
return false;
|
||||
|
||||
const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(I->RWIdx, I->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;
|
||||
}
|
||||
}
|
||||
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");
|
||||
IdxVec SelectedRWs;
|
||||
SchedModels.findRWs(SelectedDefs, SelectedRWs, IsRead);
|
||||
|
||||
const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(RWIdx, IsRead);
|
||||
|
||||
SmallVectorImpl<SmallVector<unsigned,4> > &RWSequences = IsRead
|
||||
? Trans.ReadSequences : Trans.WriteSequences;
|
||||
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) {
|
||||
RWSequences.push_back(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
|
||||
// sequence belongs to a single operand.
|
||||
for (IdxIter RWI = SelectedRWs.begin(), RWE = SelectedRWs.end();
|
||||
RWI != RWE; ++RWI, ++OperIdx) {
|
||||
IdxVec ExpandedRWs;
|
||||
if (IsRead)
|
||||
ExpandedRWs.push_back(*RWI);
|
||||
else
|
||||
SchedModels.expandRWSequence(*RWI, ExpandedRWs, IsRead);
|
||||
RWSequences[OperIdx].insert(RWSequences[OperIdx].end(),
|
||||
ExpandedRWs.begin(), ExpandedRWs.end());
|
||||
}
|
||||
assert(OperIdx == RWSequences.size() && "missed a sequence");
|
||||
}
|
||||
else {
|
||||
// Push this transition's expanded sequence onto this transition's last
|
||||
// sequence (add to the current operand's sequence).
|
||||
SmallVectorImpl<unsigned> &Seq = RWSequences.back();
|
||||
IdxVec ExpandedRWs;
|
||||
for (IdxIter RWI = SelectedRWs.begin(), RWE = SelectedRWs.end();
|
||||
RWI != RWE; ++RWI) {
|
||||
if (IsRead)
|
||||
ExpandedRWs.push_back(*RWI);
|
||||
else
|
||||
SchedModels.expandRWSequence(*RWI, ExpandedRWs, IsRead);
|
||||
}
|
||||
Seq.insert(Seq.end(), ExpandedRWs.begin(), ExpandedRWs.end());
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
// of TransVec.
|
||||
void PredTransitions::substituteVariantOperand(
|
||||
const SmallVectorImpl<unsigned> &RWSeq, bool IsRead, unsigned StartIdx) {
|
||||
|
||||
// Visit each original RW within the current sequence.
|
||||
for (SmallVectorImpl<unsigned>::const_iterator
|
||||
RWI = RWSeq.begin(), RWE = RWSeq.end(); RWI != RWE; ++RWI) {
|
||||
const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(*RWI, IsRead);
|
||||
// Push this RW on all partial PredTransitions or distribute variants.
|
||||
// New PredTransitions may be pushed within this loop which should not be
|
||||
// revisited (TransEnd must be loop invariant).
|
||||
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 (IsRead)
|
||||
TransVec[TransIdx].ReadSequences.back().push_back(*RWI);
|
||||
else
|
||||
TransVec[TransIdx].WriteSequences.back().push_back(*RWI);
|
||||
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");
|
||||
if (mutuallyExclusive(PredDef, TransVec[TransIdx].PredTerm))
|
||||
continue;
|
||||
if (IntersectingVariants.empty())
|
||||
// The first variant builds on the existing transition.
|
||||
IntersectingVariants.push_back(std::make_pair(*VI, TransIdx));
|
||||
else {
|
||||
// Push another copy of the current transition for more variants.
|
||||
IntersectingVariants.push_back(
|
||||
std::make_pair(*VI, TransVec.size()));
|
||||
TransVec.push_back(TransVec[TransIdx]);
|
||||
}
|
||||
}
|
||||
// Now expand each variant on top of its copy of the transition.
|
||||
for (std::vector<std::pair<Record*, unsigned> >::const_iterator
|
||||
IVI = IntersectingVariants.begin(),
|
||||
IVE = IntersectingVariants.end();
|
||||
IVI != IVE; ++IVI)
|
||||
pushVariant(*RWI, IVI->first, TransVec[IVI->second], IsRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For each variant of a Read/Write in Trans, substitute the sequence of
|
||||
// Read/Writes guarded by the variant. This is exponential in the number of
|
||||
// variant Read/Writes, but in practice detection of mutually exclusive
|
||||
// predicates should result in linear growth in the total number variants.
|
||||
//
|
||||
// This is one step in a breadth-first search of nested variants.
|
||||
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.back().PredTerm = Trans.PredTerm;
|
||||
|
||||
// Visit each original write sequence.
|
||||
for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
|
||||
WSI = Trans.WriteSequences.begin(), WSE = Trans.WriteSequences.end();
|
||||
WSI != WSE; ++WSI) {
|
||||
// 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);
|
||||
}
|
||||
substituteVariantOperand(*WSI, /*IsRead=*/false, StartIdx);
|
||||
}
|
||||
// Visit each original read sequence.
|
||||
for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
|
||||
RSI = Trans.ReadSequences.begin(), RSE = Trans.ReadSequences.end();
|
||||
RSI != RSE; ++RSI) {
|
||||
// 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);
|
||||
}
|
||||
substituteVariantOperand(*RSI, /*IsRead=*/true, StartIdx);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
CodeGenSchedModels &SchedModels) {
|
||||
// For each PredTransition, create a new CodeGenSchedTransition, which usually
|
||||
// requires creating a new SchedClass.
|
||||
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));
|
||||
}
|
||||
IdxVec OperReadsVariant;
|
||||
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.
|
||||
OperReadsVariant.push_back(
|
||||
SchedModels.findOrInsertRW(*RSI, /*IsRead=*/true));
|
||||
}
|
||||
CodeGenSchedTransition SCTrans;
|
||||
SCTrans.ToClassIdx =
|
||||
SchedModels.addSchedClass(OperWritesVariant, OperReadsVariant,
|
||||
ProcIndices);
|
||||
SCTrans.ProcIndices = ProcIndices;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
/// Find each variant write that OperWrites or OperaReads refers to and create a
|
||||
/// new SchedClass for each variant.
|
||||
void CodeGenSchedModels::inferFromRW(const IdxVec &OperWrites,
|
||||
const IdxVec &OperReads,
|
||||
unsigned FromClassIdx,
|
||||
const IdxVec &ProcIndices) {
|
||||
DEBUG(dbgs() << "INFERRW Writes: ");
|
||||
|
||||
// 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);
|
||||
for (IdxIter I = OperWrites.begin(), E = OperWrites.end(); I != E; ++I) {
|
||||
IdxVec WriteSeq;
|
||||
expandRWSequence(*I, 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: ");
|
||||
for (IdxIter I = OperReads.begin(), E = OperReads.end(); I != E; ++I) {
|
||||
IdxVec ReadSeq;
|
||||
expandRWSequence(*I, 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() << ") ");
|
||||
}
|
||||
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());
|
||||
LastTransitions.swap(Transitions.TransVec);
|
||||
}
|
||||
// If the first transition has no variants, nothing to do.
|
||||
if (LastTransitions[0].PredTerm.empty())
|
||||
return;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void CodeGenProcModel::dump() const {
|
||||
dbgs() << Index << ": " << ModelName << " "
|
||||
@ -655,4 +1120,34 @@ void CodeGenSchedClass::dump(const CodeGenSchedModels* SchedModels) const {
|
||||
}
|
||||
dbgs() << "\n ProcIdx: "; dumpIdxVec(ProcIndices); dbgs() << '\n';
|
||||
}
|
||||
|
||||
void PredTransitions::dump() const {
|
||||
dbgs() << "Expanded Variants:\n";
|
||||
for (std::vector<PredTransition>::const_iterator
|
||||
TI = TransVec.begin(), TE = TransVec.end(); TI != TE; ++TI) {
|
||||
dbgs() << "{";
|
||||
for (SmallVectorImpl<PredCheck>::const_iterator
|
||||
PCI = TI->PredTerm.begin(), PCE = TI->PredTerm.end();
|
||||
PCI != PCE; ++PCI) {
|
||||
if (PCI != TI->PredTerm.begin())
|
||||
dbgs() << ", ";
|
||||
dbgs() << SchedModels.getSchedRW(PCI->RWIdx, PCI->IsRead).Name
|
||||
<< ":" << PCI->Predicate->getName();
|
||||
}
|
||||
dbgs() << "},\n => {";
|
||||
for (SmallVectorImpl<SmallVector<unsigned,4> >::const_iterator
|
||||
WSI = TI->WriteSequences.begin(), WSE = TI->WriteSequences.end();
|
||||
WSI != WSE; ++WSI) {
|
||||
dbgs() << "(";
|
||||
for (SmallVectorImpl<unsigned>::const_iterator
|
||||
WI = WSI->begin(), WE = WSI->end(); WI != WE; ++WI) {
|
||||
if (WI != WSI->begin())
|
||||
dbgs() << ", ";
|
||||
dbgs() << SchedModels.getSchedWrite(*WI).Name;
|
||||
}
|
||||
dbgs() << "),";
|
||||
}
|
||||
dbgs() << "}\n";
|
||||
}
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
@ -83,6 +83,13 @@ struct CodeGenSchedRW {
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Represent a transition between SchedClasses induced by SchedWriteVariant.
|
||||
struct CodeGenSchedTransition {
|
||||
unsigned ToClassIdx;
|
||||
IdxVec ProcIndices;
|
||||
RecVec PredTerm;
|
||||
};
|
||||
|
||||
/// Scheduling class.
|
||||
///
|
||||
/// Each instruction description will be mapped to a scheduling class. There are
|
||||
@ -116,6 +123,8 @@ struct CodeGenSchedClass {
|
||||
// Sorted list of ProcIdx, where ProcIdx==0 implies any processor.
|
||||
IdxVec ProcIndices;
|
||||
|
||||
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.
|
||||
RecVec InstRWs;
|
||||
@ -308,6 +317,7 @@ public:
|
||||
|
||||
void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const;
|
||||
void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const;
|
||||
void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const;
|
||||
|
||||
unsigned addSchedClass(const IdxVec &OperWrites, const IdxVec &OperReads,
|
||||
const IdxVec &ProcIndices);
|
||||
@ -337,6 +347,13 @@ private:
|
||||
void collectProcItins();
|
||||
|
||||
void collectProcItinRW();
|
||||
|
||||
void inferSchedClasses();
|
||||
|
||||
void inferFromRW(const IdxVec &OperWrites, const IdxVec &OperReads,
|
||||
unsigned FromClassIdx, const IdxVec &ProcIndices);
|
||||
void inferFromItinClass(Record *ItinClassDef, unsigned FromClassIdx);
|
||||
void inferFromInstRWs(unsigned SCIdx);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
Loading…
x
Reference in New Issue
Block a user