[llvm] f4676b6 - [X86] Add Support for X86 TLSDESC Relocations (#83136)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 15 07:09:59 PDT 2024
Author: Phoebe Wang
Date: 2024-03-15T22:09:56+08:00
New Revision: f4676b6be6ee0d908c92d64936d17bd6fa3fbda8
URL: https://github.com/llvm/llvm-project/commit/f4676b6be6ee0d908c92d64936d17bd6fa3fbda8
DIFF: https://github.com/llvm/llvm-project/commit/f4676b6be6ee0d908c92d64936d17bd6fa3fbda8.diff
LOG: [X86] Add Support for X86 TLSDESC Relocations (#83136)
Added:
llvm/test/CodeGen/X86/tls-desc.ll
Modified:
clang/lib/Driver/ToolChains/CommonArgs.cpp
clang/test/Driver/tls-dialect.c
llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
llvm/lib/Target/X86/X86ISelLowering.cpp
llvm/lib/Target/X86/X86ISelLowering.h
llvm/lib/Target/X86/X86InstrCompiler.td
llvm/lib/Target/X86/X86InstrFragments.td
llvm/lib/Target/X86/X86MCInstLower.cpp
Removed:
################################################################################
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 100e71245394d8..83015b0cb81a6e 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -740,7 +740,8 @@ bool tools::isTLSDESCEnabled(const ToolChain &TC,
SupportedArgument = V == "desc" || V == "trad";
EnableTLSDESC = V == "desc";
} else if (Triple.isX86()) {
- SupportedArgument = V == "gnu";
+ SupportedArgument = V == "gnu" || V == "gnu2";
+ EnableTLSDESC = V == "gnu2";
} else {
Unsupported = true;
}
diff --git a/clang/test/Driver/tls-dialect.c b/clang/test/Driver/tls-dialect.c
index f73915b28ec2a3..a808dd81531ce7 100644
--- a/clang/test/Driver/tls-dialect.c
+++ b/clang/test/Driver/tls-dialect.c
@@ -2,6 +2,7 @@
// RUN: %clang -### --target=riscv64-linux -mtls-dialect=trad %s 2>&1 | FileCheck --check-prefix=NODESC %s
// RUN: %clang -### --target=riscv64-linux %s 2>&1 | FileCheck --check-prefix=NODESC %s
// RUN: %clang -### --target=x86_64-linux -mtls-dialect=gnu %s 2>&1 | FileCheck --check-prefix=NODESC %s
+// RUN: %clang -### --target=x86_64-linux -mtls-dialect=gnu2 %s 2>&1 | FileCheck --check-prefix=DESC %s
/// Android supports TLSDESC by default on RISC-V
/// TLSDESC is not on by default in Linux, even on RISC-V, and is covered above
@@ -18,7 +19,6 @@
/// Unsupported argument
// RUN: not %clang -### --target=riscv64-linux -mtls-dialect=gnu2 %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED-ARG %s
-// RUN: not %clang -### --target=x86_64-linux -mtls-dialect=gnu2 %s 2>&1 | FileCheck --check-prefix=UNSUPPORTED-ARG %s
// DESC: "-cc1" {{.*}}"-enable-tlsdesc"
// NODESC-NOT: "-enable-tlsdesc"
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 76c6c1645239ab..4e4241efd63d6b 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -3090,13 +3090,19 @@ bool X86DAGToDAGISel::selectLEAAddr(SDValue N,
bool X86DAGToDAGISel::selectTLSADDRAddr(SDValue N, SDValue &Base,
SDValue &Scale, SDValue &Index,
SDValue &Disp, SDValue &Segment) {
- assert(N.getOpcode() == ISD::TargetGlobalTLSAddress);
- auto *GA = cast<GlobalAddressSDNode>(N);
+ assert(N.getOpcode() == ISD::TargetGlobalTLSAddress ||
+ N.getOpcode() == ISD::TargetExternalSymbol);
X86ISelAddressMode AM;
- AM.GV = GA->getGlobal();
- AM.Disp += GA->getOffset();
- AM.SymbolFlags = GA->getTargetFlags();
+ if (auto *GA = dyn_cast<GlobalAddressSDNode>(N)) {
+ AM.GV = GA->getGlobal();
+ AM.Disp += GA->getOffset();
+ AM.SymbolFlags = GA->getTargetFlags();
+ } else {
+ auto *SA = cast<ExternalSymbolSDNode>(N);
+ AM.ES = SA->getSymbol();
+ AM.SymbolFlags = SA->getTargetFlags();
+ }
if (Subtarget->is32Bit()) {
AM.Scale = 1;
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 2b5e3c0379a138..dbfcb3752ae845 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -18592,13 +18592,22 @@ GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA,
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
SDLoc dl(GA);
- SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
- GA->getValueType(0),
- GA->getOffset(),
- OperandFlags);
+ SDValue TGA;
+ bool UseTLSDESC = DAG.getTarget().useTLSDESC();
+ if (LocalDynamic && UseTLSDESC) {
+ TGA = DAG.getTargetExternalSymbol("_TLS_MODULE_BASE_", PtrVT, OperandFlags);
+ auto UI = TGA->use_begin();
+ // Reuse existing GetTLSADDR node if we can find it.
+ if (UI != TGA->use_end())
+ return SDValue(*UI->use_begin()->use_begin(), 0);
+ } else {
+ TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl, GA->getValueType(0),
+ GA->getOffset(), OperandFlags);
+ }
- X86ISD::NodeType CallType = LocalDynamic ? X86ISD::TLSBASEADDR
- : X86ISD::TLSADDR;
+ X86ISD::NodeType CallType = UseTLSDESC ? X86ISD::TLSDESC
+ : LocalDynamic ? X86ISD::TLSBASEADDR
+ : X86ISD::TLSADDR;
if (InGlue) {
SDValue Ops[] = { Chain, TGA, *InGlue };
@@ -18613,7 +18622,19 @@ GetTLSADDR(SelectionDAG &DAG, SDValue Chain, GlobalAddressSDNode *GA,
MFI.setHasCalls(true);
SDValue Glue = Chain.getValue(1);
- return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue);
+ SDValue Ret = DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue);
+
+ if (!UseTLSDESC)
+ return Ret;
+
+ const X86Subtarget &Subtarget = DAG.getSubtarget<X86Subtarget>();
+ unsigned Seg = Subtarget.is64Bit() ? X86AS::FS : X86AS::GS;
+
+ Value *Ptr = Constant::getNullValue(PointerType::get(*DAG.getContext(), Seg));
+ SDValue Offset =
+ DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), DAG.getIntPtrConstant(0, dl),
+ MachinePointerInfo(Ptr));
+ return DAG.getNode(ISD::ADD, dl, PtrVT, Ret, Offset);
}
// Lower ISD::GlobalTLSAddress using the "general dynamic" model, 32 bit
@@ -33426,6 +33447,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
NODE_NAME_CASE(TLSADDR)
NODE_NAME_CASE(TLSBASEADDR)
NODE_NAME_CASE(TLSCALL)
+ NODE_NAME_CASE(TLSDESC)
NODE_NAME_CASE(EH_SJLJ_SETJMP)
NODE_NAME_CASE(EH_SJLJ_LONGJMP)
NODE_NAME_CASE(EH_SJLJ_SETUP_DISPATCH)
@@ -36206,6 +36228,8 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
case X86::TLS_base_addr32:
case X86::TLS_base_addr64:
case X86::TLS_base_addrX32:
+ case X86::TLS_desc32:
+ case X86::TLS_desc64:
return EmitLoweredTLSAddr(MI, BB);
case X86::INDIRECT_THUNK_CALL32:
case X86::INDIRECT_THUNK_CALL64:
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index fe1943b5760844..0a1e8ca4427314 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -295,6 +295,10 @@ namespace llvm {
// thunk at the address from an earlier relocation.
TLSCALL,
+ // Thread Local Storage. A descriptor containing pointer to
+ // code and to argument to get the TLS offset for the symbol.
+ TLSDESC,
+
// Exception Handling helpers.
EH_RETURN,
diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td
index f393f86e64aadd..ce3b6af4cab47b 100644
--- a/llvm/lib/Target/X86/X86InstrCompiler.td
+++ b/llvm/lib/Target/X86/X86InstrCompiler.td
@@ -507,6 +507,16 @@ def TLS_base_addrX32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
Requires<[In64BitMode, NotLP64]>;
}
+// TLSDESC only clobbers EAX and EFLAGS. ESP is marked as a use to prevent
+// stack-pointer assignments that appear immediately before calls from
+// potentially appearing dead.
+let Defs = [EAX, EFLAGS], usesCustomInserter = 1, Uses = [RSP, SSP] in {
+ def TLS_desc32 : I<0, Pseudo, (outs), (ins i32mem:$sym),
+ "# TLS_desc32", [(X86tlsdesc tls32addr:$sym)]>;
+ def TLS_desc64 : I<0, Pseudo, (outs), (ins i64mem:$sym),
+ "# TLS_desc64", [(X86tlsdesc tls64addr:$sym)]>;
+}
+
// Darwin TLS Support
// For i386, the address of the thunk is passed on the stack, on return the
// address of the variable is in %eax. %ecx is trashed during the function
diff --git a/llvm/lib/Target/X86/X86InstrFragments.td b/llvm/lib/Target/X86/X86InstrFragments.td
index adf527d72f5b43..f14c7200af968a 100644
--- a/llvm/lib/Target/X86/X86InstrFragments.td
+++ b/llvm/lib/Target/X86/X86InstrFragments.td
@@ -223,6 +223,9 @@ def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR,
def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR,
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
+def X86tlsdesc : SDNode<"X86ISD::TLSDESC", SDT_X86TLSADDR,
+ [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
+
def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET,
[SDNPHasChain]>;
diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp
index 64d4d411e7b43b..e2330ff34c1753 100644
--- a/llvm/lib/Target/X86/X86MCInstLower.cpp
+++ b/llvm/lib/Target/X86/X86MCInstLower.cpp
@@ -519,10 +519,8 @@ void X86MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering,
const MachineInstr &MI) {
NoAutoPaddingScope NoPadScope(*OutStreamer);
- bool Is64Bits = MI.getOpcode() != X86::TLS_addr32 &&
- MI.getOpcode() != X86::TLS_base_addr32;
- bool Is64BitsLP64 = MI.getOpcode() == X86::TLS_addr64 ||
- MI.getOpcode() == X86::TLS_base_addr64;
+ bool Is64Bits = getSubtarget().is64Bit();
+ bool Is64BitsLP64 = getSubtarget().isTarget64BitLP64();
MCContext &Ctx = OutStreamer->getContext();
MCSymbolRefExpr::VariantKind SRVK;
@@ -539,6 +537,10 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering,
case X86::TLS_base_addrX32:
SRVK = MCSymbolRefExpr::VK_TLSLD;
break;
+ case X86::TLS_desc32:
+ case X86::TLS_desc64:
+ SRVK = MCSymbolRefExpr::VK_TLSDESC;
+ break;
default:
llvm_unreachable("unexpected opcode");
}
@@ -554,7 +556,26 @@ void X86AsmPrinter::LowerTlsAddr(X86MCInstLower &MCInstLowering,
bool UseGot = MMI->getModule()->getRtLibUseGOT() &&
Ctx.getTargetOptions()->X86RelaxRelocations;
- if (Is64Bits) {
+ if (SRVK == MCSymbolRefExpr::VK_TLSDESC) {
+ const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(
+ MCInstLowering.GetSymbolFromOperand(MI.getOperand(3)),
+ MCSymbolRefExpr::VK_TLSCALL, Ctx);
+ EmitAndCountInstruction(
+ MCInstBuilder(Is64BitsLP64 ? X86::LEA64r : X86::LEA32r)
+ .addReg(Is64BitsLP64 ? X86::RAX : X86::EAX)
+ .addReg(Is64Bits ? X86::RIP : X86::EBX)
+ .addImm(1)
+ .addReg(0)
+ .addExpr(Sym)
+ .addReg(0));
+ EmitAndCountInstruction(
+ MCInstBuilder(Is64Bits ? X86::CALL64m : X86::CALL32m)
+ .addReg(Is64BitsLP64 ? X86::RAX : X86::EAX)
+ .addImm(1)
+ .addReg(0)
+ .addExpr(Expr)
+ .addReg(0));
+ } else if (Is64Bits) {
bool NeedsPadding = SRVK == MCSymbolRefExpr::VK_TLSGD;
if (NeedsPadding && Is64BitsLP64)
EmitAndCountInstruction(MCInstBuilder(X86::DATA16_PREFIX));
@@ -2164,6 +2185,8 @@ void X86AsmPrinter::emitInstruction(const MachineInstr *MI) {
case X86::TLS_base_addr32:
case X86::TLS_base_addr64:
case X86::TLS_base_addrX32:
+ case X86::TLS_desc32:
+ case X86::TLS_desc64:
return LowerTlsAddr(MCInstLowering, *MI);
case X86::MOVPC32r: {
diff --git a/llvm/test/CodeGen/X86/tls-desc.ll b/llvm/test/CodeGen/X86/tls-desc.ll
new file mode 100644
index 00000000000000..c73986e69e7918
--- /dev/null
+++ b/llvm/test/CodeGen/X86/tls-desc.ll
@@ -0,0 +1,199 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc < %s -mtriple=i686 --relocation-model=pic -enable-tlsdesc | FileCheck %s --check-prefix=X86
+; RUN: llc < %s -mtriple=x86_64-pc-linux-gnux32 --relocation-model=pic -enable-tlsdesc | FileCheck %s --check-prefix=X32
+; RUN: llc < %s -mtriple=x86_64 --relocation-model=pic -enable-tlsdesc | FileCheck %s --check-prefix=X64
+
+ at x = thread_local global i32 0, align 4
+ at y = internal thread_local global i32 1, align 4
+ at z = external hidden thread_local global i32, align 4
+
+define ptr @f1() nounwind {
+; X86-LABEL: f1:
+; X86: # %bb.0:
+; X86-NEXT: pushl %ebp
+; X86-NEXT: pushl %ebx
+; X86-NEXT: pushl %edi
+; X86-NEXT: pushl %esi
+; X86-NEXT: pushl %eax
+; X86-NEXT: calll .L0$pb
+; X86-NEXT: .L0$pb:
+; X86-NEXT: popl %ebx
+; X86-NEXT: .Ltmp0:
+; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp0-.L0$pb), %ebx
+; X86-NEXT: #APP
+; X86-NEXT: #NO_APP
+; X86-NEXT: movl %eax, (%esp) # 4-byte Spill
+; X86-NEXT: leal x at tlsdesc(%ebx), %eax
+; X86-NEXT: calll *x at tlscall(%eax)
+; X86-NEXT: addl %gs:0, %eax
+; X86-NEXT: movl (%esp), %ebx # 4-byte Reload
+; X86-NEXT: #APP
+; X86-NEXT: #NO_APP
+; X86-NEXT: addl $4, %esp
+; X86-NEXT: popl %esi
+; X86-NEXT: popl %edi
+; X86-NEXT: popl %ebx
+; X86-NEXT: popl %ebp
+; X86-NEXT: retl
+;
+; X32-LABEL: f1:
+; X32: # %bb.0:
+; X32-NEXT: pushq %rax
+; X32-NEXT: #APP
+; X32-NEXT: #NO_APP
+; X32-NEXT: leal x at tlsdesc(%rip), %eax
+; X32-NEXT: callq *x at tlscall(%eax)
+; X32-NEXT: # kill: def $eax killed $eax def $rax
+; X32-NEXT: addl %fs:0, %eax
+; X32-NEXT: #APP
+; X32-NEXT: #NO_APP
+; X32-NEXT: popq %rcx
+; X32-NEXT: retq
+;
+; X64-LABEL: f1:
+; X64: # %bb.0:
+; X64-NEXT: pushq %rax
+; X64-NEXT: #APP
+; X64-NEXT: #NO_APP
+; X64-NEXT: leaq x at tlsdesc(%rip), %rax
+; X64-NEXT: callq *x at tlscall(%rax)
+; X64-NEXT: addq %fs:0, %rax
+; X64-NEXT: #APP
+; X64-NEXT: #NO_APP
+; X64-NEXT: popq %rcx
+; X64-NEXT: retq
+ %a = call { i32, i32, i32, i32, i32, i32 } asm sideeffect "", "=r,=r,=r,=r,=r,=r,~{dirflag},~{fpsr},~{flags}"()
+ %b = call ptr @llvm.threadlocal.address.p0(ptr @x)
+ %a.0 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 0
+ %a.1 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 1
+ %a.2 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 2
+ %a.3 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 3
+ %a.4 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 4
+ %a.5 = extractvalue { i32, i32, i32, i32, i32, i32 } %a, 5
+ call void asm sideeffect "", "r,r,r,r,r,r,~{dirflag},~{fpsr},~{flags}"(i32 %a.0, i32 %a.1, i32 %a.2, i32 %a.3, i32 %a.4, i32 %a.5)
+ ret ptr %b
+}
+
+define i32 @f2() nounwind {
+; X86-LABEL: f2:
+; X86: # %bb.0:
+; X86-NEXT: pushl %ebx
+; X86-NEXT: calll .L1$pb
+; X86-NEXT: .L1$pb:
+; X86-NEXT: popl %ebx
+; X86-NEXT: .Ltmp1:
+; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp1-.L1$pb), %ebx
+; X86-NEXT: movl %gs:0, %ecx
+; X86-NEXT: leal x at tlsdesc(%ebx), %eax
+; X86-NEXT: calll *x at tlscall(%eax)
+; X86-NEXT: movl (%eax,%ecx), %eax
+; X86-NEXT: popl %ebx
+; X86-NEXT: retl
+;
+; X32-LABEL: f2:
+; X32: # %bb.0:
+; X32-NEXT: pushq %rax
+; X32-NEXT: movl %fs:0, %ecx
+; X32-NEXT: leal x at tlsdesc(%rip), %eax
+; X32-NEXT: callq *x at tlscall(%eax)
+; X32-NEXT: movl (%eax,%ecx), %eax
+; X32-NEXT: popq %rcx
+; X32-NEXT: retq
+;
+; X64-LABEL: f2:
+; X64: # %bb.0:
+; X64-NEXT: pushq %rax
+; X64-NEXT: movq %fs:0, %rcx
+; X64-NEXT: leaq x at tlsdesc(%rip), %rax
+; X64-NEXT: callq *x at tlscall(%rax)
+; X64-NEXT: movl (%rax,%rcx), %eax
+; X64-NEXT: popq %rcx
+; X64-NEXT: retq
+ %1 = tail call ptr @llvm.threadlocal.address.p0(ptr @x)
+ %2 = load i32, ptr %1
+ ret i32 %2
+}
+
+define ptr @f3() nounwind {
+; X86-LABEL: f3:
+; X86: # %bb.0:
+; X86-NEXT: pushl %ebx
+; X86-NEXT: calll .L2$pb
+; X86-NEXT: .L2$pb:
+; X86-NEXT: popl %ebx
+; X86-NEXT: .Ltmp2:
+; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp2-.L2$pb), %ebx
+; X86-NEXT: leal x at tlsdesc(%ebx), %eax
+; X86-NEXT: calll *x at tlscall(%eax)
+; X86-NEXT: addl %gs:0, %eax
+; X86-NEXT: popl %ebx
+; X86-NEXT: retl
+;
+; X32-LABEL: f3:
+; X32: # %bb.0:
+; X32-NEXT: pushq %rax
+; X32-NEXT: leal x at tlsdesc(%rip), %eax
+; X32-NEXT: callq *x at tlscall(%eax)
+; X32-NEXT: # kill: def $eax killed $eax def $rax
+; X32-NEXT: addl %fs:0, %eax
+; X32-NEXT: popq %rcx
+; X32-NEXT: retq
+;
+; X64-LABEL: f3:
+; X64: # %bb.0:
+; X64-NEXT: pushq %rax
+; X64-NEXT: leaq x at tlsdesc(%rip), %rax
+; X64-NEXT: callq *x at tlscall(%rax)
+; X64-NEXT: addq %fs:0, %rax
+; X64-NEXT: popq %rcx
+; X64-NEXT: retq
+ %1 = tail call ptr @llvm.threadlocal.address.p0(ptr @x)
+ ret ptr %1
+}
+
+define i32 @f4() nounwind {
+; X86-LABEL: f4:
+; X86: # %bb.0:
+; X86-NEXT: pushl %ebx
+; X86-NEXT: calll .L3$pb
+; X86-NEXT: .L3$pb:
+; X86-NEXT: popl %ebx
+; X86-NEXT: .Ltmp3:
+; X86-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp3-.L3$pb), %ebx
+; X86-NEXT: movl %gs:0, %edx
+; X86-NEXT: leal _TLS_MODULE_BASE_ at tlsdesc(%ebx), %eax
+; X86-NEXT: calll *_TLS_MODULE_BASE_ at tlscall(%eax)
+; X86-NEXT: movl y at DTPOFF(%eax,%edx), %ecx
+; X86-NEXT: addl z at DTPOFF(%eax,%edx), %ecx
+; X86-NEXT: movl %ecx, %eax
+; X86-NEXT: popl %ebx
+; X86-NEXT: retl
+;
+; X32-LABEL: f4:
+; X32: # %bb.0:
+; X32-NEXT: pushq %rax
+; X32-NEXT: movl %fs:0, %edx
+; X32-NEXT: leal _TLS_MODULE_BASE_ at tlsdesc(%rip), %eax
+; X32-NEXT: callq *_TLS_MODULE_BASE_ at tlscall(%eax)
+; X32-NEXT: movl y at DTPOFF(%eax,%edx), %ecx
+; X32-NEXT: addl z at DTPOFF(%eax,%edx), %ecx
+; X32-NEXT: movl %ecx, %eax
+; X32-NEXT: popq %rcx
+; X32-NEXT: retq
+;
+; X64-LABEL: f4:
+; X64: # %bb.0:
+; X64-NEXT: pushq %rax
+; X64-NEXT: movq %fs:0, %rdx
+; X64-NEXT: leaq _TLS_MODULE_BASE_ at tlsdesc(%rip), %rax
+; X64-NEXT: callq *_TLS_MODULE_BASE_ at tlscall(%rax)
+; X64-NEXT: movl y at DTPOFF(%rax,%rdx), %ecx
+; X64-NEXT: addl z at DTPOFF(%rax,%rdx), %ecx
+; X64-NEXT: movl %ecx, %eax
+; X64-NEXT: popq %rcx
+; X64-NEXT: retq
+ %1 = load i32, ptr @y, align 4
+ %2 = load i32, ptr @z, align 4
+ %3 = add nsw i32 %1, %2
+ ret i32 %3
+}
More information about the llvm-commits
mailing list