Author: Lucas Chollet
Date: 2026-07-27T09:37:37Z
New Revision: 8dfdcfb11624fe3eba614af21aa739fffd7ae94f

URL: 
https://github.com/llvm/llvm-project/commit/8dfdcfb11624fe3eba614af21aa739fffd7ae94f
DIFF: 
https://github.com/llvm/llvm-project/commit/8dfdcfb11624fe3eba614af21aa739fffd7ae94f.diff

LOG: [RISCV] Add support for vector registers with -fzero-call-used-regs 
(#206206)

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.

Added: 
    llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/Driver/ToolChains/Clang.cpp
    llvm/include/llvm/CodeGen/TargetFrameLowering.h
    llvm/lib/CodeGen/PrologEpilogInserter.cpp
    llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
    llvm/lib/Target/AArch64/AArch64FrameLowering.h
    llvm/lib/Target/RISCV/RISCVCallingConv.cpp
    llvm/lib/Target/RISCV/RISCVCallingConv.h
    llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
    llvm/lib/Target/RISCV/RISCVFrameLowering.h
    llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
    llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td
    llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
    llvm/lib/Target/X86/X86FrameLowering.cpp
    llvm/lib/Target/X86/X86FrameLowering.h

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 61e8378b1704a..dbbf1b8e88d74 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -155,6 +155,8 @@ features cannot lower the translation-unit ABI level;
 
 ### 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

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 660e61d7c5de3..0904d116b5cba 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7064,9 +7064,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
     // FIXME: There's no reason for this to be restricted to some backend.
     // 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/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 
diff erent section.

diff  --git a/llvm/lib/CodeGen/PrologEpilogInserter.cpp 
b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
index 338c3d0ec98e3..c033079ef8370 100644
--- a/llvm/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/llvm/lib/CodeGen/PrologEpilogInserter.cpp
@@ -1349,7 +1349,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/RISCVCallingConv.cpp 
b/llvm/lib/Target/RISCV/RISCVCallingConv.cpp
index 76bc813d63c43..381ab62e2bd64 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.hasVInstructions())
+    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..b1c943536ae44 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();
 
@@ -1500,6 +1501,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,7 +1514,50 @@ void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector 
RegsToZero,
     } else if (TRI.isFPRegister(Reg)) {
       if (MCRegister MaybeReg = getLargestFPRegisterOrZero(STI, TRI, Reg))
         FinalRegsToZero.set(MaybeReg.id());
+    } else if (RISCVRegisterInfo::isRVVRegClass(
+                   TRI.getMinimalPhysRegClass(Reg))) {
+      if (!STI.hasVInstructions())
+        continue;
+      HasVRegister = true;
+
+      for (MCRegister SubReg : TRI.subregs_inclusive(Reg)) {
+        if (TRI.subregs(SubReg).empty())
+          FinalRegsToZero.set(SubReg.id());
+      }
+    }
+  }
+
+  if (HasVRegister) {
+    RISCVVType::VLMUL VLMUL = RISCVVType::encodeLMUL(1, /*Fractional=*/false);
+    unsigned VTypeImm = RISCVVType::encodeVTYPE(
+        VLMUL, /*SEW=*/32, /*TailAgnostic=*/true, /*MaskAgnostic=*/true);
+
+    MCRegister TemporaryReg = RISCV::NoRegister;
+    for (MCRegister Reg : FinalRegsToZero.set_bits()) {
+      if (TRI.isGeneralPurposeRegister(MF, Reg)) {
+        TemporaryReg = Reg;
+        break;
+      }
+    }
+
+    if (TemporaryReg == RISCV::NoRegister) {
+      RS->enterBasicBlockEnd(MBB);
+      TemporaryReg = RS->scavengeRegisterBackwards(RISCV::GPRRegClass, MBBI,
+                                                   /*RestoreAfter=*/false,
+                                                   /*SPAdj=*/0);
     }
+
+    if (MBB.getParent()
+            ->getFunction()
+            .getFnAttribute("zero-call-used-regs")
+            .getValueAsString() == "used")
+      FinalRegsToZero.set(TemporaryReg.id());
+
+    BuildMI(MBB, MBBI, DL, TII.get(RISCV::VSETVLI), TemporaryReg)
+        .addReg(RISCV::X0)
+        .addImm(VTypeImm)
+        .addReg(RISCV::VL, RegState::ImplicitDefine)
+        .addReg(RISCV::VTYPE, RegState::ImplicitDefine);
   }
 
   for (MCRegister Reg : FinalRegsToZero.set_bits())

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/RISCV/RISCVInstrInfo.cpp 
b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 50f548857a97b..6b8c781714baa 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -3977,9 +3977,11 @@ 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");
+        "buildClearRegister is not implemented for " + TRI.getRegAsmName(Reg));
   }
 }
 

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td 
b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td
index 077b8f8058932..c2bd8b82b2272 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, Uses = [VL, VTYPE] 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/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
new file mode 100644
index 0000000000000..d85897b07db73
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs-v.ll
@@ -0,0 +1,231 @@
+; 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
+; 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
+; 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 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
+; 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 a1, zero, e32, m1, ta, ma
+; CHECK-NEXT:    vmv.v.i v8, 0
+; CHECK-NEXT:    vmv.v.i v9, 0
+; CHECK-NEXT:    li a1, 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 a0, zero, e32, m1, ta, ma
+; CHECK-NEXT:    vmv.v.i v9, 0
+; CHECK-NEXT:    ret
+entry:
+    %sum = add <4 x i32> %a, %b
+    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 a0, zero, e32, m1, ta, ma
+; 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 a0, 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
+; 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
+}
+
+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, ta, ma
+; 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
+}
+
+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