[llvm] [RISCV] Add explicit defs in PseudoLA_TLSDESC (PR #205494)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 24 01:57:27 PDT 2026


https://github.com/LukeZhuang updated https://github.com/llvm/llvm-project/pull/205494

>From b38952b6527b591274a364b02d920dd4cb34ce69 Mon Sep 17 00:00:00 2001
From: Zhi Zhuang <zhuangzhi.zz at alibaba-inc.com>
Date: Wed, 24 Jun 2026 12:21:49 +0800
Subject: [PATCH] [RISCV] Add explicit defs in PseudoLA_TLSDESC (#205494)

Per the psABI, la.tlsdesc clobbers a0/t0. The defs are not strictly
required now because the expanding happens pre-RA, while just
in case some passes may need it or the expanding may be moved to
post-RA in the future.

Also, a test case is added as well showing the right behavior of
TLSDESC clobbering.
---
 llvm/lib/Target/RISCV/RISCVInstrInfo.td    |  4 +-
 llvm/test/CodeGen/RISCV/tlsdesc-clobber.ll | 53 ++++++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/RISCV/tlsdesc-clobber.ll

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 2abd63202a4bf..7b72dfbbad91e 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1956,7 +1956,9 @@ def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
                              "la.tls.gd", "$dst, $src">;
 
 let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 32 in
-def PseudoLA_TLSDESC : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), []>;
+def PseudoLA_TLSDESC : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), []> {
+  let Defs = [X5, X10];
+}
 
 def TLSDESCCallSymbol : AsmOperandClass {
   let Name = "TLSDESCCallSymbol";
diff --git a/llvm/test/CodeGen/RISCV/tlsdesc-clobber.ll b/llvm/test/CodeGen/RISCV/tlsdesc-clobber.ll
new file mode 100644
index 0000000000000..132ff7d83235d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/tlsdesc-clobber.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv64 -relocation-model=pic -enable-tlsdesc < %s \
+; RUN:     | FileCheck %s --check-prefix=RV64
+; RUN: llc -mtriple=riscv32 -relocation-model=pic -enable-tlsdesc < %s \
+; RUN:     | FileCheck %s --check-prefix=RV32
+
+;; Verify that the TLSDESC resolver only clobbers a0 and t0 per the psABI.
+;; Arguments in ra/a1-a3 need not be saved/restored across the TLSDESC call,
+;; unlike a normal function call.
+
+ at tls_var = external thread_local global i32
+
+;; ra/a1-a3 need not be saved to stack or moved to s-regs.
+
+define i32 @test_clobber(i32 %a, i32 %b, i32 %c, i32 %d) nounwind {
+; RV64-LABEL: test_clobber:
+; RV64:       # %bb.0: # %entry
+; RV64-NEXT:  .Ltlsdesc_hi0:
+; RV64-NEXT:    auipc a5, %tlsdesc_hi(tls_var)
+; RV64-NEXT:    ld a6, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a5)
+; RV64-NEXT:    mv a4, a0
+; RV64-NEXT:    addi a0, a5, %tlsdesc_add_lo(.Ltlsdesc_hi0)
+; RV64-NEXT:    jalr t0, 0(a6), %tlsdesc_call(.Ltlsdesc_hi0)
+; RV64-NEXT:    add a1, a4, a1
+; RV64-NEXT:    add a2, a2, a3
+; RV64-NEXT:    add a3, a0, tp
+; RV64-NEXT:    addw a0, a1, a2
+; RV64-NEXT:    li a1, 1
+; RV64-NEXT:    sw a1, 0(a3)
+; RV64-NEXT:    ret
+;
+; RV32-LABEL: test_clobber:
+; RV32:       # %bb.0: # %entry
+; RV32-NEXT:  .Ltlsdesc_hi0:
+; RV32-NEXT:    auipc a5, %tlsdesc_hi(tls_var)
+; RV32-NEXT:    lw a6, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a5)
+; RV32-NEXT:    mv a4, a0
+; RV32-NEXT:    addi a0, a5, %tlsdesc_add_lo(.Ltlsdesc_hi0)
+; RV32-NEXT:    jalr t0, 0(a6), %tlsdesc_call(.Ltlsdesc_hi0)
+; RV32-NEXT:    add a1, a4, a1
+; RV32-NEXT:    add a2, a2, a3
+; RV32-NEXT:    add a3, a0, tp
+; RV32-NEXT:    add a0, a1, a2
+; RV32-NEXT:    li a1, 1
+; RV32-NEXT:    sw a1, 0(a3)
+; RV32-NEXT:    ret
+entry:
+  store i32 1, ptr @tls_var
+  %sum1 = add i32 %a, %b
+  %sum2 = add i32 %sum1, %c
+  %sum3 = add i32 %sum2, %d
+  ret i32 %sum3
+}



More information about the llvm-commits mailing list