[llvm] 953a778 - [RISCV][FPEnv] Lowering of fpenv intrinsics (#141498)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 11 05:08:26 PDT 2025
Author: Serge Pavlov
Date: 2025-06-11T19:08:23+07:00
New Revision: 953a778fabc48025569fe0d5b3b363b981263f21
URL: https://github.com/llvm/llvm-project/commit/953a778fabc48025569fe0d5b3b363b981263f21
DIFF: https://github.com/llvm/llvm-project/commit/953a778fabc48025569fe0d5b3b363b981263f21.diff
LOG: [RISCV][FPEnv] Lowering of fpenv intrinsics (#141498)
The change implements custom lowering of `get_fpenv`, `set_fpenv` and
`reset_fpenv` for RISCV target.
Added:
llvm/test/CodeGen/RISCV/fpenv-xlen.ll
Modified:
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.h
llvm/lib/Target/RISCV/RISCVInstrInfo.td
llvm/lib/Target/RISCV/RISCVRegisterInfo.td
llvm/test/CodeGen/RISCV/frm-write-in-loop.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 498adee35550c..a157c94849f37 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -649,6 +649,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::GET_ROUNDING, XLenVT, Custom);
setOperationAction(ISD::SET_ROUNDING, MVT::Other, Custom);
+ setOperationAction(ISD::GET_FPENV, XLenVT, Custom);
+ setOperationAction(ISD::SET_FPENV, XLenVT, Custom);
+ setOperationAction(ISD::RESET_FPENV, MVT::Other, Custom);
}
setOperationAction({ISD::GlobalAddress, ISD::BlockAddress, ISD::ConstantPool,
@@ -8159,6 +8162,12 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
return lowerGET_ROUNDING(Op, DAG);
case ISD::SET_ROUNDING:
return lowerSET_ROUNDING(Op, DAG);
+ case ISD::GET_FPENV:
+ return lowerGET_FPENV(Op, DAG);
+ case ISD::SET_FPENV:
+ return lowerSET_FPENV(Op, DAG);
+ case ISD::RESET_FPENV:
+ return lowerRESET_FPENV(Op, DAG);
case ISD::EH_DWARF_CFA:
return lowerEH_DWARF_CFA(Op, DAG);
case ISD::VP_MERGE:
@@ -13799,6 +13808,41 @@ SDValue RISCVTargetLowering::lowerSET_ROUNDING(SDValue Op,
RMValue);
}
+SDValue RISCVTargetLowering::lowerGET_FPENV(SDValue Op,
+ SelectionDAG &DAG) const {
+ const MVT XLenVT = Subtarget.getXLenVT();
+ SDLoc DL(Op);
+ SDValue Chain = Op->getOperand(0);
+ SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
+ SDVTList VTs = DAG.getVTList(XLenVT, MVT::Other);
+ return DAG.getNode(RISCVISD::READ_CSR, DL, VTs, Chain, SysRegNo);
+}
+
+SDValue RISCVTargetLowering::lowerSET_FPENV(SDValue Op,
+ SelectionDAG &DAG) const {
+ const MVT XLenVT = Subtarget.getXLenVT();
+ SDLoc DL(Op);
+ SDValue Chain = Op->getOperand(0);
+ SDValue EnvValue = Op->getOperand(1);
+ SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
+
+ EnvValue = DAG.getNode(ISD::ZERO_EXTEND, DL, XLenVT, EnvValue);
+ return DAG.getNode(RISCVISD::WRITE_CSR, DL, MVT::Other, Chain, SysRegNo,
+ EnvValue);
+}
+
+SDValue RISCVTargetLowering::lowerRESET_FPENV(SDValue Op,
+ SelectionDAG &DAG) const {
+ const MVT XLenVT = Subtarget.getXLenVT();
+ SDLoc DL(Op);
+ SDValue Chain = Op->getOperand(0);
+ SDValue EnvValue = DAG.getRegister(RISCV::X0, XLenVT);
+ SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
+
+ return DAG.getNode(RISCVISD::WRITE_CSR, DL, MVT::Other, Chain, SysRegNo,
+ EnvValue);
+}
+
SDValue RISCVTargetLowering::lowerEH_DWARF_CFA(SDValue Op,
SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index 2ea2bf656ffd7..417d684a62382 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -544,6 +544,9 @@ class RISCVTargetLowering : public TargetLowering {
unsigned ExtendOpc) const;
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerRESET_FPENV(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerCTLZ_CTTZ_ZERO_UNDEF(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 0d1ff09f4da3a..70fad925cf070 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -2037,6 +2037,13 @@ let hasSideEffects = true in {
def ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>;
def WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>;
}
+
+let hasPostISelHook = 1 in {
+def ReadFCSR : ReadSysReg<SysRegFCSR, [FRM, FFLAGS]>;
+def WriteFCSR : WriteSysReg<SysRegFCSR, [FRM, FFLAGS]>;
+def WriteFCSRImm : WriteSysRegImm<SysRegFCSR, [FRM, FFLAGS]>;
+}
+
/// Other pseudo-instructions
// Pessimistically assume the stack pointer will be clobbered
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
index 80213e1503b0a..e87f4523a84f9 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.td
@@ -846,6 +846,7 @@ foreach m = LMULList in {
def FFLAGS : RISCVReg<0, "fflags">;
def FRM : RISCVReg<0, "frm">;
+def FCSR : RISCVReg<0, "fcsr">;
// Shadow Stack register
def SSP : RISCVReg<0, "ssp">;
diff --git a/llvm/test/CodeGen/RISCV/fpenv-xlen.ll b/llvm/test/CodeGen/RISCV/fpenv-xlen.ll
new file mode 100644
index 0000000000000..148186b21c125
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/fpenv-xlen.ll
@@ -0,0 +1,37 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs | FileCheck %s
+; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs | FileCheck %s
+; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+zfinx -verify-machineinstrs | FileCheck %s
+; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+zfinx -verify-machineinstrs | FileCheck %s
+; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs -O0 | FileCheck %s
+; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs -O0 | FileCheck %s
+
+define iXLen @func_get_fpenv() {
+; CHECK-LABEL: func_get_fpenv:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: frcsr a0
+; CHECK-NEXT: ret
+entry:
+ %fpenv = call iXLen @llvm.get.fpenv.iXLen()
+ ret iXLen %fpenv
+}
+
+define void @func_set_fpenv(iXLen %fpenv) {
+; CHECK-LABEL: func_set_fpenv:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: fscsr a0
+; CHECK-NEXT: ret
+entry:
+ call void @llvm.set.fpenv.iXLen(iXLen %fpenv)
+ ret void
+}
+
+define void @func_reset_fpenv() {
+; CHECK-LABEL: func_reset_fpenv:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: fscsr zero
+; CHECK-NEXT: ret
+entry:
+ call void @llvm.reset.fpenv()
+ ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/frm-write-in-loop.ll b/llvm/test/CodeGen/RISCV/frm-write-in-loop.ll
index 4f435067343b7..72c5951178276 100644
--- a/llvm/test/CodeGen/RISCV/frm-write-in-loop.ll
+++ b/llvm/test/CodeGen/RISCV/frm-write-in-loop.ll
@@ -90,3 +90,34 @@ loop:
exit:
ret double %f2
}
+
+define double @foo2(double %0, double %1, i64 %n, i64 %fcsr) strictfp {
+; CHECK-LABEL: foo2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: fmv.d.x fa5, zero
+; CHECK-NEXT: .LBB2_1: # %loop
+; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT: csrwi fcsr, 0
+; CHECK-NEXT: fadd.d fa5, fa5, fa0
+; CHECK-NEXT: addi a0, a0, -1
+; CHECK-NEXT: fscsr a1
+; CHECK-NEXT: fadd.d fa5, fa5, fa1
+; CHECK-NEXT: beqz a0, .LBB2_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.fpenv(i64 0) strictfp
+ %f1 = call double @llvm.experimental.constrained.fadd.f64(double %acc, double %0, metadata !"round.dynamic", metadata !"fpexcept.ignore") strictfp
+ call void @llvm.set.fpenv(i64 %fcsr) 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
+}
More information about the llvm-commits
mailing list