aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2010-01-09 00:21:08 +0000
committerEvan Cheng <evan.cheng@apple.com>2010-01-09 00:21:08 +0000
commit54e146b935123d3d325e8eb30c2e1f2eca3377ac (patch)
tree98ec275ffa281d16c404c3423d1e0fbafc8c30b9 /lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
parent87563b39370d7adfd42b0f531409ff9bc2bfcc56 (diff)
Dan pointed out checking whether a node is dead by comparing its opcode to ISD::DELETED_NODE is not safe. Use a DAGUpdateListener to remove dead nodes from work list instead.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@93031 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp34
1 files changed, 26 insertions, 8 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index c87e4bf716..edcd91e8de 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -438,6 +438,25 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB,
SDB->clear();
}
+namespace {
+/// WorkListRemover - This class is a DAGUpdateListener that removes any deleted
+/// nodes from the worklist.
+class SDOPsWorkListRemover : public SelectionDAG::DAGUpdateListener {
+ SmallVector<SDNode*, 128> &Worklist;
+public:
+ SDOPsWorkListRemover(SmallVector<SDNode*, 128> &wl) : Worklist(wl) {}
+
+ virtual void NodeDeleted(SDNode *N, SDNode *E) {
+ Worklist.erase(std::remove(Worklist.begin(), Worklist.end(), N),
+ Worklist.end());
+ }
+
+ virtual void NodeUpdated(SDNode *N) {
+ // Ignore updates.
+ }
+};
+}
+
/// ShrinkDemandedOps - A late transformation pass that shrink expressions
/// using TargetLowering::TargetLoweringOpt::ShrinkDemandedOp. It converts
/// x+y to (VT)((SmallVT)x+(SmallVT)y) if the casts are free.
@@ -459,8 +478,7 @@ void SelectionDAGISel::ShrinkDemandedOps() {
SDNode *N = Worklist.pop_back_val();
if (N->use_empty() && N != CurDAG->getRoot().getNode()) {
- if (N->getOpcode() != ISD::DELETED_NODE)
- CurDAG->DeleteNode(N);
+ CurDAG->DeleteNode(N);
continue;
}
@@ -485,7 +503,9 @@ void SelectionDAGISel::ShrinkDemandedOps() {
errs() << '\n');
Worklist.push_back(TLO.New.getNode());
- CurDAG->ReplaceAllUsesOfValueWith(TLO.Old, TLO.New);
+
+ SDOPsWorkListRemover DeadNodes(Worklist);
+ CurDAG->ReplaceAllUsesOfValueWith(TLO.Old, TLO.New, &DeadNodes);
if (TLO.Old.getNode()->use_empty()) {
for (unsigned i = 0, e = TLO.Old.getNode()->getNumOperands();
@@ -493,15 +513,13 @@ void SelectionDAGISel::ShrinkDemandedOps() {
SDNode *OpNode = TLO.Old.getNode()->getOperand(i).getNode();
if (OpNode->hasOneUse()) {
Worklist.erase(std::remove(Worklist.begin(), Worklist.end(),
- OpNode),
- Worklist.end());
- Worklist.push_back(TLO.Old.getNode()->getOperand(i).getNode());
+ OpNode), Worklist.end());
+ Worklist.push_back(OpNode);
}
}
Worklist.erase(std::remove(Worklist.begin(), Worklist.end(),
- TLO.Old.getNode()),
- Worklist.end());
+ TLO.Old.getNode()), Worklist.end());
CurDAG->DeleteNode(TLO.Old.getNode());
}
}