https://github.com/LucasChollet updated 
https://github.com/llvm/llvm-project/pull/206206

>From a8e3f525ae53b301b9d6e65918096a913c19631e Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Tue, 23 Jun 2026 11:30:36 +0200
Subject: [PATCH 01/14] [RISCV] Add support for vector registers with
 -fzero-call-used-regs

The implementation is quite straightforward. Compared to the FP or GP
register implementations, the main difference is that we need to
configure the vector registers before clearing them.

Now that the backend supports clearing all standard registers, this
patch makes the clang driver accept all -fzero-call-used-regs options.
---
 clang/lib/Driver/ToolChains/Clang.cpp         |   3 +-
 llvm/lib/Target/RISCV/RISCVCallingConv.cpp    |   7 +
 llvm/lib/Target/RISCV/RISCVCallingConv.h      |   1 +
 llvm/lib/Target/RISCV/RISCVFrameLowering.cpp  |  17 ++
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp      |   2 +
 .../Target/RISCV/RISCVInstrInfoVPseudos.td    |   5 +
 llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp   |   3 +
 .../CodeGen/RISCV/zero-call-used-regs-v.ll    | 154 ++++++++++++++++++
 8 files changed, 190 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 8c9b98795b194..163e46ae7ad41 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7041,8 +7041,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
     // The backend code needs to be changed to include the appropriate function
     // calls automatically.
     StringRef Value = A->getValue();
-    if (!Triple.isX86() && !Triple.isAArch64() &&
-        !(Triple.isRISCV() && (Value == "skip" || Value.contains("gpr"))))
+    if (!Triple.isX86() && !Triple.isAArch64() && !Triple.isRISCV())
       D.Diag(diag::err_drv_unsupported_opt_for_target)
           << A->getAsString(Args) << TripleStr;
   }
diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp 
b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
index 76bc813d63c43..e98bcc780e1b0 100644
--- a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
@@ -205,6 +205,13 @@ ArrayRef<MCPhysReg> RISCV::getArgFPRs(const RISCVSubtarget 
&STI) {
   return ArrayRef(ArgFPR32s);
 }
 
+ArrayRef<MCPhysReg> RISCV::getArgVRs(const RISCVSubtarget &STI) {
+  if (STI.hasStdExtV())
+    return ArrayRef(ArgVRs);
+
+  return {};
+}
+
 static ArrayRef<MCPhysReg> getArgGPR16s(const RISCVABI::ABI ABI) {
   // The GPRs used for passing arguments in the ILP32* and LP64* ABIs, except
   // the ILP32E ABI.
diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.h 
b/llvm/lib/Target/RISCV/RISCVCallingConv.h
index 42b115a68c1b6..f5b7773b6f384 100644
--- a/llvm/lib/Target/RISCV/RISCVCallingConv.h
+++ b/llvm/lib/Target/RISCV/RISCVCallingConv.h
@@ -27,6 +27,7 @@ namespace RISCV {
 
 ArrayRef<MCPhysReg> getArgGPRs(const RISCVSubtarget &STI);
 ArrayRef<MCPhysReg> getArgFPRs(const RISCVSubtarget &STI);
+ArrayRef<MCPhysReg> getArgVRs(const RISCVSubtarget &STI);
 
 } // end namespace RISCV
 
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index bbd1738cd5117..031491b3be3cc 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1500,6 +1500,8 @@ void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector 
RegsToZero,
 
   BitVector FinalRegsToZero(TRI.getNumRegs());
 
+  bool HasVRegister = false;
+
   for (MCRegister Reg : RegsToZero.set_bits()) {
     if (TRI.isGeneralPurposeRegister(MF, Reg)) {
       FinalRegsToZero.set(getPhysicalGPR(TRI, Reg).id());
@@ -1511,9 +1513,24 @@ void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector 
RegsToZero,
     } else if (TRI.isFPRegister(Reg)) {
       if (MCRegister MaybeReg = getLargestFPRegisterOrZero(STI, TRI, Reg))
         FinalRegsToZero.set(MaybeReg.id());
+    } else if (RISCV::VRRegClass.contains(Reg)) {
+      if (!STI.hasStdExtV())
+        continue;
+      HasVRegister = true;
+      FinalRegsToZero.set(Reg.id());
     }
   }
 
+  if (HasVRegister) {
+    RISCVVType::VLMUL VLMUL = RISCVVType::encodeLMUL(1, /*Fractional=*/false);
+    unsigned VTypeImm = RISCVVType::encodeVTYPE(
+        VLMUL, /*SEW=*/32, /*TailAgnostic=*/false, /*MaskAgnostic=*/false);
+
+    BuildMI(MBB, MBBI, DL, TII.get(RISCV::VSETVLI), RISCV::X5)
+        .addReg(RISCV::X0)
+        .addImm(VTypeImm);
+  }
+
   for (MCRegister Reg : FinalRegsToZero.set_bits())
     TII.buildClearRegister(Reg, MBB, MBBI, DL);
 }
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp 
b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 50f548857a97b..72ac24473473f 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -3977,6 +3977,8 @@ void RISCVInstrInfo::buildClearRegister(Register Reg, 
MachineBasicBlock &MBB,
     BuildMI(MBB, Iter, DL, get(RISCV::PseudoClearFPR64), Reg);
   } else if (RISCV::FPR128RegClass.contains(Reg)) {
     BuildMI(MBB, Iter, DL, get(RISCV::PseudoClearFPR128), Reg);
+  } else if (RISCV::VRRegClass.contains(Reg)) {
+    BuildMI(MBB, Iter, DL, get(RISCV::PseudoClearVR), Reg);
   } else {
     llvm::reportFatalInternalError(
         "buildClearRegister is not implemented for vector registers");
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td 
b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td
index 077b8f8058932..4a39376aa0107 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td
@@ -6069,6 +6069,11 @@ foreach lmul = MxList in {
   }
 }
 
