LGTM :) Luke Zhuang <[email protected]>於 2026年7月2日週四,00:02寫道:
> gentle ping :) > > Luke Zhuang > > ------------------------------------------------------------------ > From:Luke Zhuang <[email protected]> > Send Time:Thu, Jun 25, 2026, 13:45 > To:"gcc-patches"<[email protected]> > CC:"kito.cheng"<[email protected]>; palmer<[email protected]>; > "rdapp.gcc"<[email protected]>; andrew<[email protected]>; > "jim.wilson.gcc"<[email protected]>; "juzhe.zhong"< > [email protected]>; rdsandiford<[email protected]>; > "jeffrey.law"<[email protected]>; "zhuangzhi.zz"< > [email protected]>; Luke Zhuang<[email protected]> > Subject:[PATCH v4] RISC-V: Declare TLSDESC clobbers for vector registers > and CSRs per psABI > > > From: "Luke Zhuang" <[email protected]> > > 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. > --- > gcc/config/riscv/riscv.md | 11 +++- > .../gcc.target/riscv/tlsdesc_clobber.c | 29 ++++++++++ > .../gcc.target/riscv/tlsdesc_clobber_v.c | 56 +++++++++++++++++++ > .../gcc.target/riscv/tlsdesc_clobber_v_csr.c | 39 +++++++++++++ > 4 files changed, 134 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/gcc.target/riscv/tlsdesc_clobber.c > create mode 100644 gcc/testsuite/gcc.target/riscv/tlsdesc_clobber_v.c > create mode 100644 gcc/testsuite/gcc.target/riscv/tlsdesc_clobber_v_csr.c > > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md > index b90bfe0745a..d3cddacb566 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 00000000000..6a004d6820f > --- /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 00000000000..a5fb350f76e > --- /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 00000000000..ffb9c9a61a4 > --- /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 } } */ > -- > 2.47.1 > >
