[llvm] r258100 - [LTO] Restore original linkage of externals prior to splitting

Tobias Edler von Koch via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 18 15:24:55 PST 2016


Author: tobiasvk
Date: Mon Jan 18 17:24:54 2016
New Revision: 258100

URL: http://llvm.org/viewvc/llvm-project?rev=258100&view=rev
Log:
[LTO] Restore original linkage of externals prior to splitting

Summary:
This is a companion patch for http://reviews.llvm.org/D16124.

Internalized symbols increase the size of strongly-connected components in
SCC-based module splitting and thus reduce the amount of parallelism. This
patch records the original linkage of non-local symbols prior to
internalization and then restores it just before splitting/CodeGen. This is
also useful for cases where the linker requires symbols to remain external, for
instance, so they can be placed according to linker script rules.

It's currently under its own flag (-restore-globals) but should eventually
share a common flag with D16124.

Reviewers: joker.eph, pcc

Subscribers: slarin, llvm-commits, joker.eph

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

Added:
    llvm/trunk/test/LTO/X86/restore-externals.ll
Modified:
    llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h
    llvm/trunk/lib/LTO/LTOCodeGenerator.cpp

Modified: llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h?rev=258100&r1=258099&r2=258100&view=diff
==============================================================================
--- llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h (original)
+++ llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h Mon Jan 18 17:24:54 2016
@@ -39,6 +39,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/StringMap.h"
+#include "llvm/IR/GlobalValue.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
 #include <string>
