Change the 'global modification' APIs in SelectionDAG to take a new

DAGUpdateListener object pointer instead of just returning a vector 
of deleted nodes.  This makes the interfaces more efficient (no more
allocating a vector [at least a malloc], filling it in, then walking
it) and more clean.  This also allows the client to be notified of
nodes that are *changed* but not deleted.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@46677 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner
2008-02-03 06:49:24 +00:00
parent 3d62d780ab
commit f8dc0617ba
4 changed files with 267 additions and 199 deletions

View File

@ -81,13 +81,6 @@ namespace {
AddToWorkList(*UI);
}
/// removeFromWorkList - remove all instances of N from the worklist.
///
void removeFromWorkList(SDNode *N) {
WorkList.erase(std::remove(WorkList.begin(), WorkList.end(), N),
WorkList.end());
}
/// visit - call the node-specific routine that knows how to fold each
/// particular type of node.
SDOperand visit(SDNode *N);
@ -100,35 +93,16 @@ namespace {
WorkList.push_back(N);
}
SDOperand CombineTo(SDNode *N, const SDOperand *To, unsigned NumTo,
bool AddTo = true) {
assert(N->getNumValues() == NumTo && "Broken CombineTo call!");
++NodesCombined;
DOUT << "\nReplacing.1 "; DEBUG(N->dump(&DAG));
DOUT << "\nWith: "; DEBUG(To[0].Val->dump(&DAG));
DOUT << " and " << NumTo-1 << " other values\n";
std::vector<SDNode*> NowDead;
DAG.ReplaceAllUsesWith(N, To, &NowDead);
if (AddTo) {
// Push the new nodes and any users onto the worklist
for (unsigned i = 0, e = NumTo; i != e; ++i) {
AddToWorkList(To[i].Val);
AddUsersToWorkList(To[i].Val);
}
}
// Nodes can be reintroduced into the worklist. Make sure we do not
// process a node that has been replaced.
removeFromWorkList(N);
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);
return SDOperand(N, 0);
/// removeFromWorkList - remove all instances of N from the worklist.
///
void removeFromWorkList(SDNode *N) {
WorkList.erase(std::remove(WorkList.begin(), WorkList.end(), N),
WorkList.end());
}
SDOperand CombineTo(SDNode *N, const SDOperand *To, unsigned NumTo,
bool AddTo = true);
SDOperand CombineTo(SDNode *N, SDOperand Res, bool AddTo = true) {
return CombineTo(N, &Res, 1, AddTo);
}
@ -144,50 +118,7 @@ namespace {
/// SimplifyDemandedBits - Check the specified integer node value to see if
/// it can be simplified or if things it uses can be simplified by bit
/// propagation. If so, return true.
bool SimplifyDemandedBits(SDOperand Op, uint64_t Demanded = ~0ULL) {
TargetLowering::TargetLoweringOpt TLO(DAG, AfterLegalize);
uint64_t KnownZero, KnownOne;
Demanded &= MVT::getIntVTBitMask(Op.getValueType());
if (!TLI.SimplifyDemandedBits(Op, Demanded, KnownZero, KnownOne, TLO))
return false;
// Revisit the node.
AddToWorkList(Op.Val);
// Replace the old value with the new one.
++NodesCombined;
DOUT << "\nReplacing.2 "; DEBUG(TLO.Old.Val->dump(&DAG));
DOUT << "\nWith: "; DEBUG(TLO.New.Val->dump(&DAG));
DOUT << '\n';
std::vector<SDNode*> NowDead;
DAG.ReplaceAllUsesOfValueWith(TLO.Old, TLO.New, &NowDead);
// Push the new node and any (possibly new) users onto the worklist.
AddToWorkList(TLO.New.Val);
AddUsersToWorkList(TLO.New.Val);
// 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, if the node is now dead, remove it from the graph. The node
// may not be dead if the replacement process recursively simplified to
// something else needing this node.
if (TLO.Old.Val->use_empty()) {
removeFromWorkList(TLO.Old.Val);
// If the operands of this node are only used by the node, they will now
// be dead. Make sure to visit them first to delete dead nodes early.
for (unsigned i = 0, e = TLO.Old.Val->getNumOperands(); i != e; ++i)
if (TLO.Old.Val->getOperand(i).Val->hasOneUse())
AddToWorkList(TLO.Old.Val->getOperand(i).Val);
DAG.DeleteNode(TLO.Old.Val);
}
return true;
}
bool SimplifyDemandedBits(SDOperand Op, uint64_t Demanded = ~0ULL);
bool CombineToPreIndexedLoadStore(SDNode *N);
bool CombineToPostIndexedLoadStore(SDNode *N);
@ -322,6 +253,27 @@ public:
};
}
namespace {
/// WorkListRemover - This class is a DAGUpdateListener that removes any deleted
/// nodes from the worklist.
class VISIBILITY_HIDDEN WorkListRemover :
public SelectionDAG::DAGUpdateListener {
DAGCombiner &DC;
public:
WorkListRemover(DAGCombiner &dc) : DC(dc) {}
virtual void NodeDeleted(SDNode *N) {
printf("remove from WL: %p\n", (void*)N);
DC.removeFromWorkList(N);
}
virtual void NodeUpdated(SDNode *N) {
// Ignore updates.
}
};
}
//===----------------------------------------------------------------------===//
// TargetLowering::DAGCombinerInfo implementation
//===----------------------------------------------------------------------===//
@ -543,6 +495,78 @@ SDOperand DAGCombiner::ReassociateOps(unsigned Opc, SDOperand N0, SDOperand N1){
return SDOperand();
}
SDOperand DAGCombiner::CombineTo(SDNode *N, const SDOperand *To, unsigned NumTo,
bool AddTo) {
assert(N->getNumValues() == NumTo && "Broken CombineTo call!");
++NodesCombined;
DOUT << "\nReplacing.1 "; DEBUG(N->dump(&DAG));
DOUT << "\nWith: "; DEBUG(To[0].Val->dump(&DAG));
DOUT << " and " << NumTo-1 << " other values\n";
WorkListRemover DeadNodes(*this);
DAG.ReplaceAllUsesWith(N, To, &DeadNodes);
if (AddTo) {
// Push the new nodes and any users onto the worklist
for (unsigned i = 0, e = NumTo; i != e; ++i) {
AddToWorkList(To[i].Val);
AddUsersToWorkList(To[i].Val);
}
}
// Nodes can be reintroduced into the worklist. Make sure we do not
// process a node that has been replaced.
removeFromWorkList(N);
// Finally, since the node is now dead, remove it from the graph.
DAG.DeleteNode(N);
return SDOperand(N, 0);
}
/// SimplifyDemandedBits - Check the specified integer node value to see if
/// it can be simplified or if things it uses can be simplified by bit
/// propagation. If so, return true.
bool DAGCombiner::SimplifyDemandedBits(SDOperand Op, uint64_t Demanded) {
TargetLowering::TargetLoweringOpt TLO(DAG, AfterLegalize);
uint64_t KnownZero, KnownOne;
Demanded &= MVT::getIntVTBitMask(Op.getValueType());
if (!TLI.SimplifyDemandedBits(Op, Demanded, KnownZero, KnownOne, TLO))
return false;
// Revisit the node.
AddToWorkList(Op.Val);
// Replace the old value with the new one.
++NodesCombined;
DOUT << "\nReplacing.2 "; DEBUG(TLO.Old.Val->dump(&DAG));
DOUT << "\nWith: "; DEBUG(TLO.New.Val->dump(&DAG));
DOUT << '\n';
// Replace all uses. If any nodes become isomorphic to other nodes and
// are deleted, make sure to remove them from our worklist.
WorkListRemover DeadNodes(*this);
DAG.ReplaceAllUsesOfValueWith(TLO.Old, TLO.New, &DeadNodes);
// Push the new node and any (possibly new) users onto the worklist.
AddToWorkList(TLO.New.Val);
AddUsersToWorkList(TLO.New.Val);
// Finally, if the node is now dead, remove it from the graph. The node
// may not be dead if the replacement process recursively simplified to
// something else needing this node.
if (TLO.Old.Val->use_empty()) {
removeFromWorkList(TLO.Old.Val);
// If the operands of this node are only used by the node, they will now
// be dead. Make sure to visit them first to delete dead nodes early.
for (unsigned i = 0, e = TLO.Old.Val->getNumOperands(); i != e; ++i)
if (TLO.Old.Val->getOperand(i).Val->hasOneUse())
AddToWorkList(TLO.Old.Val->getOperand(i).Val);
DAG.DeleteNode(TLO.Old.Val);
}
return true;
}
//===----------------------------------------------------------------------===//
// Main DAG Combiner implementation
//===----------------------------------------------------------------------===//
@ -603,14 +627,14 @@ void DAGCombiner::Run(bool RunningAfterLegalize) {
DOUT << "\nReplacing.3 "; DEBUG(N->dump(&DAG));
DOUT << "\nWith: "; DEBUG(RV.Val->dump(&DAG));
DOUT << '\n';
std::vector<SDNode*> NowDead;
WorkListRemover DeadNodes(*this);
if (N->getNumValues() == RV.Val->getNumValues())
DAG.ReplaceAllUsesWith(N, RV.Val, &NowDead);
DAG.ReplaceAllUsesWith(N, RV.Val, &DeadNodes);
else {
assert(N->getValueType(0) == RV.getValueType() &&
N->getNumValues() == 1 && "Type mismatch");
SDOperand OpV = RV;
DAG.ReplaceAllUsesWith(N, &OpV, &NowDead);
DAG.ReplaceAllUsesWith(N, &OpV, &DeadNodes);
}
// Push the new node and any users onto the worklist
@ -626,8 +650,6 @@ void DAGCombiner::Run(bool RunningAfterLegalize) {
// Nodes can be reintroduced into the worklist. Make sure we do not
// process a node that has been replaced.
removeFromWorkList(N);
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);
@ -3084,7 +3106,9 @@ SDOperand DAGCombiner::ReduceLoadWidth(SDNode *N) {
LN0->isVolatile(), NewAlign);
AddToWorkList(N);
if (CombineSRL) {
DAG.ReplaceAllUsesOfValueWith(N0.getValue(1), Load.getValue(1));
WorkListRemover DeadNodes(*this);
DAG.ReplaceAllUsesOfValueWith(N0.getValue(1), Load.getValue(1),
&DeadNodes);
CombineTo(N->getOperand(0).Val, Load);
} else
CombineTo(N0.Val, Load, Load.getValue(1));
@ -3990,30 +4014,24 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
DOUT << "\nReplacing.4 "; DEBUG(N->dump(&DAG));
DOUT << "\nWith: "; DEBUG(Result.Val->dump(&DAG));
DOUT << '\n';
std::vector<SDNode*> NowDead;
WorkListRemover DeadNodes(*this);
if (isLoad) {
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0),
&NowDead);
&DeadNodes);
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2),
&NowDead);
&DeadNodes);
} else {
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1),
&NowDead);
&DeadNodes);
}
// 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);
&DeadNodes);
removeFromWorkList(Ptr.Val);
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
removeFromWorkList(NowDead[i]);
DAG.DeleteNode(Ptr.Val);
return true;
@ -4121,33 +4139,26 @@ bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) {
DOUT << "\nReplacing.5 "; DEBUG(N->dump(&DAG));
DOUT << "\nWith: "; DEBUG(Result.Val->dump(&DAG));
DOUT << '\n';
std::vector<SDNode*> NowDead;
WorkListRemover DeadNodes(*this);
if (isLoad) {
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0),
&NowDead);
&DeadNodes);
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2),
&NowDead);
&DeadNodes);
} else {
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1),
&NowDead);
&DeadNodes);
}
// 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);
&DeadNodes);
removeFromWorkList(Op);
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
removeFromWorkList(NowDead[i]);
DAG.DeleteNode(Op);
return true;
}
}
@ -4228,13 +4239,11 @@ SDOperand DAGCombiner::visitLOAD(SDNode *N) {
// v3 = add v2, c
// Now we replace use of chain2 with chain1. This makes the second load
// isomorphic to the one we are deleting, and thus makes this load live.
std::vector<SDNode*> NowDead;
DOUT << "\nReplacing.6 "; DEBUG(N->dump(&DAG));
DOUT << "\nWith chain: "; DEBUG(Chain.Val->dump(&DAG));
DOUT << "\n";
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Chain, &NowDead);
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
removeFromWorkList(NowDead[i]);
WorkListRemover DeadNodes(*this);
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Chain, &DeadNodes);
if (N->use_empty()) {
removeFromWorkList(N);
DAG.DeleteNode(N);
@ -4245,19 +4254,17 @@ SDOperand DAGCombiner::visitLOAD(SDNode *N) {
// Indexed loads.
assert(N->getValueType(2) == MVT::Other && "Malformed indexed loads?");
if (N->hasNUsesOfValue(0, 0) && N->hasNUsesOfValue(0, 1)) {
std::vector<SDNode*> NowDead;
SDOperand Undef = DAG.getNode(ISD::UNDEF, N->getValueType(0));
DOUT << "\nReplacing.6 "; DEBUG(N->dump(&DAG));
DOUT << "\nWith: "; DEBUG(Undef.Val->dump(&DAG));
DOUT << " and 2 other values\n";
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Undef, &NowDead);
WorkListRemover DeadNodes(*this);
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Undef, &DeadNodes);
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1),
DAG.getNode(ISD::UNDEF, N->getValueType(1)),
&NowDead);
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 2), Chain, &NowDead);
&DeadNodes);
DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 2), Chain, &DeadNodes);
removeFromWorkList(N);
for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
removeFromWorkList(NowDead[i]);
DAG.DeleteNode(N);
return SDOperand(N, 0); // Return N so it doesn't get rechecked!
}