Index: test/tools/gold/X86/Inputs/thinlto_linkonceresolution.ll =================================================================== --- /dev/null +++ test/tools/gold/X86/Inputs/thinlto_linkonceresolution.ll @@ -0,0 +1,4 @@ +target triple = "x86_64-unknown-linux-gnu" +define linkonce_odr hidden void @f() { + ret void +} Index: test/tools/gold/X86/thinlto_linkonceresolution.ll =================================================================== --- /dev/null +++ test/tools/gold/X86/thinlto_linkonceresolution.ll @@ -0,0 +1,27 @@ +; RUN: llvm-as -function-summary %s -o %t.o +; RUN: llvm-as -function-summary %p/Inputs/thinlto_linkonceresolution.ll -o %t2.o + +; Ensure the plugin changes the symbol resolution for linkonce_odr +; f() to LDPR_PREVAILING_DEF_IRONLY instead of LDPR_PREEMPTED_IR +; for ThinLTO, since it isn't a full LTO link and the unreferenced +; f() will be deleted in the other module. Note that gold picks the +; first copy of f() as the prevailing one, so listing %t2.o first +; is sufficient to ensure that this copy is preempted. Also, +; set the import-instr-limit to 0 to prevent f() from being imported +; from %t2.o which hides the problem. +; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \ +; RUN: --plugin-opt=thinlto \ +; RUN: --plugin-opt=-import-instr-limit=0 \ +; RUN: -o %t3.o %t2.o %t.o +; RUN: llvm-nm %t3.o | FileCheck %s + +; CHECK-NOT: U f + +target triple = "x86_64-unknown-linux-gnu" +define i32 @g() { + call void @f() + ret i32 0 +} +define linkonce_odr hidden void @f() { + ret void +} Index: tools/gold/gold-plugin.cpp =================================================================== --- tools/gold/gold-plugin.cpp +++ tools/gold/gold-plugin.cpp @@ -712,6 +712,14 @@ if (Resolution == LDPR_PREVAILING_DEF_IRONLY_EXP && !Res.IsLinkonceOdr) Resolution = LDPR_PREVAILING_DEF; + // For ThinLTO the IR files are compiled through the backend independently, + // so gold's preemption decisions must be ignored for linkonce symbols. + // There is no guarantee that the symbol will be emitted into the object + // file with the prevailing copy. + if (options::thinlto && Res.IsLinkonceOdr && + Resolution == LDPR_PREEMPTED_IR) + Resolution = LDPR_PREVAILING_DEF_IRONLY; + GV->setUnnamedAddr(Res.UnnamedAddr); GV->setVisibility(Res.Visibility);