mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
Corrected load folding check. We need to start from the root of the sub-dag
being matched and ensure there isn't a non-direct path to the load (i.e. a path that goes out of the sub-dag.) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30958 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bddc5d04d7
commit
27e1fe9dab
@ -134,7 +134,7 @@ namespace {
|
||||
|
||||
virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
|
||||
|
||||
virtual bool CanBeFoldedBy(SDNode *N, SDNode *U);
|
||||
virtual bool CanBeFoldedBy(SDNode *N, SDNode *U, SDNode *Root);
|
||||
|
||||
// Include the pieces autogenerated from the target description.
|
||||
#include "X86GenDAGISel.inc"
|
||||
@ -227,52 +227,54 @@ static SDNode *findFlagUse(SDNode *N) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void findNonImmUse(SDNode* Use, SDNode* Def, SDNode *Ignore, bool &found,
|
||||
static void findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse,
|
||||
SDNode *Root, SDNode *Skip, bool &found,
|
||||
std::set<SDNode *> &Visited) {
|
||||
if (found ||
|
||||
Use->getNodeId() > Def->getNodeId() ||
|
||||
!Visited.insert(Use).second)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) {
|
||||
for (unsigned i = 0, e = Use->getNumOperands(); !found && i != e; ++i) {
|
||||
SDNode *N = Use->getOperand(i).Val;
|
||||
if (N == Ignore)
|
||||
if (N == Skip)
|
||||
continue;
|
||||
if (N != Def) {
|
||||
findNonImmUse(N, Def, Ignore, found, Visited);
|
||||
} else {
|
||||
if (N == Def) {
|
||||
if (Use == ImmedUse)
|
||||
continue; // Immediate use is ok.
|
||||
if (Use == Root) {
|
||||
assert(Use->getOpcode() == ISD::STORE ||
|
||||
Use->getOpcode() == X86ISD::CMP);
|
||||
continue;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
findNonImmUse(N, Def, ImmedUse, Root, Skip, found, Visited);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool isNonImmUse(SDNode* Use, SDNode* Def, SDNode *Ignore=NULL) {
|
||||
/// isNonImmUse - Start searching from Root up the DAG to check is Def can
|
||||
/// be reached. Return true if that's the case. However, ignore direct uses
|
||||
/// by ImmedUse (which would be U in the example illustrated in
|
||||
/// CanBeFoldedBy) and by Root (which can happen in the store case).
|
||||
/// FIXME: to be really generic, we should allow direct use by any node
|
||||
/// that is being folded. But realisticly since we only fold loads which
|
||||
/// have one non-chain use, we only need to watch out for load/op/store
|
||||
/// and load/op/cmp case where the root (store / cmp) may reach the load via
|
||||
/// its chain operand.
|
||||
static inline bool isNonImmUse(SDNode *Root, SDNode *Def, SDNode *ImmedUse,
|
||||
SDNode *Skip = NULL) {
|
||||
std::set<SDNode *> Visited;
|
||||
bool found = false;
|
||||
for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) {
|
||||
SDNode *N = Use->getOperand(i).Val;
|
||||
if (N != Def && N != Ignore) {
|
||||
findNonImmUse(N, Def, Ignore, found, Visited);
|
||||
if (found) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && Ignore) {
|
||||
// We must be checking for reachability between Def and a flag use. Go down
|
||||
// recursively if Use also produces a flag.
|
||||
MVT::ValueType VT = Use->getValueType(Use->getNumValues()-1);
|
||||
if (VT == MVT::Flag && !Use->use_empty()) {
|
||||
SDNode *FU = findFlagUse(Use);
|
||||
if (FU)
|
||||
return !isNonImmUse(FU, Def, Use);
|
||||
}
|
||||
}
|
||||
findNonImmUse(Root, Def, ImmedUse, Root, Skip, found, Visited);
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
bool X86DAGToDAGISel::CanBeFoldedBy(SDNode *N, SDNode *U) {
|
||||
bool X86DAGToDAGISel::CanBeFoldedBy(SDNode *N, SDNode *U, SDNode *Root) {
|
||||
if (FastISel) return false;
|
||||
|
||||
// If U use can somehow reach N through another path then U can't fold N or
|
||||
// it will create a cycle. e.g. In the following diagram, U can reach N
|
||||
// through X. If N is folded into into U, then X is both a predecessor and
|
||||
@ -285,7 +287,10 @@ bool X86DAGToDAGISel::CanBeFoldedBy(SDNode *N, SDNode *U) {
|
||||
// / [X]
|
||||
// | ^
|
||||
// [U]--------|
|
||||
if (!FastISel && !isNonImmUse(U, N)) {
|
||||
|
||||
if (isNonImmUse(Root, N, U))
|
||||
return false;
|
||||
|
||||
// If U produces a flag, then it gets (even more) interesting. Since it
|
||||
// would have been "glued" together with its flag use, we need to check if
|
||||
// it might reach N:
|
||||
@ -295,6 +300,7 @@ bool X86DAGToDAGISel::CanBeFoldedBy(SDNode *N, SDNode *U) {
|
||||
// | |
|
||||
// [U] \--
|
||||
// ^ [TF]
|
||||
// | ^
|
||||
// | |
|
||||
// \ /
|
||||
// [FU]
|
||||
@ -302,16 +308,23 @@ bool X86DAGToDAGISel::CanBeFoldedBy(SDNode *N, SDNode *U) {
|
||||
// If FU (flag use) indirectly reach N (the load), and U fold N (call it
|
||||
// NU), then TF is a predecessor of FU and a successor of NU. But since
|
||||
// NU and FU are flagged together, this effectively creates a cycle.
|
||||
MVT::ValueType VT = U->getValueType(U->getNumValues()-1);
|
||||
if (VT == MVT::Flag && !U->use_empty()) {
|
||||
SDNode *FU = findFlagUse(U);
|
||||
if (FU)
|
||||
return !isNonImmUse(FU, N, U);
|
||||
bool HasFlagUse = false;
|
||||
MVT::ValueType VT = Root->getValueType(Root->getNumValues()-1);
|
||||
while ((VT == MVT::Flag && !Root->use_empty())) {
|
||||
SDNode *FU = findFlagUse(Root);
|
||||
if (FU == NULL)
|
||||
break;
|
||||
else {
|
||||
Root = FU;
|
||||
HasFlagUse = true;
|
||||
}
|
||||
VT = Root->getValueType(Root->getNumValues()-1);
|
||||
}
|
||||
|
||||
if (HasFlagUse)
|
||||
return !isNonImmUse(Root, N, Root, U);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand
|
||||
/// and move load below the TokenFactor. Replace store's chain operand with
|
||||
@ -909,7 +922,7 @@ bool X86DAGToDAGISel::TryFoldLoad(SDOperand P, SDOperand N,
|
||||
SDOperand &Index, SDOperand &Disp) {
|
||||
if (ISD::isNON_EXTLoad(N.Val) &&
|
||||
N.hasOneUse() &&
|
||||
CanBeFoldedBy(N.Val, P.Val))
|
||||
CanBeFoldedBy(N.Val, P.Val, P.Val))
|
||||
return SelectAddr(N.getOperand(1), Base, Scale, Index, Disp);
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user