diff options
author | Evan Cheng <evan.cheng@apple.com> | 2010-01-09 00:21:08 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2010-01-09 00:21:08 +0000 |
commit | 0c6defd577ccf0b33e6c7ede703ac05916985454 (patch) | |
tree | 9a8332732e1d981b83132d9a59446e2e5ba21a99 /llvm/lib/CodeGen/SelectionDAG | |
parent | 8f0474065082fb2ada19423685add1cd9d6ff76c (diff) | |
download | bcm5719-llvm-0c6defd577ccf0b33e6c7ede703ac05916985454.tar.gz bcm5719-llvm-0c6defd577ccf0b33e6c7ede703ac05916985454.zip |
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.
llvm-svn: 93031
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 34 |
1 files changed, 26 insertions, 8 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index c87e4bf716a..edcd91e8ded 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/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()); } } |