[llvm] r275474 - [ThinLTO/gold] Perform index-based weak/linkonce resolution

Teresa Johnson via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 14 14:13:24 PDT 2016


Author: tejohnson
Date: Thu Jul 14 16:13:24 2016
New Revision: 275474

URL: http://llvm.org/viewvc/llvm-project?rev=275474&view=rev
Log:
[ThinLTO/gold] Perform index-based weak/linkonce resolution

Summary:
Invoke the weak/linkonce symbol resolution support (already used by
libLTO) that operates via the summary index.

This ensures prevailing linkonce are kept, by making them weak, and
marks preempted copies as available_externally when possible.

With this change, the older support for keeping the prevailing linkonce
(by changing their symbol resolution) is removed.

Reviewers: mehdi_amini

Subscribers: llvm-commits, mehdi_amini

Differential Revision: http://reviews.llvm.org/D22302

Added:
    llvm/trunk/test/tools/gold/X86/Inputs/thinlto_weak_resolution.ll
    llvm/trunk/test/tools/gold/X86/thinlto_weak_resolution.ll
Modified:
    llvm/trunk/tools/gold/gold-plugin.cpp

Added: llvm/trunk/test/tools/gold/X86/Inputs/thinlto_weak_resolution.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/Inputs/thinlto_weak_resolution.ll?rev=275474&view=auto
==============================================================================
--- llvm/trunk/test/tools/gold/X86/Inputs/thinlto_weak_resolution.ll (added)
+++ llvm/trunk/test/tools/gold/X86/Inputs/thinlto_weak_resolution.ll Thu Jul 14 16:13:24 2016
@@ -0,0 +1,37 @@
+target triple = "x86_64-unknown-linux-gnu"
+
+; Alias are not optimized
+ at linkonceodralias = linkonce_odr alias void (), void ()* @linkonceodrfuncwithalias
+
+; Alias are not optimized
+ at linkoncealias = linkonce alias void (), void ()* @linkoncefuncwithalias
+
+; Function with an alias are not optimized
+define linkonce_odr void @linkonceodrfuncwithalias() #0 {
+entry:
+  ret void
+}
+
+; Function with an alias are not optimized
+define linkonce void @linkoncefuncwithalias() #0 {
+entry:
+  ret void
+}
+
+define linkonce_odr void @linkonceodrfunc() #0 {
+entry:
+  ret void
+}
+define linkonce void @linkoncefunc() #0 {
+entry:
+  ret void
+}
+define weak_odr void @weakodrfunc() #0 {
+entry:
+  ret void
+}
+define weak void @weakfunc() #0 {
+entry:
+  ret void
+}
+

Added: llvm/trunk/test/tools/gold/X86/thinlto_weak_resolution.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/gold/X86/thinlto_weak_resolution.ll?rev=275474&view=auto
==============================================================================
--- llvm/trunk/test/tools/gold/X86/thinlto_weak_resolution.ll (added)
+++ llvm/trunk/test/tools/gold/X86/thinlto_weak_resolution.ll Thu Jul 14 16:13:24 2016
@@ -0,0 +1,87 @@
+; RUN: opt -module-summary %s -o %t.o
+; RUN: opt -module-summary %p/Inputs/thinlto_weak_resolution.ll -o %t2.o
+
+; Verify that prevailing weak for linker symbol is kept.
+; Note that gold picks the first copy of a function as the prevailing one,
+; so listing %t.o first is sufficient to ensure that its copies are prevailing.
+; RUN: %gold -m elf_x86_64 -plugin %llvmshlibdir/LLVMgold.so \
+; RUN:     --plugin-opt=thinlto \
+; RUN:     --plugin-opt=save-temps \
+; RUN:     -shared \
+; RUN:     -o %t3.o %t.o %t2.o
+
+; RUN: llvm-nm %t3.o | FileCheck %s
+; CHECK: weakfunc
+
+; All of the preempted functions should have been eliminated (the plugin will
+; not link them in).
+; RUN: llvm-dis %t2.o.opt.bc -o - | FileCheck --check-prefix=OPT2 %s
+; OPT2-NOT: @
+
+; RUN: llvm-dis %t.o.opt.bc -o - | FileCheck --check-prefix=OPT %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+
+define i32 @main() #0 {
+entry:
+  call void @linkonceodralias()
+  call void @linkoncealias()
+  call void @linkonceodrfuncwithalias()
+  call void @linkoncefuncwithalias()
+  call void @linkonceodrfunc()
+  call void @linkoncefunc()
+  call void @weakodrfunc()
+  call void @weakfunc()
+  call void @linkonceodrfuncInSingleModule()
+  ret i32 0
+}
+
+; Alias are resolved
+; OPT: @linkonceodralias = weak_odr alias void (), void ()* @linkonceodrfuncwithalias
+ at linkonceodralias = linkonce_odr alias void (), void ()* @linkonceodrfuncwithalias
+
+; Alias are resolved
+; OPT: @linkoncealias = weak alias void (), void ()* @linkoncefuncwithalias
+ at linkoncealias = linkonce alias void (), void ()* @linkoncefuncwithalias
+
+; Function with an alias are not optimized
+; OPT: define linkonce_odr void @linkonceodrfuncwithalias()
+define linkonce_odr void @linkonceodrfuncwithalias() #0 {
+entry:
+  ret void
+}
+
+; Function with an alias are not optimized
+; OPT: define linkonce void @linkoncefuncwithalias()
+define linkonce void @linkoncefuncwithalias() #0 {
+entry:
+  ret void
+}
+
+; OPT: define weak_odr void @linkonceodrfunc()
+define linkonce_odr void @linkonceodrfunc() #0 {
+entry:
+  ret void
+}
+; OPT: define weak void @linkoncefunc()
+define linkonce void @linkoncefunc() #0 {
+entry:
+  ret void
+}
+; OPT: define weak_odr void @weakodrfunc()
+define weak_odr void @weakodrfunc() #0 {
+entry:
+  ret void
+}
+; OPT: define weak void @weakfunc()
+define weak void @weakfunc() #0 {
+entry:
+  ret void
+}
+
+; OPT: weak_odr void @linkonceodrfuncInSingleModule()
+define linkonce_odr void @linkonceodrfuncInSingleModule() #0 {
+entry:
+  ret void
+}