+// Used by -fzero-call-used-regs to zero out registers.
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+def PseudoClearVR : Pseudo<(outs VR:$vd), (ins), []>,
+                    PseudoInstExpansion<(VMV_V_I VR:$vd, 0)>;
+
 
//===----------------------------------------------------------------------===//
 // 6. Configuration-Setting Instructions
 
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp 
b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index 3311841505685..3dfb8af892bd9 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -841,6 +841,9 @@ bool RISCVRegisterInfo::isArgumentRegister(const 
MachineFunction &MF,
   if (TRI->isFPRegister(Reg))
     return llvm::is_contained(RISCV::getArgFPRs(STI), Reg);
 
+  if (RISCV::VRRegClass.contains(Reg))
+    return llvm::is_contained(RISCV::getArgVRs(STI), Reg);
+
   return false;
 }
 
diff --git a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll 
b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
new file mode 100644
index 0000000000000..c270bc9960f7e
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
@@ -0,0 +1,154 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 6
+; RUN: llc < %s -verify-machineinstrs -mtriple=riscv64-unknown-unknown 
-mattr="+i,+m,+v" | FileCheck %s  --check-prefixes=CHECK
+
+define void @all() "zero-call-used-regs"="all" {
+; CHECK-LABEL: all:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vmv.v.i v0, 0
+; CHECK-NEXT:    vmv.v.i v1, 0
+; CHECK-NEXT:    vmv.v.i v2, 0
+; CHECK-NEXT:    vmv.v.i v3, 0
+; CHECK-NEXT:    vmv.v.i v4, 0
+; CHECK-NEXT:    vmv.v.i v5, 0
+; CHECK-NEXT:    vmv.v.i v6, 0
+; CHECK-NEXT:    vmv.v.i v7, 0
+; CHECK-NEXT:    vmv.v.i v8, 0
+; CHECK-NEXT:    vmv.v.i v9, 0
+; CHECK-NEXT:    vmv.v.i v10, 0
+; CHECK-NEXT:    vmv.v.i v11, 0
+; CHECK-NEXT:    vmv.v.i v12, 0
+; CHECK-NEXT:    vmv.v.i v13, 0
+; CHECK-NEXT:    vmv.v.i v14, 0
+; CHECK-NEXT:    vmv.v.i v15, 0
+; CHECK-NEXT:    vmv.v.i v16, 0
+; CHECK-NEXT:    vmv.v.i v17, 0
+; CHECK-NEXT:    vmv.v.i v18, 0
+; CHECK-NEXT:    vmv.v.i v19, 0
+; CHECK-NEXT:    vmv.v.i v20, 0
+; CHECK-NEXT:    vmv.v.i v21, 0
+; CHECK-NEXT:    vmv.v.i v22, 0
+; CHECK-NEXT:    vmv.v.i v23, 0
+; CHECK-NEXT:    vmv.v.i v24, 0
+; CHECK-NEXT:    vmv.v.i v25, 0
+; CHECK-NEXT:    vmv.v.i v26, 0
+; CHECK-NEXT:    vmv.v.i v27, 0
+; CHECK-NEXT:    vmv.v.i v28, 0
+; CHECK-NEXT:    vmv.v.i v29, 0
+; CHECK-NEXT:    vmv.v.i v30, 0
+; CHECK-NEXT:    vmv.v.i v31, 0
+; CHECK-NEXT:    li t0, 0
+; CHECK-NEXT:    li t1, 0
+; CHECK-NEXT:    li t2, 0
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    li a1, 0
+; CHECK-NEXT:    li a2, 0
+; CHECK-NEXT:    li a3, 0
+; CHECK-NEXT:    li a4, 0
+; CHECK-NEXT:    li a5, 0
+; CHECK-NEXT:    li a6, 0
+; CHECK-NEXT:    li a7, 0
+; CHECK-NEXT:    li t3, 0
+; CHECK-NEXT:    li t4, 0
+; CHECK-NEXT:    li t5, 0
+; CHECK-NEXT:    li t6, 0
+; CHECK-NEXT:    fmv.d.x ft0, zero
+; CHECK-NEXT:    fmv.d.x ft1, zero
+; CHECK-NEXT:    fmv.d.x ft2, zero
+; CHECK-NEXT:    fmv.d.x ft3, zero
+; CHECK-NEXT:    fmv.d.x ft4, zero
+; CHECK-NEXT:    fmv.d.x ft5, zero
+; CHECK-NEXT:    fmv.d.x ft6, zero
+; CHECK-NEXT:    fmv.d.x ft7, zero
+; CHECK-NEXT:    fmv.d.x fa0, zero
+; CHECK-NEXT:    fmv.d.x fa1, zero
+; CHECK-NEXT:    fmv.d.x fa2, zero
+; CHECK-NEXT:    fmv.d.x fa3, zero
+; CHECK-NEXT:    fmv.d.x fa4, zero
+; CHECK-NEXT:    fmv.d.x fa5, zero
+; CHECK-NEXT:    fmv.d.x fa6, zero
+; CHECK-NEXT:    fmv.d.x fa7, zero
+; CHECK-NEXT:    fmv.d.x ft8, zero
+; CHECK-NEXT:    fmv.d.x ft9, zero
+; CHECK-NEXT:    fmv.d.x ft10, zero
+; CHECK-NEXT:    fmv.d.x ft11, zero
+; CHECK-NEXT:    ret
+entry:
+  ret void
+}
+
+define void @all_arg() "zero-call-used-regs"="all-arg" {
+; CHECK-LABEL: all_arg:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vmv.v.i v8, 0
+; CHECK-NEXT:    vmv.v.i v9, 0
+; CHECK-NEXT:    vmv.v.i v10, 0
+; CHECK-NEXT:    vmv.v.i v11, 0
+; CHECK-NEXT:    vmv.v.i v12, 0
+; CHECK-NEXT:    vmv.v.i v13, 0
+; CHECK-NEXT:    vmv.v.i v14, 0
+; CHECK-NEXT:    vmv.v.i v15, 0
+; CHECK-NEXT:    vmv.v.i v16, 0
+; CHECK-NEXT:    vmv.v.i v17, 0
+; CHECK-NEXT:    vmv.v.i v18, 0
+; CHECK-NEXT:    vmv.v.i v19, 0
+; CHECK-NEXT:    vmv.v.i v20, 0
+; CHECK-NEXT:    vmv.v.i v21, 0
+; CHECK-NEXT:    vmv.v.i v22, 0
+; CHECK-NEXT:    vmv.v.i v23, 0
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    li a1, 0
+; CHECK-NEXT:    li a2, 0
+; CHECK-NEXT:    li a3, 0
+; CHECK-NEXT:    li a4, 0
+; CHECK-NEXT:    li a5, 0
+; CHECK-NEXT:    li a6, 0
+; CHECK-NEXT:    li a7, 0
+; CHECK-NEXT:    fmv.d.x fa0, zero
+; CHECK-NEXT:    fmv.d.x fa1, zero
+; CHECK-NEXT:    fmv.d.x fa2, zero
+; CHECK-NEXT:    fmv.d.x fa3, zero
+; CHECK-NEXT:    fmv.d.x fa4, zero
+; CHECK-NEXT:    fmv.d.x fa5, zero
+; CHECK-NEXT:    fmv.d.x fa6, zero
+; CHECK-NEXT:    fmv.d.x fa7, zero
+; CHECK-NEXT:    ret
+entry:
+  ret void
+}
+
+define i32 @used(i32 %x) "zero-call-used-regs"="used" {
+; CHECK-LABEL: used:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT:    vmv.s.x v8, zero
+; CHECK-NEXT:    vmv.v.x v9, a0
+; CHECK-NEXT:    vredsum.vs v8, v9, v8
+; CHECK-NEXT:    vmv.x.s a0, v8
+; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vmv.v.i v8, 0
+; CHECK-NEXT:    vmv.v.i v9, 0
+; CHECK-NEXT:    ret
+entry:
+    %tmp = insertelement <4 x i32> poison, i32 %x, i32 0
+    %vec = shufflevector <4 x i32> %tmp, <4 x i32> poison,
+                         <4 x i32> zeroinitializer
+
+    %sum = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %vec)
+    ret i32 %sum
+}
+
+define <4 x i32> @used_arg(<4 x i32> %a, <4 x i32> %b) 
"zero-call-used-regs"="used-arg" {
+; CHECK-LABEL: used_arg:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT:    vadd.vv v8, v8, v9
+; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vmv.v.i v9, 0
+; CHECK-NEXT:    ret
+entry:
+    %sum = add <4 x i32> %a, %b
+    ret <4 x i32> %sum
+}
+

