mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-07 12:28:24 +00:00
move big chunks of code out-of-line, no functionality change.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31658 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -178,241 +178,10 @@ namespace {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CombineToPreIndexedLoadStore - Try turning a load / store and a
|
bool CombineToPreIndexedLoadStore(SDNode *N);
|
||||||
/// pre-indexed load / store when the base pointer is a add or subtract
|
bool CombineToPostIndexedLoadStore(SDNode *N);
|
||||||
/// and it has other uses besides the load / store. After the
|
|
||||||
/// transformation, the new indexed load / store has effectively folded
|
|
||||||
/// the add / subtract in and all of its other uses are redirected to the
|
|
||||||
/// new load / store.
|
|
||||||
bool CombineToPreIndexedLoadStore(SDNode *N) {
|
|
||||||
if (!AfterLegalize)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool isLoad = true;
|
|
||||||
SDOperand Ptr;
|
|
||||||
MVT::ValueType VT;
|
|
||||||
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
|
|
||||||
VT = LD->getLoadedVT();
|
|
||||||
if (!TLI.isIndexedLoadLegal(ISD::PRE_INC, VT) &&
|
|
||||||
!TLI.isIndexedLoadLegal(ISD::PRE_DEC, VT))
|
|
||||||
return false;
|
|
||||||
Ptr = LD->getBasePtr();
|
|
||||||
} else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
|
|
||||||
VT = ST->getStoredVT();
|
|
||||||
if (!TLI.isIndexedStoreLegal(ISD::PRE_INC, VT) &&
|
|
||||||
!TLI.isIndexedStoreLegal(ISD::PRE_DEC, VT))
|
|
||||||
return false;
|
|
||||||
Ptr = ST->getBasePtr();
|
|
||||||
isLoad = false;
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ((Ptr.getOpcode() == ISD::ADD || Ptr.getOpcode() == ISD::SUB) &&
|
|
||||||
Ptr.Val->use_size() > 1) {
|
|
||||||
SDOperand BasePtr;
|
|
||||||
SDOperand Offset;
|
|
||||||
ISD::MemIndexedMode AM = ISD::UNINDEXED;
|
|
||||||
if (TLI.getPreIndexedAddressParts(N, BasePtr, Offset, AM, DAG)) {
|
|
||||||
// Try turning it into a pre-indexed load / store except when
|
|
||||||
// 1) If N is a store and the ptr is either the same as or is a
|
|
||||||
// predecessor of the value being stored.
|
|
||||||
// 2) Another use of base ptr is a predecessor of N. If ptr is folded
|
|
||||||
// that would create a cycle.
|
|
||||||
// 3) All uses are load / store ops that use it as base ptr.
|
|
||||||
|
|
||||||
// Checking #1.
|
|
||||||
if (!isLoad) {
|
|
||||||
SDOperand Val = cast<StoreSDNode>(N)->getValue();
|
|
||||||
if (Val == Ptr || Ptr.Val->isPredecessor(Val.Val))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now check for #2 and #3.
|
|
||||||
bool RealUse = false;
|
|
||||||
for (SDNode::use_iterator I = Ptr.Val->use_begin(),
|
|
||||||
E = Ptr.Val->use_end(); I != E; ++I) {
|
|
||||||
SDNode *Use = *I;
|
|
||||||
if (Use == N)
|
|
||||||
continue;
|
|
||||||
if (Use->isPredecessor(N))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!((Use->getOpcode() == ISD::LOAD &&
|
|
||||||
cast<LoadSDNode>(Use)->getBasePtr() == Ptr) ||
|
|
||||||
(Use->getOpcode() == ISD::STORE) &&
|
|
||||||
cast<StoreSDNode>(Use)->getBasePtr() == Ptr))
|
|
||||||
RealUse = true;
|
|
||||||
}
|
|
||||||
if (!RealUse)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
SDOperand Result = isLoad
|
|
||||||
? DAG.getIndexedLoad(SDOperand(N,0), BasePtr, Offset, AM)
|
|
||||||
: DAG.getIndexedStore(SDOperand(N,0), BasePtr, Offset, AM);
|
|
||||||
++PreIndexedNodes;
|
|
||||||
++NodesCombined;
|
|
||||||
DEBUG(std::cerr << "\nReplacing.4 "; N->dump();
|
|
||||||
std::cerr << "\nWith: "; Result.Val->dump(&DAG);
|
|
||||||
std::cerr << '\n');
|
|
||||||
std::vector<SDNode*> NowDead;
|
|
||||||
if (isLoad) {
|
|
||||||
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0),
|
|
||||||
NowDead);
|
|
||||||
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2),
|
|
||||||
NowDead);
|
|
||||||
} else {
|
|
||||||
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1),
|
|
||||||
NowDead);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nodes can end up on the worklist more than once. Make sure we do
|
|
||||||
// not process a node that has been replaced.
|
|
||||||
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
|
|
||||||
removeFromWorkList(NowDead[i]);
|
|
||||||
// Finally, since the node is now dead, remove it from the graph.
|
|
||||||
DAG.DeleteNode(N);
|
|
||||||
|
|
||||||
// Replace the uses of Ptr with uses of the updated base value.
|
|
||||||
DAG.ReplaceAllUsesOfValueWith(Ptr, Result.getValue(isLoad ? 1 : 0),
|
|
||||||
NowDead);
|
|
||||||
removeFromWorkList(Ptr.Val);
|
|
||||||
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
|
|
||||||
removeFromWorkList(NowDead[i]);
|
|
||||||
DAG.DeleteNode(Ptr.Val);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// CombineToPostIndexedLoadStore - Try combine a load / store with a
|
|
||||||
/// add / sub of the base pointer node into a post-indexed load / store.
|
|
||||||
/// The transformation folded the add / subtract into the new indexed
|
|
||||||
/// load / store effectively and all of its uses are redirected to the
|
|
||||||
/// new load / store.
|
|
||||||
bool CombineToPostIndexedLoadStore(SDNode *N) {
|
|
||||||
if (!AfterLegalize)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool isLoad = true;
|
|
||||||
SDOperand Ptr;
|
|
||||||
MVT::ValueType VT;
|
|
||||||
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
|
|
||||||
VT = LD->getLoadedVT();
|
|
||||||
if (!TLI.isIndexedLoadLegal(ISD::POST_INC, VT) &&
|
|
||||||
!TLI.isIndexedLoadLegal(ISD::POST_DEC, VT))
|
|
||||||
return false;
|
|
||||||
Ptr = LD->getBasePtr();
|
|
||||||
} else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
|
|
||||||
VT = ST->getStoredVT();
|
|
||||||
if (!TLI.isIndexedStoreLegal(ISD::POST_INC, VT) &&
|
|
||||||
!TLI.isIndexedStoreLegal(ISD::POST_DEC, VT))
|
|
||||||
return false;
|
|
||||||
Ptr = ST->getBasePtr();
|
|
||||||
isLoad = false;
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (Ptr.Val->use_size() > 1) {
|
|
||||||
for (SDNode::use_iterator I = Ptr.Val->use_begin(),
|
|
||||||
E = Ptr.Val->use_end(); I != E; ++I) {
|
|
||||||
SDNode *Op = *I;
|
|
||||||
if (Op == N ||
|
|
||||||
(Op->getOpcode() != ISD::ADD && Op->getOpcode() != ISD::SUB))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
SDOperand BasePtr;
|
|
||||||
SDOperand Offset;
|
|
||||||
ISD::MemIndexedMode AM = ISD::UNINDEXED;
|
|
||||||
if (TLI.getPostIndexedAddressParts(N, Op, BasePtr, Offset, AM, DAG)) {
|
|
||||||
if (Ptr == Offset)
|
|
||||||
std::swap(BasePtr, Offset);
|
|
||||||
if (Ptr != BasePtr)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Try turning it into a post-indexed load / store except when
|
|
||||||
// 1) All uses are load / store ops that use it as base ptr.
|
|
||||||
// 2) Op must be independent of N, i.e. Op is neither a predecessor
|
|
||||||
// nor a successor of N. Otherwise, if Op is folded that would
|
|
||||||
// create a cycle.
|
|
||||||
|
|
||||||
// Check for #1.
|
|
||||||
bool TryNext = false;
|
|
||||||
for (SDNode::use_iterator II = BasePtr.Val->use_begin(),
|
|
||||||
EE = BasePtr.Val->use_end(); II != EE; ++II) {
|
|
||||||
SDNode *Use = *II;
|
|
||||||
if (Use == Ptr.Val)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// If all the uses are load / store addresses, then don't do the
|
|
||||||
// transformation.
|
|
||||||
if (Use->getOpcode() == ISD::ADD || Use->getOpcode() == ISD::SUB){
|
|
||||||
bool RealUse = false;
|
|
||||||
for (SDNode::use_iterator III = Use->use_begin(),
|
|
||||||
EEE = Use->use_end(); III != EEE; ++III) {
|
|
||||||
SDNode *UseUse = *III;
|
|
||||||
if (!((UseUse->getOpcode() == ISD::LOAD &&
|
|
||||||
cast<LoadSDNode>(UseUse)->getBasePtr().Val == Use) ||
|
|
||||||
(UseUse->getOpcode() == ISD::STORE) &&
|
|
||||||
cast<StoreSDNode>(UseUse)->getBasePtr().Val == Use))
|
|
||||||
RealUse = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RealUse) {
|
|
||||||
TryNext = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (TryNext)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Check for #2
|
|
||||||
if (!Op->isPredecessor(N) && !N->isPredecessor(Op)) {
|
|
||||||
SDOperand Result = isLoad
|
|
||||||
? DAG.getIndexedLoad(SDOperand(N,0), BasePtr, Offset, AM)
|
|
||||||
: DAG.getIndexedStore(SDOperand(N,0), BasePtr, Offset, AM);
|
|
||||||
++PostIndexedNodes;
|
|
||||||
++NodesCombined;
|
|
||||||
DEBUG(std::cerr << "\nReplacing.5 "; N->dump();
|
|
||||||
std::cerr << "\nWith: "; Result.Val->dump(&DAG);
|
|
||||||
std::cerr << '\n');
|
|
||||||
std::vector<SDNode*> NowDead;
|
|
||||||
if (isLoad) {
|
|
||||||
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0),
|
|
||||||
NowDead);
|
|
||||||
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2),
|
|
||||||
NowDead);
|
|
||||||
} else {
|
|
||||||
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1),
|
|
||||||
NowDead);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nodes can end up on the worklist more than once. Make sure we do
|
|
||||||
// not process a node that has been replaced.
|
|
||||||
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
|
|
||||||
removeFromWorkList(NowDead[i]);
|
|
||||||
// Finally, since the node is now dead, remove it from the graph.
|
|
||||||
DAG.DeleteNode(N);
|
|
||||||
|
|
||||||
// Replace the uses of Use with uses of the updated base value.
|
|
||||||
DAG.ReplaceAllUsesOfValueWith(SDOperand(Op, 0),
|
|
||||||
Result.getValue(isLoad ? 1 : 0),
|
|
||||||
NowDead);
|
|
||||||
removeFromWorkList(Op);
|
|
||||||
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
|
|
||||||
removeFromWorkList(NowDead[i]);
|
|
||||||
DAG.DeleteNode(Op);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// visit - call the node-specific routine that knows how to fold each
|
/// visit - call the node-specific routine that knows how to fold each
|
||||||
/// particular type of node.
|
/// particular type of node.
|
||||||
SDOperand visit(SDNode *N);
|
SDOperand visit(SDNode *N);
|
||||||
@@ -2938,6 +2707,243 @@ SDOperand DAGCombiner::visitBR_CC(SDNode *N) {
|
|||||||
return SDOperand();
|
return SDOperand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// CombineToPreIndexedLoadStore - Try turning a load / store and a
|
||||||
|
/// pre-indexed load / store when the base pointer is a add or subtract
|
||||||
|
/// and it has other uses besides the load / store. After the
|
||||||
|
/// transformation, the new indexed load / store has effectively folded
|
||||||
|
/// the add / subtract in and all of its other uses are redirected to the
|
||||||
|
/// new load / store.
|
||||||
|
bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
|
||||||
|
if (!AfterLegalize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool isLoad = true;
|
||||||
|
SDOperand Ptr;
|
||||||
|
MVT::ValueType VT;
|
||||||
|
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
|
||||||
|
VT = LD->getLoadedVT();
|
||||||
|
if (!TLI.isIndexedLoadLegal(ISD::PRE_INC, VT) &&
|
||||||
|
!TLI.isIndexedLoadLegal(ISD::PRE_DEC, VT))
|
||||||
|
return false;
|
||||||
|
Ptr = LD->getBasePtr();
|
||||||
|
} else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
|
||||||
|
VT = ST->getStoredVT();
|
||||||
|
if (!TLI.isIndexedStoreLegal(ISD::PRE_INC, VT) &&
|
||||||
|
!TLI.isIndexedStoreLegal(ISD::PRE_DEC, VT))
|
||||||
|
return false;
|
||||||
|
Ptr = ST->getBasePtr();
|
||||||
|
isLoad = false;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((Ptr.getOpcode() == ISD::ADD || Ptr.getOpcode() == ISD::SUB) &&
|
||||||
|
Ptr.Val->use_size() > 1) {
|
||||||
|
SDOperand BasePtr;
|
||||||
|
SDOperand Offset;
|
||||||
|
ISD::MemIndexedMode AM = ISD::UNINDEXED;
|
||||||
|
if (TLI.getPreIndexedAddressParts(N, BasePtr, Offset, AM, DAG)) {
|
||||||
|
// Try turning it into a pre-indexed load / store except when
|
||||||
|
// 1) If N is a store and the ptr is either the same as or is a
|
||||||
|
// predecessor of the value being stored.
|
||||||
|
// 2) Another use of base ptr is a predecessor of N. If ptr is folded
|
||||||
|
// that would create a cycle.
|
||||||
|
// 3) All uses are load / store ops that use it as base ptr.
|
||||||
|
|
||||||
|
// Checking #1.
|
||||||
|
if (!isLoad) {
|
||||||
|
SDOperand Val = cast<StoreSDNode>(N)->getValue();
|
||||||
|
if (Val == Ptr || Ptr.Val->isPredecessor(Val.Val))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now check for #2 and #3.
|
||||||
|
bool RealUse = false;
|
||||||
|
for (SDNode::use_iterator I = Ptr.Val->use_begin(),
|
||||||
|
E = Ptr.Val->use_end(); I != E; ++I) {
|
||||||
|
SDNode *Use = *I;
|
||||||
|
if (Use == N)
|
||||||
|
continue;
|
||||||
|
if (Use->isPredecessor(N))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!((Use->getOpcode() == ISD::LOAD &&
|
||||||
|
cast<LoadSDNode>(Use)->getBasePtr() == Ptr) ||
|
||||||
|
(Use->getOpcode() == ISD::STORE) &&
|
||||||
|
cast<StoreSDNode>(Use)->getBasePtr() == Ptr))
|
||||||
|
RealUse = true;
|
||||||
|
}
|
||||||
|
if (!RealUse)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SDOperand Result = isLoad
|
||||||
|
? DAG.getIndexedLoad(SDOperand(N,0), BasePtr, Offset, AM)
|
||||||
|
: DAG.getIndexedStore(SDOperand(N,0), BasePtr, Offset, AM);
|
||||||
|
++PreIndexedNodes;
|
||||||
|
++NodesCombined;
|
||||||
|
DEBUG(std::cerr << "\nReplacing.4 "; N->dump();
|
||||||
|
std::cerr << "\nWith: "; Result.Val->dump(&DAG);
|
||||||
|
std::cerr << '\n');
|
||||||
|
std::vector<SDNode*> NowDead;
|
||||||
|
if (isLoad) {
|
||||||
|
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0),
|
||||||
|
NowDead);
|
||||||
|
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2),
|
||||||
|
NowDead);
|
||||||
|
} else {
|
||||||
|
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1),
|
||||||
|
NowDead);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nodes can end up on the worklist more than once. Make sure we do
|
||||||
|
// not process a node that has been replaced.
|
||||||
|
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
|
||||||
|
removeFromWorkList(NowDead[i]);
|
||||||
|
// Finally, since the node is now dead, remove it from the graph.
|
||||||
|
DAG.DeleteNode(N);
|
||||||
|
|
||||||
|
// Replace the uses of Ptr with uses of the updated base value.
|
||||||
|
DAG.ReplaceAllUsesOfValueWith(Ptr, Result.getValue(isLoad ? 1 : 0),
|
||||||
|
NowDead);
|
||||||
|
removeFromWorkList(Ptr.Val);
|
||||||
|
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
|
||||||
|
removeFromWorkList(NowDead[i]);
|
||||||
|
DAG.DeleteNode(Ptr.Val);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CombineToPostIndexedLoadStore - Try combine a load / store with a
|
||||||
|
/// add / sub of the base pointer node into a post-indexed load / store.
|
||||||
|
/// The transformation folded the add / subtract into the new indexed
|
||||||
|
/// load / store effectively and all of its uses are redirected to the
|
||||||
|
/// new load / store.
|
||||||
|
bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) {
|
||||||
|
if (!AfterLegalize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool isLoad = true;
|
||||||
|
SDOperand Ptr;
|
||||||
|
MVT::ValueType VT;
|
||||||
|
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
|
||||||
|
VT = LD->getLoadedVT();
|
||||||
|
if (!TLI.isIndexedLoadLegal(ISD::POST_INC, VT) &&
|
||||||
|
!TLI.isIndexedLoadLegal(ISD::POST_DEC, VT))
|
||||||
|
return false;
|
||||||
|
Ptr = LD->getBasePtr();
|
||||||
|
} else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
|
||||||
|
VT = ST->getStoredVT();
|
||||||
|
if (!TLI.isIndexedStoreLegal(ISD::POST_INC, VT) &&
|
||||||
|
!TLI.isIndexedStoreLegal(ISD::POST_DEC, VT))
|
||||||
|
return false;
|
||||||
|
Ptr = ST->getBasePtr();
|
||||||
|
isLoad = false;
|
||||||
|
} else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Ptr.Val->use_size() > 1) {
|
||||||
|
for (SDNode::use_iterator I = Ptr.Val->use_begin(),
|
||||||
|
E = Ptr.Val->use_end(); I != E; ++I) {
|
||||||
|
SDNode *Op = *I;
|
||||||
|
if (Op == N ||
|
||||||
|
(Op->getOpcode() != ISD::ADD && Op->getOpcode() != ISD::SUB))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SDOperand BasePtr;
|
||||||
|
SDOperand Offset;
|
||||||
|
ISD::MemIndexedMode AM = ISD::UNINDEXED;
|
||||||
|
if (TLI.getPostIndexedAddressParts(N, Op, BasePtr, Offset, AM, DAG)) {
|
||||||
|
if (Ptr == Offset)
|
||||||
|
std::swap(BasePtr, Offset);
|
||||||
|
if (Ptr != BasePtr)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Try turning it into a post-indexed load / store except when
|
||||||
|
// 1) All uses are load / store ops that use it as base ptr.
|
||||||
|
// 2) Op must be independent of N, i.e. Op is neither a predecessor
|
||||||
|
// nor a successor of N. Otherwise, if Op is folded that would
|
||||||
|
// create a cycle.
|
||||||
|
|
||||||
|
// Check for #1.
|
||||||
|
bool TryNext = false;
|
||||||
|
for (SDNode::use_iterator II = BasePtr.Val->use_begin(),
|
||||||
|
EE = BasePtr.Val->use_end(); II != EE; ++II) {
|
||||||
|
SDNode *Use = *II;
|
||||||
|
if (Use == Ptr.Val)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// If all the uses are load / store addresses, then don't do the
|
||||||
|
// transformation.
|
||||||
|
if (Use->getOpcode() == ISD::ADD || Use->getOpcode() == ISD::SUB){
|
||||||
|
bool RealUse = false;
|
||||||
|
for (SDNode::use_iterator III = Use->use_begin(),
|
||||||
|
EEE = Use->use_end(); III != EEE; ++III) {
|
||||||
|
SDNode *UseUse = *III;
|
||||||
|
if (!((UseUse->getOpcode() == ISD::LOAD &&
|
||||||
|
cast<LoadSDNode>(UseUse)->getBasePtr().Val == Use) ||
|
||||||
|
(UseUse->getOpcode() == ISD::STORE) &&
|
||||||
|
cast<StoreSDNode>(UseUse)->getBasePtr().Val == Use))
|
||||||
|
RealUse = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RealUse) {
|
||||||
|
TryNext = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (TryNext)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Check for #2
|
||||||
|
if (!Op->isPredecessor(N) && !N->isPredecessor(Op)) {
|
||||||
|
SDOperand Result = isLoad
|
||||||
|
? DAG.getIndexedLoad(SDOperand(N,0), BasePtr, Offset, AM)
|
||||||
|
: DAG.getIndexedStore(SDOperand(N,0), BasePtr, Offset, AM);
|
||||||
|
++PostIndexedNodes;
|
||||||
|
++NodesCombined;
|
||||||
|
DEBUG(std::cerr << "\nReplacing.5 "; N->dump();
|
||||||
|
std::cerr << "\nWith: "; Result.Val->dump(&DAG);
|
||||||
|
std::cerr << '\n');
|
||||||
|
std::vector<SDNode*> NowDead;
|
||||||
|
if (isLoad) {
|
||||||
|
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0),
|
||||||
|
NowDead);
|
||||||
|
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2),
|
||||||
|
NowDead);
|
||||||
|
} else {
|
||||||
|
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1),
|
||||||
|
NowDead);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nodes can end up on the worklist more than once. Make sure we do
|
||||||
|
// not process a node that has been replaced.
|
||||||
|
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
|
||||||
|
removeFromWorkList(NowDead[i]);
|
||||||
|
// Finally, since the node is now dead, remove it from the graph.
|
||||||
|
DAG.DeleteNode(N);
|
||||||
|
|
||||||
|
// Replace the uses of Use with uses of the updated base value.
|
||||||
|
DAG.ReplaceAllUsesOfValueWith(SDOperand(Op, 0),
|
||||||
|
Result.getValue(isLoad ? 1 : 0),
|
||||||
|
NowDead);
|
||||||
|
removeFromWorkList(Op);
|
||||||
|
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
|
||||||
|
removeFromWorkList(NowDead[i]);
|
||||||
|
DAG.DeleteNode(Op);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SDOperand DAGCombiner::visitLOAD(SDNode *N) {
|
SDOperand DAGCombiner::visitLOAD(SDNode *N) {
|
||||||
LoadSDNode *LD = cast<LoadSDNode>(N);
|
LoadSDNode *LD = cast<LoadSDNode>(N);
|
||||||
SDOperand Chain = LD->getChain();
|
SDOperand Chain = LD->getChain();
|
||||||
|
Reference in New Issue
Block a user