]> granicus.if.org Git - llvm/commitdiff
New llc option pie-copy-relocations to optimize access to extern globals.
authorSriraman Tallam <tmsriram@google.com>
Thu, 13 Oct 2016 20:54:39 +0000 (20:54 +0000)
committerSriraman Tallam <tmsriram@google.com>
Thu, 13 Oct 2016 20:54:39 +0000 (20:54 +0000)
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
include/llvm/MC/MCTargetOptionsCommandFlags.h
lib/MC/MCTargetOptions.cpp
lib/Target/TargetMachine.cpp
test/CodeGen/X86/global-access-pie-copyrelocs.ll [new file with mode: 0644]

index fd4c6e4e4fbf0bab5671323937d0a7bf72a12ef9..21091b378f8ff5e44446da9e9278279d3c469743 100644 (file)
@@ -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) &&
index 801dd6a2d502dd5b5d5de6dea45228e92c4cd410..cb020845801a4cd81228fc6b1ca0651811ade37f 100644 (file)
@@ -38,6 +38,8 @@ cl::opt<bool> IncrementalLinkerCompatible(
         "When used with filetype=obj, "
         "emit an object file which can be used with an incremental linker"));
 
+cl::opt<bool> PIECopyRelocations("pie-copy-relocations", cl::desc("PIE Copy Relocations"));
+
 cl::opt<int> 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;
index 1d956a8ffceb2b4b0e5362857bd303f9f741a2e4..e847a17dfec5dbc73c7a07dd745b985eb4519a88 100644 (file)
@@ -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 {
index 43a587ba847bf6c2fe7200e78bd1094881f44898..792280af84dd2e7f4a20e0ccd6d1e3ababab1290 100644 (file)
@@ -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<GlobalVariable>(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 (file)
index 0000000..5c4a87c
--- /dev/null
@@ -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}