diff options
| -rw-r--r-- | llvm/include/llvm/LTO/LTOCodeGenerator.h | 21 | ||||
| -rw-r--r-- | llvm/lib/LTO/LTOCodeGenerator.cpp | 42 | ||||
| -rw-r--r-- | llvm/test/LTO/X86/restore-externals.ll | 24 |
3 files changed, 85 insertions, 2 deletions
diff --git a/llvm/include/llvm/LTO/LTOCodeGenerator.h b/llvm/include/llvm/LTO/LTOCodeGenerator.h index 3820b211a38..b40aa5cb87d 100644 --- a/llvm/include/llvm/LTO/LTOCodeGenerator.h +++ b/llvm/include/llvm/LTO/LTOCodeGenerator.h @@ -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; }; } diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp index 66df23bab1b..70626682d55 100644 --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -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::applyScopeRestrictions() { 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(ArrayRef<raw_pwrite_stream *> Out) { 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(ArrayRef<raw_pwrite_stream *> Out) { // MergedModule. MergedModule = splitCodeGen(std::move(MergedModule), Out, MCpu, FeatureStr, Options, - RelocModel, CodeModel::Default, CGOptLevel, FileType); + RelocModel, CodeModel::Default, CGOptLevel, FileType, + ShouldRestoreGlobalsLinkage); return true; } diff --git a/llvm/test/LTO/X86/restore-externals.ll b/llvm/test/LTO/X86/restore-externals.ll new file mode 100644 index 00000000000..05b6d65b47e --- /dev/null +++ b/llvm/test/LTO/X86/restore-externals.ll @@ -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 +} + |

