mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-23 12:11:58 +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] << ", ";
|
dbgs() << V[i] << ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
static void dumpIdxVec(const SmallVectorImpl<unsigned> &V) {
|
||||||
|
for (unsigned i = 0, e = V.size(); i < e; ++i) {
|
||||||
|
dbgs() << V[i] << ", ";
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// CodeGenModels ctor interprets machine model records and populates maps.
|
/// 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.
|
// Find ItinRW records for each processor and itinerary class.
|
||||||
// (For per-operand resources mapped to itinerary classes).
|
// (For per-operand resources mapped to itinerary classes).
|
||||||
collectProcItinRW();
|
collectProcItinRW();
|
||||||
|
|
||||||
|
// Infer new SchedClasses from SchedVariant.
|
||||||
|
inferSchedClasses();
|
||||||
|
|
||||||
|
DEBUG(for (unsigned i = 0; i < SchedClasses.size(); ++i)
|
||||||
|
SchedClasses[i].dump(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gather all processor models.
|
/// 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
|
/// Visit all the instruction definitions for this target to gather and
|
||||||
/// enumerate the itinerary classes. These are the explicitly specified
|
/// enumerate the itinerary classes. These are the explicitly specified
|
||||||
/// SchedClasses. More SchedClasses may be inferred.
|
/// 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
|
#ifndef NDEBUG
|
||||||
void CodeGenProcModel::dump() const {
|
void CodeGenProcModel::dump() const {
|
||||||
dbgs() << Index << ": " << ModelName << " "
|
dbgs() << Index << ": " << ModelName << " "
|
||||||
@ -655,4 +1120,34 @@ void CodeGenSchedClass::dump(const CodeGenSchedModels* SchedModels) const {
|
|||||||
}
|
}
|
||||||
dbgs() << "\n ProcIdx: "; dumpIdxVec(ProcIndices); dbgs() << '\n';
|
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
|
#endif // NDEBUG
|
||||||
|
@ -83,6 +83,13 @@ struct CodeGenSchedRW {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Represent a transition between SchedClasses induced by SchedWriteVariant.
|
||||||
|
struct CodeGenSchedTransition {
|
||||||
|
unsigned ToClassIdx;
|
||||||
|
IdxVec ProcIndices;
|
||||||
|
RecVec PredTerm;
|
||||||
|
};
|
||||||
|
|
||||||
/// Scheduling class.
|
/// Scheduling class.
|
||||||
///
|
///
|
||||||
/// Each instruction description will be mapped to a scheduling class. There are
|
/// 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.
|
// Sorted list of ProcIdx, where ProcIdx==0 implies any processor.
|
||||||
IdxVec ProcIndices;
|
IdxVec ProcIndices;
|
||||||
|
|
||||||
|
std::vector<CodeGenSchedTransition> Transitions;
|
||||||
|
|
||||||
// InstReadWrite records associated with this class. Any Instrs that the
|
// InstReadWrite records associated with this class. Any Instrs that the
|
||||||
// definitions refer to that are not mapped to this class should be ignored.
|
// definitions refer to that are not mapped to this class should be ignored.
|
||||||
RecVec InstRWs;
|
RecVec InstRWs;
|
||||||
@ -308,6 +317,7 @@ 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;
|
||||||
|
|
||||||
unsigned addSchedClass(const IdxVec &OperWrites, const IdxVec &OperReads,
|
unsigned addSchedClass(const IdxVec &OperWrites, const IdxVec &OperReads,
|
||||||
const IdxVec &ProcIndices);
|
const IdxVec &ProcIndices);
|
||||||
@ -337,6 +347,13 @@ private:
|
|||||||
void collectProcItins();
|
void collectProcItins();
|
||||||
|
|
||||||
void collectProcItinRW();
|
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
|
} // namespace llvm
|
||||||
|
Loading…
x
Reference in New Issue
Block a user