[llvm] [RISCV] Explicitly set FRM defs as non-dead to prevent their reordering with instructions that may use it (PR #135176)
Sergey Kachkov via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 10 06:24:36 PDT 2025
https://github.com/skachkov-sc created https://github.com/llvm/llvm-project/pull/135176
Fixes #135172. The proposed solution is to conservatively reset dead flag from all $frm defs in AdjustInstrPostInstrSelection (this is probably a bit hacky, so I'm open to the better ideas)
>From c24c643b0ed323c0cc2d4ef6cd82eecca78c79e4 Mon Sep 17 00:00:00 2001
From: Sergey Kachkov <sergey.kachkov at syntacore.com>
Date: Thu, 10 Apr 2025 12:56:12 +0300
Subject: [PATCH 1/2] [RISCV][NFC] Add pre-commit test
---
llvm/test/CodeGen/RISCV/frm-write-in-loop.ll | 35 ++++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 llvm/test/CodeGen/RISCV/frm-write-in-loop.ll
diff --git a/llvm/test/CodeGen/RISCV/frm-write-in-loop.ll b/llvm/test/CodeGen/RISCV/frm-write-in-loop.ll
new file mode 100644
index 0000000000000..9501b93cd11b9
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/frm-write-in-loop.ll
@@ -0,0 +1,35 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -O3 -mtriple=riscv64 -mattr=+f,+d < %s | FileCheck %s
+
+; Make sure WriteFRM is not hoisted out of loop due to dead implicit-def.
+
+define double @foo(double %0, double %1, i64 %n) strictfp {
+; CHECK-LABEL: foo:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: fmv.d.x fa5, zero
+; CHECK-NEXT: fsrmi 3
+; CHECK-NEXT: fsrmi 0
+; CHECK-NEXT: .LBB0_1: # %loop
+; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: fadd.d fa5, fa5, fa0
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: fadd.d fa5, fa5, fa1
+; CHECK-NEXT: beqz a0, .LBB0_1
+; CHECK-NEXT: # %bb.2: # %exit
+; CHECK-NEXT: fmv.d fa0, fa5
+; CHECK-NEXT: ret
+entry:
+ br label %loop
+loop:
+ %cnt = phi i64 [0, %entry], [%cnt_inc, %loop]
+ %acc = phi double [0.0, %entry], [%f2, %loop]
+ call void @llvm.set.rounding(i32 2) strictfp
+ %f1 = call double @llvm.experimental.constrained.fadd.f64(double %acc, double %0, metadata !"round.dynamic", metadata !"fpexcept.ignore") strictfp
+ call void @llvm.set.rounding(i32 1) strictfp
+ %f2 = call double @llvm.experimental.constrained.fadd.f64(double %f1, double %1, metadata !"round.dynamic", metadata !"fpexcept.ignore") strictfp
+ %cnt_inc = add i64 %cnt, 1
+ %cond = icmp eq i64 %cnt_inc, %n
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret double %f2
+}
>From 9b559ca74069fe242eaf87d35000d50e8255af60 Mon Sep 17 00:00:00 2001
From: Sergey Kachkov <sergey.kachkov at syntacore.com>
Date: Thu, 10 Apr 2025 12:48:08 +0300
Subject: [PATCH 2/2] [RISCV] Explicitly set FRM defs as non-dead to prevent
their reordering with instructions that may use it
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 9 +++++++++
llvm/lib/Target/RISCV/RISCVInstrInfo.td | 2 ++
llvm/test/CodeGen/RISCV/frm-write-in-loop.ll | 4 ++--
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index f7d192756fd56..414fb58f0cbeb 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20926,6 +20926,15 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
void RISCVTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI,
SDNode *Node) const {
+ // If instruction defines FRM operand, conservatively set it as non-dead to
+ // express data dependency with FRM users and prevent incorrect instruction
+ // reordering (these defs are marked as dead because at the moment of
+ // instruction emission they actually don't have any uses - they are added
+ // later in this hook).
+ if (auto *FRMDef = MI.findRegisterDefOperand(RISCV::FRM, /*TRI=*/nullptr)) {
+ FRMDef->setIsDead(false);
+ return;
+ }
// Add FRM dependency to any instructions with dynamic rounding mode.
int Idx = RISCV::getNamedOperandIdx(MI.getOpcode(), RISCV::OpName::frm);
if (Idx < 0) {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index c87452171f090..1104d9089536f 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -1941,9 +1941,11 @@ class SwapSysRegImm<SysReg SR, list<Register> Regs>
}
def ReadFRM : ReadSysReg<SysRegFRM, [FRM]>;
+let hasPostISelHook = 1 in {
def WriteFRM : WriteSysReg<SysRegFRM, [FRM]>;
def WriteFRMImm : WriteSysRegImm<SysRegFRM, [FRM]>;
def SwapFRMImm : SwapSysRegImm<SysRegFRM, [FRM]>;
+}
def WriteVXRMImm : WriteSysRegImm<SysRegVXRM, [VXRM]>;
diff --git a/llvm/test/CodeGen/RISCV/frm-write-in-loop.ll b/llvm/test/CodeGen/RISCV/frm-write-in-loop.ll
index 9501b93cd11b9..9ef8e4b67edd7 100644
--- a/llvm/test/CodeGen/RISCV/frm-write-in-loop.ll
+++ b/llvm/test/CodeGen/RISCV/frm-write-in-loop.ll
@@ -7,11 +7,11 @@ define double @foo(double %0, double %1, i64 %n) strictfp {
; CHECK-LABEL: foo:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: fmv.d.x fa5, zero
-; CHECK-NEXT: fsrmi 3
-; CHECK-NEXT: fsrmi 0
; CHECK-NEXT: .LBB0_1: # %loop
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: fsrmi 3
; CHECK-NEXT: fadd.d fa5, fa5, fa0
+; CHECK-NEXT: fsrmi 0
; CHECK-NEXT: addi a0, a0, -1
; CHECK-NEXT: fadd.d fa5, fa5, fa1
; CHECK-NEXT: beqz a0, .LBB0_1
More information about the llvm-commits
mailing list