>From 62761221569b7385c4db9083438121f4df3939b6 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Wed, 8 Jul 2026 12:49:44 +0200
Subject: [PATCH 02/14] Prefer hasVInstructions

---
 llvm/lib/Target/RISCV/RISCVCallingConv.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp 
b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
index e98bcc780e1b0..381ab62e2bd64 100644
--- a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
+++ b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
@@ -206,7 +206,7 @@ ArrayRef<MCPhysReg> RISCV::getArgFPRs(const RISCVSubtarget 
&STI) {
 }
 
 ArrayRef<MCPhysReg> RISCV::getArgVRs(const RISCVSubtarget &STI) {
-  if (STI.hasStdExtV())
+  if (STI.hasVInstructions())
     return ArrayRef(ArgVRs);
 
   return {};

>From e407a3277ed0d26fc07b9a17fcff54a49fa8b75e Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Wed, 8 Jul 2026 12:52:17 +0200
Subject: [PATCH 03/14] Remove stale error

---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp 
b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 72ac24473473f..6b8c781714baa 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -3981,7 +3981,7 @@ void RISCVInstrInfo::buildClearRegister(Register Reg, 
MachineBasicBlock &MBB,
     BuildMI(MBB, Iter, DL, get(RISCV::PseudoClearVR), Reg);
   } else {
     llvm::reportFatalInternalError(
-        "buildClearRegister is not implemented for vector registers");
+        "buildClearRegister is not implemented for " + TRI.getRegAsmName(Reg));
   }
 }
 

>From 4a23758c6e6588d1f2d0cad89b21b63db4d46b3f Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Wed, 8 Jul 2026 13:56:33 +0200
Subject: [PATCH 04/14] Support MMul > 1

