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
This commit is contained in:
Chandler Carruth 2012-04-08 17:51:45 +00:00
parent 34797136cb
commit 253933ee9e
4 changed files with 80 additions and 3 deletions

View File

@ -42,8 +42,8 @@ namespace llvm {
GuaranteedTailCallOpt(false), DisableTailCalls(false), GuaranteedTailCallOpt(false), DisableTailCalls(false),
StackAlignmentOverride(0), RealignStack(true), StackAlignmentOverride(0), RealignStack(true),
DisableJumpTables(false), EnableFastISel(false), DisableJumpTables(false), EnableFastISel(false),
EnableSegmentedStacks(false), TrapFuncName(""), PositionIndependentExecutable(false), EnableSegmentedStacks(false),
FloatABIType(FloatABI::Default) TrapFuncName(""), FloatABIType(FloatABI::Default)
{} {}
/// PrintMachineCode - This flag is enabled when the -print-machineinstrs /// PrintMachineCode - This flag is enabled when the -print-machineinstrs
@ -164,6 +164,12 @@ namespace llvm {
/// compile time. /// compile time.
unsigned EnableFastISel : 1; 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; unsigned EnableSegmentedStacks : 1;
/// getTrapFunctionName - If this returns a non-empty string, this means /// getTrapFunctionName - If this returns a non-empty string, this means

View File

@ -82,7 +82,8 @@ TLSModel::Model TargetMachine::getTLSModel(const GlobalValue *GV) const {
// For variables, is internal different from hidden? // For variables, is internal different from hidden?
bool isHidden = GV->hasHiddenVisibility(); bool isHidden = GV->hasHiddenVisibility();
if (getRelocationModel() == Reloc::PIC_) { if (getRelocationModel() == Reloc::PIC_ &&
!Options.PositionIndependentExecutable) {
if (isLocal || isHidden) if (isLocal || isHidden)
return TLSModel::LocalDynamic; return TLSModel::LocalDynamic;
else else

View File

@ -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
}

View File

@ -262,6 +262,11 @@ TrapFuncName("trap-func", cl::Hidden,
cl::desc("Emit a call to trap function rather than a trap instruction"), cl::desc("Emit a call to trap function rather than a trap instruction"),
cl::init("")); cl::init(""));
static cl::opt<bool>
EnablePIE("enable-pie",
cl::desc("Assume the creation of a position independent executable."),
cl::init(false));
static cl::opt<bool> static cl::opt<bool>
SegmentedStacks("segmented-stacks", SegmentedStacks("segmented-stacks",
cl::desc("Use segmented stacks if possible."), cl::desc("Use segmented stacks if possible."),
@ -467,6 +472,7 @@ int main(int argc, char **argv) {
Options.RealignStack = EnableRealignStack; Options.RealignStack = EnableRealignStack;
Options.DisableJumpTables = DisableSwitchTables; Options.DisableJumpTables = DisableSwitchTables;
Options.TrapFuncName = TrapFuncName; Options.TrapFuncName = TrapFuncName;
Options.PositionIndependentExecutable = EnablePIE;
Options.EnableSegmentedStacks = SegmentedStacks; Options.EnableSegmentedStacks = SegmentedStacks;
std::auto_ptr<TargetMachine> std::auto_ptr<TargetMachine>