[llvm] [RISCV] Declare TLSDESC clobbers for vector registers and CSRs per psABI (PR #205027)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 25 00:58:03 PDT 2026


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

>From 7b80229f0a3e515cce41c0946f303baedce5b814 Mon Sep 17 00:00:00 2001
From: Luke Zhuang <luke.zhuang at linux.alibaba.com>
Date: Wed, 24 Jun 2026 17:33:16 +0800
Subject: [PATCH] [RISCV] Declare TLSDESC clobbers for vector registers and
 CSRs per psABI (#205027)

Per the RISC-V psABI, the TLSDESC resolver clobbers a0 and t0 in the
base case. By the new ABI updates
(https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/496),
when the V extension is enabled, it now additionally clobbers
all vector registers and vector CSRs.

This patch adds V-regs/csrs clobbering to the existing
PseudoLA_TLSDESC and PseudoTLSDESCCall in RISCVInstrInfo.td,
as well as 2 additional tests covering the V-register clobber
and V-CSRs clobber cases.
---
 llvm/lib/Target/RISCV/RISCVInstrInfo.td       |   8 +-
 .../RISCV/tlsdesc-clobber-vector-csrs.ll      |  61 ++++
 .../RISCV/tlsdesc-clobber-vector-regs.ll      | 338 ++++++++++++++++++
 llvm/test/CodeGen/RISCV/tlsdesc-clobber.ll    |   4 +
 4 files changed, 409 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/RISCV/tlsdesc-clobber-vector-csrs.ll
 create mode 100644 llvm/test/CodeGen/RISCV/tlsdesc-clobber-vector-regs.ll

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 7b72dfbbad91e..5ad3f5c9af497 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1955,9 +1955,13 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 8,
 def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
                              "la.tls.gd", "$dst, $src">;
 
+defvar TLSDESCVClobbers = !listconcat(
+    !foreach(i, !range(32), !cast<Register>("V"#i)),
+    [VTYPE, VL, VXSAT, VXRM]);
+
 let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 32 in
 def PseudoLA_TLSDESC : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), []> {
-  let Defs = [X5, X10];
+  let Defs = !listconcat([X5, X10], TLSDESCVClobbers);
 }
 
 def TLSDESCCallSymbol : AsmOperandClass {
@@ -1982,7 +1986,7 @@ def PseudoTLSDESCCall : Pseudo<(outs GPR:$rd),
                          (ins GPR:$rs1, simm12_lo:$imm12, tlsdesc_call_symbol:$src), [],
                          "jalr", "$rd, ${imm12}(${rs1}), $src">,
                          Sched<[WriteJalr, ReadJalr]> {
-  let Defs = [X10];
+  let Defs = !listconcat([X10], TLSDESCVClobbers);
   let Uses = [X10];
 }
 
diff --git a/llvm/test/CodeGen/RISCV/tlsdesc-clobber-vector-csrs.ll b/llvm/test/CodeGen/RISCV/tlsdesc-clobber-vector-csrs.ll
new file mode 100644
index 0000000000000..f6ca65650031f
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/tlsdesc-clobber-vector-csrs.ll
@@ -0,0 +1,61 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv64 -mattr=+v -relocation-model=pic -enable-tlsdesc < %s \
+; RUN:     | FileCheck %s --check-prefix=RV64
+; RUN: llc -mtriple=riscv32 -mattr=+v -relocation-model=pic -enable-tlsdesc < %s \
+; RUN:     | FileCheck %s --check-prefix=RV32
+
+;; 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 vsetvl after the TLSDESC call to recover the vector configuration
+
+ at tls_var = external thread_local global i32
+
+define void @test_vector_csr_clobber(ptr %in, ptr %out) nounwind {
+; RV64-LABEL: test_vector_csr_clobber:
+; RV64:       # %bb.0: # %entry
+; RV64-NEXT:    mv a2, a0
+; RV64-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV64-NEXT:    vle32.v v8, (a0)
+; RV64-NEXT:  .Ltlsdesc_hi0:
+; RV64-NEXT:    auipc a0, %tlsdesc_hi(tls_var)
+; RV64-NEXT:    vse32.v v8, (a1)
+; RV64-NEXT:    ld a3, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0)
+; RV64-NEXT:    addi a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0)
+; RV64-NEXT:    jalr t0, 0(a3), %tlsdesc_call(.Ltlsdesc_hi0)
+; RV64-NEXT:    add a0, a0, tp
+; RV64-NEXT:    li a3, 1
+; RV64-NEXT:    sw a3, 0(a0)
+; RV64-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV64-NEXT:    vle32.v v8, (a2)
+; RV64-NEXT:    vse32.v v8, (a1)
+; RV64-NEXT:    ret
+;
+; RV32-LABEL: test_vector_csr_clobber:
+; RV32:       # %bb.0: # %entry
+; RV32-NEXT:    mv a2, a0
+; RV32-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV32-NEXT:    vle32.v v8, (a0)
+; RV32-NEXT:  .Ltlsdesc_hi0:
+; RV32-NEXT:    auipc a0, %tlsdesc_hi(tls_var)
+; RV32-NEXT:    vse32.v v8, (a1)
+; RV32-NEXT:    lw a3, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0)
+; RV32-NEXT:    addi a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0)
+; RV32-NEXT:    jalr t0, 0(a3), %tlsdesc_call(.Ltlsdesc_hi0)
+; RV32-NEXT:    add a0, a0, tp
+; RV32-NEXT:    li a3, 1
+; RV32-NEXT:    sw a3, 0(a0)
+; RV32-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; RV32-NEXT:    vle32.v v8, (a2)
+; RV32-NEXT:    vse32.v v8, (a1)
+; RV32-NEXT:    ret
+entry:
+  %v1 = load <4 x i32>, ptr %in
+  store <4 x i32> %v1, ptr %out
+
+  store i32 1, ptr @tls_var
+
+  ;; We must re-emit vsetvli here because TLSDESC clobbered it
+  %v2 = load <4 x i32>, ptr %in
+  store <4 x i32> %v2, ptr %out
+  ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/tlsdesc-clobber-vector-regs.ll b/llvm/test/CodeGen/RISCV/tlsdesc-clobber-vector-regs.ll
new file mode 100644
index 0000000000000..a5e3ede958825
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/tlsdesc-clobber-vector-regs.ll
@@ -0,0 +1,338 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv64 -mattr=+v -relocation-model=pic -enable-tlsdesc < %s \
+; RUN:     | FileCheck %s --check-prefix=RV64
+; RUN: llc -mtriple=riscv32 -mattr=+v -relocation-model=pic -enable-tlsdesc < %s \
+; RUN:     | FileCheck %s --check-prefix=RV32
+
+;; Verify that when the V extension is enabled, vector registers whose live
+;; ranges span a TLSDESC call are spilled and reloaded, because the TLSDESC
+;; resolver clobbers all vector registers per the psABI.
+
+ at tls_var = external thread_local global i32
+
+define void @test_vector_reg_clobber() nounwind {
+; RV64-LABEL: test_vector_reg_clobber:
+; RV64:       # %bb.0: # %entry
+; RV64-NEXT:    addi sp, sp, -16
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a0, a0, 3
+; RV64-NEXT:    sub sp, sp, a0
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # def v1
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a1, a0, 3
+; RV64-NEXT:    sub a0, a1, a0
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vs1r.v v1, (a0) # vscale x 8-byte Folded Spill
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # def v2
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a0, a0, 1
+; RV64-NEXT:    mv a1, a0
+; RV64-NEXT:    slli a0, a0, 1
+; RV64-NEXT:    add a0, a0, a1
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vs1r.v v2, (a0) # vscale x 8-byte Folded Spill
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # def v3
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a1, a0, 2
+; RV64-NEXT:    add a0, a1, a0
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vs1r.v v3, (a0) # vscale x 8-byte Folded Spill
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # def v4
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a0, a0, 2
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vs1r.v v4, (a0) # vscale x 8-byte Folded Spill
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # def v5
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a1, a0, 1
+; RV64-NEXT:    add a0, a1, a0
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vs1r.v v5, (a0) # vscale x 8-byte Folded Spill
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # def v6
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a0, a0, 1
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vs1r.v v6, (a0) # vscale x 8-byte Folded Spill
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # def v7
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vs1r.v v7, (a0) # vscale x 8-byte Folded Spill
+; RV64-NEXT:  .Ltlsdesc_hi0:
+; RV64-NEXT:    auipc a0, %tlsdesc_hi(tls_var)
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # def v8
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    addi a1, sp, 16
+; RV64-NEXT:    vs1r.v v8, (a1) # vscale x 8-byte Folded Spill
+; RV64-NEXT:    ld a1, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0)
+; RV64-NEXT:    addi a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0)
+; RV64-NEXT:    jalr t0, 0(a1), %tlsdesc_call(.Ltlsdesc_hi0)
+; RV64-NEXT:    add a0, a0, tp
+; RV64-NEXT:    li a1, 1
+; RV64-NEXT:    sw a1, 0(a0)
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a1, a0, 3
+; RV64-NEXT:    sub a0, a1, a0
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vl1r.v v1, (a0) # vscale x 8-byte Folded Reload
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # use v1
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a0, a0, 1
+; RV64-NEXT:    mv a1, a0
+; RV64-NEXT:    slli a0, a0, 1
+; RV64-NEXT:    add a0, a0, a1
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vl1r.v v2, (a0) # vscale x 8-byte Folded Reload
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # use v2
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a1, a0, 2
+; RV64-NEXT:    add a0, a1, a0
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vl1r.v v3, (a0) # vscale x 8-byte Folded Reload
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # use v3
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a0, a0, 2
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vl1r.v v4, (a0) # vscale x 8-byte Folded Reload
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # use v4
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a1, a0, 1
+; RV64-NEXT:    add a0, a1, a0
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vl1r.v v5, (a0) # vscale x 8-byte Folded Reload
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # use v5
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a0, a0, 1
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vl1r.v v6, (a0) # vscale x 8-byte Folded Reload
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # use v6
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    add a0, sp, a0
+; RV64-NEXT:    addi a0, a0, 16
+; RV64-NEXT:    vl1r.v v7, (a0) # vscale x 8-byte Folded Reload
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # use v7
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    addi a0, sp, 16
+; RV64-NEXT:    vl1r.v v8, (a0) # vscale x 8-byte Folded Reload
+; RV64-NEXT:    #APP
+; RV64-NEXT:    # use v8
+; RV64-NEXT:    #NO_APP
+; RV64-NEXT:    csrr a0, vlenb
+; RV64-NEXT:    slli a0, a0, 3
+; RV64-NEXT:    add sp, sp, a0
+; RV64-NEXT:    addi sp, sp, 16
+; RV64-NEXT:    ret
+;
+; RV32-LABEL: test_vector_reg_clobber:
+; RV32:       # %bb.0: # %entry
+; RV32-NEXT:    addi sp, sp, -16
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a0, a0, 3
+; RV32-NEXT:    sub sp, sp, a0
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # def v1
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a1, a0, 3
+; RV32-NEXT:    sub a0, a1, a0
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vs1r.v v1, (a0) # vscale x 8-byte Folded Spill
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # def v2
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a0, a0, 1
+; RV32-NEXT:    mv a1, a0
+; RV32-NEXT:    slli a0, a0, 1
+; RV32-NEXT:    add a0, a0, a1
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vs1r.v v2, (a0) # vscale x 8-byte Folded Spill
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # def v3
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a1, a0, 2
+; RV32-NEXT:    add a0, a1, a0
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vs1r.v v3, (a0) # vscale x 8-byte Folded Spill
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # def v4
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a0, a0, 2
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vs1r.v v4, (a0) # vscale x 8-byte Folded Spill
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # def v5
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a1, a0, 1
+; RV32-NEXT:    add a0, a1, a0
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vs1r.v v5, (a0) # vscale x 8-byte Folded Spill
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # def v6
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a0, a0, 1
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vs1r.v v6, (a0) # vscale x 8-byte Folded Spill
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # def v7
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vs1r.v v7, (a0) # vscale x 8-byte Folded Spill
+; RV32-NEXT:  .Ltlsdesc_hi0:
+; RV32-NEXT:    auipc a0, %tlsdesc_hi(tls_var)
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # def v8
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    addi a1, sp, 16
+; RV32-NEXT:    vs1r.v v8, (a1) # vscale x 8-byte Folded Spill
+; RV32-NEXT:    lw a1, %tlsdesc_load_lo(.Ltlsdesc_hi0)(a0)
+; RV32-NEXT:    addi a0, a0, %tlsdesc_add_lo(.Ltlsdesc_hi0)
+; RV32-NEXT:    jalr t0, 0(a1), %tlsdesc_call(.Ltlsdesc_hi0)
+; RV32-NEXT:    add a0, a0, tp
+; RV32-NEXT:    li a1, 1
+; RV32-NEXT:    sw a1, 0(a0)
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a1, a0, 3
+; RV32-NEXT:    sub a0, a1, a0
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vl1r.v v1, (a0) # vscale x 8-byte Folded Reload
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # use v1
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a0, a0, 1
+; RV32-NEXT:    mv a1, a0
+; RV32-NEXT:    slli a0, a0, 1
+; RV32-NEXT:    add a0, a0, a1
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vl1r.v v2, (a0) # vscale x 8-byte Folded Reload
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # use v2
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a1, a0, 2
+; RV32-NEXT:    add a0, a1, a0
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vl1r.v v3, (a0) # vscale x 8-byte Folded Reload
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # use v3
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a0, a0, 2
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vl1r.v v4, (a0) # vscale x 8-byte Folded Reload
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # use v4
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a1, a0, 1
+; RV32-NEXT:    add a0, a1, a0
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vl1r.v v5, (a0) # vscale x 8-byte Folded Reload
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # use v5
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a0, a0, 1
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vl1r.v v6, (a0) # vscale x 8-byte Folded Reload
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # use v6
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    add a0, sp, a0
+; RV32-NEXT:    addi a0, a0, 16
+; RV32-NEXT:    vl1r.v v7, (a0) # vscale x 8-byte Folded Reload
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # use v7
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    addi a0, sp, 16
+; RV32-NEXT:    vl1r.v v8, (a0) # vscale x 8-byte Folded Reload
+; RV32-NEXT:    #APP
+; RV32-NEXT:    # use v8
+; RV32-NEXT:    #NO_APP
+; RV32-NEXT:    csrr a0, vlenb
+; RV32-NEXT:    slli a0, a0, 3
+; RV32-NEXT:    add sp, sp, a0
+; RV32-NEXT:    addi sp, sp, 16
+; RV32-NEXT:    ret
+entry:
+  %v1 = call <vscale x 2 x i32> asm sideeffect "# def v1", "={v1}"()
+  %v2 = call <vscale x 2 x i32> asm sideeffect "# def v2", "={v2}"()
+  %v3 = call <vscale x 2 x i32> asm sideeffect "# def v3", "={v3}"()
+  %v4 = call <vscale x 2 x i32> asm sideeffect "# def v4", "={v4}"()
+  %v5 = call <vscale x 2 x i32> asm sideeffect "# def v5", "={v5}"()
+  %v6 = call <vscale x 2 x i32> asm sideeffect "# def v6", "={v6}"()
+  %v7 = call <vscale x 2 x i32> asm sideeffect "# def v7", "={v7}"()
+  %v8 = call <vscale x 2 x i32> asm sideeffect "# def v8", "={v8}"()
+
+  store i32 1, ptr @tls_var
+
+  call void asm sideeffect "# use v1", "{v1}"(<vscale x 2 x i32> %v1)
+  call void asm sideeffect "# use v2", "{v2}"(<vscale x 2 x i32> %v2)
+  call void asm sideeffect "# use v3", "{v3}"(<vscale x 2 x i32> %v3)
+  call void asm sideeffect "# use v4", "{v4}"(<vscale x 2 x i32> %v4)
+  call void asm sideeffect "# use v5", "{v5}"(<vscale x 2 x i32> %v5)
+  call void asm sideeffect "# use v6", "{v6}"(<vscale x 2 x i32> %v6)
+  call void asm sideeffect "# use v7", "{v7}"(<vscale x 2 x i32> %v7)
+  call void asm sideeffect "# use v8", "{v8}"(<vscale x 2 x i32> %v8)
+  ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/tlsdesc-clobber.ll b/llvm/test/CodeGen/RISCV/tlsdesc-clobber.ll
index 132ff7d83235d..6cfd90c65a6f5 100644
--- a/llvm/test/CodeGen/RISCV/tlsdesc-clobber.ll
+++ b/llvm/test/CodeGen/RISCV/tlsdesc-clobber.ll
@@ -3,6 +3,10 @@
 ; RUN:     | FileCheck %s --check-prefix=RV64
 ; RUN: llc -mtriple=riscv32 -relocation-model=pic -enable-tlsdesc < %s \
 ; RUN:     | FileCheck %s --check-prefix=RV32
+; RUN: llc -mtriple=riscv64 -mattr=+v -relocation-model=pic -enable-tlsdesc < %s \
+; RUN:     | FileCheck %s --check-prefix=RV64
+; RUN: llc -mtriple=riscv32 -mattr=+v -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,



More information about the llvm-commits mailing list