diff options
author | Craig Topper <craig.topper@sifive.com> | 2021-03-04 23:05:30 -0800 |
---|---|---|
committer | Craig Topper <craig.topper@sifive.com> | 2021-03-04 23:05:32 -0800 |
commit | ad532be01251c3593616d7ede29bc43a87e30726 (patch) | |
tree | d704efc0a5ad2bbb9471a2e2a9a60397be4868d8 /llvm/lib | |
parent | 74e6030bcbcc8e628f9a99a424342a0c656456f9 (diff) | |
download | llvm-ad532be01251c3593616d7ede29bc43a87e30726.zip llvm-ad532be01251c3593616d7ede29bc43a87e30726.tar.gz llvm-ad532be01251c3593616d7ede29bc43a87e30726.tar.bz2 |
[SelectionDAG] Assert that operands to SelectionDAG::getNode are not DELETED_NODE to catch issues like PR49393 earlier.
I'm not sure this would catch all such issues, but it would catch some.
The problem for PR49393 was that we were holding a reference to a node that
wasn't connect edto the DAG across a function that could delete unused nodes. In
this particular case we managed to try to use the deleted node while it was in
the deleted state before its memory got recycled.
It could also happen that we delete the node, something allocates a new node
which recycles the memory. Then we try to use the reference we were holding and
it is now a completely different node with different valid opcode. This patch
would not catch that.
Reviewed By: spatel
Differential Revision: https://reviews.llvm.org/D97969
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 2b74aae..b6f903d1 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4419,6 +4419,8 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue Operand, const SDNodeFlags Flags) { + assert(Operand.getOpcode() != ISD::DELETED_NODE && + "Operand is DELETED_NODE!"); // Constant fold unary operations with an integer constant operand. Even // opaque constant will be folded, because the folding of unary operations // doesn't create new constants with different values. Nevertheless, the @@ -5254,6 +5256,9 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, SDValue N2, const SDNodeFlags Flags) { + assert(N1.getOpcode() != ISD::DELETED_NODE && + N2.getOpcode() != ISD::DELETED_NODE && + "Operand is DELETED_NODE!"); ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2); ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1); @@ -5729,6 +5734,10 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, const SDNodeFlags Flags) { + assert(N1.getOpcode() != ISD::DELETED_NODE && + N2.getOpcode() != ISD::DELETED_NODE && + N3.getOpcode() != ISD::DELETED_NODE && + "Operand is DELETED_NODE!"); // Perform various simplifications. switch (Opcode) { case ISD::FMA: { @@ -7613,6 +7622,12 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT, default: break; } +#ifndef NDEBUG + for (auto &Op : Ops) + assert(Op.getOpcode() != ISD::DELETED_NODE && + "Operand is DELETED_NODE!"); +#endif + switch (Opcode) { default: break; case ISD::BUILD_VECTOR: @@ -7686,6 +7701,12 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, if (VTList.NumVTs == 1) return getNode(Opcode, DL, VTList.VTs[0], Ops); +#ifndef NDEBUG + for (auto &Op : Ops) + assert(Op.getOpcode() != ISD::DELETED_NODE && + "Operand is DELETED_NODE!"); +#endif + switch (Opcode) { case ISD::STRICT_FP_EXTEND: assert(VTList.NumVTs == 2 && Ops.size() == 2 && |