Index: llvm/trunk/lib/Linker/LinkModules.cpp =================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp +++ llvm/trunk/lib/Linker/LinkModules.cpp @@ -509,6 +509,8 @@ ComdatsChosen; bool getComdatResult(const Comdat *SrcC, Comdat::SelectionKind &SK, bool &LinkFromSrc); + // Keep track of the global value members of each comdat in source. + DenseMap> ComdatMembers; /// Given a global in the source module, return the global in the /// destination module that is being linked to, if any. @@ -1386,6 +1388,7 @@ std::tie(SK, LinkFromSrc) = ComdatsChosen[SC]; C = DstM->getOrInsertComdat(SC->getName()); C->setSelectionKind(SK); + ComdatMembers[SC].push_back(SGV); } else if (DGV) { if (shouldLinkFromSource(LinkFromSrc, *DGV, *SGV)) return true; @@ -1589,6 +1592,19 @@ bool ModuleLinker::linkGlobalValueBody(GlobalValue &Src) { Value *Dst = ValueMap[&Src]; assert(Dst); + if (const Comdat *SC = Src.getComdat()) { + // To ensure that we don't generate an incomplete comdat group, + // we must materialize and map in any other members that are not + // yet materialized in Dst, which also ensures their definitions + // are linked in. Otherwise, linkonce and other lazy linked GVs will + // not be materialized if they aren't referenced. + for (auto *SGV : ComdatMembers[SC]) { + if (ValueMap[SGV]) + continue; + Value *NewV = ValMaterializer.materializeValueFor(SGV); + ValueMap[SGV] = NewV; + } + } if (shouldInternalizeLinkedSymbols()) if (auto *DGV = dyn_cast(Dst)) DGV->setLinkage(GlobalValue::InternalLinkage); Index: llvm/trunk/test/Linker/Inputs/only-needed-named-metadata.ll =================================================================== --- llvm/trunk/test/Linker/Inputs/only-needed-named-metadata.ll +++ llvm/trunk/test/Linker/Inputs/only-needed-named-metadata.ll @@ -2,11 +2,8 @@ declare i32 @foo() -declare void @c1_a() - define void @bar() { load i32, i32* @X call i32 @foo() - call void @c1_a() ret void } Index: llvm/trunk/test/Linker/comdat_group.ll =================================================================== --- llvm/trunk/test/Linker/comdat_group.ll +++ llvm/trunk/test/Linker/comdat_group.ll @@ -0,0 +1,20 @@ +; RUN: llvm-as -function-summary %s -o %t.bc + +; Ensure complete comdat group is materialized +; RUN: llvm-link %t.bc -S | FileCheck %s +; CHECK: $linkoncecomdat = comdat any +; CHECK: @linkoncecomdat = linkonce global i32 2 +; CHECK: @linkoncecomdat_unref_var = linkonce global i32 2, comdat($linkoncecomdat) +; CHECK: define linkonce void @linkoncecomdat_unref_func() comdat($linkoncecomdat) + +$linkoncecomdat = comdat any +@linkoncecomdat = linkonce global i32 2, comdat($linkoncecomdat) +@linkoncecomdat_unref_var = linkonce global i32 2, comdat($linkoncecomdat) +define linkonce void @linkoncecomdat_unref_func() comdat($linkoncecomdat) { + ret void +} +; Reference one member of comdat so that comdat is generated. +define void @ref_linkoncecomdat() { + load i32, i32* @linkoncecomdat, align 4 + ret void +} Index: llvm/trunk/test/Linker/only-needed-named-metadata.ll =================================================================== --- llvm/trunk/test/Linker/only-needed-named-metadata.ll +++ llvm/trunk/test/Linker/only-needed-named-metadata.ll @@ -25,17 +25,6 @@ ; ONLYNEEDED-NOT:@globalfunc1() ; ONLYNEEDED-NOT:@analias ; ONLYNEEDED-NOT:@globalfunc2() -; ONLYNEEDED-NOT:@c1_c -; ONLYNEEDED-NOT:@c1() - -$c1 = comdat any -@c1_c = global i32 0, comdat($c1) -define void @c1() comdat { - ret void -} -define void @c1_a() comdat($c1) { - ret void -} @X = global i32 5 @U = global i32 6 @@ -64,7 +53,7 @@ ret void } -!llvm.named = !{!0, !1, !2, !3, !4, !5, !6, !7} +!llvm.named = !{!0, !1, !2, !3, !4, !5, !6} !0 = !{i32 ()* @unused} !1 = !{i32* @U} !2 = !{i32 ()* @unused_linkonce} @@ -72,4 +61,3 @@ !4 = !{void (...)* @weakalias} !5 = !{void (...)* @analias} !6 = !{void (...)* @linkoncealias} -!7 = !{void ()* @c1}