https://github.com/LucasChollet updated https://github.com/llvm/llvm-project/pull/206206
>From c00b7eb211f52471a6a399eeb212af813cba8643 Mon Sep 17 00:00:00 2001 From: Lucas Chollet <[email protected]> Date: Tue, 23 Jun 2026 11:30:36 +0200 Subject: [PATCH 1/7] [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/docs/ReleaseNotes.rst | 4 +- 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 ++++++++++++++++++ 9 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 93f770c10afae..1e13333556ed5 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -418,9 +418,7 @@ Modified Compiler Flags - The `-mno-outline` and `-moutline` compiler flags are now allowed on RISC-V and X86, which both support the machine outliner. - The `-mno-outline` flag will now add the `nooutline` IR attribute, so that `-mno-outline` and `-moutline` objects can be mixed correctly during LTO. -- The `-fzero-call-used-regs` compiler flag is now allowed on RISC-V, only the - "skip", "used-gpr", "used-gpr-arg", "all-gpr" and "all-gpr-arg" options are - supported for the moment. +- The `-fzero-call-used-regs` compiler flag is now allowed on RISC-V. - Slightly changed hash id generation to get the unique linkage symbols names by ``-unique-internal-linkage-names`` option. Now it uses a path that diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a3a3954bc464e..418da7ed18d79 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7022,8 +7022,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 e513dcf560e24..9d411f641c0ec 100644 --- a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp +++ b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp @@ -203,6 +203,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 fadbc95a2090f..20ccf87b73ab0 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 RISCVABI::ABI ABI); 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 5c5d081007796..08d402cee42fb 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -1478,15 +1478,32 @@ 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(Reg.id()); } 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 4de0a27790eca..4bbbb3193411b 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -3962,6 +3962,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 7828f07cdbaa5..d56b601c0ef89 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -835,6 +835,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 bb70bfebc9d11da0fc92d53defac841d1dc8fac7 Mon Sep 17 00:00:00 2001 From: Lucas Chollet <[email protected]> Date: Wed, 8 Jul 2026 12:49:44 +0200 Subject: [PATCH 2/7] 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 9d411f641c0ec..d96ba5fff12bf 100644 --- a/llvm/lib/Target/RISCV/RISCVCallingConv.cpp +++ b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp @@ -204,7 +204,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 c14fcbe49abbcc3a33b6736e1f7817dac26e1eff Mon Sep 17 00:00:00 2001 From: Lucas Chollet <[email protected]> Date: Wed, 8 Jul 2026 12:52:17 +0200 Subject: [PATCH 3/7] 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 4bbbb3193411b..68f2c547b4e3e 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp @@ -3966,7 +3966,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 df1e8654c9f5344a937107c53fb4087c10a48c5d Mon Sep 17 00:00:00 2001 From: Lucas Chollet <[email protected]> Date: Wed, 8 Jul 2026 13:56:33 +0200 Subject: [PATCH 4/7] 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 08d402cee42fb..cd40fd7fab355 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -1486,11 +1486,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 c3fe46604f2f6e65cc6d540ad33abb6424f586ae Mon Sep 17 00:00:00 2001 From: Lucas Chollet <[email protected]> Date: Wed, 8 Jul 2026 13:59:23 +0200 Subject: [PATCH 5/7] Always clear VSETVLI's used reg --- llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 11 ++++++++++- llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll | 6 +++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index cd40fd7fab355..5f379062fe4ae 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -1504,7 +1504,16 @@ 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; + } + } + 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..288675a18de0e 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 @@ -146,6 +147,7 @@ define <4 x i32> @used_arg(<4 x i32> %a, <4 x i32> %b) "zero-call-used-regs"="us ; 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: li t0, 0 ; CHECK-NEXT: ret entry: %sum = add <4 x i32> %a, %b @@ -160,6 +162,7 @@ define <8 x i32> @used_arg_lmul2(<8 x i32> %a, <8 x i32> %b) "zero-call-used-reg ; 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: li t0, 0 ; CHECK-NEXT: ret entry: %sum = add <8 x i32> %a, %b @@ -181,6 +184,7 @@ define <32 x i32> @used_arg_lmul8(<32 x i32> %a, <32 x i32> %b) "zero-call-used- ; CHECK-NEXT: vmv.v.i v21, 0 ; CHECK-NEXT: vmv.v.i v22, 0 ; CHECK-NEXT: vmv.v.i v23, 0 +; CHECK-NEXT: li t0, 0 ; CHECK-NEXT: ret entry: %sum = add <32 x i32> %a, %b >From 62bc7f71638d69e7a89a37719b75ae059be21432 Mon Sep 17 00:00:00 2001 From: Lucas Chollet <[email protected]> Date: Wed, 8 Jul 2026 14:16:06 +0200 Subject: [PATCH 6/7] Add a test for unaligned segmented load --- .../CodeGen/RISCV/zero-call-used-regs-v.ll | 26 +++++++++++++++++++ 1 file changed, 26 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 288675a18de0e..a20fecf112905 100644 --- a/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll +++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll @@ -191,3 +191,29 @@ entry: ret <32 x i32> %sum } +; Test unaligned segment load. +define <8 x i8> @load_segment(ptr %base, ptr %out, <8 x i8> %use_v8) "zero-call-used-regs"="used" { +; CHECK-LABEL: load_segment: +; 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 a68cb481a401b909e60ba52e0b392f117b74b649 Mon Sep 17 00:00:00 2001 From: Lucas Chollet <[email protected]> Date: Wed, 8 Jul 2026 16:31:06 +0200 Subject: [PATCH 7/7] 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)>; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
