IR: Metadata: Detect an RAUW recursion
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 9 Dec 2014 23:04:59 +0000 (23:04 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 9 Dec 2014 23:04:59 +0000 (23:04 +0000)
Speculatively handle a recursion in
`GenericMDNode::handleChangedOperand()`.  I'm hoping this fixes the
failing hexagon bot [1].

[1]: http://lab.llvm.org:8011/builders/llvm-hexagon-elf/builds/13434

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@223849 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/Metadata.h
lib/IR/Metadata.cpp

index ffdd7002ceaabe0eef22def4998975a301464cb1..573e49fbb06954cff94d35f0cd0be83129008153 100644 (file)
@@ -49,6 +49,7 @@ class Metadata {
 protected:
   /// \brief Storage flag for non-uniqued, otherwise unowned, metadata.
   bool IsDistinctInContext : 1;
+  bool InRAUW : 1;
   // TODO: expose remaining bits to subclasses.
 
   unsigned short SubclassData16;
@@ -65,8 +66,8 @@ public:
 
 protected:
   Metadata(unsigned ID)
-      : SubclassID(ID), IsDistinctInContext(false), SubclassData16(0),
-        SubclassData32(0) {}
+      : SubclassID(ID), IsDistinctInContext(false), InRAUW(false),
+        SubclassData16(0), SubclassData32(0) {}
   ~Metadata() {}
 
   /// \brief Store this in a big non-uniqued untyped bucket.
index 805b7377bceb44d958fd30738d26532b946e20e6..7a354c42c4c221f76501d89a7752d4570bdeafb5 100644 (file)
@@ -495,6 +495,14 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
     setOperand(Op, New);
     return;
   }
+  if (InRAUW) {
+    // We just hit a recursion due to RAUW.  Set the operand and move on, since
+    // we're about to be deleted.
+    //
+    // FIXME: Can this cycle really happen?
+    setOperand(Op, New);
+    return;
+  }
 
   auto &Store = getContext().pImpl->MDNodeSet;
   Store.erase(this);
@@ -550,6 +558,7 @@ void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
   // Collision.
   if (!isResolved()) {
     // Still unresolved, so RAUW.
+    InRAUW = true;
     ReplaceableUses->replaceAllUsesWith(*I);
     delete this;
     return;