Modified: llvm/trunk/tools/gold/gold-plugin.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=275474&r1=275473&r2=275474&view=diff
==============================================================================
--- llvm/trunk/tools/gold/gold-plugin.cpp (original)
+++ llvm/trunk/tools/gold/gold-plugin.cpp Thu Jul 14 16:13:24 2016
@@ -735,16 +735,6 @@ getModuleForFile(LLVMContext &Context, c
     if (Resolution == LDPR_PREVAILING_DEF_IRONLY_EXP && !Res.IsLinkonceOdr)
       Resolution = LDPR_PREVAILING_DEF;
 
-    // In ThinLTO mode change all prevailing resolutions to LDPR_PREVAILING_DEF.
-    // For ThinLTO the IR files are compiled through the backend independently,
-    // so we need to ensure that any prevailing linkonce copy will be emitted
-    // into the object file by making it weak. Additionally, we can skip the
-    // IRONLY handling for internalization, which isn't performed in ThinLTO
-    // mode currently anyway.
-    if (options::thinlto && (Resolution == LDPR_PREVAILING_DEF_IRONLY_EXP ||
-                             Resolution == LDPR_PREVAILING_DEF_IRONLY))
-      Resolution = LDPR_PREVAILING_DEF;
-
     GV->setUnnamedAddr(Res.UnnamedAddr);
     GV->setVisibility(Res.Visibility);
 
@@ -998,6 +988,9 @@ void CodeGen::runLTOPasses() {
   M->setDataLayout(TM->createDataLayout());
 
   if (CombinedIndex) {
+    // Apply summary-based LinkOnce/Weak resolution decisions.
+    thinLTOResolveWeakForLinkerModule(*M, *DefinedGlobals);
+
     // Apply summary-based internalization decisions. Skip if there are no
     // defined globals from the summary since not only is it unnecessary, but
     // if this module did not have a summary section the internalizer will
@@ -1322,6 +1315,10 @@ static ld_plugin_status thinLTOLink(raw_
   // are referenced outside of a single IR module.
   DenseSet<GlobalValue::GUID> Preserve;
 
+  // Keep track of the prevailing copy for each GUID, for use in resolving
+  // weak linkages.
+  DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
+
   ModuleSummaryIndex CombinedIndex;
   uint64_t NextModuleId = 0;
   for (claimed_file &F : Modules) {
@@ -1342,19 +1339,27 @@ static ld_plugin_status thinLTOLink(raw_
 
     std::unique_ptr<ModuleSummaryIndex> Index = getModuleSummaryIndexForFile(F);
 
-    // Skip files without a module summary.
-    if (Index)
-      CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId);
-
     // Use gold's symbol resolution information to identify symbols referenced
-    // by more than a single IR module (before importing, which is checked
-    // separately).
+    // by more than a single IR module (i.e. referenced by multiple IR modules
+    // or by a non-IR module). Cross references introduced by importing are
+    // checked separately via the export lists. Also track the prevailing copy
+    // for later symbol resolution.
     for (auto &Sym : F.syms) {
       ld_plugin_symbol_resolution Resolution =
           (ld_plugin_symbol_resolution)Sym.resolution;
+      GlobalValue::GUID SymGUID = GlobalValue::getGUID(Sym.name);
       if (Resolution != LDPR_PREVAILING_DEF_IRONLY)
-        Preserve.insert(GlobalValue::getGUID(Sym.name));
+        Preserve.insert(SymGUID);
+
+      if (Index && (Resolution == LDPR_PREVAILING_DEF ||
+                    Resolution == LDPR_PREVAILING_DEF_IRONLY ||
+                    Resolution == LDPR_PREVAILING_DEF_IRONLY_EXP))
+        PrevailingCopy[SymGUID] = Index->getGlobalValueSummary(SymGUID);
     }
+
+    // Skip files without a module summary.
+    if (Index)
+      CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId);
   }
 
   // Collect for each module the list of function it defines (GUID ->
@@ -1368,6 +1373,12 @@ static ld_plugin_status thinLTOLink(raw_
   ComputeCrossModuleImport(CombinedIndex, ModuleToDefinedGVSummaries,
                            ImportLists, ExportLists);
 
+  auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
+    const auto &Prevailing = PrevailingCopy.find(GUID);
+    assert(Prevailing != PrevailingCopy.end());
+    return Prevailing->second == S;
+  };
+
   // Callback for internalization, to prevent internalization of symbols
   // that were not candidates initially, and those that are being imported
   // (which introduces new cross references).
@@ -1378,6 +1389,11 @@ static ld_plugin_status thinLTOLink(raw_
            Preserve.count(GUID);
   };
 
+  thinLTOResolveWeakForLinkerInIndex(
+      CombinedIndex, isPrevailing,
+      [](StringRef ModuleIdentifier, GlobalValue::GUID GUID,
+         GlobalValue::LinkageTypes NewLinkage) {});
+
   // Use global summary-based analysis to identify symbols that can be
   // internalized (because they aren't exported or preserved as per callback).
   // Changes are made in the index, consumed in the ThinLTO backends.




More information about the llvm-commits mailing list