Linker: Fix references to uniqued nodes after r243883
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 4 Aug 2015 06:42:31 +0000 (06:42 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Tue, 4 Aug 2015 06:42:31 +0000 (06:42 +0000)
r243883 started moving 'distinct' nodes instead of duplicated them in
lib/Linker.  This had the side-effect of sometimes not cloning uniqued
nodes that reference them.  I missed a corner case:

    !named = !{!0}
    !0 = !{!1}
    !1 = distinct !{!0}

!0 is the entry point for "remapping", and a temporary clone (say,
!0-temp) is created and mapped in case we need to model a uniquing
cycle.

    Recursive descent into !1.  !1 is distinct, so we leave it alone,
    but update its operand to !0-temp.

Pop back out to !0.  Its only operand, !1, hasn't changed, so we don't
need to use !0-temp.  !0-temp goes out of scope, and we're finished
remapping, but we're left with:

    !named = !{!0}
    !0 = !{!1}
    !1 = distinct !{null} ; uh oh...

Previously, if !0 and !0-temp ended up with identical operands, then
!0-temp couldn't have been referenced at all.  Now that distinct nodes
don't get duplicated, that assumption is invalid.  We need to
!0-temp->replaceAllUsesWith(!0) before freeing !0-temp.

I found this while running an internal `-flto -g` bootstrap.  Strangely,
there was no case of this in the open source bootstrap I'd done before
commit...

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

lib/Transforms/Utils/ValueMapper.cpp
test/Linker/uniqued-distinct-cycles.ll [new file with mode: 0644]

index d967e0a95c6fb09c8ecc329ea5834524352b70eb..8aa546c7211447f9ae409615eb26d07418f7c09c 100644 (file)
@@ -258,9 +258,11 @@ static Metadata *mapUniquedNode(const MDNode *Node,
 
   // Create a temporary node upfront in case we have a metadata cycle.
   auto ClonedMD = Node->clone();
-  if (!remap(Node, ClonedMD.get(), Cycles, VM, Flags, TypeMapper, Materializer))
+  if (!remap(Node, ClonedMD.get(), Cycles, VM, Flags, TypeMapper, Materializer)) {
     // No operands changed, so use the identity mapping.
+    ClonedMD->replaceAllUsesWith(const_cast<MDNode *>(Node));
     return mapToSelf(VM, Node);
+  }
 
   // At least one operand has changed, so uniquify the cloned node.
   return mapToMetadata(VM, Node,
diff --git a/test/Linker/uniqued-distinct-cycles.ll b/test/Linker/uniqued-distinct-cycles.ll
new file mode 100644 (file)
index 0000000..05cc80d
--- /dev/null
@@ -0,0 +1,14 @@
+; RUN: llvm-link -o - %s | llvm-dis | FileCheck %s
+
+; CHECK: !named = !{!0, !2}
+!named = !{!0, !2}
+
+; CHECK:      !0 = !{!1}
+; CHECK-NEXT: !1 = distinct !{!0}
+!0 = !{!1}
+!1 = distinct !{!0}
+
+; CHECK-NEXT: !2 = distinct !{!3}
+; CHECK-NEXT: !3 = !{!2}
+!2 = distinct !{!3}
+!3 = !{!2}