IR: Prevent handleChangedOperand() recursion

Instead of returning early on `handleChangedOperand()` recursion
(finally identified (and test added) in r225657), prevent it upfront by
releasing operands before RAUW.

Aside from massively different program flow, there should be no
functionality change ;).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225665 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan P. N. Exon Smith 2015-01-12 19:36:35 +00:00
parent d275e025d2
commit aea8ab800f
2 changed files with 8 additions and 11 deletions

View File

@ -49,7 +49,6 @@ class Metadata {
protected: protected:
/// \brief Storage flag for non-uniqued, otherwise unowned, metadata. /// \brief Storage flag for non-uniqued, otherwise unowned, metadata.
bool IsDistinctInContext : 1; bool IsDistinctInContext : 1;
bool InRAUW : 1;
// TODO: expose remaining bits to subclasses. // TODO: expose remaining bits to subclasses.
unsigned short SubclassData16; unsigned short SubclassData16;
@ -66,8 +65,8 @@ public:
protected: protected:
Metadata(unsigned ID) Metadata(unsigned ID)
: SubclassID(ID), IsDistinctInContext(false), InRAUW(false), : SubclassID(ID), IsDistinctInContext(false), SubclassData16(0),
SubclassData16(0), SubclassData32(0) {} SubclassData32(0) {}
~Metadata() {} ~Metadata() {}
/// \brief Store this in a big non-uniqued untyped bucket. /// \brief Store this in a big non-uniqued untyped bucket.

View File

@ -534,12 +534,6 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
setOperand(Op, New); setOperand(Op, New);
return; return;
} }
if (InRAUW) {
// We just hit a recursion due to RAUW. Set the operand and move on, since
// we're about to be deleted.
setOperand(Op, New);
return;
}
auto &Store = getContext().pImpl->MDNodeSet; auto &Store = getContext().pImpl->MDNodeSet;
Store.erase(this); Store.erase(this);
@ -571,13 +565,17 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
// Collision. // Collision.
if (!isResolved()) { if (!isResolved()) {
// Still unresolved, so RAUW. // Still unresolved, so RAUW.
InRAUW = true; //
// First, clear out all operands to prevent any recursion (similar to
// dropAllReferences(), but we still need the use-list).
for (unsigned O = 0, E = getNumOperands(); O != E; ++O)
setOperand(O, nullptr);
ReplaceableUses->replaceAllUsesWith(*I); ReplaceableUses->replaceAllUsesWith(*I);
delete this; delete this;
return; return;
} }
// Store in non-uniqued form if this node has already been resolved. // Store in non-uniqued form if RAUW isn't possible.
storeDistinctInContext(); storeDistinctInContext();
} }