mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-30 23:21:04 +00:00
[X86] Support for the mno-tls-direct-seg-refs flag
Allows to disable direct TLS segment access (%fs or %gs). GCC supports a similar flag, it can be useful in some circumstances, e.g. when a thread context block needs to be updated directly from user space. More info and specific use cases: https://bugs.llvm.org/show_bug.cgi?id=16145 There is another revision for clang as well. Related: D53102 All X86 CodeGen tests appear to pass: ``` [46/47] Running lit suite /SourceCache/llvm-trunk-8.0/test/CodeGen Testing Time: 23.17s Expected Passes : 3801 Expected Failures : 15 Unsupported Tests : 8021 ``` Reviewed by: Craig Topper. Patch by nruslan (Ruslan Nikolaev). Differential Revision: https://reviews.llvm.org/D53103 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@344723 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d2a4fba6e8
commit
e97176ffba
@ -1450,6 +1450,10 @@ example:
|
||||
``noredzone``
|
||||
This attribute indicates that the code generator should not use a
|
||||
red zone, even if the target-specific ABI normally permits it.
|
||||
``indirect-tls-seg-refs``
|
||||
This attribute indicates that the code generator should not use
|
||||
direct TLS access through segment registers, even if the
|
||||
target-specific ABI normally permits it.
|
||||
``noreturn``
|
||||
This function attribute indicates that the function never returns
|
||||
normally. This produces undefined behavior at runtime if the
|
||||
|
@ -165,6 +165,9 @@ namespace {
|
||||
/// If true, selector should try to optimize for minimum code size.
|
||||
bool OptForMinSize;
|
||||
|
||||
/// Disable direct TLS access through segment registers.
|
||||
bool IndirectTlsSegRefs;
|
||||
|
||||
public:
|
||||
explicit X86DAGToDAGISel(X86TargetMachine &tm, CodeGenOpt::Level OptLevel)
|
||||
: SelectionDAGISel(tm, OptLevel), OptForSize(false),
|
||||
@ -177,6 +180,8 @@ namespace {
|
||||
bool runOnMachineFunction(MachineFunction &MF) override {
|
||||
// Reset the subtarget each time through.
|
||||
Subtarget = &MF.getSubtarget<X86Subtarget>();
|
||||
IndirectTlsSegRefs = MF.getFunction().hasFnAttribute(
|
||||
"indirect-tls-seg-refs");
|
||||
SelectionDAGISel::runOnMachineFunction(MF);
|
||||
return true;
|
||||
}
|
||||
@ -981,6 +986,7 @@ bool X86DAGToDAGISel::matchLoadInAddress(LoadSDNode *N, X86ISelAddressMode &AM){
|
||||
// For more information see http://people.redhat.com/drepper/tls.pdf
|
||||
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Address))
|
||||
if (C->getSExtValue() == 0 && AM.Segment.getNode() == nullptr &&
|
||||
!IndirectTlsSegRefs &&
|
||||
(Subtarget->isTargetGlibc() || Subtarget->isTargetAndroid() ||
|
||||
Subtarget->isTargetFuchsia()))
|
||||
switch (N->getPointerInfo().getAddrSpace()) {
|
||||
|
@ -1,5 +1,7 @@
|
||||
; RUN: llc < %s -mtriple=i386-linux-gnu | FileCheck -check-prefix=X86_LINUX %s
|
||||
; RUN: llc < %s -mtriple=x86_64-linux-gnu | FileCheck -check-prefix=X64_LINUX %s
|
||||
; RUN: llc < %s -mtriple=i386-linux-gnu -fast-isel | FileCheck -check-prefix=X86_ISEL_LINUX %s
|
||||
; RUN: llc < %s -mtriple=x86_64-linux-gnu -fast-isel | FileCheck -check-prefix=X64_ISEL_LINUX %s
|
||||
; RUN: llc < %s -mtriple=i686-pc-win32 | FileCheck -check-prefix=X86_WIN %s
|
||||
; RUN: llc < %s -mtriple=x86_64-pc-win32 | FileCheck -check-prefix=X64_WIN %s
|
||||
; RUN: llc < %s -mtriple=i686-pc-windows-gnu | FileCheck -check-prefix=MINGW32 %s
|
||||
@ -453,3 +455,59 @@ define i32* @f16() {
|
||||
|
||||
ret i32* @i6
|
||||
}
|
||||
|
||||
; NOTE: Similar to f1() but with direct TLS segment access disabled
|
||||
define i32 @f17() #0 {
|
||||
; X86_LINUX-LABEL: f17:
|
||||
; X86_LINUX: movl %gs:0, %eax
|
||||
; X86_LINUX-NEXT: movl i1@NTPOFF(%eax), %eax
|
||||
; X86_LINUX-NEXT: ret
|
||||
; X64_LINUX-LABEL: f17:
|
||||
; X64_LINUX: movq %fs:0, %rax
|
||||
; X64_LINUX-NEXT: movl i1@TPOFF(%rax), %eax
|
||||
; X64_LINUX-NEXT: ret
|
||||
; X86_ISEL_LINUX-LABEL: f17:
|
||||
; X86_ISEL_LINUX: movl %gs:0, %eax
|
||||
; X86_ISEL_LINUX-NEXT: movl i1@NTPOFF(%eax), %eax
|
||||
; X86_ISEL_LINUX-NEXT: ret
|
||||
; X64_ISEL_LINUX-LABEL: f17:
|
||||
; X64_ISEL_LINUX: movq %fs:0, %rax
|
||||
; X64_ISEL_LINUX-NEXT: movl i1@TPOFF(%rax), %eax
|
||||
; X64_ISEL_LINUX-NEXT: ret
|
||||
|
||||
entry:
|
||||
%tmp1 = load i32, i32* @i1
|
||||
ret i32 %tmp1
|
||||
}
|
||||
|
||||
; NOTE: Similar to f3() but with direct TLS segment access disabled
|
||||
define i32 @f18() #1 {
|
||||
; X86_LINUX-LABEL: f18:
|
||||
; X86_LINUX: movl i2@INDNTPOFF, %eax
|
||||
; X86_LINUX-NEXT: movl %gs:0, %ecx
|
||||
; X86_LINUX-NEXT: movl (%ecx,%eax), %eax
|
||||
; X86_LINUX-NEXT: ret
|
||||
; X64_LINUX-LABEL: f18:
|
||||
; X64_LINUX: movq i2@GOTTPOFF(%rip), %rax
|
||||
; X64_LINUX-NEXT: movq %fs:0, %rcx
|
||||
; X64_LINUX-NEXT: movl (%rcx,%rax), %eax
|
||||
; X64_LINUX-NEXT: ret
|
||||
; X86_ISEL_LINUX-LABEL: f18:
|
||||
; X86_ISEL_LINUX: movl i2@INDNTPOFF, %eax
|
||||
; X86_ISEL_LINUX-NEXT: movl %gs:0, %ecx
|
||||
; X86_ISEL_LINUX-NEXT: movl (%ecx,%eax), %eax
|
||||
; X86_ISEL_LINUX-NEXT: ret
|
||||
; X64_ISEL_LINUX-LABEL: f18:
|
||||
; X64_ISEL_LINUX: movq i2@GOTTPOFF(%rip), %rax
|
||||
; X64_ISEL_LINUX-NEXT: movq %fs:0, %rcx
|
||||
; X64_ISEL_LINUX-NEXT: movl (%rcx,%rax), %eax
|
||||
; X64_ISEL_LINUX-NEXT: ret
|
||||
|
||||
|
||||
entry:
|
||||
%tmp1 = load i32, i32* @i2
|
||||
ret i32 %tmp1
|
||||
}
|
||||
|
||||
attributes #0 = { "indirect-tls-seg-refs" }
|
||||
attributes #1 = { nounwind "indirect-tls-seg-refs" }
|
||||
|
Loading…
Reference in New Issue
Block a user