mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 16:33:28 +00:00
Fix for PR1075: bottom-up register-reduction scheduling actually increases register pressure.
- Fixed bugs in sethi-ullman number computation and priority queue comparison functions. - Separate code that handles priority computation special cases from SU number computation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33025 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ddae4bd683
commit
c62d4bb695
@ -414,6 +414,12 @@ namespace {
|
|||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
|
static inline bool isCopyFromLiveIn(const SUnit *SU) {
|
||||||
|
SDNode *N = SU->Node;
|
||||||
|
return N->getOpcode() == ISD::CopyFromReg &&
|
||||||
|
N->getOperand(N->getNumOperands()-1).getValueType() != MVT::Flag;
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template<class SF>
|
template<class SF>
|
||||||
class VISIBILITY_HIDDEN RegReductionPriorityQueue
|
class VISIBILITY_HIDDEN RegReductionPriorityQueue
|
||||||
@ -428,7 +434,7 @@ namespace {
|
|||||||
std::vector<SUnit> &sunits) {}
|
std::vector<SUnit> &sunits) {}
|
||||||
virtual void releaseState() {}
|
virtual void releaseState() {}
|
||||||
|
|
||||||
virtual int getSethiUllmanNumber(unsigned NodeNum) const {
|
virtual unsigned getSethiUllmanNumber(const SUnit *SU) const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,7 +470,7 @@ namespace {
|
|||||||
const std::vector<SUnit> *SUnits;
|
const std::vector<SUnit> *SUnits;
|
||||||
|
|
||||||
// SethiUllmanNumbers - The SethiUllman number for each node.
|
// SethiUllmanNumbers - The SethiUllman number for each node.
|
||||||
std::vector<int> SethiUllmanNumbers;
|
std::vector<unsigned> SethiUllmanNumbers;
|
||||||
|
|
||||||
const TargetInstrInfo *TII;
|
const TargetInstrInfo *TII;
|
||||||
public:
|
public:
|
||||||
@ -486,9 +492,30 @@ namespace {
|
|||||||
SethiUllmanNumbers.clear();
|
SethiUllmanNumbers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getSethiUllmanNumber(unsigned NodeNum) const {
|
unsigned getSethiUllmanNumber(const SUnit *SU) const {
|
||||||
assert(NodeNum < SethiUllmanNumbers.size());
|
assert(SU->NodeNum < SethiUllmanNumbers.size());
|
||||||
return SethiUllmanNumbers[NodeNum];
|
unsigned Opc = SU->Node->getOpcode();
|
||||||
|
if (Opc == ISD::CopyFromReg && !isCopyFromLiveIn(SU))
|
||||||
|
// CopyFromReg should be close to its def because it restricts
|
||||||
|
// allocation choices. But if it is a livein then perhaps we want it
|
||||||
|
// closer to its uses so it can be coalesced.
|
||||||
|
return 0xffff;
|
||||||
|
else if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg)
|
||||||
|
// CopyToReg should be close to its uses to facilitate coalescing and
|
||||||
|
// avoid spilling.
|
||||||
|
return 0;
|
||||||
|
else if (SU->NumSuccs == 0)
|
||||||
|
// If SU does not have a use, i.e. it doesn't produce a value that would
|
||||||
|
// be consumed (e.g. store), then it terminates a chain of computation.
|
||||||
|
// Give it a large SethiUllman number so it will be scheduled right
|
||||||
|
// before its predecessors that it doesn't lengthen their live ranges.
|
||||||
|
return 0xffff;
|
||||||
|
else if (SU->NumPreds == 0)
|
||||||
|
// If SU does not have a def, schedule it close to its uses because it
|
||||||
|
// does not lengthen any live ranges.
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return SethiUllmanNumbers[SU->NodeNum];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDUOperand(const SUnit *SU1, const SUnit *SU2) {
|
bool isDUOperand(const SUnit *SU1, const SUnit *SU2) {
|
||||||
@ -507,7 +534,7 @@ namespace {
|
|||||||
bool canClobber(SUnit *SU, SUnit *Op);
|
bool canClobber(SUnit *SU, SUnit *Op);
|
||||||
void AddPseudoTwoAddrDeps();
|
void AddPseudoTwoAddrDeps();
|
||||||
void CalculatePriorities();
|
void CalculatePriorities();
|
||||||
int CalcNodePriority(const SUnit *SU);
|
unsigned CalcNodePriority(const SUnit *SU);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -520,7 +547,7 @@ namespace {
|
|||||||
const std::vector<SUnit> *SUnits;
|
const std::vector<SUnit> *SUnits;
|
||||||
|
|
||||||
// SethiUllmanNumbers - The SethiUllman number for each node.
|
// SethiUllmanNumbers - The SethiUllman number for each node.
|
||||||
std::vector<int> SethiUllmanNumbers;
|
std::vector<unsigned> SethiUllmanNumbers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TDRegReductionPriorityQueue() {}
|
TDRegReductionPriorityQueue() {}
|
||||||
@ -538,86 +565,38 @@ namespace {
|
|||||||
SethiUllmanNumbers.clear();
|
SethiUllmanNumbers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int getSethiUllmanNumber(unsigned NodeNum) const {
|
unsigned getSethiUllmanNumber(const SUnit *SU) const {
|
||||||
assert(NodeNum < SethiUllmanNumbers.size());
|
assert(SU->NodeNum < SethiUllmanNumbers.size());
|
||||||
return SethiUllmanNumbers[NodeNum];
|
return SethiUllmanNumbers[SU->NodeNum];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CalculatePriorities();
|
void CalculatePriorities();
|
||||||
int CalcNodePriority(const SUnit *SU);
|
unsigned CalcNodePriority(const SUnit *SU);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isFloater(const SUnit *SU) {
|
|
||||||
if (SU->Node->isTargetOpcode()) {
|
|
||||||
if (SU->NumPreds == 0)
|
|
||||||
return true;
|
|
||||||
if (SU->NumPreds == 1) {
|
|
||||||
for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end();
|
|
||||||
I != E; ++I) {
|
|
||||||
if (I->second) continue;
|
|
||||||
|
|
||||||
SUnit *PredSU = I->first;
|
|
||||||
unsigned Opc = PredSU->Node->getOpcode();
|
|
||||||
if (Opc != ISD::EntryToken && Opc != ISD::TokenFactor &&
|
|
||||||
Opc != ISD::CopyToReg)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isSimpleFloaterUse(const SUnit *SU) {
|
|
||||||
unsigned NumOps = 0;
|
|
||||||
for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
|
|
||||||
I != E; ++I) {
|
|
||||||
if (I->second) continue;
|
|
||||||
if (++NumOps > 1)
|
|
||||||
return false;
|
|
||||||
if (!isFloater(I->first))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bottom up
|
// Bottom up
|
||||||
bool bu_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
|
bool bu_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
|
||||||
unsigned LeftNum = left->NodeNum;
|
|
||||||
unsigned RightNum = right->NodeNum;
|
|
||||||
bool LIsTarget = left->Node->isTargetOpcode();
|
bool LIsTarget = left->Node->isTargetOpcode();
|
||||||
bool RIsTarget = right->Node->isTargetOpcode();
|
bool RIsTarget = right->Node->isTargetOpcode();
|
||||||
int LPriority = SPQ->getSethiUllmanNumber(LeftNum);
|
unsigned LPriority = SPQ->getSethiUllmanNumber(left);
|
||||||
int RPriority = SPQ->getSethiUllmanNumber(RightNum);
|
unsigned RPriority = SPQ->getSethiUllmanNumber(right);
|
||||||
int LBonus = 0;
|
|
||||||
int RBonus = 0;
|
|
||||||
|
|
||||||
// Schedule floaters (e.g. load from some constant address) and those nodes
|
|
||||||
// with a single predecessor each first. They maintain / reduce register
|
|
||||||
// pressure.
|
|
||||||
if (isFloater(left) || isSimpleFloaterUse(left))
|
|
||||||
LBonus += 2;
|
|
||||||
if (isFloater(right) || isSimpleFloaterUse(right))
|
|
||||||
RBonus += 2;
|
|
||||||
|
|
||||||
// Special tie breaker: if two nodes share a operand, the one that use it
|
// Special tie breaker: if two nodes share a operand, the one that use it
|
||||||
// as a def&use operand is preferred.
|
// as a def&use operand is preferred.
|
||||||
if (LIsTarget && RIsTarget) {
|
if (LIsTarget && RIsTarget) {
|
||||||
if (left->isTwoAddress && !right->isTwoAddress) {
|
if (left->isTwoAddress && !right->isTwoAddress)
|
||||||
if (SPQ->isDUOperand(left, right))
|
if (SPQ->isDUOperand(left, right))
|
||||||
LBonus += 2;
|
return false;
|
||||||
}
|
if (!left->isTwoAddress && right->isTwoAddress)
|
||||||
if (!left->isTwoAddress && right->isTwoAddress) {
|
|
||||||
if (SPQ->isDUOperand(right, left))
|
if (SPQ->isDUOperand(right, left))
|
||||||
RBonus += 2;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LPriority+LBonus < RPriority+RBonus)
|
if (LPriority > RPriority)
|
||||||
return true;
|
return true;
|
||||||
else if (LPriority+LBonus == RPriority+RBonus)
|
else if (LPriority == RPriority)
|
||||||
if (left->Height > right->Height)
|
if (left->Height > right->Height)
|
||||||
return true;
|
return true;
|
||||||
else if (left->Height == right->Height)
|
else if (left->Height == right->Height)
|
||||||
@ -629,12 +608,6 @@ bool bu_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool isCopyFromLiveIn(const SUnit *SU) {
|
|
||||||
SDNode *N = SU->Node;
|
|
||||||
return N->getOpcode() == ISD::CopyFromReg &&
|
|
||||||
N->getOperand(N->getNumOperands()-1).getValueType() != MVT::Flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: This is probably too slow!
|
// FIXME: This is probably too slow!
|
||||||
static void isReachable(SUnit *SU, SUnit *TargetSU,
|
static void isReachable(SUnit *SU, SUnit *TargetSU,
|
||||||
std::set<SUnit *> &Visited, bool &Reached) {
|
std::set<SUnit *> &Visited, bool &Reached) {
|
||||||
@ -723,47 +696,28 @@ void BURegReductionPriorityQueue<SF>::AddPseudoTwoAddrDeps() {
|
|||||||
/// CalcNodePriority - Priority is the Sethi Ullman number.
|
/// CalcNodePriority - Priority is the Sethi Ullman number.
|
||||||
/// Smaller number is the higher priority.
|
/// Smaller number is the higher priority.
|
||||||
template<class SF>
|
template<class SF>
|
||||||
int BURegReductionPriorityQueue<SF>::CalcNodePriority(const SUnit *SU) {
|
unsigned BURegReductionPriorityQueue<SF>::CalcNodePriority(const SUnit *SU) {
|
||||||
int &SethiUllmanNumber = SethiUllmanNumbers[SU->NodeNum];
|
unsigned &SethiUllmanNumber = SethiUllmanNumbers[SU->NodeNum];
|
||||||
if (SethiUllmanNumber != 0)
|
if (SethiUllmanNumber != 0)
|
||||||
return SethiUllmanNumber;
|
return SethiUllmanNumber;
|
||||||
|
|
||||||
unsigned Opc = SU->Node->getOpcode();
|
unsigned Extra = 0;
|
||||||
if (Opc == ISD::CopyFromReg && !isCopyFromLiveIn(SU))
|
for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
|
||||||
// CopyFromReg should be close to its def because it restricts allocation
|
I != E; ++I) {
|
||||||
// choices. But if it is a livein then perhaps we want it closer to the
|
if (I->second) continue; // ignore chain preds
|
||||||
// uses so it can be coalesced.
|
SUnit *PredSU = I->first;
|
||||||
SethiUllmanNumber = INT_MIN + 10;
|
unsigned PredSethiUllman = CalcNodePriority(PredSU);
|
||||||
else if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg)
|
if (PredSethiUllman > SethiUllmanNumber) {
|
||||||
// CopyToReg should be close to its uses to facilitate coalescing and avoid
|
SethiUllmanNumber = PredSethiUllman;
|
||||||
// spilling.
|
Extra = 0;
|
||||||
SethiUllmanNumber = INT_MAX - 10;
|
} else if (PredSethiUllman == SethiUllmanNumber && !I->second)
|
||||||
else if (SU->NumSuccsLeft == 0)
|
Extra++;
|
||||||
// If SU does not have a use, i.e. it doesn't produce a value that would
|
|
||||||
// be consumed (e.g. store), then it terminates a chain of computation.
|
|
||||||
// Give it a small SethiUllman number so it will be scheduled right before its
|
|
||||||
// predecessors that it doesn't lengthen their live ranges.
|
|
||||||
SethiUllmanNumber = INT_MIN + 10;
|
|
||||||
else if (SU->NumPredsLeft == 0)
|
|
||||||
// If SU does not have a def, schedule it close to its uses because it does
|
|
||||||
// not lengthen any live ranges.
|
|
||||||
SethiUllmanNumber = INT_MAX - 10;
|
|
||||||
else {
|
|
||||||
int Extra = 0;
|
|
||||||
for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
|
|
||||||
I != E; ++I) {
|
|
||||||
if (I->second) continue; // ignore chain preds
|
|
||||||
SUnit *PredSU = I->first;
|
|
||||||
int PredSethiUllman = CalcNodePriority(PredSU);
|
|
||||||
if (PredSethiUllman > SethiUllmanNumber) {
|
|
||||||
SethiUllmanNumber = PredSethiUllman;
|
|
||||||
Extra = 0;
|
|
||||||
} else if (PredSethiUllman == SethiUllmanNumber && !I->second)
|
|
||||||
Extra++;
|
|
||||||
}
|
|
||||||
|
|
||||||
SethiUllmanNumber += Extra;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SethiUllmanNumber += Extra;
|
||||||
|
|
||||||
|
if (SethiUllmanNumber == 0)
|
||||||
|
SethiUllmanNumber = 1;
|
||||||
|
|
||||||
return SethiUllmanNumber;
|
return SethiUllmanNumber;
|
||||||
}
|
}
|
||||||
@ -796,10 +750,8 @@ static unsigned SumOfUnscheduledPredsOfSuccs(const SUnit *SU) {
|
|||||||
|
|
||||||
// Top down
|
// Top down
|
||||||
bool td_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
|
bool td_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
|
||||||
unsigned LeftNum = left->NodeNum;
|
unsigned LPriority = SPQ->getSethiUllmanNumber(left);
|
||||||
unsigned RightNum = right->NodeNum;
|
unsigned RPriority = SPQ->getSethiUllmanNumber(right);
|
||||||
int LPriority = SPQ->getSethiUllmanNumber(LeftNum);
|
|
||||||
int RPriority = SPQ->getSethiUllmanNumber(RightNum);
|
|
||||||
bool LIsTarget = left->Node->isTargetOpcode();
|
bool LIsTarget = left->Node->isTargetOpcode();
|
||||||
bool RIsTarget = right->Node->isTargetOpcode();
|
bool RIsTarget = right->Node->isTargetOpcode();
|
||||||
bool LIsFloater = LIsTarget && left->NumPreds == 0;
|
bool LIsFloater = LIsTarget && left->NumPreds == 0;
|
||||||
@ -852,30 +804,30 @@ bool td_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
|
|||||||
/// CalcNodePriority - Priority is the Sethi Ullman number.
|
/// CalcNodePriority - Priority is the Sethi Ullman number.
|
||||||
/// Smaller number is the higher priority.
|
/// Smaller number is the higher priority.
|
||||||
template<class SF>
|
template<class SF>
|
||||||
int TDRegReductionPriorityQueue<SF>::CalcNodePriority(const SUnit *SU) {
|
unsigned TDRegReductionPriorityQueue<SF>::CalcNodePriority(const SUnit *SU) {
|
||||||
int &SethiUllmanNumber = SethiUllmanNumbers[SU->NodeNum];
|
unsigned &SethiUllmanNumber = SethiUllmanNumbers[SU->NodeNum];
|
||||||
if (SethiUllmanNumber != 0)
|
if (SethiUllmanNumber != 0)
|
||||||
return SethiUllmanNumber;
|
return SethiUllmanNumber;
|
||||||
|
|
||||||
unsigned Opc = SU->Node->getOpcode();
|
unsigned Opc = SU->Node->getOpcode();
|
||||||
if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg)
|
if (Opc == ISD::TokenFactor || Opc == ISD::CopyToReg)
|
||||||
SethiUllmanNumber = INT_MAX - 10;
|
SethiUllmanNumber = 0xffff;
|
||||||
else if (SU->NumSuccsLeft == 0)
|
else if (SU->NumSuccsLeft == 0)
|
||||||
// If SU does not have a use, i.e. it doesn't produce a value that would
|
// If SU does not have a use, i.e. it doesn't produce a value that would
|
||||||
// be consumed (e.g. store), then it terminates a chain of computation.
|
// be consumed (e.g. store), then it terminates a chain of computation.
|
||||||
// Give it a small SethiUllman number so it will be scheduled right before its
|
// Give it a small SethiUllman number so it will be scheduled right before its
|
||||||
// predecessors that it doesn't lengthen their live ranges.
|
// predecessors that it doesn't lengthen their live ranges.
|
||||||
SethiUllmanNumber = INT_MIN + 10;
|
SethiUllmanNumber = 0;
|
||||||
else if (SU->NumPredsLeft == 0 &&
|
else if (SU->NumPredsLeft == 0 &&
|
||||||
(Opc != ISD::CopyFromReg || isCopyFromLiveIn(SU)))
|
(Opc != ISD::CopyFromReg || isCopyFromLiveIn(SU)))
|
||||||
SethiUllmanNumber = 1;
|
SethiUllmanNumber = 0xffff;
|
||||||
else {
|
else {
|
||||||
int Extra = 0;
|
int Extra = 0;
|
||||||
for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
|
for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
if (I->second) continue; // ignore chain preds
|
if (I->second) continue; // ignore chain preds
|
||||||
SUnit *PredSU = I->first;
|
SUnit *PredSU = I->first;
|
||||||
int PredSethiUllman = CalcNodePriority(PredSU);
|
unsigned PredSethiUllman = CalcNodePriority(PredSU);
|
||||||
if (PredSethiUllman > SethiUllmanNumber) {
|
if (PredSethiUllman > SethiUllmanNumber) {
|
||||||
SethiUllmanNumber = PredSethiUllman;
|
SethiUllmanNumber = PredSethiUllman;
|
||||||
Extra = 0;
|
Extra = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user