Skip to content

Commit 953a778

Browse files
authored
[RISCV][FPEnv] Lowering of fpenv intrinsics (#141498)
The change implements custom lowering of `get_fpenv`, `set_fpenv` and `reset_fpenv` for RISCV target.
1 parent f44f411 commit 953a778

File tree

6 files changed

+123
-0
lines changed

6 files changed

+123
-0
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
649649

650650
setOperationAction(ISD::GET_ROUNDING, XLenVT, Custom);
651651
setOperationAction(ISD::SET_ROUNDING, MVT::Other, Custom);
652+
setOperationAction(ISD::GET_FPENV, XLenVT, Custom);
653+
setOperationAction(ISD::SET_FPENV, XLenVT, Custom);
654+
setOperationAction(ISD::RESET_FPENV, MVT::Other, Custom);
652655
}
653656

654657
setOperationAction({ISD::GlobalAddress, ISD::BlockAddress, ISD::ConstantPool,
@@ -8159,6 +8162,12 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
81598162
return lowerGET_ROUNDING(Op, DAG);
81608163
case ISD::SET_ROUNDING:
81618164
return lowerSET_ROUNDING(Op, DAG);
8165+
case ISD::GET_FPENV:
8166+
return lowerGET_FPENV(Op, DAG);
8167+
case ISD::SET_FPENV:
8168+
return lowerSET_FPENV(Op, DAG);
8169+
case ISD::RESET_FPENV:
8170+
return lowerRESET_FPENV(Op, DAG);
81628171
case ISD::EH_DWARF_CFA:
81638172
return lowerEH_DWARF_CFA(Op, DAG);
81648173
case ISD::VP_MERGE:
@@ -13799,6 +13808,41 @@ SDValue RISCVTargetLowering::lowerSET_ROUNDING(SDValue Op,
1379913808
RMValue);
1380013809
}
1380113810

13811+
SDValue RISCVTargetLowering::lowerGET_FPENV(SDValue Op,
13812+
SelectionDAG &DAG) const {
13813+
const MVT XLenVT = Subtarget.getXLenVT();
13814+
SDLoc DL(Op);
13815+
SDValue Chain = Op->getOperand(0);
13816+
SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
13817+
SDVTList VTs = DAG.getVTList(XLenVT, MVT::Other);
13818+
return DAG.getNode(RISCVISD::READ_CSR, DL, VTs, Chain, SysRegNo);
13819+
}
13820+
13821+
SDValue RISCVTargetLowering::lowerSET_FPENV(SDValue Op,
13822+
SelectionDAG &DAG) const {
13823+
const MVT XLenVT = Subtarget.getXLenVT();
13824+
SDLoc DL(Op);
13825+
SDValue Chain = Op->getOperand(0);
13826+
SDValue EnvValue = Op->getOperand(1);
13827+
SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
13828+
13829+
EnvValue = DAG.getNode(ISD::ZERO_EXTEND, DL, XLenVT, EnvValue);
13830+
return DAG.getNode(RISCVISD::WRITE_CSR, DL, MVT::Other, Chain, SysRegNo,
13831+
EnvValue);
13832+
}
13833+
13834+
SDValue RISCVTargetLowering::lowerRESET_FPENV(SDValue Op,
13835+
SelectionDAG &DAG) const {
13836+
const MVT XLenVT = Subtarget.getXLenVT();
13837+
SDLoc DL(Op);
13838+
SDValue Chain = Op->getOperand(0);
13839+
SDValue EnvValue = DAG.getRegister(RISCV::X0, XLenVT);
13840+
SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
13841+
13842+
return DAG.getNode(RISCVISD::WRITE_CSR, DL, MVT::Other, Chain, SysRegNo,
13843+
EnvValue);
13844+
}
13845+
1380213846
SDValue RISCVTargetLowering::lowerEH_DWARF_CFA(SDValue Op,
1380313847
SelectionDAG &DAG) const {
1380413848
MachineFunction &MF = DAG.getMachineFunction();

llvm/lib/Target/RISCV/RISCVISelLowering.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,9 @@ class RISCVTargetLowering : public TargetLowering {
544544
unsigned ExtendOpc) const;
545545
SDValue lowerGET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;
546546
SDValue lowerSET_ROUNDING(SDValue Op, SelectionDAG &DAG) const;
547+
SDValue lowerGET_FPENV(SDValue Op, SelectionDAG &DAG) const;
548+
SDValue lowerSET_FPENV(SDValue Op, SelectionDAG &DAG) const;
549+
SDValue lowerRESET_FPENV(SDValue Op, SelectionDAG &DAG) const;
547550

548551
SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
549552
SDValue lowerCTLZ_CTTZ_ZERO_UNDEF(SDValue Op, SelectionDAG &DAG) const;

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2037,6 +2037,13 @@ let hasSideEffects = true in {
20372037
def ReadFFLAGS : ReadSysReg<SysRegFFLAGS, [FFLAGS]>;
20382038
def WriteFFLAGS : WriteSysReg<SysRegFFLAGS, [FFLAGS]>;
20392039
}
2040+
2041+
let hasPostISelHook = 1 in {
2042+
def ReadFCSR : ReadSysReg<SysRegFCSR, [FRM, FFLAGS]>;
2043+
def WriteFCSR : WriteSysReg<SysRegFCSR, [FRM, FFLAGS]>;
2044+
def WriteFCSRImm : WriteSysRegImm<SysRegFCSR, [FRM, FFLAGS]>;
2045+
}
2046+
20402047
/// Other pseudo-instructions
20412048

20422049
// Pessimistically assume the stack pointer will be clobbered

llvm/lib/Target/RISCV/RISCVRegisterInfo.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,7 @@ foreach m = LMULList in {
846846

847847
def FFLAGS : RISCVReg<0, "fflags">;
848848
def FRM : RISCVReg<0, "frm">;
849+
def FCSR : RISCVReg<0, "fcsr">;
849850

850851
// Shadow Stack register
851852
def SSP : RISCVReg<0, "ssp">;

llvm/test/CodeGen/RISCV/fpenv-xlen.ll

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs | FileCheck %s
3+
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs | FileCheck %s
4+
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+zfinx -verify-machineinstrs | FileCheck %s
5+
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+zfinx -verify-machineinstrs | FileCheck %s
6+
; RUN: sed 's/iXLen/i32/g' %s | llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs -O0 | FileCheck %s
7+
; RUN: sed 's/iXLen/i64/g' %s | llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs -O0 | FileCheck %s
8+
9+
define iXLen @func_get_fpenv() {
10+
; CHECK-LABEL: func_get_fpenv:
11+
; CHECK: # %bb.0: # %entry
12+
; CHECK-NEXT: frcsr a0
13+
; CHECK-NEXT: ret
14+
entry:
15+
%fpenv = call iXLen @llvm.get.fpenv.iXLen()
16+
ret iXLen %fpenv
17+
}
18+
19+
define void @func_set_fpenv(iXLen %fpenv) {
20+
; CHECK-LABEL: func_set_fpenv:
21+
; CHECK: # %bb.0: # %entry
22+
; CHECK-NEXT: fscsr a0
23+
; CHECK-NEXT: ret
24+
entry:
25+
call void @llvm.set.fpenv.iXLen(iXLen %fpenv)
26+
ret void
27+
}
28+
29+
define void @func_reset_fpenv() {
30+
; CHECK-LABEL: func_reset_fpenv:
31+
; CHECK: # %bb.0: # %entry
32+
; CHECK-NEXT: fscsr zero
33+
; CHECK-NEXT: ret
34+
entry:
35+
call void @llvm.reset.fpenv()
36+
ret void
37+
}

llvm/test/CodeGen/RISCV/frm-write-in-loop.ll

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,34 @@ loop:
9090
exit:
9191
ret double %f2
9292
}
93+
94+
define double @foo2(double %0, double %1, i64 %n, i64 %fcsr) strictfp {
95+
; CHECK-LABEL: foo2:
96+
; CHECK: # %bb.0: # %entry
97+
; CHECK-NEXT: fmv.d.x fa5, zero
98+
; CHECK-NEXT: .LBB2_1: # %loop
99+
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
100+
; CHECK-NEXT: csrwi fcsr, 0
101+
; CHECK-NEXT: fadd.d fa5, fa5, fa0
102+
; CHECK-NEXT: addi a0, a0, -1
103+
; CHECK-NEXT: fscsr a1
104+
; CHECK-NEXT: fadd.d fa5, fa5, fa1
105+
; CHECK-NEXT: beqz a0, .LBB2_1
106+
; CHECK-NEXT: # %bb.2: # %exit
107+
; CHECK-NEXT: fmv.d fa0, fa5
108+
; CHECK-NEXT: ret
109+
entry:
110+
br label %loop
111+
loop:
112+
%cnt = phi i64 [0, %entry], [%cnt_inc, %loop]
113+
%acc = phi double [0.0, %entry], [%f2, %loop]
114+
call void @llvm.set.fpenv(i64 0) strictfp
115+
%f1 = call double @llvm.experimental.constrained.fadd.f64(double %acc, double %0, metadata !"round.dynamic", metadata !"fpexcept.ignore") strictfp
116+
call void @llvm.set.fpenv(i64 %fcsr) strictfp
117+
%f2 = call double @llvm.experimental.constrained.fadd.f64(double %f1, double %1, metadata !"round.dynamic", metadata !"fpexcept.ignore") strictfp
118+
%cnt_inc = add i64 %cnt, 1
119+
%cond = icmp eq i64 %cnt_inc, %n
120+
br i1 %cond, label %loop, label %exit
121+
exit:
122+
ret double %f2
123+
}

0 commit comments

Comments
 (0)