---
 llvm/lib/Target/RISCV/RISCVFrameLowering.cpp  | 11 ++++--
 .../CodeGen/RISCV/zero-call-used-regs-v.ll    | 35 +++++++++++++++++++
 2 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 031491b3be3cc..49418ad740389 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1513,11 +1513,16 @@ void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector 
RegsToZero,
     } else if (TRI.isFPRegister(Reg)) {
       if (MCRegister MaybeReg = getLargestFPRegisterOrZero(STI, TRI, Reg))
         FinalRegsToZero.set(MaybeReg.id());
-    } else if (RISCV::VRRegClass.contains(Reg)) {
-      if (!STI.hasStdExtV())
+    } else if (RISCVRegisterInfo::isRVVRegClass(
+                   TRI.getMinimalPhysRegClass(Reg))) {
+      if (!STI.hasVInstructions())
         continue;
       HasVRegister = true;
-      FinalRegsToZero.set(Reg.id());
+
+      for (MCRegister SubReg : TRI.subregs_inclusive(Reg)) {
+        if (TRI.subregs(SubReg).empty())
+          FinalRegsToZero.set(SubReg.id());
+      }
     }
   }
 
diff --git a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll 
b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
index c270bc9960f7e..b3df824382595 100644
--- a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
@@ -152,3 +152,38 @@ entry:
     ret <4 x i32> %sum
 }
 
+define <8 x i32> @used_arg_lmul2(<8 x i32> %a, <8 x i32> %b) 
"zero-call-used-regs"="used-arg" {
+; CHECK-LABEL: used_arg_lmul2:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
+; CHECK-NEXT:    vadd.vv v8, v8, v10
+; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vmv.v.i v10, 0
+; CHECK-NEXT:    vmv.v.i v11, 0
+; CHECK-NEXT:    ret
+entry:
+    %sum = add <8 x i32> %a, %b
+    ret <8 x i32> %sum
+}
+
+define <32 x i32> @used_arg_lmul8(<32 x i32> %a, <32 x i32> %b) 
"zero-call-used-regs"="used-arg" {
+; CHECK-LABEL: used_arg_lmul8:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    li a0, 32
+; CHECK-NEXT:    vsetvli zero, a0, e32, m8, ta, ma
+; CHECK-NEXT:    vadd.vv v8, v8, v16
+; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vmv.v.i v16, 0
+; CHECK-NEXT:    vmv.v.i v17, 0
+; CHECK-NEXT:    vmv.v.i v18, 0
+; CHECK-NEXT:    vmv.v.i v19, 0
+; CHECK-NEXT:    vmv.v.i v20, 0
+; CHECK-NEXT:    vmv.v.i v21, 0
+; CHECK-NEXT:    vmv.v.i v22, 0
+; CHECK-NEXT:    vmv.v.i v23, 0
+; CHECK-NEXT:    ret
+entry:
+    %sum = add <32 x i32> %a, %b
+    ret <32 x i32> %sum
+}
+

>From 5288047f62b57eae27cf2498f25018d7024c0c97 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Wed, 8 Jul 2026 13:59:23 +0200
Subject: [PATCH 05/14] Also clear VSETVLI's used reg

---
 llvm/lib/Target/RISCV/RISCVFrameLowering.cpp     | 15 ++++++++++++++-
 llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll |  3 ++-
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 49418ad740389..c2ddb06212e97 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1531,7 +1531,20 @@ void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector 
RegsToZero,
     unsigned VTypeImm = RISCVVType::encodeVTYPE(
         VLMUL, /*SEW=*/32, /*TailAgnostic=*/false, /*MaskAgnostic=*/false);
 
-    BuildMI(MBB, MBBI, DL, TII.get(RISCV::VSETVLI), RISCV::X5)
+    MCRegister TemporaryReg = RISCV::X5;
+    for (MCRegister Reg : FinalRegsToZero.set_bits()) {
+      if (TRI.isGeneralPurposeRegister(MF, Reg)) {
+        TemporaryReg = Reg;
+        break;
+      }
+    }
+    if (MBB.getParent()
+            ->getFunction()
+            .getFnAttribute("zero-call-used-regs")
+            .getValueAsString() == "used")
+      FinalRegsToZero.set(TemporaryReg);
+
+    BuildMI(MBB, MBBI, DL, TII.get(RISCV::VSETVLI), TemporaryReg)
         .addReg(RISCV::X0)
         .addImm(VTypeImm);
   }
