mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:50:30 +00:00
[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 llvm-svn: 258100
This commit is contained in:
parent
82a3dcbbfd
commit
c19c96e06f
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
24
test/LTO/X86/restore-externals.ll
Normal file
24
test/LTO/X86/restore-externals.ll
Normal file
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user