@@ -47,7 +48,6 @@
 namespace llvm {
   class LLVMContext;
   class DiagnosticInfo;
-  class GlobalValue;
   class Linker;
   class Mangler;
   class MemoryBuffer;
@@ -86,6 +86,22 @@ struct LTOCodeGenerator {
   void setShouldInternalize(bool Value) { ShouldInternalize = Value; }
   void setShouldEmbedUselists(bool Value) { ShouldEmbedUselists = Value; }
 
+  /// Restore linkage of globals
+  ///
+  /// When set, the linkage of globals will be restored prior to code
+  /// generation. That is, a global symbol that had external linkage prior to
+  /// LTO will be emitted with external linkage again; and a local will remain
+  /// local. Note that this option only affects the end result - globals may
+  /// still be internalized in the process of LTO and may be modified and/or
+  /// deleted where legal.
+  ///
+  /// The default behavior will internalize globals (unless on the preserve
+  /// list) and, if parallel code generation is enabled, will externalize
+  /// all locals.
+  void setShouldRestoreGlobalsLinkage(bool Value) {
+    ShouldRestoreGlobalsLinkage = Value;
+  }
+
   void addMustPreserveSymbol(StringRef Sym) { MustPreserveSymbols[Sym] = 1; }
 
   /// Pass options to the driver and optimization passes.
@@ -154,6 +170,7 @@ private:
   void initializeLTOPasses();
 
   bool compileOptimizedToFile(const char **Name);
+  void restoreLinkageForExternals();
   void applyScopeRestrictions();
   void applyRestriction(GlobalValue &GV, ArrayRef<StringRef> Libcalls,
                         std::vector<const char *> &MustPreserveList,
@@ -178,6 +195,7 @@ private:
   Reloc::Model RelocModel = Reloc::Default;
   StringSet MustPreserveSymbols;
   StringSet AsmUndefinedRefs;
+  StringMap<GlobalValue::LinkageTypes> ExternalSymbols;
   std::vector<std::string> CodegenOptions;
   std::string FeatureStr;
   std::string MCpu;
@@ -190,6 +208,7 @@ private:
   void *DiagContext = nullptr;
   bool ShouldInternalize = true;
   bool ShouldEmbedUselists = false;
+  bool ShouldRestoreGlobalsLinkage = false;
   TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_ObjectFile;
 };
 }

Modified: llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOCodeGenerator.cpp?rev=258100&r1=258099&r2=258100&view=diff
==============================================================================
--- llvm/trunk/lib/LTO/LTOCodeGenerator.cpp (original)
+++ llvm/trunk/lib/LTO/LTOCodeGenerator.cpp Mon Jan 18 17:24:54 2016
@@ -347,6 +347,12 @@ applyRestriction(GlobalValue &GV,
   if (isa<Function>(GV) &&
       std::binary_search(Libcalls.begin(), Libcalls.end(), GV.getName()))
     AsmUsed.insert(&GV);
+
+  // Record the linkage type of non-local symbols so they can be restored prior
+  // to module splitting.
+  if (ShouldRestoreGlobalsLinkage && !GV.hasAvailableExternallyLinkage() &&
+      !GV.hasLocalLinkage() && GV.hasName())
+    ExternalSymbols.insert(std::make_pair(GV.getName(), GV.getLinkage()));
 }
 
 static void findUsedValues(GlobalVariable *LLVMUsed,
@@ -454,6 +460,35 @@ void LTOCodeGenerator::applyScopeRestric
   ScopeRestrictionsDone = true;
 }
 
+/// Restore original linkage for symbols that may have been internalized
+void LTOCodeGenerator::restoreLinkageForExternals() {
+  if (!ShouldInternalize || !ShouldRestoreGlobalsLinkage)
+    return;
+
+  assert(ScopeRestrictionsDone &&
+         "Cannot externalize without internalization!");
+
+  if (ExternalSymbols.empty())
+    return;
+
+  auto externalize = [this](GlobalValue &GV) {
+    if (!GV.hasLocalLinkage() || !GV.hasName())
+      return;
+
+    auto I = ExternalSymbols.find(GV.getName());
+    if (I == ExternalSymbols.end())
+      return;
+
+    GV.setLinkage(I->second);
+  };
+
+  std::for_each(MergedModule->begin(), MergedModule->end(), externalize);
+  std::for_each(MergedModule->global_begin(), MergedModule->global_end(),
+                externalize);
+  std::for_each(MergedModule->alias_begin(), MergedModule->alias_end(),
+                externalize);
+}
+
 /// Optimize merged modules using various IPO passes
 bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline,
                                 bool DisableGVNLoadPRE,
@@ -504,6 +539,10 @@ bool LTOCodeGenerator::compileOptimized(
   preCodeGenPasses.add(createObjCARCContractPass());
   preCodeGenPasses.run(*MergedModule);
 
+  // Re-externalize globals that may have been internalized to increase scope
+  // for splitting
+  restoreLinkageForExternals();
+
   // Do code generation. We need to preserve the module in case the client calls
   // writeMergedModules() after compilation, but we only need to allow this at
   // parallelism level 1. This is achieved by having splitCodeGen return the
@@ -511,7 +550,8 @@ bool LTOCodeGenerator::compileOptimized(
   // MergedModule.
   MergedModule =
       splitCodeGen(std::move(MergedModule), Out, MCpu, FeatureStr, Options,
-                   RelocModel, CodeModel::Default, CGOptLevel, FileType);
+                   RelocModel, CodeModel::Default, CGOptLevel, FileType,
+                   ShouldRestoreGlobalsLinkage);
 
   return true;
 }

Added: llvm/trunk/test/LTO/X86/restore-externals.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/X86/restore-externals.ll?rev=258100&view=auto
==============================================================================
--- llvm/trunk/test/LTO/X86/restore-externals.ll (added)
+++ llvm/trunk/test/LTO/X86/restore-externals.ll Mon Jan 18 17:24:54 2016
@@ -0,0 +1,24 @@
+; Check that "internalizedfn" is re-externalized prior to CodeGen when
+; setShouldRestoreGlobalsLinkage is enabled.
+;
+; RUN: llvm-as < %s > %t1
+; RUN: llvm-lto -exported-symbol=preservedfn -restore-linkage -filetype=asm -o - %t1 | FileCheck %s
+;
+; CHECK: .globl internalizedfn
+
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @f()
+
+define void @internalizedfn() noinline {
+entry:
+  call void @f()
+  ret void
+}
+
+define void @preservedfn() {
+entry:
+  call void @internalizedfn()
+  ret void
+}
+




More information about the llvm-commits mailing list