diff --git a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll 
b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
index b3df824382595..0b6e914153c5b 100644
--- a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
@@ -80,7 +80,7 @@ entry:
 define void @all_arg() "zero-call-used-regs"="all-arg" {
 ; CHECK-LABEL: all_arg:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vsetvli a0, zero, e32, m1, tu, mu
 ; CHECK-NEXT:    vmv.v.i v8, 0
 ; CHECK-NEXT:    vmv.v.i v9, 0
 ; CHECK-NEXT:    vmv.v.i v10, 0
@@ -129,6 +129,7 @@ define i32 @used(i32 %x) "zero-call-used-regs"="used" {
 ; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
 ; CHECK-NEXT:    vmv.v.i v8, 0
 ; CHECK-NEXT:    vmv.v.i v9, 0
+; CHECK-NEXT:    li t0, 0
 ; CHECK-NEXT:    ret
 entry:
     %tmp = insertelement <4 x i32> poison, i32 %x, i32 0

>From e44beb4044d99a72bb5721251995137872c6b22d Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Wed, 8 Jul 2026 14:16:06 +0200
Subject: [PATCH 06/14] Add a test for unaligned segmented load

---
 .../CodeGen/RISCV/zero-call-used-regs-v.ll    | 25 +++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll 
b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
index 0b6e914153c5b..e6f34e4e0761a 100644
--- a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
@@ -188,3 +188,28 @@ entry:
     ret <32 x i32> %sum
 }
 
+define <8 x i8> @load_segmented(ptr %base, ptr %out, <8 x i8> %use_v8) 
"zero-call-used-regs"="used" {
+; CHECK-LABEL: load_segmented:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vsetivli zero, 0, e8, m1, ta, ma
+; CHECK-NEXT:    vlseg2e8.v v9, (a0)
+; CHECK-NEXT:    vs1r.v v9, (a1)
+; CHECK-NEXT:    vsetvli a0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vmv.v.i v9, 0
+; CHECK-NEXT:    vmv.v.i v10, 0
+; CHECK-NEXT:    li a0, 0
+; CHECK-NEXT:    li a1, 0
+; CHECK-NEXT:    ret
+entry:
+  %tuple = call target("riscv.vector.tuple", <vscale x 8 x i8>, 2)
+      @llvm.riscv.vlseg2.triscv.vector.tuple_nxv8i8_2t.i64(
+          target("riscv.vector.tuple", <vscale x 8 x i8>, 2) poison,
+          ptr %base,
+          i64 0,
+          i64 3)
+
+  %v0 = call <vscale x 8 x i8> 
@llvm.riscv.tuple.extract.nxv8i8.triscv.vector.tuple_nxv8i8_2t(
+          target("riscv.vector.tuple", <vscale x 8 x i8>, 2) %tuple, i32 0)
+  store <vscale x 8 x i8> %v0, ptr %out
+  ret <8 x i8> %use_v8
+}

>From 409049071ee87762c1b7d28b9368a77cc60de32e Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Wed, 8 Jul 2026 16:31:06 +0200
Subject: [PATCH 07/14] Uses = [VL, VTYPE]

---
 llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td 
b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td
index 4a39376aa0107..c2bd8b82b2272 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td
@@ -6070,7 +6070,7 @@ foreach lmul = MxList in {
 }
 
 // Used by -fzero-call-used-regs to zero out registers.
-let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
+let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [VL, VTYPE] in
 def PseudoClearVR : Pseudo<(outs VR:$vd), (ins), []>,
                     PseudoInstExpansion<(VMV_V_I VR:$vd, 0)>;
 

>From 4d134193c39ea66543b5a63a4fd54e24a18f144f Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Mon, 20 Jul 2026 17:03:19 +0200
Subject: [PATCH 08/14] Update release notes

# Conflicts:
#       clang/docs/ReleaseNotes.md
---
 clang/docs/ReleaseNotes.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 5f759555e371c..59fab4bd3b7dc 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -119,6 +119,8 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 
 ### Modified Compiler Flags
 
+- All options of the `-fzero-call-used-regs` compiler flag are now allowed on 
RISC-V.
+
 ### Removed Compiler Flags
 
 ### Attribute Changes in Clang

>From 5e74714485d18806a3c8cb78c1156bdb6852dec6 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Sat, 11 Jul 2026 14:30:07 +0200
Subject: [PATCH 09/14] Explicitly use MCRegister::id()

---
 llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index c2ddb06212e97..6a61fe68771f5 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1542,7 +1542,7 @@ void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector 
RegsToZero,
             ->getFunction()
             .getFnAttribute("zero-call-used-regs")
             .getValueAsString() == "used")
-      FinalRegsToZero.set(TemporaryReg);
+      FinalRegsToZero.set(TemporaryReg.id());
 
     BuildMI(MBB, MBBI, DL, TII.get(RISCV::VSETVLI), TemporaryReg)
         .addReg(RISCV::X0)

>From e7d420f5dc99ef6706db950c0c7618ce20c11cf4 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Mon, 20 Jul 2026 10:21:26 +0200
Subject: [PATCH 10/14] Simplify llc invocation

---
 llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll 
