From 253933ee9ef2c413ecd782efeacc5d7b9bcda09a Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sun, 8 Apr 2012 17:51:45 +0000 Subject: [PATCH] Teach LLVM about a PIE option which, when enabled on top of PIC, makes optimizations which are valid for position independent code being linked into a single executable, but not for such code being linked into a shared library. I discussed the design of this with Eric Christopher, and the decision was to support an optional bit rather than a completely separate relocation model. Fundamentally, this is still PIC relocation, its just that certain optimizations are only valid under a PIC relocation model when the resulting code won't be in a shared library. The simplest path to here is to expose a single bit option in the TargetOptions. If folks have different/better designs, I'm all ears. =] I've included the first optimization based upon this: changing TLS models to the *Exec models when PIE is enabled. This is the LLVM component of PR12380 and is all of the hard work. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154294 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetOptions.h | 10 ++++- lib/Target/TargetMachine.cpp | 3 +- test/CodeGen/X86/tls-pie.ll | 64 +++++++++++++++++++++++++++++ tools/llc/llc.cpp | 6 +++ 4 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 test/CodeGen/X86/tls-pie.ll diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 7730ab90e8f..1c100592181 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -42,8 +42,8 @@ namespace llvm { GuaranteedTailCallOpt(false), DisableTailCalls(false), StackAlignmentOverride(0), RealignStack(true), DisableJumpTables(false), EnableFastISel(false), - EnableSegmentedStacks(false), TrapFuncName(""), - FloatABIType(FloatABI::Default) + PositionIndependentExecutable(false), EnableSegmentedStacks(false), + TrapFuncName(""), FloatABIType(FloatABI::Default) {} /// PrintMachineCode - This flag is enabled when the -print-machineinstrs @@ -164,6 +164,12 @@ namespace llvm { /// compile time. unsigned EnableFastISel : 1; + /// PositionIndependentExecutable - This flag indicates whether the code + /// will eventually be linked into a single executable, despite the PIC + /// relocation model being in use. It's value is undefined (and irrelevant) + /// if the relocation model is anything other than PIC. + unsigned PositionIndependentExecutable : 1; + unsigned EnableSegmentedStacks : 1; /// getTrapFunctionName - If this returns a non-empty string, this means diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp index b8e7f15d092..b9b2526876f 100644 --- a/lib/Target/TargetMachine.cpp +++ b/lib/Target/TargetMachine.cpp @@ -82,7 +82,8 @@ TLSModel::Model TargetMachine::getTLSModel(const GlobalValue *GV) const { // For variables, is internal different from hidden? bool isHidden = GV->hasHiddenVisibility(); - if (getRelocationModel() == Reloc::PIC_) { + if (getRelocationModel() == Reloc::PIC_ && + !Options.PositionIndependentExecutable) { if (isLocal || isHidden) return TLSModel::LocalDynamic; else diff --git a/test/CodeGen/X86/tls-pie.ll b/test/CodeGen/X86/tls-pie.ll new file mode 100644 index 00000000000..6c739cbabd9 --- /dev/null +++ b/test/CodeGen/X86/tls-pie.ll @@ -0,0 +1,64 @@ +; RUN: llc < %s -march=x86 -mtriple=i386-linux-gnu -relocation-model=pic -enable-pie \ +; RUN: | FileCheck -check-prefix=X32 %s +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-linux-gnu -relocation-model=pic -enable-pie \ +; RUN: | FileCheck -check-prefix=X64 %s + +@i = thread_local global i32 15 +@i2 = external thread_local global i32 + +define i32 @f1() { +; X32: f1: +; X32: movl %gs:i@NTPOFF, %eax +; X32-NEXT: ret +; X64: f1: +; X64: movabsq $i@TPOFF, %rax +; X64-NEXT: movl %fs:(%rax), %eax +; X64-NEXT: ret + +entry: + %tmp1 = load i32* @i + ret i32 %tmp1 +} + +define i32* @f2() { +; X32: f2: +; X32: movl %gs:0, %eax +; X32-NEXT: leal i@NTPOFF(%eax), %eax +; X32-NEXT: ret +; X64: f2: +; X64: movq %fs:0, %rax +; X64-NEXT: addq $i@TPOFF, %rax +; X64-NEXT: ret + +entry: + ret i32* @i +} + +define i32 @f3() { +; X32: f3: +; X32: movl i2@INDNTPOFF, %eax +; X32-NEXT: movl %gs:(%eax), %eax +; X32-NEXT: ret +; X64: f3: +; X64: movq i2@GOTTPOFF(%rip), %rax +; X64-NEXT: movl %fs:(%rax), %eax +; X64-NEXT: ret + +entry: + %tmp1 = load i32* @i2 + ret i32 %tmp1 +} + +define i32* @f4() { +; X32: f4: +; X32: movl %gs:0, %eax +; X32-NEXT: addl i2@INDNTPOFF, %eax +; X32-NEXT: ret +; X64: f4: +; X64: movq %fs:0, %rax +; X64-NEXT: addq i2@GOTTPOFF(%rip), %rax +; X64-NEXT: ret + +entry: + ret i32* @i2 +} diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index 191b649c052..9e30ac198b2 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -262,6 +262,11 @@ TrapFuncName("trap-func", cl::Hidden, cl::desc("Emit a call to trap function rather than a trap instruction"), cl::init("")); +static cl::opt +EnablePIE("enable-pie", + cl::desc("Assume the creation of a position independent executable."), + cl::init(false)); + static cl::opt SegmentedStacks("segmented-stacks", cl::desc("Use segmented stacks if possible."), @@ -467,6 +472,7 @@ int main(int argc, char **argv) { Options.RealignStack = EnableRealignStack; Options.DisableJumpTables = DisableSwitchTables; Options.TrapFuncName = TrapFuncName; + Options.PositionIndependentExecutable = EnablePIE; Options.EnableSegmentedStacks = SegmentedStacks; std::auto_ptr -- 2.34.1