Hi Luke Seems like it's a potential bug in LRA, and can be workaround by use RVVM1QI, could you send a patch for that?
And we may fix that on LRA later... Kito Cheng <[email protected]> 於 2026年7月15日週三 下午5:34寫道: > > oops, I just pushed before I saw this mail, let me try to triage the > issue to see if we can found a right fix for that issue > > Luke Zhuang <[email protected]> 於 2026年7月15日週三 下午3:08寫道: > > > > Hi Jeff/Kito/Robin, > > Sorry I just found a fatal crash of this implementation myself, this small > > test case: > > ``` > > extern __thread int x; > > extern int bar(int); > > int f(int id) { > > x = id * 1000; > > bar(0); > > if (x != id * 1000) return bar(x); > > return 0; > > } > > ``` > > crashes with this command: `cc1 -quiet -imultilib . test.c -quiet -dumpbase > > a.c -dumpbase-ext .c -march=rv64gcv -mtls-dialect=desc -mtune=generic-ooo > > -mabi=lp64d > > -march=rv64imafdcv_zicsr_zifencei_zmmul_zaamo_zalrsc_zca_zcd_zve32f_zve32x_zve64d_zve64f_zve64x_zvl128b_zvl32b_zvl64b > > -O -fPIC -o test.o` > > It crashes in LRA process in lra-constraints.cc:6689 here: > > ``` > > static inline bool > > need_for_split_p (HARD_REG_SET potential_reload_hard_regs, int regno) > > { > > int hard_regno = regno < FIRST_PSEUDO_REGISTER ? regno : > > reg_renumber[regno]; > > lra_assert (hard_regno >= 0); > > ``` > > Looks like a huge clobber set of a non-call insn makes LRA harder to do > > spilling (maybe a potential bug in LRA instead of the implementation > > itself, not sure) > > > > My current opinion is falling back to my first edition: > > https://gcc.gnu.org/pipermail/gcc-patches/2026-June/721254.html, which > > models TLSDESC as a real call and matches what aarch64 did in <bb6ce448>. > > While there's also a small issue: a real call always clobbers `ra` and may > > result in one more spilling in some circumstances (maybe not a big problem). > > May I ask what do you think? > > > > Thank you very much! > > > > Best, > > Luke Zhuang > > > > ------------------------------------------------------------------ > > From:Kito Cheng <[email protected]> > > Send Time:Thu, Jul 2, 2026, 07:38 > > To:Luke Zhuang<[email protected]> > > CC:"gcc-patches"<[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]> > > Subject:Re: [PATCH v4] RISC-V: Declare TLSDESC clobbers for vector > > registers and CSRs per psABI > > > > 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