b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
index e6f34e4e0761a..8fa89e5e1a6ee 100644
--- a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 6
-; RUN: llc < %s -verify-machineinstrs -mtriple=riscv64-unknown-unknown 
-mattr="+i,+m,+v" | FileCheck %s  --check-prefixes=CHECK
+; RUN: llc < %s -verify-machineinstrs -mtriple=riscv64 -mattr=+v | FileCheck %s
 
 define void @all() "zero-call-used-regs"="all" {
 ; CHECK-LABEL: all:

>From 8b4411beada669bba711694243f1aabe0f4dfda9 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Mon, 20 Jul 2026 10:25:15 +0200
Subject: [PATCH 11/14] Add TODO

---
 llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll 
b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
index 8fa89e5e1a6ee..021209f6eded4 100644
--- a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
@@ -1,6 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 
UTC_ARGS: --version 6
 ; RUN: llc < %s -verify-machineinstrs -mtriple=riscv64 -mattr=+v | FileCheck %s
 
+; TODO: When clearing multiple V registers, find a way to reduce instruction 
count by using LMUL.
+
 define void @all() "zero-call-used-regs"="all" {
 ; CHECK-LABEL: all:
 ; CHECK:       # %bb.0: # %entry

>From fff0fb8974844033d80801957fe3ffd609db53a3 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Mon, 20 Jul 2026 10:27:13 +0200
Subject: [PATCH 12/14] Use TailAgnostic and MaskAgnostic VTYPE

---
 llvm/lib/Target/RISCV/RISCVFrameLowering.cpp     |  2 +-
 llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll | 14 +++++++-------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 6a61fe68771f5..fd5fe2d36e1a7 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1529,7 +1529,7 @@ void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector 
RegsToZero,
   if (HasVRegister) {
     RISCVVType::VLMUL VLMUL = RISCVVType::encodeLMUL(1, /*Fractional=*/false);
     unsigned VTypeImm = RISCVVType::encodeVTYPE(
-        VLMUL, /*SEW=*/32, /*TailAgnostic=*/false, /*MaskAgnostic=*/false);
+        VLMUL, /*SEW=*/32, /*TailAgnostic=*/true, /*MaskAgnostic=*/true);
 
     MCRegister TemporaryReg = RISCV::X5;
     for (MCRegister Reg : FinalRegsToZero.set_bits()) {
diff --git a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll 
b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
index 021209f6eded4..411f6baab8c64 100644
--- a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
@@ -6,7 +6,7 @@
 define void @all() "zero-call-used-regs"="all" {
 ; CHECK-LABEL: all:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vsetvli t0, zero, e32, m1, ta, ma
 ; CHECK-NEXT:    vmv.v.i v0, 0
 ; CHECK-NEXT:    vmv.v.i v1, 0
 ; CHECK-NEXT:    vmv.v.i v2, 0
@@ -82,7 +82,7 @@ entry:
 define void @all_arg() "zero-call-used-regs"="all-arg" {
 ; CHECK-LABEL: all_arg:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vsetvli a0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vsetvli a0, zero, e32, m1, ta, ma
 ; CHECK-NEXT:    vmv.v.i v8, 0
 ; CHECK-NEXT:    vmv.v.i v9, 0
 ; CHECK-NEXT:    vmv.v.i v10, 0
@@ -128,7 +128,7 @@ define i32 @used(i32 %x) "zero-call-used-regs"="used" {
 ; CHECK-NEXT:    vmv.v.x v9, a0
 ; CHECK-NEXT:    vredsum.vs v8, v9, v8
 ; CHECK-NEXT:    vmv.x.s a0, v8
-; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vsetvli t0, zero, e32, m1, ta, ma
 ; CHECK-NEXT:    vmv.v.i v8, 0
 ; CHECK-NEXT:    vmv.v.i v9, 0
 ; CHECK-NEXT:    li t0, 0
@@ -147,7 +147,7 @@ define <4 x i32> @used_arg(<4 x i32> %a, <4 x i32> %b) 
"zero-call-used-regs"="us
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
 ; CHECK-NEXT:    vadd.vv v8, v8, v9
-; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vsetvli t0, zero, e32, m1, ta, ma
 ; CHECK-NEXT:    vmv.v.i v9, 0
 ; CHECK-NEXT:    ret
 entry:
@@ -160,7 +160,7 @@ define <8 x i32> @used_arg_lmul2(<8 x i32> %a, <8 x i32> 
%b) "zero-call-used-reg
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
 ; CHECK-NEXT:    vadd.vv v8, v8, v10
-; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vsetvli t0, zero, e32, m1, ta, ma
 ; CHECK-NEXT:    vmv.v.i v10, 0
 ; CHECK-NEXT:    vmv.v.i v11, 0
 ; CHECK-NEXT:    ret
@@ -175,7 +175,7 @@ define <32 x i32> @used_arg_lmul8(<32 x i32> %a, <32 x i32> 
%b) "zero-call-used-
 ; CHECK-NEXT:    li a0, 32
 ; CHECK-NEXT:    vsetvli zero, a0, e32, m8, ta, ma
 ; CHECK-NEXT:    vadd.vv v8, v8, v16
-; CHECK-NEXT:    vsetvli t0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vsetvli t0, zero, e32, m1, ta, ma
 ; CHECK-NEXT:    vmv.v.i v16, 0
 ; CHECK-NEXT:    vmv.v.i v17, 0
 ; CHECK-NEXT:    vmv.v.i v18, 0
@@ -196,7 +196,7 @@ define <8 x i8> @load_segmented(ptr %base, ptr %out, <8 x 
i8> %use_v8) "zero-cal
 ; CHECK-NEXT:    vsetivli zero, 0, e8, m1, ta, ma
 ; CHECK-NEXT:    vlseg2e8.v v9, (a0)
 ; CHECK-NEXT:    vs1r.v v9, (a1)
-; CHECK-NEXT:    vsetvli a0, zero, e32, m1, tu, mu
+; CHECK-NEXT:    vsetvli a0, zero, e32, m1, ta, ma
 ; CHECK-NEXT:    vmv.v.i v9, 0
 ; CHECK-NEXT:    vmv.v.i v10, 0
 ; CHECK-NEXT:    li a0, 0

>From 40b9d3f32f5fbf38bf06d429995e2eb9b82a743e Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Mon, 20 Jul 2026 16:12:35 +0200
Subject: [PATCH 13/14] Mark VL and VTYPE as ImplicitDefine

---
 llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index fd5fe2d36e1a7..bf878d8e116b3 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1546,7 +1546,9 @@ void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector 
RegsToZero,
 
     BuildMI(MBB, MBBI, DL, TII.get(RISCV::VSETVLI), TemporaryReg)
         .addReg(RISCV::X0)
-        .addImm(VTypeImm);
+        .addImm(VTypeImm)
+        .addReg(RISCV::VL, RegState::ImplicitDefine)
+        .addReg(RISCV::VTYPE, RegState::ImplicitDefine);
   }
 
   for (MCRegister Reg : FinalRegsToZero.set_bits())

>From 62c369f26a24013f4ae2a37cafa83dd533c18dc0 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <[email protected]>
Date: Mon, 20 Jul 2026 16:19:48 +0200
Subject: [PATCH 14/14] Stop hard-coding x5 when emitting vsetvli

---
 .../llvm/CodeGen/TargetFrameLowering.h        |  3 ++-
 llvm/lib/CodeGen/PrologEpilogInserter.cpp     |  2 +-
 .../Target/AArch64/AArch64FrameLowering.cpp   |  3 ++-
 .../lib/Target/AArch64/AArch64FrameLowering.h |  4 ++--
 llvm/lib/Target/RISCV/RISCVFrameLowering.cpp  | 14 +++++++++--
 llvm/lib/Target/RISCV/RISCVFrameLowering.h    |  4 ++--
 llvm/lib/Target/X86/X86FrameLowering.cpp      |  3 ++-
 llvm/lib/Target/X86/X86FrameLowering.h        |  4 ++--
 .../CodeGen/RISCV/zero-call-used-regs-v.ll    | 24 +++++++++++++++----
 9 files changed, 44 insertions(+), 17 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/TargetFrameLowering.h 
b/llvm/include/llvm/CodeGen/TargetFrameLowering.h
index 29d521426bf04..77a1b709d9e17 100644
--- a/llvm/include/llvm/CodeGen/TargetFrameLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetFrameLowering.h
@@ -214,7 +214,8 @@ class LLVM_ABI TargetFrameLowering {
 
   /// emitZeroCallUsedRegs - Zeros out call used registers.
   virtual void emitZeroCallUsedRegs(BitVector RegsToZero,
-                                    MachineBasicBlock &MBB) const {}
+                                    MachineBasicBlock &MBB,
+                                    RegScavenger *RS) const {}
 
   /// With basic block sections, emit callee saved frame moves for basic blocks
   /// that are in a different section.
diff --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp 
b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index 43c7e89113b26..cd9d2d332e16b 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -1347,7 +1347,7 @@ void PEIImpl::insertZeroCallUsedRegs(MachineFunction &MF) 
{
   const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering();
   for (MachineBasicBlock &MBB : MF)
     if (MBB.isReturnBlock())
-      TFI.emitZeroCallUsedRegs(RegsToZero, MBB);
+      TFI.emitZeroCallUsedRegs(RegsToZero, MBB, RS);
 }
 
 /// Replace all FrameIndex operands with physical register references and 
actual
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp 
b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
index a38b9798ac1e5..6ef64b06932ab 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -844,7 +844,8 @@ static MCRegister getRegisterOrZero(MCRegister Reg, bool 
HasSVE) {
 }
 
 void AArch64FrameLowering::emitZeroCallUsedRegs(BitVector RegsToZero,
-                                                MachineBasicBlock &MBB) const {
+                                                MachineBasicBlock &MBB,
+                                                RegScavenger *) const {
   // Insertion point.
   MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
 
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.h 
b/llvm/lib/Target/AArch64/AArch64FrameLowering.h
index 19cc93d01013d..93387e3ca4d84 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.h
@@ -212,8 +212,8 @@ class AArch64FrameLowering : public TargetFrameLowering {
                                 BitVector &SavedRegs) const;
 
   /// Emit target zero call-used regs.
-  void emitZeroCallUsedRegs(BitVector RegsToZero,
-                            MachineBasicBlock &MBB) const override;
+  void emitZeroCallUsedRegs(BitVector RegsToZero, MachineBasicBlock &MBB,
+                            RegScavenger *RS) const override;
 
   /// Replace a StackProbe stub (if any) with the actual probe code inline
   void inlineStackProbe(MachineFunction &MF,
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp 
b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index bf878d8e116b3..e5c95a98a344b 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1485,7 +1485,8 @@ static MCRegister getLargestFPRegisterOrZero(const 
RISCVSubtarget &STI,
 }
 
 void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector RegsToZero,
-                                              MachineBasicBlock &MBB) const {
+                                              MachineBasicBlock &MBB,
+                                              RegScavenger *RS) const {
   // Insertion point.
   MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
 
@@ -1531,13 +1532,22 @@ void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector 
RegsToZero,
     unsigned VTypeImm = RISCVVType::encodeVTYPE(
         VLMUL, /*SEW=*/32, /*TailAgnostic=*/true, /*MaskAgnostic=*/true);
 
-    MCRegister TemporaryReg = RISCV::X5;
+    MCRegister TemporaryReg = RISCV::NoRegister;
     for (MCRegister Reg : FinalRegsToZero.set_bits()) {
       if (TRI.isGeneralPurposeRegister(MF, Reg)) {
         TemporaryReg = Reg;
         break;
       }
     }
+
+    if (TemporaryReg == RISCV::NoRegister) {
+      RS->enterBasicBlock(MBB);
+      RS->backward(MBBI);
+      TemporaryReg = RS->scavengeRegisterBackwards(RISCV::GPRRegClass, MBBI,
+                                                   /*RestoreAfter=*/true,
+                                                   /*SPAdj=*/0);
+    }
+
     if (MBB.getParent()
             ->getFunction()
             .getFnAttribute("zero-call-used-regs")
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.h 
b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
index d79e402e13fbc..f028af803f647 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
@@ -119,8 +119,8 @@ class RISCVFrameLowering : public TargetFrameLowering {
                                    bool DynAllocation) const;
 
   /// Emit target zero call-used regs.
-  void emitZeroCallUsedRegs(BitVector RegsToZero,
-                            MachineBasicBlock &MBB) const override;
+  void emitZeroCallUsedRegs(BitVector RegsToZero, MachineBasicBlock &MBB,
+                            RegScavenger *RS) const override;
 };
 } // namespace llvm
 #endif
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp 
b/llvm/lib/Target/X86/X86FrameLowering.cpp
index a6e1d998c051a..942e014c64b66 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -606,7 +606,8 @@ void X86FrameLowering::emitCalleeSavedFrameMoves(
 }
 
 void X86FrameLowering::emitZeroCallUsedRegs(BitVector RegsToZero,
-                                            MachineBasicBlock &MBB) const {
+                                            MachineBasicBlock &MBB,
+                                            RegScavenger *) const {
   const MachineFunction &MF = *MBB.getParent();
 
   // Insertion point.
diff --git a/llvm/lib/Target/X86/X86FrameLowering.h 
b/llvm/lib/Target/X86/X86FrameLowering.h
index f1e3796f5fddd..d43a6d6133f75 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.h
+++ b/llvm/lib/Target/X86/X86FrameLowering.h
@@ -280,8 +280,8 @@ class X86FrameLowering : public TargetFrameLowering {
                                        uint64_t Align) const;
 
   /// Emit target zero call-used regs.
-  void emitZeroCallUsedRegs(BitVector RegsToZero,
-                            MachineBasicBlock &MBB) const override;
+  void emitZeroCallUsedRegs(BitVector RegsToZero, MachineBasicBlock &MBB,
+                            RegScavenger *RS) const override;
 
   void adjustFrameForMsvcCxxEh(MachineFunction &MF) const;
 
diff --git a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll 
b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
index 411f6baab8c64..8b3c6109d1af8 100644
--- a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
@@ -128,10 +128,10 @@ define i32 @used(i32 %x) "zero-call-used-regs"="used" {
 ; CHECK-NEXT:    vmv.v.x v9, a0
 ; CHECK-NEXT:    vredsum.vs v8, v9, v8
 ; CHECK-NEXT:    vmv.x.s a0, v8
-; CHECK-NEXT:    vsetvli t0, zero, e32, m1, ta, ma
+; CHECK-NEXT:    vsetvli a1, zero, e32, m1, ta, ma
 ; CHECK-NEXT:    vmv.v.i v8, 0
 ; CHECK-NEXT:    vmv.v.i v9, 0
-; CHECK-NEXT:    li t0, 0
+; CHECK-NEXT:    li a1, 0
 ; CHECK-NEXT:    ret
 entry:
     %tmp = insertelement <4 x i32> poison, i32 %x, i32 0
@@ -147,7 +147,7 @@ define <4 x i32> @used_arg(<4 x i32> %a, <4 x i32> %b) 
"zero-call-used-regs"="us
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
 ; CHECK-NEXT:    vadd.vv v8, v8, v9
-; CHECK-NEXT:    vsetvli t0, zero, e32, m1, ta, ma
+; CHECK-NEXT:    vsetvli a0, zero, e32, m1, ta, ma
 ; CHECK-NEXT:    vmv.v.i v9, 0
 ; CHECK-NEXT:    ret
 entry:
@@ -160,7 +160,7 @@ define <8 x i32> @used_arg_lmul2(<8 x i32> %a, <8 x i32> 
%b) "zero-call-used-reg
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
 ; CHECK-NEXT:    vadd.vv v8, v8, v10
-; CHECK-NEXT:    vsetvli t0, zero, e32, m1, ta, ma
+; CHECK-NEXT:    vsetvli a0, zero, e32, m1, ta, ma
 ; CHECK-NEXT:    vmv.v.i v10, 0
 ; CHECK-NEXT:    vmv.v.i v11, 0
 ; CHECK-NEXT:    ret
@@ -175,7 +175,7 @@ define <32 x i32> @used_arg_lmul8(<32 x i32> %a, <32 x i32> 
%b) "zero-call-used-
 ; CHECK-NEXT:    li a0, 32
 ; CHECK-NEXT:    vsetvli zero, a0, e32, m8, ta, ma
 ; CHECK-NEXT:    vadd.vv v8, v8, v16
-; CHECK-NEXT:    vsetvli t0, zero, e32, m1, ta, ma
+; CHECK-NEXT:    vsetvli a1, zero, e32, m1, ta, ma
 ; CHECK-NEXT:    vmv.v.i v16, 0
 ; CHECK-NEXT:    vmv.v.i v17, 0
 ; CHECK-NEXT:    vmv.v.i v18, 0
@@ -215,3 +215,17 @@ entry:
   store <vscale x 8 x i8> %v0, ptr %out
   ret <8 x i8> %use_v8
 }
+
+define <4 x i32> @used_arg_fixed_x10(<4 x i32> %a, <4 x i32> %b) 
"zero-call-used-regs"="used" "target-features"="+reserve-x10" {
+; CHECK-LABEL: used_arg_fixed_x10:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
+; CHECK-NEXT:    vadd.vv v8, v8, v9
+; CHECK-NEXT:    vsetvli a1, zero, e32, m1, ta, ma
+; CHECK-NEXT:    vmv.v.i v9, 0
+; CHECK-NEXT:    li a1, 0
+; CHECK-NEXT:    ret
+entry:
+    %sum = add <4 x i32> %a, %b
+    ret <4 x i32> %sum
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to