Index: llvm/lib/Transforms/Utils/InlineFunction.cpp =================================================================== --- llvm/lib/Transforms/Utils/InlineFunction.cpp +++ llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1137,6 +1137,25 @@ } } +static void UpdateAssociatedMetadata(CallBase &CB) { + Module *M = CB.getModule(); + + Function *Callee = CB.getCalledFunction(); + if (!Callee->isUsedByMetadata()) + return; + ValueAsMetadata *CalleeMetadata = ValueAsMetadata::getIfExists(Callee); + assert(CalleeMetadata && "Expected existing metadata"); + MDNode *CalleeMDNode = MDNode::get(CB.getContext(), CalleeMetadata); + + Function *Caller = CB.getFunction(); + ValueAsMetadata *CallerMetadata = ValueAsMetadata::get(Caller); + MDNode *CallerMDNode = MDNode::get(CB.getContext(), CallerMetadata); + + for (GlobalVariable &GV : M->globals()) + if (GV.getMetadata(LLVMContext::MD_associated) == CalleeMDNode) + GV.setMetadata(LLVMContext::MD_associated, CallerMDNode); +} + static bool MayContainThrowingOrExitingCall(Instruction *Begin, Instruction *End) { @@ -1911,6 +1930,9 @@ } } + // Adjust !associated metadata to point to caller instead of callee. + UpdateAssociatedMetadata(CB); + // If there are any alloca instructions in the block that used to be the entry // block for the callee, move them to the entry block of the caller. First // calculate which instruction they should be inserted before. We insert the Index: llvm/test/Transforms/Inline/inline-md-associated.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/Inline/inline-md-associated.ll @@ -0,0 +1,41 @@ +; RUN: opt < %s -inline --inline-threshold=0 -S | FileCheck %s + +; Test that the inliner updates the !associated metadata for inlined functions. + +; CHECK: @__foo_metadata = private global [1 x i64] zeroinitializer, align 8, !associated !0 +@__foo_metadata = private global [1 x i64] zeroinitializer, align 8, !associated !0 +; CHECK: @__bar_metadata = private global [1 x i64] zeroinitializer, align 8, !associated !0 +@__bar_metadata = private global [1 x i64] zeroinitializer, align 8, !associated !1 +; CHECK: @__baz_metadata = private global [1 x i64] zeroinitializer, align 8, !associated !1 +@__baz_metadata = private global [1 x i64] zeroinitializer, align 8, !associated !2 + +define void @foo() { + call void @bar(i1 true) + ret void +} + +define internal void @bar(i1 %p) { + br i1 %p, label %bb1, label %bb2 + +bb1: + call void @foo() + ret void + +bb2: + call void @bar(i1 true) + ret void +} + +define void @baz() { +; CHECK: call void @foo() + call void @bar(i1 true) +; CHECK: call void @foo() + call void @bar(i1 false) + ret void +} + +; CHECK: !0 = !{void ()* @foo} +!0 = !{void ()* @foo} +!1 = !{void (i1)* @bar} +; CHECK: !1 = !{void ()* @baz} +!2 = !{void ()* @baz}