From fcfb682297a1b3e7341c05c7c7b94b4a9b4331ba Mon Sep 17 00:00:00 2001 From: Sriraman Tallam Date: Thu, 13 Oct 2016 20:54:39 +0000 Subject: [PATCH] New llc option pie-copy-relocations to optimize access to extern globals. This option indicates copy relocations support is available from the linker when building as PIE and allows accesses to extern globals to avoid the GOT. Differential Revision: https://reviews.llvm.org/D24849 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284160 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCTargetOptions.h | 2 + include/llvm/MC/MCTargetOptionsCommandFlags.h | 3 + lib/MC/MCTargetOptions.cpp | 3 +- lib/Target/TargetMachine.cpp | 7 +- .../X86/global-access-pie-copyrelocs.ll | 119 ++++++++++++++++++ 5 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 test/CodeGen/X86/global-access-pie-copyrelocs.ll diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h index fd4c6e4e4fb..21091b378f8 100644 --- a/include/llvm/MC/MCTargetOptions.h +++ b/include/llvm/MC/MCTargetOptions.h @@ -41,6 +41,7 @@ public: bool MCSaveTempLabels : 1; bool MCUseDwarfDirectory : 1; bool MCIncrementalLinkerCompatible : 1; + bool MCPIECopyRelocations : 1; bool ShowMCEncoding : 1; bool ShowMCInst : 1; bool AsmVerbose : 1; @@ -67,6 +68,7 @@ inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) { ARE_EQUAL(MCSaveTempLabels) && ARE_EQUAL(MCUseDwarfDirectory) && ARE_EQUAL(MCIncrementalLinkerCompatible) && + ARE_EQUAL(MCPIECopyRelocations) && ARE_EQUAL(ShowMCEncoding) && ARE_EQUAL(ShowMCInst) && ARE_EQUAL(AsmVerbose) && diff --git a/include/llvm/MC/MCTargetOptionsCommandFlags.h b/include/llvm/MC/MCTargetOptionsCommandFlags.h index 801dd6a2d50..cb020845801 100644 --- a/include/llvm/MC/MCTargetOptionsCommandFlags.h +++ b/include/llvm/MC/MCTargetOptionsCommandFlags.h @@ -38,6 +38,8 @@ cl::opt IncrementalLinkerCompatible( "When used with filetype=obj, " "emit an object file which can be used with an incremental linker")); +cl::opt PIECopyRelocations("pie-copy-relocations", cl::desc("PIE Copy Relocations")); + cl::opt DwarfVersion("dwarf-version", cl::desc("Dwarf version"), cl::init(0)); @@ -62,6 +64,7 @@ static inline MCTargetOptions InitMCTargetOptionsFromFlags() { (AsmInstrumentation == MCTargetOptions::AsmInstrumentationAddress); Options.MCRelaxAll = RelaxAll; Options.MCIncrementalLinkerCompatible = IncrementalLinkerCompatible; + Options.MCPIECopyRelocations = PIECopyRelocations; Options.DwarfVersion = DwarfVersion; Options.ShowMCInst = ShowMCInst; Options.ABIName = ABIName; diff --git a/lib/MC/MCTargetOptions.cpp b/lib/MC/MCTargetOptions.cpp index 1d956a8ffce..e847a17dfec 100644 --- a/lib/MC/MCTargetOptions.cpp +++ b/lib/MC/MCTargetOptions.cpp @@ -16,7 +16,8 @@ MCTargetOptions::MCTargetOptions() : SanitizeAddress(false), MCRelaxAll(false), MCNoExecStack(false), MCFatalWarnings(false), MCNoWarn(false), MCSaveTempLabels(false), MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false), - ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false), + MCPIECopyRelocations(false), ShowMCEncoding(false), + ShowMCInst(false), AsmVerbose(false), PreserveAsmComments(true), DwarfVersion(0), ABIName() {} StringRef MCTargetOptions::getABIName() const { diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index 43a587ba847..792280af84d 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -115,9 +115,6 @@ static TLSModel::Model getSelectedTLSModel(const GlobalValue *GV) { llvm_unreachable("invalid TLS model"); } -// FIXME: make this a proper option -static bool CanUseCopyRelocWithPIE = false; - bool TargetMachine::shouldAssumeDSOLocal(const Module &M, const GlobalValue *GV) const { Reloc::Model RM = getRelocationModel(); @@ -154,8 +151,10 @@ bool TargetMachine::shouldAssumeDSOLocal(const Module &M, return true; bool IsTLS = GV && GV->isThreadLocal(); + bool IsAccessViaCopyRelocs = + Options.MCOptions.MCPIECopyRelocations && GV && isa(GV); // Check if we can use copy relocations. - if (!IsTLS && (RM == Reloc::Static || CanUseCopyRelocWithPIE)) + if (!IsTLS && (RM == Reloc::Static || IsAccessViaCopyRelocs)) return true; } diff --git a/test/CodeGen/X86/global-access-pie-copyrelocs.ll b/test/CodeGen/X86/global-access-pie-copyrelocs.ll new file mode 100644 index 00000000000..5c4a87c969c --- /dev/null +++ b/test/CodeGen/X86/global-access-pie-copyrelocs.ll @@ -0,0 +1,119 @@ +; RUN: llc < %s -march=x86-64 -mcpu=generic -mtriple=x86_64-linux-gnu -relocation-model=pic -pie-copy-relocations \ +; RUN: | FileCheck -check-prefix=X64 %s +; RUN: llc < %s -emulated-tls -march=x86 -mcpu=generic -mtriple=i386-linux-gnu -relocation-model=pic -pie-copy-relocations \ +; RUN: | FileCheck -check-prefix=X32 %s + +; External Linkage +@a = global i32 0, align 4 + +define i32 @my_access_global_a() #0 { +; X32-LABEL: my_access_global_a: +; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax +; X32-NEXT: movl a@GOTOFF(%eax), %eax +; X64-LABEL: my_access_global_a: +; X64: movl a(%rip), %eax + +entry: + %0 = load i32, i32* @a, align 4 + ret i32 %0 +} + +; WeakAny Linkage +@b = weak global i32 0, align 4 + +define i32 @my_access_global_b() #0 { +; X32-LABEL: my_access_global_b: +; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax +; X32-NEXT: movl b@GOTOFF(%eax), %eax +; X64-LABEL: my_access_global_b: +; X64: movl b(%rip), %eax + +entry: + %0 = load i32, i32* @b, align 4 + ret i32 %0 +} + +; Internal Linkage +@c = internal global i32 0, align 4 + +define i32 @my_access_global_c() #0 { +; X32-LABEL: my_access_global_c: +; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax +; X32-NEXT: movl c@GOTOFF(%eax), %eax +; X64-LABEL: my_access_global_c: +; X64: movl c(%rip), %eax + +entry: + %0 = load i32, i32* @c, align 4 + ret i32 %0 +} + +; External Linkage, only declaration. +@d = external global i32, align 4 + +define i32 @my_access_global_load_d() #0 { +; X32-LABEL: my_access_global_load_d: +; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax +; X32-NEXT: movl d@GOTOFF(%eax), %eax +; X64-LABEL: my_access_global_load_d: +; X64: movl d(%rip), %eax + +entry: + %0 = load i32, i32* @d, align 4 + ret i32 %0 +} + +; External Linkage, only declaration, store a value. + +define i32 @my_access_global_store_d() #0 { +; X32-LABEL: my_access_global_store_d: +; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %eax +; X32-NEXT: movl $2, d@GOTOFF(%eax) +; X64-LABEL: my_access_global_store_d: +; X64: movl $2, d(%rip) + +entry: + store i32 2, i32* @d, align 4 + ret i32 0 +} + +; External Linkage, function pointer access. +declare i32 @access_fp(i32 ()*) +declare i32 @foo() + +define i32 @my_access_fp_foo() #0 { +; X32-LABEL: my_access_fp_foo: +; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %ebx +; X32-NEXT: movl foo@GOT(%ebx), %eax +; X64-LABEL: my_access_fp_foo: +; X64: movq foo@GOTPCREL(%rip), %rdi + +entry: + %call = call i32 @access_fp(i32 ()* @foo) + ret i32 %call +} + +; LinkOnceODR Linkage, function pointer access. + +$bar = comdat any + +define linkonce_odr i32 @bar() comdat { +entry: + ret i32 0 +} + +define i32 @my_access_fp_bar() #0 { +; X32-LABEL: my_access_fp_bar: +; X32: addl $_GLOBAL_OFFSET_TABLE_{{.*}}, %ebx +; X32-NEXT: leal bar@GOTOFF(%ebx), %eax +; X64-LABEL: my_access_fp_bar: +; X64: leaq bar(%rip), %rdi + +entry: + %call = call i32 @access_fp(i32 ()* @bar) + ret i32 %call +} + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"PIC Level", i32 1} +!1 = !{i32 1, !"PIE Level", i32 1} -- 2.50.0