[clang] [llvm] [AArch64] Add an option to get the TLS pointer from software (PR #130932)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 17 18:48:55 PDT 2025
https://github.com/xerpi updated https://github.com/llvm/llvm-project/pull/130932
>From 0836ddbda0f00117ebbd82b13f3a1ba12cbdbfa0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sergi=20=28=E3=82=BB=E3=83=AB=E3=82=B8=29?=
<sergi-granell-escalfet at arkedgespace.com>
Date: Wed, 12 Mar 2025 16:20:07 +0900
Subject: [PATCH] [AArch64] Add an option to get the TLS pointer from software
This patch adds an option to get the TLS pointer via a call to __aarch64_read_tp() (similar to __aeabi_read_tp on ARM).
This mode is enabled when -mtp=soft is passed to clang.
Necessary on Nintendo Horizon OS, which puts the TLS pointer at a calculated offset from TPIDR_EL0.
Co-authored-by: Mary Guillemard <mary at mary.zone>
Signed-off-by: Sergi Granell Escalfet <xerpi.g.12 at gmail.com>
---
clang/include/clang/Driver/Options.td | 2 +-
clang/lib/Driver/ToolChains/Arch/AArch64.cpp | 56 ++++++++++++++-----
clang/lib/Driver/ToolChains/Arch/AArch64.h | 15 ++++-
clang/test/Driver/aarch64-thread-pointer.c | 15 +++++
.../AArch64/AArch64ExpandPseudoInsts.cpp | 11 ++++
llvm/lib/Target/AArch64/AArch64Features.td | 4 ++
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 15 ++++-
.../CodeGen/AArch64/arm64-builtins-linux.ll | 3 +
.../CodeGen/AArch64/arm64-tls-dynamics.ll | 39 +++++++++++++
9 files changed, 144 insertions(+), 16 deletions(-)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index e69cd6b833c3a..01ffaa9d8f8f4 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4732,7 +4732,7 @@ let Flags = [TargetSpecific] in {
def mtp_mode_EQ : Joined<["-"], "mtp=">, Group<m_arm_Features_Group>, Values<"soft,cp15,tpidrurw,tpidruro,tpidrprw,el0,el1,el2,el3,tpidr_el0,tpidr_el1,tpidr_el2,tpidr_el3,tpidrro_el0,auto">,
HelpText<"Thread pointer access method. "
"For AArch32: 'soft' uses a function call, or 'tpidrurw', 'tpidruro' or 'tpidrprw' use the three CP15 registers. 'cp15' is an alias for 'tpidruro'. "
- "For AArch64: 'tpidr_el0', 'tpidr_el1', 'tpidr_el2', 'tpidr_el3' or 'tpidrro_el0' use the five system registers. 'elN' is an alias for 'tpidr_elN'.">;
+ "For AArch64: 'soft' uses a function call, 'tpidr_el0', 'tpidr_el1', 'tpidr_el2', 'tpidr_el3' or 'tpidrro_el0' use the five system registers. 'elN' is an alias for 'tpidr_elN'.">;
def mpure_code : Flag<["-"], "mpure-code">, Alias<mexecute_only>; // Alias for GCC compatibility
def mno_pure_code : Flag<["-"], "mno-pure-code">, Alias<mno_execute_only>;
def mtvos_version_min_EQ : Joined<["-"], "mtvos-version-min=">, Group<m_Group>;
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index 6e70effe9e325..4bab0c6f1d37f 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -192,6 +192,35 @@ getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
return getAArch64MicroArchFeaturesFromMtune(D, CPU, Args, Features);
}
+// Select mode for reading thread pointer (-mtp=).
+aarch64::ReadTPMode aarch64::getReadTPMode(const Driver &D, const ArgList &Args,
+ const llvm::Triple &Triple,
+ bool ForAS) {
+ Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ);
+ if (A) {
+ aarch64::ReadTPMode ThreadPointer =
+ llvm::StringSwitch<aarch64::ReadTPMode>(A->getValue())
+ .Case("soft", aarch64::ReadTPMode::Soft)
+ .Case("tpidr_el0", aarch64::ReadTPMode::TPIDR_EL0)
+ .Case("tpidr_el1", aarch64::ReadTPMode::TPIDR_EL1)
+ .Case("tpidr_el2", aarch64::ReadTPMode::TPIDR_EL2)
+ .Case("tpidr_el3", aarch64::ReadTPMode::TPIDR_EL3)
+ .Case("tpidrro_el0", aarch64::ReadTPMode::TPIDRRO_EL0)
+ .Case("el0", aarch64::ReadTPMode::TPIDR_EL0)
+ .Case("el1", aarch64::ReadTPMode::TPIDR_EL1)
+ .Case("el2", aarch64::ReadTPMode::TPIDR_EL2)
+ .Case("el3", aarch64::ReadTPMode::TPIDR_EL3)
+ .Default(ReadTPMode::Invalid);
+ if (ThreadPointer != ReadTPMode::Invalid)
+ return ThreadPointer;
+ if (StringRef(A->getValue()).empty())
+ D.Diag(diag::err_drv_missing_arg_mtp) << A->getAsString(Args);
+ else
+ D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
+ }
+ return ReadTPMode::Invalid;
+}
+
void aarch64::getAArch64TargetFeatures(const Driver &D,
const llvm::Triple &Triple,
const ArgList &Args,
@@ -262,19 +291,20 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
// set to a feature list.
Extensions.toLLVMFeatureList(Features);
- if (Arg *A = Args.getLastArg(options::OPT_mtp_mode_EQ)) {
- StringRef Mtp = A->getValue();
- if (Mtp == "el3" || Mtp == "tpidr_el3")
- Features.push_back("+tpidr-el3");
- else if (Mtp == "el2" || Mtp == "tpidr_el2")
- Features.push_back("+tpidr-el2");
- else if (Mtp == "el1" || Mtp == "tpidr_el1")
- Features.push_back("+tpidr-el1");
- else if (Mtp == "tpidrro_el0")
- Features.push_back("+tpidrro-el0");
- else if (Mtp != "el0" && Mtp != "tpidr_el0")
- D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
- }
+ aarch64::ReadTPMode TPMode = getReadTPMode(D, Args, Triple, ForAS);
+
+ if (TPMode == Soft)
+ Features.push_back("+read-tp-soft");
+ else if (TPMode == TPIDR_EL1)
+ Features.push_back("+tpidr-el1");
+ else if (TPMode == TPIDR_EL2)
+ Features.push_back("+tpidr-el2");
+ else if (TPMode == TPIDR_EL3)
+ Features.push_back("+tpidr-el3");
+ else if (TPMode == TPIDRRO_EL0)
+ Features.push_back("+tpidrro-el0");
+ else if (TPMode != TPIDR_EL0 && TPMode != Soft)
+ D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args);
// Enable/disable straight line speculation hardening.
if (Arg *A = Args.getLastArg(options::OPT_mharden_sls_EQ)) {
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.h b/clang/lib/Driver/ToolChains/Arch/AArch64.h
index 2057272867a17..d4eaa0c6a64e4 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.h
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.h
@@ -20,6 +20,16 @@ namespace driver {
namespace tools {
namespace aarch64 {
+enum class ReadTPMode {
+ Invalid,
+ Soft,
+ TPIDR_EL0,
+ TPIDR_EL1,
+ TPIDR_EL2,
+ TPIDR_EL3,
+ TPIDRRO_EL0,
+};
+
void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args,
std::vector<llvm::StringRef> &Features,
@@ -28,11 +38,14 @@ void getAArch64TargetFeatures(const Driver &D, const llvm::Triple &Triple,
std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args,
const llvm::Triple &Triple, llvm::opt::Arg *&A);
+ReadTPMode getReadTPMode(const Driver &D, const llvm::opt::ArgList &Args,
+ const llvm::Triple &Triple, bool ForAS);
+
void setPAuthABIInTriple(const Driver &D, const llvm::opt::ArgList &Args,
llvm::Triple &triple);
} // end namespace aarch64
-} // end namespace target
+} // end namespace tools
} // end namespace driver
} // end namespace clang
diff --git a/clang/test/Driver/aarch64-thread-pointer.c b/clang/test/Driver/aarch64-thread-pointer.c
index b1c6df4ac5e5d..6186a53bf3954 100644
--- a/clang/test/Driver/aarch64-thread-pointer.c
+++ b/clang/test/Driver/aarch64-thread-pointer.c
@@ -7,10 +7,13 @@
// RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL0 %s
// RUN: %clang --target=aarch64-linux -### -S %s -mtp=tpidr_el0 2>&1 | \
// RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL0 %s
+// RUN: %clang --target=aarch64-linux -### -S %s -mtp=soft 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL0 %s
// ARMv8_THREAD_POINTER_EL0-NOT: "-target-feature" "+tpidrro-el0"
// ARMv8_THREAD_POINTER_EL0-NOT: "-target-feature" "+tpidr-el1"
// ARMv8_THREAD_POINTER_EL0-NOT: "-target-feature" "+tpidr-el2"
// ARMv8_THREAD_POINTER_EL0-NOT: "-target-feature" "+tpidr-el3"
+// ARMv8_THREAD_POINTER_EL0-NOT: "-target-feature" "+read-tp-soft"
// RUN: %clang --target=aarch64-linux -### -S %s -mtp=tpidrro_el0 2>&1 | \
// RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_ROEL0 %s
@@ -18,6 +21,7 @@
// ARMv8_THREAD_POINTER_ROEL0-NOT: "-target-feature" "+tpidr-el1"
// ARMv8_THREAD_POINTER_ROEL0-NOT: "-target-feature" "+tpidr-el2"
// ARMv8_THREAD_POINTER_ROEL0-NOT: "-target-feature" "+tpidr-el3"
+// ARMv8_THREAD_POINTER_ROEL0-NOT: "-target-feature" "+read-tp-soft"
// RUN: %clang --target=aarch64-linux -### -S %s -mtp=el1 2>&1 | \
// RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL1 %s
@@ -27,6 +31,7 @@
// ARMv8_THREAD_POINTER_EL1: "-target-feature" "+tpidr-el1"
// ARMv8_THREAD_POINTER_EL1-NOT: "-target-feature" "+tpidr-el2"
// ARMv8_THREAD_POINTER_EL1-NOT: "-target-feature" "+tpidr-el3"
+// ARMv8_THREAD_POINTER_EL1-NOT: "-target-feature" "+read-tp-soft"
// RUN: %clang --target=aarch64-linux -### -S %s -mtp=el2 2>&1 | \
// RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL2 %s
@@ -36,6 +41,7 @@
// ARMv8_THREAD_POINTER_EL2-NOT: "-target-feature" "+tpidr-el1"
// ARMv8_THREAD_POINTER_EL2: "-target-feature" "+tpidr-el2"
// ARMv8_THREAD_POINTER_EL2-NOT: "-target-feature" "+tpidr-el3"
+// ARMv8_THREAD_POINTER_EL2-NOT: "-target-feature" "+read-tp-soft"
// RUN: %clang --target=aarch64-linux -### -S %s -mtp=el3 2>&1 | \
// RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_EL3 %s
@@ -45,3 +51,12 @@
// ARMv8_THREAD_POINTER_EL3-NOT: "-target-feature" "+tpidr-el1"
// ARMv8_THREAD_POINTER_EL3-NOT: "-target-feature" "+tpidr-el2"
// ARMv8_THREAD_POINTER_EL3: "-target-feature" "+tpidr-el3"
+// ARMv8_THREAD_POINTER_EL3-NOT: "-target-feature" "+read-tp-soft"
+
+// RUN: %clang --target=aarch64-linux -### -S %s -mtp=soft 2>&1 | \
+// RUN: FileCheck -check-prefix=ARMv8_THREAD_POINTER_SOFT %s
+// ARMv8_THREAD_POINTER_SOFT-NOT: "-target-feature" "+tpidrro-el0"
+// ARMv8_THREAD_POINTER_SOFT-NOT: "-target-feature" "+tpidr-el1"
+// ARMv8_THREAD_POINTER_SOFT-NOT: "-target-feature" "+tpidr-el2"
+// ARMv8_THREAD_POINTER_SOFT-NOT: "-target-feature" "+tpidr-el3"
+// ARMv8_THREAD_POINTER_SOFT: "-target-feature" "+read-tp-soft"
diff --git a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
index 55a441b7d22b6..09ced5298cf61 100644
--- a/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp
@@ -1487,6 +1487,17 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB,
return true;
}
+ case AArch64::GETbaseTLSsoft: {
+ Register DstReg = MI.getOperand(0).getReg();
+ MachineInstrBuilder MIB =
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::BL))
+ .addExternalSymbol("__aarch64_read_tp")
+ .cloneMemRefs(MI);
+ transferImpOps(MI, MIB, MIB);
+ MI.eraseFromParent();
+ return true;
+ }
+
case AArch64::MOVi32imm:
return expandMOVImm(MBB, MBBI, 32);
case AArch64::MOVi64imm:
diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td
index 357f526d5e308..42069e6dc5c17 100644
--- a/llvm/lib/Target/AArch64/AArch64Features.td
+++ b/llvm/lib/Target/AArch64/AArch64Features.td
@@ -818,6 +818,10 @@ def FeatureUseFixedOverScalableIfEqualCost : SubtargetFeature<"use-fixed-over-sc
def FeatureAvoidLDAPUR : SubtargetFeature<"avoid-ldapur", "AvoidLDAPUR", "true",
"Prefer add+ldapr to offset ldapur">;
+// Read the TLS by calling __aarch64_read_tp
+def FeatureReadTpSoft : SubtargetFeature<"read-tp-soft", "ReadTpSoft",
+ "true", "Read thread pointer from __aarch64_read_tp" >;
+
//===----------------------------------------------------------------------===//
// Architectures.
//
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 6c61e3a613f6f..7a6ee0ab2bad8 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -395,6 +395,8 @@ def AArch64LocalRecover : SDNode<"ISD::LOCAL_RECOVER",
def AllowMisalignedMemAccesses : Predicate<"!Subtarget->requiresStrictAlign()">;
+def IsReadTPHard : Predicate<"!Subtarget->readTpSoft()">;
+def IsReadTPSoft : Predicate<"Subtarget->readTpSoft()">;
//===----------------------------------------------------------------------===//
// AArch64-specific DAG Nodes.
@@ -2121,7 +2123,18 @@ def : Pat<(AArch64mrs imm:$id),
// The thread pointer (on Linux, at least, where this has been implemented) is
// TPIDR_EL0.
def MOVbaseTLS : Pseudo<(outs GPR64:$dst), (ins),
- [(set GPR64:$dst, AArch64threadpointer)]>, Sched<[WriteSys]>;
+ [(set GPR64:$dst, AArch64threadpointer)]>, Sched<[WriteSys]>,
+ Requires<[IsReadTPHard]>;
+
+// __aarch64_read_tp preserves the registers x1-x7.
+// This is a pseudo inst so that we can get the encoding right,
+// complete with fixup for the aarch64_read_tp function.
+let isCall = 1,
+ Defs = [X0, X16, X17, LR], Uses = [SP] in {
+ def GETbaseTLSsoft : Pseudo<(outs), (ins),
+ [(set X0, AArch64threadpointer)]>, Sched<[WriteBr]>,
+ Requires<[IsReadTPSoft]>;
+}
// This gets lowered into a 24-byte instruction sequence
let Defs = [ X9, X16, X17, NZCV ], Size = 24 in {
diff --git a/llvm/test/CodeGen/AArch64/arm64-builtins-linux.ll b/llvm/test/CodeGen/AArch64/arm64-builtins-linux.ll
index 679e4ac0bd27c..b796f59a54171 100644
--- a/llvm/test/CodeGen/AArch64/arm64-builtins-linux.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-builtins-linux.ll
@@ -4,6 +4,7 @@
; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+tpidr-el1 | FileCheck --check-prefix=USEEL1 %s
; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+tpidr-el2 | FileCheck --check-prefix=USEEL2 %s
; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+tpidr-el3 | FileCheck --check-prefix=USEEL3 %s
+; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+read-tp-soft | FileCheck --check-prefix=SOFT %s
; Function Attrs: nounwind readnone
declare ptr @llvm.thread.pointer() #1
@@ -19,6 +20,8 @@ define ptr @thread_pointer() {
; USEEL2: mrs {{x[0-9]+}}, TPIDR_EL2
; USEEL3: thread_pointer:
; USEEL3: mrs {{x[0-9]+}}, TPIDR_EL3
+; SOFT: thread_pointer:
+; SOFT: bl __aarch64_read_tp
%1 = tail call ptr @llvm.thread.pointer()
ret ptr %1
}
diff --git a/llvm/test/CodeGen/AArch64/arm64-tls-dynamics.ll b/llvm/test/CodeGen/AArch64/arm64-tls-dynamics.ll
index c12730bd3b0d7..ccca5d7ff01a1 100644
--- a/llvm/test/CodeGen/AArch64/arm64-tls-dynamics.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-tls-dynamics.ll
@@ -3,6 +3,7 @@
; RUN: llc < %s -debug-entry-values -mtriple=arm64-none-linux-gnu -stop-after=machineverifier -relocation-model=pic -aarch64-elf-ldtls-generation=1 < %s
; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -verify-machineinstrs -mattr=+read-tp-soft < %s | FileCheck --check-prefix=CHECK-TP-SOFT %s
; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -aarch64-elf-ldtls-generation=1 -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-RELOC %s
; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-NOLD %s
; RUN: llc -mtriple=arm64-none-linux-gnu -relocation-model=pic -filetype=obj < %s | llvm-objdump -r - | FileCheck --check-prefix=CHECK-NOLD-RELOC %s
@@ -27,6 +28,12 @@ define i32 @test_generaldynamic() {
; CHECK-NEXT: .tlsdesccall general_dynamic_var
; CHECK-NEXT: blr [[CALLEE]]
+; CHECK-TP-SOFT: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var
+; CHECK-TP-SOFT-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var]
+; CHECK-TP-SOFT-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var
+; CHECK-TP-SOFT-NEXT: .tlsdesccall general_dynamic_var
+; CHECK-TP-SOFT-NEXT: blr [[CALLEE]]
+
; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var
; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var]
; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var
@@ -36,6 +43,9 @@ define i32 @test_generaldynamic() {
; CHECK: mrs x[[TP:[0-9]+]], TPIDR_EL0
; CHECK: ldr w0, [x[[TP]], x0]
+; CHECK-TP-SOFT: mov x[[TMP:[0-9]+]], x0
+; CHECK-TP-SOFT: bl __aarch64_read_tp
+; CHECK-TP-SOFT: ldr w0, [x0, x[[TMP]]]
; CHECK-NOLD: mrs x[[TP:[0-9]+]], TPIDR_EL0
; CHECK-NOLD: ldr w0, [x[[TP]], x0]
@@ -62,8 +72,17 @@ define ptr @test_generaldynamic_addr() {
; CHECK-NEXT: .tlsdesccall general_dynamic_var
; CHECK-NEXT: blr [[CALLEE]]
+; CHECK-TP-SOFT: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:general_dynamic_var
+; CHECK-TP-SOFT-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var]
+; CHECK-TP-SOFT-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:general_dynamic_var
+; CHECK-TP-SOFT-NEXT: .tlsdesccall general_dynamic_var
+; CHECK-TP-SOFT-NEXT: blr [[CALLEE]]
+
; CHECK: mrs [[TP:x[0-9]+]], TPIDR_EL0
; CHECK: add x0, [[TP]], x0
+; CHECK-TP-SOFT: mov x[[TMP:[0-9]+]], x0
+; CHECK-TP-SOFT: bl __aarch64_read_tp
+; CHECK-TP-SOFT: add x0, x0, x[[TMP]]
; CHECK-RELOC: R_AARCH64_TLSDESC_ADR_PAGE21
; CHECK-RELOC: R_AARCH64_TLSDESC_LD64_LO12
@@ -95,6 +114,16 @@ define i32 @test_localdynamic() {
; CHECK-DAG: add x[[TPOFF]], x[[TPOFF]], :dtprel_lo12_nc:local_dynamic_var
; CHECK: ldr w0, [x[[TPIDR]], x[[TPOFF]]]
+; CHECK-TP-SOFT: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_
+; CHECK-TP-SOFT-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_]
+; CHECK-TP-SOFT-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_
+; CHECK-TP-SOFT-NEXT: .tlsdesccall _TLS_MODULE_BASE_
+; CHECK-TP-SOFT-NEXT: blr [[CALLEE]]
+; CHECK-TP-SOFT-NEXT: add x[[TPOFF:[0-9]+]], x0, :dtprel_hi12:local_dynamic_var
+; CHECK-TP-SOFT-DAG: bl __aarch64_read_tp
+; CHECK-TP-SOFT-DAG: add x[[TPOFF]], x[[TPOFF]], :dtprel_lo12_nc:local_dynamic_var
+; CHECK-TP-SOFT: ldr w0, [x0, x[[TPOFF]]]
+
; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:local_dynamic_var
; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var]
; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var
@@ -131,6 +160,16 @@ define ptr @test_localdynamic_addr() {
; CHECK-DAG: mrs x[[TPIDR:[0-9]+]], TPIDR_EL0
; CHECK: add x0, x[[TPIDR]], x[[TPOFF]]
+; CHECK-TP-SOFT: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:_TLS_MODULE_BASE_
+; CHECK-TP-SOFT-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_]
+; CHECK-TP-SOFT-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:_TLS_MODULE_BASE_
+; CHECK-TP-SOFT-NEXT: .tlsdesccall _TLS_MODULE_BASE_
+; CHECK-TP-SOFT-NEXT: blr [[CALLEE]]
+; CHECK-TP-SOFT-NEXT: add x[[TPOFF:[0-9]+]], x0, :dtprel_hi12:local_dynamic_var
+; CHECK-TP-SOFT-DAG: add x[[TPOFF]], x[[TPOFF]], :dtprel_lo12_nc:local_dynamic_var
+; CHECK-TP-SOFT-DAG: bl __aarch64_read_tp
+; CHECK-TP-SOFT: add x0, x0, x[[TPOFF]]
+
; CHECK-NOLD: adrp x[[TLSDESC_HI:[0-9]+]], :tlsdesc:local_dynamic_var
; CHECK-NOLD-NEXT: ldr [[CALLEE:x[0-9]+]], [x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var]
; CHECK-NOLD-NEXT: add x0, x[[TLSDESC_HI]], :tlsdesc_lo12:local_dynamic_var
More information about the llvm-commits
mailing list