[clang] [llvm] [RISCV] Add partial support for -fzero-call-used-regs (PR #194883)
Lucas Chollet via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 30 07:27:36 PDT 2026
https://github.com/LucasChollet updated https://github.com/llvm/llvm-project/pull/194883
>From d334278699f0d2faf41f7141bb09521cf9894191 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Wed, 29 Apr 2026 15:00:27 +0200
Subject: [PATCH 1/4] [RISCV] Add partial support for -fzero-call-used-regs
This implements the "-fzero-call-used-regs" option on RISCV for the
"skip" and "*gpr*" arguments. Zeroing floating points and vector
registers will be implemented later.
---
clang/include/clang/Options/Options.td | 2 +-
clang/lib/Driver/ToolChains/Clang.cpp | 10 +-
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 21 ++
llvm/lib/Target/RISCV/RISCVFrameLowering.h | 4 +
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 16 ++
llvm/lib/Target/RISCV/RISCVInstrInfo.h | 4 +
llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 10 +
llvm/lib/Target/RISCV/RISCVRegisterInfo.h | 3 +
llvm/lib/Target/RISCV/RISCVRegisterInfo.td | 8 +
.../test/CodeGen/RISCV/zero-call-used-regs.ll | 225 ++++++++++++++++++
10 files changed, 298 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/zero-call-used-regs.ll
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index c16c41ad4057d..12edf04797616 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4977,7 +4977,7 @@ defm raw_string_literals : BoolFOption<"raw-string-literals",
def fzero_call_used_regs_EQ
: Joined<["-"], "fzero-call-used-regs=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
- HelpText<"Clear call-used registers upon function return (AArch64/x86 only)">,
+ HelpText<"Clear call-used registers upon function return (AArch64/RISCV/x86 only)">,
Values<"skip,used-gpr-arg,used-gpr,used-arg,used,all-gpr-arg,all-gpr,all-arg,all">,
NormalizedValues<["Skip", "UsedGPRArg", "UsedGPR", "UsedArg", "Used",
"AllGPRArg", "AllGPR", "AllArg", "All"]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index cf5a29f19aaff..00348c3f5ba6e 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6802,10 +6802,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_check_new);
if (Arg *A = Args.getLastArg(options::OPT_fzero_call_used_regs_EQ)) {
- // FIXME: There's no reason for this to be restricted to X86. The backend
- // code needs to be changed to include the appropriate function calls
- // automatically.
- if (!Triple.isX86() && !Triple.isAArch64())
+ // 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"))))
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
}
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 1be81ea93129a..207ffde5cbf23 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1433,6 +1433,27 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
emitSiFiveCLICStackSwap(MF, MBB, MBBI, DL);
}
+void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector RegsToZero,
+ MachineBasicBlock &MBB) const {
+ // Insertion point.
+ MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
+
+ // Fake a debug loc.
+ DebugLoc DL;
+ if (MBBI != MBB.end())
+ DL = MBBI->getDebugLoc();
+
+ const MachineFunction &MF = *MBB.getParent();
+ const RISCVSubtarget &STI = MF.getSubtarget<RISCVSubtarget>();
+ const RISCVRegisterInfo &TRI = STI.getTargetABI();
+ const RISCVInstrInfo &TII = *STI.getInstrInfo();
+
+ for (MCRegister Reg : RegsToZero.set_bits()) {
+ if (TRI.isGeneralPurposeRegister(MF, Reg))
+ TII.buildClearRegister(Reg, MBB, MBBI, DL);
+ }
+}
+
StackOffset
RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
Register &FrameReg) const {
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.h b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
index 84e48dbc05d67..496af9b9fd9cc 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
@@ -115,6 +115,10 @@ class RISCVFrameLowering : public TargetFrameLowering {
const DebugLoc &DL, int64_t Amount,
MachineInstr::MIFlag Flag, bool EmitCFI,
bool DynAllocation) const;
+
+ /// Emit target zero call-used regs.
+ void emitZeroCallUsedRegs(BitVector RegsToZero,
+ MachineBasicBlock &MBB) const override;
};
} // namespace llvm
#endif
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 15024404b05ca..94722a28b2241 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -3939,6 +3939,22 @@ MachineBasicBlock::iterator RISCVInstrInfo::insertOutlinedCall(
return It;
}
+void RISCVInstrInfo::buildClearRegister(Register Reg, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator Iter,
+ DebugLoc &DL,
+ bool AllowSideEffects) const {
+
+ const MachineFunction &MF = *MBB.getParent();
+ const RISCVSubtarget &STI = MF.getSubtarget<RISCVSubtarget>();
+ const RISCVRegisterInfo &TRI = *STI.getRegisterInfo();
+
+ if (TRI.isGeneralPurposeRegister(MF, Reg)) {
+ BuildMI(MBB, Iter, DL, get(RISCV::PseudoLI), Reg).addImm(0);
+ } else {
+ llvm_unreachable("Implement buildClearRegister for non-GPR registers");
+ }
+}
+
std::optional<RegImmPair> RISCVInstrInfo::isAddImmediate(const MachineInstr &MI,
Register Reg) const {
// TODO: Handle cases where Reg is a super- or sub-register of the
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index b11f290c8c107..e816f862301a0 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -256,6 +256,10 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
MachineBasicBlock::iterator &It, MachineFunction &MF,
outliner::Candidate &C) const override;
+ void buildClearRegister(Register Reg, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator Iter, DebugLoc &DL,
+ bool AllowSideEffects = true) const override;
+
std::optional<RegImmPair> isAddImmediate(const MachineInstr &MI,
Register Reg) const override;
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index 6baa30cf9e6f6..520a893b5fe23 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -809,6 +809,16 @@ Register RISCVRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
return TFI->hasFP(MF) ? RISCV::X8 : RISCV::X2;
}
+bool RISCVRegisterInfo::isArgumentRegister(const MachineFunction &MF,
+ MCRegister Reg) const {
+ auto const &STI = MF.getSubtarget<RISCVSubtarget>();
+ if (!STI.getRegisterInfo()->isGeneralPurposeRegister(MF, Reg))
+ llvm_unreachable("Implement isArgumentRegister for non-GPR registers");
+
+ return llvm::any_of(RISCV::getArgGPRs(STI.getTargetABI()),
+ [&](MCPhysReg R) { return Reg == R; });
+}
+
StringRef RISCVRegisterInfo::getRegAsmName(MCRegister Reg) const {
if (Reg == RISCV::SF_VCIX_STATE)
return "sf.vcix_state";
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
index 3a77820d28bbd..df203dc073786 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h
@@ -125,6 +125,9 @@ struct RISCVRegisterInfo : public RISCVGenRegisterInfo {
Register getFrameRegister(const MachineFunction &MF) const override;
+ bool isArgumentRegister(const MachineFunction &MF,
+ MCRegister Reg) const override;
+
StringRef getRegAsmName(MCRegister Reg) const override;
bool requiresRegisterScavenging(const MachineFunction &MF) const override {
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
index d3a387d57b338..7338edca1947a 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -1012,3 +1012,11 @@ def MR : RISCVRegisterClass<[i8, v8i1], 8,
}
def MR0 : RISCVRegisterClass<[i8, v8i1], 8, (add M0)>;
+
+//===----------------------------------------------------------------------===//
+// Register categories.
+//
+
+def GeneralPurposeRegisters : RegisterCategory<[GPR]>;
+
+def FixedRegisters : RegisterCategory<[GPRX0]>;
diff --git a/llvm/test/CodeGen/RISCV/zero-call-used-regs.ll b/llvm/test/CodeGen/RISCV/zero-call-used-regs.ll
new file mode 100644
index 0000000000000..e962f3fe6724c
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs.ll
@@ -0,0 +1,225 @@
+; RUN: llc < %s -verify-machineinstrs -mtriple=riscv64-unknown-unknown | FileCheck %s
+; RUN: llc < %s -verify-machineinstrs -mtriple=riscv32-unknown-unknown | FileCheck %s
+
+target triple = "riscv64-unknown-linux-gnu"
+
+define dso_local i32 @skip(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 "zero-call-used-regs"="skip" {
+; CHECK-LABEL: skip:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mul{{w?}} a0, a1, a0
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: ret
+
+entry:
+ %mul = mul nsw i32 %b, %a
+ %or = or i32 %mul, %c
+ ret i32 %or
+}
+
+define dso_local i32 @used_gpr_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used-gpr-arg" {
+; CHECK-LABEL: used_gpr_arg:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mul{{w?}} a0, a1, a0
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: li a1, 0
+; CHECK-NEXT: li a2, 0
+; CHECK-NEXT: ret
+
+entry:
+ %mul = mul nsw i32 %b, %a
+ %or = or i32 %mul, %c
+ ret i32 %or
+}
+
+define dso_local i32 @used_gpr(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used-gpr" {
+; CHECK-LABEL: used_gpr:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mul{{w?}} a0, a1, a0
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: li a1, 0
+; CHECK-NEXT: li a2, 0
+; CHECK-NEXT: ret
+
+entry:
+ %mul = mul nsw i32 %b, %a
+ %or = or i32 %mul, %c
+ ret i32 %or
+}
+
+define dso_local i32 @used_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used-arg" {
+; CHECK-LABEL: used_arg:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mul{{w?}} a0, a1, a0
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: li a1, 0
+; CHECK-NEXT: li a2, 0
+; CHECK-NEXT: ret
+
+entry:
+ %mul = mul nsw i32 %b, %a
+ %or = or i32 %mul, %c
+ ret i32 %or
+}
+
+define dso_local i32 @used(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used" {
+; CHECK-LABEL: used:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mul{{w?}} a0, a1, a0
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: li a1, 0
+; CHECK-NEXT: li a2, 0
+; CHECK-NEXT: ret
+
+entry:
+ %mul = mul nsw i32 %b, %a
+ %or = or i32 %mul, %c
+ ret i32 %or
+}
+
+define dso_local i32 @all_gpr_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 "zero-call-used-regs"="all-gpr-arg" {
+; CHECK-LABEL: all_gpr_arg:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mul{{w?}} a0, a1, a0
+; CHECK-NEXT: or a0, a0, a2
+; 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: ret
+
+entry:
+ %mul = mul nsw i32 %b, %a
+ %or = or i32 %mul, %c
+ ret i32 %or
+}
+
+define dso_local i32 @all_gpr(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 "zero-call-used-regs"="all-gpr" {
+; CHECK-LABEL: all_gpr:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: mul{{w?}} a0, a1, a0
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: li t0, 0
+; CHECK-NEXT: li t1, 0
+; CHECK-NEXT: li t2, 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: ret
+
+entry:
+ %mul = mul nsw i32 %b, %a
+ %or = or i32 %mul, %c
+ ret i32 %or
+}
+
+define dso_local double @skip_float(double noundef %a, float noundef %b) local_unnamed_addr #0 "zero-call-used-regs"="skip" {
+; CHECK-LABEL: skip_float:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: fcvt.d.s fa5, fa1
+; CHECK-NEXT: fmul.d fa0, fa5, fa0
+; CHECK-NEXT: ret
+
+entry:
+ %conv = fpext float %b to double
+ %mul = fmul double %conv, %a
+ ret double %mul
+}
+
+define dso_local double @used_gpr_arg_float(double noundef %a, float noundef %b) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used-gpr-arg" {
+; CHECK-LABEL: used_gpr_arg_float:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: fcvt.d.s fa5, fa1
+; CHECK-NEXT: fmul.d fa0, fa5, fa0
+; CHECK-NEXT: ret
+
+entry:
+ %conv = fpext float %b to double
+ %mul = fmul double %conv, %a
+ ret double %mul
+}
+
+define dso_local double @used_gpr_float(double noundef %a, float noundef %b) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used-gpr" {
+; CHECK-LABEL: used_gpr_float:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: fcvt.d.s fa5, fa1
+; CHECK-NEXT: fmul.d fa0, fa5, fa0
+; CHECK-NEXT: ret
+
+entry:
+ %conv = fpext float %b to double
+ %mul = fmul double %conv, %a
+ ret double %mul
+}
+
+define dso_local double @all_gpr_arg_float(double noundef %a, float noundef %b) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="all-gpr-arg" {
+; CHECK-LABEL: all_gpr_arg_float:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: fcvt.d.s fa5, fa1
+; CHECK-NEXT: fmul.d fa0, fa5, fa0
+; 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: ret
+
+entry:
+ %conv = fpext float %b to double
+ %mul = fmul double %conv, %a
+ ret double %mul
+}
+
+define dso_local double @all_gpr_float(double noundef %a, float noundef %b) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="all-gpr" {
+; CHECK-LABEL: all_gpr_float:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: fcvt.d.s fa5, fa1
+; CHECK-NEXT: fmul.d fa0, fa5, fa0
+; 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: ret
+
+entry:
+ %conv = fpext float %b to double
+ %mul = fmul double %conv, %a
+ ret double %mul
+}
+
+; Don't emit zeroing registers in "main" function.
+define dso_local i32 @main() local_unnamed_addr #0 {
+; CHECK-LABEL: main:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li a0, 0
+; CHECK-NEXT: ret
+
+entry:
+ ret i32 0
+}
+
+attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn uwtable "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+m,+f,+d" }
>From 2e55fce507fb07468fc9619cf4056a40e02e9596 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Wed, 29 Apr 2026 20:29:58 +0200
Subject: [PATCH 2/4] fix comments #1
---
clang/include/clang/Options/Options.td | 2 +-
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 2 +-
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 3 +-
llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 3 +-
.../test/CodeGen/RISCV/zero-call-used-regs.ll | 28 +++++++++----------
5 files changed, 20 insertions(+), 18 deletions(-)
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 12edf04797616..c5e1fa85a150a 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4977,7 +4977,7 @@ defm raw_string_literals : BoolFOption<"raw-string-literals",
def fzero_call_used_regs_EQ
: Joined<["-"], "fzero-call-used-regs=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
- HelpText<"Clear call-used registers upon function return (AArch64/RISCV/x86 only)">,
+ HelpText<"Clear call-used registers upon function return (AArch64/RISC-V/x86 only)">,
Values<"skip,used-gpr-arg,used-gpr,used-arg,used,all-gpr-arg,all-gpr,all-arg,all">,
NormalizedValues<["Skip", "UsedGPRArg", "UsedGPR", "UsedArg", "Used",
"AllGPRArg", "AllGPR", "AllArg", "All"]>,
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 207ffde5cbf23..661a5bb471a26 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -1445,7 +1445,7 @@ void RISCVFrameLowering::emitZeroCallUsedRegs(BitVector RegsToZero,
const MachineFunction &MF = *MBB.getParent();
const RISCVSubtarget &STI = MF.getSubtarget<RISCVSubtarget>();
- const RISCVRegisterInfo &TRI = STI.getTargetABI();
+ const RISCVRegisterInfo &TRI = *STI.getRegisterInfo();
const RISCVInstrInfo &TII = *STI.getInstrInfo();
for (MCRegister Reg : RegsToZero.set_bits()) {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 94722a28b2241..da59d4f8a8942 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -3951,7 +3951,8 @@ void RISCVInstrInfo::buildClearRegister(Register Reg, MachineBasicBlock &MBB,
if (TRI.isGeneralPurposeRegister(MF, Reg)) {
BuildMI(MBB, Iter, DL, get(RISCV::PseudoLI), Reg).addImm(0);
} else {
- llvm_unreachable("Implement buildClearRegister for non-GPR registers");
+ llvm::report_fatal_error(
+ "buildClearRegister is not implemented for non-GPR registers");
}
}
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index 520a893b5fe23..e26d57efe5eb9 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -813,7 +813,8 @@ bool RISCVRegisterInfo::isArgumentRegister(const MachineFunction &MF,
MCRegister Reg) const {
auto const &STI = MF.getSubtarget<RISCVSubtarget>();
if (!STI.getRegisterInfo()->isGeneralPurposeRegister(MF, Reg))
- llvm_unreachable("Implement isArgumentRegister for non-GPR registers");
+ llvm::report_fatal_error(
+ "isArgumentRegister is not implemented for non-GPR registers");
return llvm::any_of(RISCV::getArgGPRs(STI.getTargetABI()),
[&](MCPhysReg R) { return Reg == R; });
diff --git a/llvm/test/CodeGen/RISCV/zero-call-used-regs.ll b/llvm/test/CodeGen/RISCV/zero-call-used-regs.ll
index e962f3fe6724c..fa10fbf4213db 100644
--- a/llvm/test/CodeGen/RISCV/zero-call-used-regs.ll
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs.ll
@@ -3,7 +3,7 @@
target triple = "riscv64-unknown-linux-gnu"
-define dso_local i32 @skip(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 "zero-call-used-regs"="skip" {
+define i32 @skip(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="skip" {
; CHECK-LABEL: skip:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: mul{{w?}} a0, a1, a0
@@ -16,7 +16,7 @@ entry:
ret i32 %or
}
-define dso_local i32 @used_gpr_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used-gpr-arg" {
+define i32 @used_gpr_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="used-gpr-arg" {
; CHECK-LABEL: used_gpr_arg:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: mul{{w?}} a0, a1, a0
@@ -31,7 +31,7 @@ entry:
ret i32 %or
}
-define dso_local i32 @used_gpr(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used-gpr" {
+define i32 @used_gpr(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="used-gpr" {
; CHECK-LABEL: used_gpr:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: mul{{w?}} a0, a1, a0
@@ -46,7 +46,7 @@ entry:
ret i32 %or
}
-define dso_local i32 @used_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used-arg" {
+define i32 @used_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="used-arg" {
; CHECK-LABEL: used_arg:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: mul{{w?}} a0, a1, a0
@@ -61,7 +61,7 @@ entry:
ret i32 %or
}
-define dso_local i32 @used(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used" {
+define i32 @used(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="used" {
; CHECK-LABEL: used:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: mul{{w?}} a0, a1, a0
@@ -76,7 +76,7 @@ entry:
ret i32 %or
}
-define dso_local i32 @all_gpr_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 "zero-call-used-regs"="all-gpr-arg" {
+define i32 @all_gpr_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="all-gpr-arg" {
; CHECK-LABEL: all_gpr_arg:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: mul{{w?}} a0, a1, a0
@@ -96,7 +96,7 @@ entry:
ret i32 %or
}
-define dso_local i32 @all_gpr(i32 noundef %a, i32 noundef %b, i32 noundef %c) local_unnamed_addr #0 "zero-call-used-regs"="all-gpr" {
+define i32 @all_gpr(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="all-gpr" {
; CHECK-LABEL: all_gpr:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: mul{{w?}} a0, a1, a0
@@ -123,7 +123,7 @@ entry:
ret i32 %or
}
-define dso_local double @skip_float(double noundef %a, float noundef %b) local_unnamed_addr #0 "zero-call-used-regs"="skip" {
+define double @skip_float(double noundef %a, float noundef %b) #0 "zero-call-used-regs"="skip" {
; CHECK-LABEL: skip_float:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fcvt.d.s fa5, fa1
@@ -136,7 +136,7 @@ entry:
ret double %mul
}
-define dso_local double @used_gpr_arg_float(double noundef %a, float noundef %b) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used-gpr-arg" {
+define double @used_gpr_arg_float(double noundef %a, float noundef %b) #0 "zero-call-used-regs"="used-gpr-arg" {
; CHECK-LABEL: used_gpr_arg_float:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fcvt.d.s fa5, fa1
@@ -149,7 +149,7 @@ entry:
ret double %mul
}
-define dso_local double @used_gpr_float(double noundef %a, float noundef %b) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="used-gpr" {
+define double @used_gpr_float(double noundef %a, float noundef %b) #0 "zero-call-used-regs"="used-gpr" {
; CHECK-LABEL: used_gpr_float:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fcvt.d.s fa5, fa1
@@ -162,7 +162,7 @@ entry:
ret double %mul
}
-define dso_local double @all_gpr_arg_float(double noundef %a, float noundef %b) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="all-gpr-arg" {
+define double @all_gpr_arg_float(double noundef %a, float noundef %b) #0 "zero-call-used-regs"="all-gpr-arg" {
; CHECK-LABEL: all_gpr_arg_float:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fcvt.d.s fa5, fa1
@@ -183,7 +183,7 @@ entry:
ret double %mul
}
-define dso_local double @all_gpr_float(double noundef %a, float noundef %b) local_unnamed_addr #0 noinline optnone "zero-call-used-regs"="all-gpr" {
+define double @all_gpr_float(double noundef %a, float noundef %b) #0 "zero-call-used-regs"="all-gpr" {
; CHECK-LABEL: all_gpr_float:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fcvt.d.s fa5, fa1
@@ -212,7 +212,7 @@ entry:
}
; Don't emit zeroing registers in "main" function.
-define dso_local i32 @main() local_unnamed_addr #0 {
+define i32 @main() #0 {
; CHECK-LABEL: main:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: li a0, 0
@@ -222,4 +222,4 @@ entry:
ret i32 0
}
-attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn uwtable "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+m,+f,+d" }
+attributes #0 = { "target-cpu"="generic" "target-features"="+m,+f,+d" }
>From e632936e8b4f3971ea63ed578afb861d78131d6f Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Thu, 30 Apr 2026 15:55:59 +0200
Subject: [PATCH 3/4] Add changelog entry
---
clang/docs/ReleaseNotes.rst | 3 +++
1 file changed, 3 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2f72d55eb4ef8..fbbb2196f33e9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -285,6 +285,9 @@ 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.
Removed Compiler Flags
----------------------
>From 6d6bf4715a646801d57c9e224edfc6b51fa14ff1 Mon Sep 17 00:00:00 2001
From: Lucas Chollet <lucas.chollet at serenityos.org>
Date: Thu, 30 Apr 2026 15:56:23 +0200
Subject: [PATCH 4/4] Use utils/update_llc_test_checks.py to generate the test
case
---
.../test/CodeGen/RISCV/zero-call-used-regs.ll | 214 ++++++++++++------
1 file changed, 143 insertions(+), 71 deletions(-)
diff --git a/llvm/test/CodeGen/RISCV/zero-call-used-regs.ll b/llvm/test/CodeGen/RISCV/zero-call-used-regs.ll
index fa10fbf4213db..44dd85e700534 100644
--- a/llvm/test/CodeGen/RISCV/zero-call-used-regs.ll
+++ b/llvm/test/CodeGen/RISCV/zero-call-used-regs.ll
@@ -1,14 +1,21 @@
-; RUN: llc < %s -verify-machineinstrs -mtriple=riscv64-unknown-unknown | FileCheck %s
-; RUN: llc < %s -verify-machineinstrs -mtriple=riscv32-unknown-unknown | FileCheck %s
+; 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 | FileCheck %s --check-prefixes=CHECK,64-BITS
+; RUN: llc < %s -verify-machineinstrs -mtriple=riscv32-unknown-unknown | FileCheck %s --check-prefixes=CHECK,32-BITS
target triple = "riscv64-unknown-linux-gnu"
define i32 @skip(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="skip" {
-; CHECK-LABEL: skip:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: mul{{w?}} a0, a1, a0
-; CHECK-NEXT: or a0, a0, a2
-; CHECK-NEXT: ret
+; 64-BITS-LABEL: skip:
+; 64-BITS: # %bb.0: # %entry
+; 64-BITS-NEXT: mulw a0, a1, a0
+; 64-BITS-NEXT: or a0, a0, a2
+; 64-BITS-NEXT: ret
+;
+; 32-BITS-LABEL: skip:
+; 32-BITS: # %bb.0: # %entry
+; 32-BITS-NEXT: mul a0, a1, a0
+; 32-BITS-NEXT: or a0, a0, a2
+; 32-BITS-NEXT: ret
entry:
%mul = mul nsw i32 %b, %a
@@ -17,13 +24,21 @@ entry:
}
define i32 @used_gpr_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="used-gpr-arg" {
-; CHECK-LABEL: used_gpr_arg:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: mul{{w?}} a0, a1, a0
-; CHECK-NEXT: or a0, a0, a2
-; CHECK-NEXT: li a1, 0
-; CHECK-NEXT: li a2, 0
-; CHECK-NEXT: ret
+; 64-BITS-LABEL: used_gpr_arg:
+; 64-BITS: # %bb.0: # %entry
+; 64-BITS-NEXT: mulw a0, a1, a0
+; 64-BITS-NEXT: or a0, a0, a2
+; 64-BITS-NEXT: li a1, 0
+; 64-BITS-NEXT: li a2, 0
+; 64-BITS-NEXT: ret
+;
+; 32-BITS-LABEL: used_gpr_arg:
+; 32-BITS: # %bb.0: # %entry
+; 32-BITS-NEXT: mul a0, a1, a0
+; 32-BITS-NEXT: or a0, a0, a2
+; 32-BITS-NEXT: li a1, 0
+; 32-BITS-NEXT: li a2, 0
+; 32-BITS-NEXT: ret
entry:
%mul = mul nsw i32 %b, %a
@@ -32,13 +47,21 @@ entry:
}
define i32 @used_gpr(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="used-gpr" {
-; CHECK-LABEL: used_gpr:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: mul{{w?}} a0, a1, a0
-; CHECK-NEXT: or a0, a0, a2
-; CHECK-NEXT: li a1, 0
-; CHECK-NEXT: li a2, 0
-; CHECK-NEXT: ret
+; 64-BITS-LABEL: used_gpr:
+; 64-BITS: # %bb.0: # %entry
+; 64-BITS-NEXT: mulw a0, a1, a0
+; 64-BITS-NEXT: or a0, a0, a2
+; 64-BITS-NEXT: li a1, 0
+; 64-BITS-NEXT: li a2, 0
+; 64-BITS-NEXT: ret
+;
+; 32-BITS-LABEL: used_gpr:
+; 32-BITS: # %bb.0: # %entry
+; 32-BITS-NEXT: mul a0, a1, a0
+; 32-BITS-NEXT: or a0, a0, a2
+; 32-BITS-NEXT: li a1, 0
+; 32-BITS-NEXT: li a2, 0
+; 32-BITS-NEXT: ret
entry:
%mul = mul nsw i32 %b, %a
@@ -47,13 +70,21 @@ entry:
}
define i32 @used_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="used-arg" {
-; CHECK-LABEL: used_arg:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: mul{{w?}} a0, a1, a0
-; CHECK-NEXT: or a0, a0, a2
-; CHECK-NEXT: li a1, 0
-; CHECK-NEXT: li a2, 0
-; CHECK-NEXT: ret
+; 64-BITS-LABEL: used_arg:
+; 64-BITS: # %bb.0: # %entry
+; 64-BITS-NEXT: mulw a0, a1, a0
+; 64-BITS-NEXT: or a0, a0, a2
+; 64-BITS-NEXT: li a1, 0
+; 64-BITS-NEXT: li a2, 0
+; 64-BITS-NEXT: ret
+;
+; 32-BITS-LABEL: used_arg:
+; 32-BITS: # %bb.0: # %entry
+; 32-BITS-NEXT: mul a0, a1, a0
+; 32-BITS-NEXT: or a0, a0, a2
+; 32-BITS-NEXT: li a1, 0
+; 32-BITS-NEXT: li a2, 0
+; 32-BITS-NEXT: ret
entry:
%mul = mul nsw i32 %b, %a
@@ -62,13 +93,21 @@ entry:
}
define i32 @used(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="used" {
-; CHECK-LABEL: used:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: mul{{w?}} a0, a1, a0
-; CHECK-NEXT: or a0, a0, a2
-; CHECK-NEXT: li a1, 0
-; CHECK-NEXT: li a2, 0
-; CHECK-NEXT: ret
+; 64-BITS-LABEL: used:
+; 64-BITS: # %bb.0: # %entry
+; 64-BITS-NEXT: mulw a0, a1, a0
+; 64-BITS-NEXT: or a0, a0, a2
+; 64-BITS-NEXT: li a1, 0
+; 64-BITS-NEXT: li a2, 0
+; 64-BITS-NEXT: ret
+;
+; 32-BITS-LABEL: used:
+; 32-BITS: # %bb.0: # %entry
+; 32-BITS-NEXT: mul a0, a1, a0
+; 32-BITS-NEXT: or a0, a0, a2
+; 32-BITS-NEXT: li a1, 0
+; 32-BITS-NEXT: li a2, 0
+; 32-BITS-NEXT: ret
entry:
%mul = mul nsw i32 %b, %a
@@ -77,18 +116,31 @@ entry:
}
define i32 @all_gpr_arg(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="all-gpr-arg" {
-; CHECK-LABEL: all_gpr_arg:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: mul{{w?}} a0, a1, a0
-; CHECK-NEXT: or a0, a0, a2
-; 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: ret
+; 64-BITS-LABEL: all_gpr_arg:
+; 64-BITS: # %bb.0: # %entry
+; 64-BITS-NEXT: mulw a0, a1, a0
+; 64-BITS-NEXT: or a0, a0, a2
+; 64-BITS-NEXT: li a1, 0
+; 64-BITS-NEXT: li a2, 0
+; 64-BITS-NEXT: li a3, 0
+; 64-BITS-NEXT: li a4, 0
+; 64-BITS-NEXT: li a5, 0
+; 64-BITS-NEXT: li a6, 0
+; 64-BITS-NEXT: li a7, 0
+; 64-BITS-NEXT: ret
+;
+; 32-BITS-LABEL: all_gpr_arg:
+; 32-BITS: # %bb.0: # %entry
+; 32-BITS-NEXT: mul a0, a1, a0
+; 32-BITS-NEXT: or a0, a0, a2
+; 32-BITS-NEXT: li a1, 0
+; 32-BITS-NEXT: li a2, 0
+; 32-BITS-NEXT: li a3, 0
+; 32-BITS-NEXT: li a4, 0
+; 32-BITS-NEXT: li a5, 0
+; 32-BITS-NEXT: li a6, 0
+; 32-BITS-NEXT: li a7, 0
+; 32-BITS-NEXT: ret
entry:
%mul = mul nsw i32 %b, %a
@@ -97,25 +149,45 @@ entry:
}
define i32 @all_gpr(i32 noundef %a, i32 noundef %b, i32 noundef %c) #0 "zero-call-used-regs"="all-gpr" {
-; CHECK-LABEL: all_gpr:
-; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: mul{{w?}} a0, a1, a0
-; CHECK-NEXT: or a0, a0, a2
-; CHECK-NEXT: li t0, 0
-; CHECK-NEXT: li t1, 0
-; CHECK-NEXT: li t2, 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: ret
+; 64-BITS-LABEL: all_gpr:
+; 64-BITS: # %bb.0: # %entry
+; 64-BITS-NEXT: mulw a0, a1, a0
+; 64-BITS-NEXT: or a0, a0, a2
+; 64-BITS-NEXT: li t0, 0
+; 64-BITS-NEXT: li t1, 0
+; 64-BITS-NEXT: li t2, 0
+; 64-BITS-NEXT: li a1, 0
+; 64-BITS-NEXT: li a2, 0
+; 64-BITS-NEXT: li a3, 0
+; 64-BITS-NEXT: li a4, 0
+; 64-BITS-NEXT: li a5, 0
+; 64-BITS-NEXT: li a6, 0
+; 64-BITS-NEXT: li a7, 0
+; 64-BITS-NEXT: li t3, 0
+; 64-BITS-NEXT: li t4, 0
+; 64-BITS-NEXT: li t5, 0
+; 64-BITS-NEXT: li t6, 0
+; 64-BITS-NEXT: ret
+;
+; 32-BITS-LABEL: all_gpr:
+; 32-BITS: # %bb.0: # %entry
+; 32-BITS-NEXT: mul a0, a1, a0
+; 32-BITS-NEXT: or a0, a0, a2
+; 32-BITS-NEXT: li t0, 0
+; 32-BITS-NEXT: li t1, 0
+; 32-BITS-NEXT: li t2, 0
+; 32-BITS-NEXT: li a1, 0
+; 32-BITS-NEXT: li a2, 0
+; 32-BITS-NEXT: li a3, 0
+; 32-BITS-NEXT: li a4, 0
+; 32-BITS-NEXT: li a5, 0
+; 32-BITS-NEXT: li a6, 0
+; 32-BITS-NEXT: li a7, 0
+; 32-BITS-NEXT: li t3, 0
+; 32-BITS-NEXT: li t4, 0
+; 32-BITS-NEXT: li t5, 0
+; 32-BITS-NEXT: li t6, 0
+; 32-BITS-NEXT: ret
entry:
%mul = mul nsw i32 %b, %a
@@ -127,7 +199,7 @@ define double @skip_float(double noundef %a, float noundef %b) #0 "zero-call-use
; CHECK-LABEL: skip_float:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fcvt.d.s fa5, fa1
-; CHECK-NEXT: fmul.d fa0, fa5, fa0
+; CHECK-NEXT: fmul.d fa0, fa5, fa0
; CHECK-NEXT: ret
entry:
@@ -140,7 +212,7 @@ define double @used_gpr_arg_float(double noundef %a, float noundef %b) #0 "zero-
; CHECK-LABEL: used_gpr_arg_float:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fcvt.d.s fa5, fa1
-; CHECK-NEXT: fmul.d fa0, fa5, fa0
+; CHECK-NEXT: fmul.d fa0, fa5, fa0
; CHECK-NEXT: ret
entry:
@@ -153,7 +225,7 @@ define double @used_gpr_float(double noundef %a, float noundef %b) #0 "zero-call
; CHECK-LABEL: used_gpr_float:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fcvt.d.s fa5, fa1
-; CHECK-NEXT: fmul.d fa0, fa5, fa0
+; CHECK-NEXT: fmul.d fa0, fa5, fa0
; CHECK-NEXT: ret
entry:
@@ -166,7 +238,7 @@ define double @all_gpr_arg_float(double noundef %a, float noundef %b) #0 "zero-c
; CHECK-LABEL: all_gpr_arg_float:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fcvt.d.s fa5, fa1
-; CHECK-NEXT: fmul.d fa0, fa5, fa0
+; CHECK-NEXT: fmul.d fa0, fa5, fa0
; CHECK-NEXT: li a0, 0
; CHECK-NEXT: li a1, 0
; CHECK-NEXT: li a2, 0
@@ -187,7 +259,7 @@ define double @all_gpr_float(double noundef %a, float noundef %b) #0 "zero-call-
; CHECK-LABEL: all_gpr_float:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fcvt.d.s fa5, fa1
-; CHECK-NEXT: fmul.d fa0, fa5, fa0
+; CHECK-NEXT: fmul.d fa0, fa5, fa0
; CHECK-NEXT: li t0, 0
; CHECK-NEXT: li t1, 0
; CHECK-NEXT: li t2, 0
More information about the cfe-commits
mailing list