[gcc r17-2408] RISC-V: Declare TLSDESC clobbers for vector registers and CSRs per psABI

Kito Cheng via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:0748d2c83fc0440f101fe01cc3dfc97c8e11c3b2

commit r17-2408-g0748d2c83fc0440f101fe01cc3dfc97c8e11c3b2
Author: Luke Zhuang <[email protected]>
Date:   Thu Jun 25 13:45:16 2026 +0800

    RISC-V: Declare TLSDESC clobbers for vector registers and CSRs per psABI
    
    Per the RISC-V psABI, the TLSDESC resolver clobbers a0 and t0 in the
    base case.  With the new psABI update
    (https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/496),
    when the V extension is enabled, it additionally clobbers all vector
    registers and vector CSRs.
    
    This patch updates the clobbering of tlsdesc define_insn: clobbering
    not only a0 and t0, but also all V-regs (using 4 x LMUL8 reg
    groups covering all 32 physical V-regs), and 4 vector CSRs
    (vl/vtype/vxrm/vxstat).
    
    Three new tests are added covering GPR, vector register, and vector
    CSR clobber behavior.
    
    gcc/ChangeLog:
    
            * config/riscv/riscv.md (VXSAT_REGNUM): New constant.
            (@tlsdesc<mode>): update clobbering.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/tlsdesc_clobber.c: New test.
            * gcc.target/riscv/tlsdesc_clobber_v.c: New test.
            * gcc.target/riscv/tlsdesc_clobber_v_csr.c: New test.

Diff:
---
 gcc/config/riscv/riscv.md                          | 11 ++++-
 gcc/testsuite/gcc.target/riscv/tlsdesc_clobber.c   | 29 +++++++++++
 gcc/testsuite/gcc.target/riscv/tlsdesc_clobber_v.c | 56 ++++++++++++++++++++++
 .../gcc.target/riscv/tlsdesc_clobber_v_csr.c       | 39 +++++++++++++++
 4 files changed, 134 insertions(+), 1 deletion(-)

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index f10a08460acf..c64e4ff3c77b 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -181,6 +181,7 @@
    (VTYPE_REGNUM		67)
    (VXRM_REGNUM			68)
    (FRM_REGNUM			69)
+   (VXSAT_REGNUM		70)
 ])
 
 (include "predicates.md")
@@ -2478,7 +2479,15 @@
 	(unspec:P
 	    [(match_operand:P 0 "symbolic_operand" "")]
 	    UNSPEC_TLSDESC))
