https://github.com/LucasChollet updated https://github.com/llvm/llvm-project/pull/206206
>From b48c09cf94866208b44961c66dca18f74c56d1cd 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 a30b01a675b99..663055ed68923 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7029,8 +7029,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 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 7dbdc881ea6c0..0b619d57d8a2c 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 eb0bf3ea45ab688bb31ef222b2248ca35b1e851f 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 9b18817f04cc40ff76c2fd2c6c8d9eb9b6629824 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 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 697216c84d21730ecf05ee5078663f634dec3863 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 8bc22359cca777aec36ee888bac7a96564cb7d7a 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 c55da31edb3e49dfdcc0fb0d039736aedf664a6b 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 b29608fe4fd0569fd3ebcc6ef4b9dcae024ed4d7 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 897c49cf40af9fdfce71b853e21be8f11ce3b949 Mon Sep 17 00:00:00 2001 From: Lucas Chollet <[email protected]> Date: Fri, 10 Jul 2026 08:20:35 +0200 Subject: [PATCH 08/14] Update release notes --- clang/docs/ReleaseNotes.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 449a3792eb4ba..4bad3f0a84782 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -448,9 +448,7 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the - 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 normalized in favor of the target system (same as the preprocessor does >From b6ad4e25e2fdf23cf2ecf50302b81d0b1318c522 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 5b0de58f97eddb0bbe6a75f3145f64606710420b 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 786ee6292ecfece9955311f886da0039b62aaace 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 4d8dce80cf78f53ea728115e994b907a065442df 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 205d4f9dbb0e92e77bc058a9376fa559bb571b3c 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 bc6fc444b207b05a28c4164021220faa7632fa8f 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 66b1cc137e06c..e708547a9a3f7 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 6aa8380c99c8b..409fcd546f9de 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
