Linker: Move distinct MDNodes instead of cloning

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
This commit is contained in:
Duncan P. N. Exon Smith 2015-08-03 17:09:38 +00:00
parent 14e67e43a7
commit 4fb46cb818
5 changed files with 153 additions and 33 deletions

View 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) {

View 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

View 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;
}

View 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

View 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));
}
}