diff options
| author | Hans Wennborg <hans@hanshq.net> | 2017-08-24 01:08:27 +0000 |
|---|---|---|
| committer | Hans Wennborg <hans@hanshq.net> | 2017-08-24 01:08:27 +0000 |
| commit | c39ec95d886b2dd1977021cdf7a52dc43a76f8c8 (patch) | |
| tree | 3679fdf5455d7ce35e5f9f9d67366eca47ef3f4d /llvm/lib/CodeGen/SelectionDAG | |
| parent | c064881a361ce46687eec2695777f092d417496f (diff) | |
| download | bcm5719-llvm-c39ec95d886b2dd1977021cdf7a52dc43a76f8c8.tar.gz bcm5719-llvm-c39ec95d886b2dd1977021cdf7a52dc43a76f8c8.zip | |
[DAG] Fix Node Replacement in PromoteIntBinOp
When one operand is a user of another in a promoted binary operation
we may replace and delete the returned value before returning
triggering an assertion. Reorder node replacements to prevent this.
Fixes PR34137.
Landing on behalf of Nirav.
Differential Revision: https://reviews.llvm.org/D36581
llvm-svn: 311623
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index ab459cd7ea0..e6f2eb5480e 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1168,22 +1168,30 @@ SDValue DAGCombiner::PromoteIntBinOp(SDValue Op) { SDValue RV = DAG.getNode(ISD::TRUNCATE, DL, VT, DAG.getNode(Opc, DL, PVT, NN0, NN1)); - // New replace instances of N0 and N1 - if (Replace0 && N0 && N0.getOpcode() != ISD::DELETED_NODE && NN0 && - NN0.getOpcode() != ISD::DELETED_NODE) { + // We are always replacing N0/N1's use in N and only need + // additional replacements if there are additional uses. + Replace0 &= !N0->hasOneUse(); + Replace1 &= (N0 != N1) && !N1->hasOneUse(); + + // Combine Op here so it is presreved past replacements. + CombineTo(Op.getNode(), RV); + + // If operands have a use ordering, make sur we deal with + // predecessor first. + if (Replace0 && Replace1 && N0.getNode()->isPredecessorOf(N1.getNode())) { + std::swap(N0, N1); + std::swap(NN0, NN1); + } + + if (Replace0) { AddToWorklist(NN0.getNode()); ReplaceLoadWithPromotedLoad(N0.getNode(), NN0.getNode()); } - - if (Replace1 && N1 && N1.getOpcode() != ISD::DELETED_NODE && NN1 && - NN1.getOpcode() != ISD::DELETED_NODE) { + if (Replace1) { AddToWorklist(NN1.getNode()); ReplaceLoadWithPromotedLoad(N1.getNode(), NN1.getNode()); } - - // Deal with Op being deleted. - if (Op && Op.getOpcode() != ISD::DELETED_NODE) - return RV; + return Op; } return SDValue(); } |

