Linker: Move distinct MDNodes instead of cloning
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Mon, 3 Aug 2015 17:09:38 +0000 (17:09 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Mon, 3 Aug 2015 17:09:38 +0000 (17:09 +0000)
Instead of cloning distinct `MDNode`s when linking in a module, just
move them over.  The module linker destroys the source module, so the
old node would otherwise just be leaked on the context.  Create the new
node in place.  This also reduces the number of cloned uniqued nodes
(since it's less likely their operands have changed).

This mapping strategy is only correct when we're discarding the source,
so the linker turns it on via a ValueMapper flag, `RF_MoveDistinctMDs`.

There's nothing observable in terms of `llvm-link` output here: the
linked module should be semantically identical.

I'll be adding more 'distinct' nodes to the debug info metadata graph in
order to break uniquing cycles, so the benefits of this will partly come
in future commits.  However, we should get some gains immediately, since
we have a fair number of 'distinct' `DILocation`s being linked in.

llvm-svn: 243883

llvm/include/llvm/Transforms/Utils/ValueMapper.h
llvm/lib/Linker/LinkModules.cpp
llvm/lib/Transforms/Utils/ValueMapper.cpp
llvm/unittests/Linker/LinkModulesTest.cpp
llvm/unittests/Transforms/Utils/ValueMapperTest.cpp

index 047ab81..1419618 100644 (file)
@@ -59,7 +59,11 @@ namespace llvm {
     /// RF_IgnoreMissingEntries - If this flag is set, the remapper ignores
     /// entries that are not in the value map.  If it is unset, it aborts if an
     /// operand is asked to be remapped which doesn't exist in the mapping.
-    RF_IgnoreMissingEntries = 2
+    RF_IgnoreMissingEntries = 2,
+
+    /// Instruct the remapper to move distinct metadata instead of duplicating
+    /// it when there are module-level changes.
+    RF_MoveDistinctMDs = 4,
   };
 
   static inline RemapFlags operator|(RemapFlags LHS, RemapFlags RHS) {
index f090680..e102119 100644 (file)
@@ -1156,7 +1156,7 @@ void ModuleLinker::linkAppendingVarInit(const AppendingVarInfo &AVI) {
         continue;
     }
     DstElements.push_back(
-        MapValue(V, ValueMap, RF_None, &TypeMap, &ValMaterializer));
+        MapValue(V, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer));
   }
   if (IsNewStructor) {
     NewType = ArrayType::get(NewType->getElementType(), DstElements.size());
@@ -1170,8 +1170,8 @@ void ModuleLinker::linkAppendingVarInit(const AppendingVarInfo &AVI) {
 /// referenced are in Dest.
 void ModuleLinker::linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src) {
   // Figure out what the initializer looks like in the dest module.
-  Dst.setInitializer(MapValue(Src.getInitializer(), ValueMap, RF_None, &TypeMap,
-                              &ValMaterializer));
+  Dst.setInitializer(MapValue(Src.getInitializer(), ValueMap,
+                              RF_MoveDistinctMDs, &TypeMap, &ValMaterializer));
 }
 
 /// Copy the source function over into the dest function and fix up references
@@ -1186,18 +1186,20 @@ bool ModuleLinker::linkFunctionBody(Function &Dst, Function &Src) {
 
   // Link in the prefix data.
   if (Src.hasPrefixData())
-    Dst.setPrefixData(MapValue(Src.getPrefixData(), ValueMap, RF_None, &TypeMap,
-                               &ValMaterializer));
+    Dst.setPrefixData(MapValue(Src.getPrefixData(), ValueMap,
+                               RF_MoveDistinctMDs, &TypeMap, &ValMaterializer));
 
   // Link in the prologue data.
   if (Src.hasPrologueData())
-    Dst.setPrologueData(MapValue(Src.getPrologueData(), ValueMap, RF_None,
-                                 &TypeMap, &ValMaterializer));
+    Dst.setPrologueData(MapValue(Src.getPrologueData(), ValueMap,
+                                 RF_MoveDistinctMDs, &TypeMap,
+                                 &ValMaterializer));
 
   // Link in the personality function.
   if (Src.hasPersonalityFn())
-    Dst.setPersonalityFn(MapValue(Src.getPersonalityFn(), ValueMap, RF_None,
-                                  &TypeMap, &ValMaterializer));
+    Dst.setPersonalityFn(MapValue(Src.getPersonalityFn(), ValueMap,
+                                  RF_MoveDistinctMDs, &TypeMap,
+                                  &ValMaterializer));
 
   // Go through and convert function arguments over, remembering the mapping.
   Function::arg_iterator DI = Dst.arg_begin();
@@ -1213,8 +1215,8 @@ bool ModuleLinker::linkFunctionBody(Function &Dst, Function &Src) {
   SmallVector<std::pair<unsigned, MDNode *>, 8> MDs;
   Src.getAllMetadata(MDs);
   for (const auto &I : MDs)
-    Dst.setMetadata(I.first, MapMetadata(I.second, ValueMap, RF_None, &TypeMap,
-                                         &ValMaterializer));
+    Dst.setMetadata(I.first, MapMetadata(I.second, ValueMap, RF_MoveDistinctMDs,
+                                         &TypeMap, &ValMaterializer));
 
   // Splice the body of the source function into the dest function.
   Dst.getBasicBlockList().splice(Dst.end(), Src.getBasicBlockList());
@@ -1225,7 +1227,8 @@ bool ModuleLinker::linkFunctionBody(Function &Dst, Function &Src) {
   // functions and patch them up to point to the local versions.
   for (BasicBlock &BB : Dst)
     for (Instruction &I : BB)
-      RemapInstruction(&I, ValueMap, RF_IgnoreMissingEntries, &TypeMap,
+      RemapInstruction(&I, ValueMap,
+                       RF_IgnoreMissingEntries | RF_MoveDistinctMDs, &TypeMap,
                        &ValMaterializer);
 
   // There is no need to map the arguments anymore.
@@ -1238,8 +1241,8 @@ bool ModuleLinker::linkFunctionBody(Function &Dst, Function &Src) {
 
 void ModuleLinker::linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src) {
   Constant *Aliasee = Src.getAliasee();
-  Constant *Val =
-      MapValue(Aliasee, ValueMap, RF_None, &TypeMap, &ValMaterializer);
+  Constant *Val = MapValue(Aliasee, ValueMap, RF_MoveDistinctMDs, &TypeMap,
+                           &ValMaterializer);
   Dst.setAliasee(Val);
 }
 
@@ -1266,8 +1269,8 @@ void ModuleLinker::linkNamedMDNodes() {
     NamedMDNode *DestNMD = DstM->getOrInsertNamedMetadata(NMD.getName());
     // Add Src elements into Dest node.
     for (const MDNode *op : NMD.operands())
-      DestNMD->addOperand(
-          MapMetadata(op, ValueMap, RF_None, &TypeMap, &ValMaterializer));
+      DestNMD->addOperand(MapMetadata(op, ValueMap, RF_MoveDistinctMDs,
+                                      &TypeMap, &ValMaterializer));
   }
 }
 
@@ -1574,7 +1577,7 @@ bool ModuleLinker::run() {
       continue;
     const GlobalValue *GV = SrcM->getNamedValue(C.getName());
     if (GV)
-      MapValue(GV, ValueMap, RF_None, &TypeMap, &ValMaterializer);
+      MapValue(GV, ValueMap, RF_MoveDistinctMDs, &TypeMap, &ValMaterializer);
   }
 
   // Strip replaced subprograms before mapping any metadata -- so that we're
index 8daf546..d967e0a 100644 (file)
@@ -216,9 +216,12 @@ static bool remap(const MDNode *OldNode, MDNode *NewNode,
   return AnyChanged;
 }
 
-/// \brief Map a distinct MDNode.
+/// Map a distinct MDNode.
 ///
-/// Distinct nodes are not uniqued, so they must always recreated.
+/// Whether distinct nodes change is independent of their operands.  If \a
+/// RF_MoveDistinctMDs, then they are reused, and their operands remapped in
+/// place; effectively, they're moved from one graph to another.  Otherwise,
+/// they're cloned/duplicated, and the new copy's operands are remapped.
 static Metadata *mapDistinctNode(const MDNode *Node,
                                  SmallVectorImpl<MDNode *> &Cycles,
                                  ValueToValueMapTy &VM, RemapFlags Flags,
@@ -226,7 +229,11 @@ static Metadata *mapDistinctNode(const MDNode *Node,
                                  ValueMaterializer *Materializer) {
   assert(Node->isDistinct() && "Expected distinct node");
 
-  MDNode *NewMD = MDNode::replaceWithDistinct(Node->clone());
+  MDNode *NewMD;
+  if (Flags & RF_MoveDistinctMDs)
+    NewMD = const_cast<MDNode *>(Node);
+  else
+    NewMD = MDNode::replaceWithDistinct(Node->clone());
 
   // Remap the operands.  If any change, track those that could be involved in
   // uniquing cycles.
@@ -318,20 +325,21 @@ Metadata *llvm::MapMetadata(const Metadata *MD, ValueToValueMapTy &VM,
   Metadata *NewMD =
       MapMetadataImpl(MD, Cycles, VM, Flags, TypeMapper, Materializer);
 
-  // Resolve cycles underneath MD.
-  if (NewMD && NewMD != MD) {
-    if (auto *N = dyn_cast<MDNode>(NewMD))
-      if (!N->isResolved())
-        N->resolveCycles();
-
-    for (MDNode *N : Cycles)
-      if (!N->isResolved())
-        N->resolveCycles();
-  } else {
-    // Shouldn't get unresolved cycles if nothing was remapped.
-    assert(Cycles.empty() && "Expected no unresolved cycles");
+  if ((Flags & RF_NoModuleLevelChanges) ||
+      (MD == NewMD && !(Flags & RF_MoveDistinctMDs))) {
+    assert(Cycles.empty() && "Unresolved cycles without remapping anything?");
+    return NewMD;
   }
 
+  if (auto *N = dyn_cast<MDNode>(NewMD))
+    if (!N->isResolved())
+      N->resolveCycles();
+
+  // Resolve cycles underneath MD.
+  for (MDNode *N : Cycles)
+    if (!N->isResolved())
+      N->resolveCycles();
+
   return NewMD;
 }
 
index 45f1308..904ba58 100644 (file)
@@ -7,6 +7,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/DataLayout.h"
@@ -219,4 +220,77 @@ TEST_F(LinkModuleTest, CAPIFailure) {
   LLVMDisposeMessage(errout);
 }
 
+TEST_F(LinkModuleTest, MoveDistinctMDs) {
+  LLVMContext C;
+  SMDiagnostic Err;
+
+  const char *SrcStr = "define void @foo() !attach !0 {\n"
+                       "entry:\n"
+                       "  call void @llvm.md(metadata !1)\n"
+                       "  ret void, !attach !2\n"
+                       "}\n"
+                       "declare void @llvm.md(metadata)\n"
+                       "!named = !{!3, !4}\n"
+                       "!0 = distinct !{}\n"
+                       "!1 = distinct !{}\n"
+                       "!2 = distinct !{}\n"
+                       "!3 = distinct !{}\n"
+                       "!4 = !{!3}\n";
+
+  std::unique_ptr<Module> Src = parseAssemblyString(SrcStr, Err, C);
+  assert(Src);
+  ASSERT_TRUE(Src.get());
+
+  // Get the addresses of the Metadata before merging.
+  Function *F = &*Src->begin();
+  ASSERT_EQ("foo", F->getName());
+  BasicBlock *BB = &F->getEntryBlock();
+  auto *CI = cast<CallInst>(&BB->front());
+  auto *RI = cast<ReturnInst>(BB->getTerminator());
+  NamedMDNode *NMD = &*Src->named_metadata_begin();
+
+  MDNode *M0 = F->getMetadata("attach");
+  MDNode *M1 =
+      cast<MDNode>(cast<MetadataAsValue>(CI->getArgOperand(0))->getMetadata());
+  MDNode *M2 = RI->getMetadata("attach");
+  MDNode *M3 = NMD->getOperand(0);
+  MDNode *M4 = NMD->getOperand(1);
+
+  // Confirm a few things about the IR.
+  EXPECT_TRUE(M0->isDistinct());
+  EXPECT_TRUE(M1->isDistinct());
+  EXPECT_TRUE(M2->isDistinct());
+  EXPECT_TRUE(M3->isDistinct());
+  EXPECT_TRUE(M4->isUniqued());
+  EXPECT_EQ(M3, M4->getOperand(0));
+
+  // Link into destination module.
+  auto Dst = llvm::make_unique<Module>("Linked", C);
+  ASSERT_TRUE(Dst.get());
+  Linker::LinkModules(Dst.get(), Src.get(),
+                      [](const llvm::DiagnosticInfo &) {});
+
+  // Check that distinct metadata was moved, not cloned.  Even !4, the uniqued
+  // node, should effectively be moved, since its only operand hasn't changed.
+  F = &*Dst->begin();
+  BB = &F->getEntryBlock();
+  CI = cast<CallInst>(&BB->front());
+  RI = cast<ReturnInst>(BB->getTerminator());
+  NMD = &*Dst->named_metadata_begin();
+
+  EXPECT_EQ(M0, F->getMetadata("attach"));
+  EXPECT_EQ(M1, cast<MetadataAsValue>(CI->getArgOperand(0))->getMetadata());
+  EXPECT_EQ(M2, RI->getMetadata("attach"));
+  EXPECT_EQ(M3, NMD->getOperand(0));
+  EXPECT_EQ(M4, NMD->getOperand(1));
+
+  // Confirm a few things about the IR.  This shouldn't have changed.
+  EXPECT_TRUE(M0->isDistinct());
+  EXPECT_TRUE(M1->isDistinct());
+  EXPECT_TRUE(M2->isDistinct());
+  EXPECT_TRUE(M3->isDistinct());
+  EXPECT_TRUE(M4->isUniqued());
+  EXPECT_EQ(M3, M4->getOperand(0));
+}
+
 } // end anonymous namespace
index 137a260..9dbe4db 100644 (file)
@@ -24,4 +24,35 @@ TEST(ValueMapperTest, MapMetadataUnresolved) {
   EXPECT_EQ(T.get(), MapMetadata(T.get(), VM, RF_NoModuleLevelChanges));
 }
 
+TEST(ValueMapperTest, MapMetadataDistinct) {
+  LLVMContext Context;
+  auto *D = MDTuple::getDistinct(Context, None);
+
+  {
+    // The node should be cloned.
+    ValueToValueMapTy VM;
+    EXPECT_NE(D, MapMetadata(D, VM, RF_None));
+  }
+  {
+    // The node should be moved.
+    ValueToValueMapTy VM;
+    EXPECT_EQ(D, MapMetadata(D, VM, RF_MoveDistinctMDs));
+  }
+}
+
+TEST(ValueMapperTest, MapMetadataDistinctOperands) {
+  LLVMContext Context;
+  Metadata *Old = MDTuple::getDistinct(Context, None);
+  auto *D = MDTuple::getDistinct(Context, Old);
+  ASSERT_EQ(Old, D->getOperand(0));
+
+  Metadata *New = MDTuple::getDistinct(Context, None);
+  ValueToValueMapTy VM;
+  VM.MD()[Old].reset(New);
+
+  // Make sure operands are updated.
+  EXPECT_EQ(D, MapMetadata(D, VM, RF_MoveDistinctMDs));
+  EXPECT_EQ(New, D->getOperand(0));
+}
+
 }