Index: llvm/lib/Transforms/Utils/InlineFunction.cpp =================================================================== --- llvm/lib/Transforms/Utils/InlineFunction.cpp +++ llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1137,6 +1137,23 @@ } } +static void UpdateAssociatedMetadata(CallBase &CB) { + Module *M = CB.getModule(); + + Function *Callee = CB.getCalledFunction(); + MDNode *CalleeMD = MDNode::get(CB.getContext(), ValueAsMetadata::get(Callee)); + Function *Caller = CB.getFunction(); + MDNode *CallerMD = MDNode::get(CB.getContext(), ValueAsMetadata::get(Caller)); + + for (GlobalVariable &GV : M->globals()) { + MDNode *MD = GV.getMetadata(LLVMContext::MD_associated); + if (!MD) + continue; + if (MD == CalleeMD) + GV.setMetadata(LLVMContext::MD_associated, CallerMD); + } +} + static bool MayContainThrowingOrExitingCall(Instruction *Begin, Instruction *End) { @@ -1900,6 +1917,9 @@ // Propagate llvm.mem.parallel_loop_access if necessary. PropagateParallelLoopAccessMetadata(CB, VMap); + // Adjust !associated metadata to point to caller instead of callee. + UpdateAssociatedMetadata(CB); + // Register any cloned assumptions. if (IFI.GetAssumptionCache) for (BasicBlock &NewBlock : 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}