-   (clobber (reg:P T0_REGNUM))]
+   (clobber (reg:P T0_REGNUM))
+   (clobber (reg:RVVM8QI 96))
+   (clobber (reg:RVVM8QI 104))
+   (clobber (reg:RVVM8QI 112))
+   (clobber (reg:RVVM8QI 120))
+   (clobber (reg:SI VL_REGNUM))
+   (clobber (reg:SI VTYPE_REGNUM))
+   (clobber (reg:SI VXRM_REGNUM))
+   (clobber (reg:SI VXSAT_REGNUM))]
   "TARGET_TLSDESC"
   {
     return ".LT%=: auipc\ta0,%%tlsdesc_hi(%0)\;"
diff --git a/gcc/testsuite/gcc.target/riscv/tlsdesc_clobber.c b/gcc/testsuite/gcc.target/riscv/tlsdesc_clobber.c
new file mode 100644
index 000000000000..6a004d6820fd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/tlsdesc_clobber.c
@@ -0,0 +1,29 @@
+/* Verify that the TLSDESC resolver only clobbers a0 and t0 while assuming
+   all other registers as preserved per its custom ABI (no vector case),
+   which is different from a normal call.  */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-O2 -fpic -mtls-dialect=desc -march=rv64gc -mabi=lp64d" } */
+/* { dg-require-effective-target fpic } */
+
+extern __thread int tls_var;
+
+long
+test_clobber (long a, long b, long c, long d)
+{
+  /* a=a0, b=a1, c=a2, d=a3.
+     TLSDESC clobbers a0 and t0 only, so the compiler must save/restore
+     a0 (by stack or mv or whatever), but should not do the same thing
+     for a1-a3 like a normal call.  */
+  tls_var = 1;
+  return a + b + c + d;
+}
+
+/* The TLSDESC call should be present.  */
+/* { dg-final { scan-assembler-times {jalr\tt0,} 1 } } */
+
+/* ra/a1-a3 should NOT be moved to s-regs or saved to stack.  */
+/* { dg-final { scan-assembler-not {mv\ts[0-9]+,a[0-9]+} } } */
+/* { dg-final { scan-assembler-not {sd\ta[0-9]+,.*\(sp\)} } } */
+/* { dg-final { scan-assembler-not {sd\tra,.*\(sp\)} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/tlsdesc_clobber_v.c b/gcc/testsuite/gcc.target/riscv/tlsdesc_clobber_v.c
new file mode 100644
index 000000000000..a5fb350f76e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/tlsdesc_clobber_v.c
@@ -0,0 +1,56 @@
+/* Verify that when the V extension is enabled, the TLSDESC resolver clobbers
+   all vector registers per the psABI.  The compiler must save/restore any
+   live vector registers across the TLSDESC call.  */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-O2 -fpic -mtls-dialect=desc -march=rv64gcv -mabi=lp64d" } */
+/* { dg-require-effective-target fpic } */
+
+extern __thread int tls_var;
+
+void
+test_vector_reg_clobber (void)
+{
+  __rvv_int32m1_t v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12;
+
+  /* Write two v-regs.  */
+  asm volatile ("# def v1" : "=vr"(v1));
+  asm volatile ("# def v2" : "=vr"(v2));
+  asm volatile ("# def v3" : "=vr"(v3));
+  asm volatile ("# def v4" : "=vr"(v4));
+  asm volatile ("# def v5" : "=vr"(v5));
+  asm volatile ("# def v6" : "=vr"(v6));
+  asm volatile ("# def v7" : "=vr"(v7));
+  asm volatile ("# def v8" : "=vr"(v8));
+  asm volatile ("# def v9" : "=vr"(v9));
+  asm volatile ("# def v10" : "=vr"(v10));
+  asm volatile ("# def v11" : "=vr"(v11));
+  asm volatile ("# def v12" : "=vr"(v12));
+
+  /* TLSDESC call — clobbers all vector regs.  */
+  asm volatile ("" ::: "memory");  /* Prevent scheduling...  */
+  tls_var = 1;
+  asm volatile ("" ::: "memory");  /* Prevent scheduling...  */
+
+  /* Read the two v-regs; their live-range spans across the TLSDESC call,
+     so the compiler must emit vector store/load pairs to preserve them.  */
+  asm volatile ("# use v1" : : "vr"(v1));
+  asm volatile ("# use v2" : : "vr"(v2));
+  asm volatile ("# use v3" : : "vr"(v3));
+  asm volatile ("# use v4" : : "vr"(v4));
+  asm volatile ("# use v5" : : "vr"(v5));
+  asm volatile ("# use v6" : : "vr"(v6));
+  asm volatile ("# use v7" : : "vr"(v7));
+  asm volatile ("# use v8" : : "vr"(v8));
+  asm volatile ("# use v9" : : "vr"(v9));
+  asm volatile ("# use v10" : : "vr"(v10));
+  asm volatile ("# use v11" : : "vr"(v11));
+  asm volatile ("# use v12" : : "vr"(v12));
+}
+
+/* { dg-final { scan-assembler-times {jalr\tt0,} 1 } } */
+
+/* Vector stores before and loads after the TLSDESC call.  */
+/* { dg-final { scan-assembler-times {\tvs[0-9]+r\.v\t} 12 } } */
+/* { dg-final { scan-assembler-times {\tvl[0-9]+re[0-9]+\.v\t} 12 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/tlsdesc_clobber_v_csr.c b/gcc/testsuite/gcc.target/riscv/tlsdesc_clobber_v_csr.c
new file mode 100644
index 000000000000..ffb9c9a61a47
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/tlsdesc_clobber_v_csr.c
@@ -0,0 +1,39 @@
+/* Verify that when the V extension is enabled, the TLSDESC resolver clobbers
+   vector CSRs (vl, vtype, vxrm, vxsat) per the psABI.  The compiler must
+   re-emit a vsetvli after the TLSDESC call to recover the vector status. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-O2 -fpic -mtls-dialect=desc -march=rv64gcv -mabi=lp64d" } */
+/* { dg-require-effective-target fpic } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+extern __thread int tls_var;
+
+void
+test_vector_csr_clobber (v4si *in, v4si *out)
+{
+  v4si vec;
+
+  /* A pair of local load/store whose live-range does not span accross
+     the TLSDESC.  It has a special size format so it needs a vsetvli.  */
+  vec = *in;
+  *out = vec;
+
+  /* TLSDESC call — clobbers all vector CSRs including vl/vtype.  */
+  asm volatile ("" ::: "memory");  /* Prevent scheduling...  */
+  tls_var = 1;
+  asm volatile ("" ::: "memory");  /* Prevent scheduling...  */
+
+   /* Another pair of local load/store. But since TLSDESC clobbers vl/vtype, we
+     must re-emit a vsetvli here.  */
+  vec = *in;
+  *out = vec;
+}
+
+/* { dg-final { scan-assembler-times {jalr\tt0,} 1 } } */
+
+/* Two vsetvli: one before each vector segment.  The second is needed because
+   TLSDESC clobbers vl/vtype.  */
+/* { dg-final { scan-assembler-times {vsetvli|vsetivli} 2 } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.