Re-apply "SDAG: Update ChainNodesMatched as nodes are deleted"

My first attempt at this had an overly aggressive assert - chain nodes
will only be removed, but we could hit the assert if a non-chain node
was CSE'd (NodeToMatch, for instance).

This reapplies r271706 by reverting r271713 and fixing an assert.

Original message:

Avoid relying on UB by looking into deleted nodes for a marker value.
Instead, update the list of chain nodes as we go.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271733 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Justin Bogner 2016-06-03 20:47:40 +00:00
parent ca03c97596
commit 78cd7cbf25
2 changed files with 17 additions and 4 deletions

View File

@ -249,6 +249,14 @@ public:
virtual void NodeUpdated(SDNode *N);
};
struct DAGNodeDeletedListener : public DAGUpdateListener {
std::function<void(SDNode *, SDNode *)> Callback;
DAGNodeDeletedListener(SelectionDAG &DAG,
std::function<void(SDNode *, SDNode *)> Callback)
: DAGUpdateListener(DAG), Callback(Callback) {}
void NodeDeleted(SDNode *N, SDNode *E) override { Callback(N, E); }
};
/// When true, additional steps are taken to
/// ensure that getConstant() and similar functions return DAG nodes that
/// have legal types. This is important after type legalization since

View File

@ -2163,10 +2163,8 @@ void SelectionDAGISel::UpdateChains(
// Replace all the chain results with the final chain we ended up with.
for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) {
SDNode *ChainNode = ChainNodesMatched[i];
// If this node was already deleted, don't look at it.
if (ChainNode->getOpcode() == ISD::DELETED_NODE)
continue;
assert(ChainNode->getOpcode() != ISD::DELETED_NODE &&
"Deleted node left in chain");
// Don't replace the results of the root node if we're doing a
// MorphNodeTo.
@ -3368,6 +3366,13 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
} else {
assert(NodeToMatch->getOpcode() != ISD::DELETED_NODE &&
"NodeToMatch was removed partway through selection");
SelectionDAG::DAGNodeDeletedListener NDL(*CurDAG, [&](SDNode *N,
SDNode *E) {
auto &Chain = ChainNodesMatched;
assert((!E || llvm::find(Chain, N) == Chain.end()) &&
"Chain node replaced during MorphNode");
Chain.erase(std::remove(Chain.begin(), Chain.end(), N), Chain.end());
});
Res = MorphNode(NodeToMatch, TargetOpc, VTList, Ops, EmitNodeInfo);
}