Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,17 @@ inline static bool isValidRoundingMode(unsigned Mode) {
}
} // namespace RISCVVXRndMode

namespace RISCVExceptFlags {
enum ExceptionFlag {
NX = 0x01, // Inexact
UF = 0x02, // Underflow
OF = 0x04, // Overflow
DZ = 0x08, // Divide by zero
NV = 0x10, // Invalid operation
ALL = 0x1F // Mask for all accrued exception flags
};
}

//===----------------------------------------------------------------------===//
// Floating-point Immediates
//
Expand Down
58 changes: 58 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::GET_FPENV, XLenVT, Custom);
setOperationAction(ISD::SET_FPENV, XLenVT, Custom);
setOperationAction(ISD::RESET_FPENV, MVT::Other, Custom);
setOperationAction(ISD::GET_FPMODE, XLenVT, Custom);
setOperationAction(ISD::SET_FPMODE, XLenVT, Custom);
setOperationAction(ISD::RESET_FPMODE, MVT::Other, Custom);
}

setOperationAction({ISD::GlobalAddress, ISD::BlockAddress, ISD::ConstantPool,
Expand Down Expand Up @@ -8226,6 +8229,12 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
return lowerSET_FPENV(Op, DAG);
case ISD::RESET_FPENV:
return lowerRESET_FPENV(Op, DAG);
case ISD::GET_FPMODE:
return lowerGET_FPMODE(Op, DAG);
case ISD::SET_FPMODE:
return lowerSET_FPMODE(Op, DAG);
case ISD::RESET_FPMODE:
return lowerRESET_FPMODE(Op, DAG);
case ISD::EH_DWARF_CFA:
return lowerEH_DWARF_CFA(Op, DAG);
case ISD::VP_MERGE:
Expand Down Expand Up @@ -13998,6 +14007,55 @@ SDValue RISCVTargetLowering::lowerRESET_FPENV(SDValue Op,
EnvValue);
}

const uint64_t ModeMask64 = ~RISCVExceptFlags::ALL;
const uint32_t ModeMask32 = ~RISCVExceptFlags::ALL;

SDValue RISCVTargetLowering::lowerGET_FPMODE(SDValue Op,
SelectionDAG &DAG) const {
const MVT XLenVT = Subtarget.getXLenVT();
const uint64_t ModeMaskValue = Subtarget.is64Bit() ? ModeMask64 : ModeMask32;
SDLoc DL(Op);
SDValue Chain = Op->getOperand(0);
SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
SDValue ModeMask = DAG.getConstant(ModeMaskValue, DL, XLenVT);
SDVTList VTs = DAG.getVTList(XLenVT, MVT::Other);
SDValue Result = DAG.getNode(RISCVISD::READ_CSR, DL, VTs, Chain, SysRegNo);
Chain = Result.getValue(1);
Result = DAG.getNode(ISD::AND, DL, XLenVT, Result, ModeMask);
return DAG.getMergeValues({Result, Chain}, DL);
}

SDValue RISCVTargetLowering::lowerSET_FPMODE(SDValue Op,
SelectionDAG &DAG) const {
const MVT XLenVT = Subtarget.getXLenVT();
const uint64_t ModeMaskValue = Subtarget.is64Bit() ? ModeMask64 : ModeMask32;
SDLoc DL(Op);
SDValue Chain = Op->getOperand(0);
SDValue EnvValue = Op->getOperand(1);
SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
SDValue ModeMask = DAG.getConstant(ModeMaskValue, DL, XLenVT);

EnvValue = DAG.getNode(ISD::ZERO_EXTEND, DL, XLenVT, EnvValue);
EnvValue = DAG.getNode(ISD::AND, DL, XLenVT, EnvValue, ModeMask);
Chain = DAG.getNode(RISCVISD::CLEAR_CSR, DL, MVT::Other, Chain, SysRegNo,
ModeMask);
return DAG.getNode(RISCVISD::SET_CSR, DL, MVT::Other, Chain, SysRegNo,
EnvValue);
}

SDValue RISCVTargetLowering::lowerRESET_FPMODE(SDValue Op,
SelectionDAG &DAG) const {
const MVT XLenVT = Subtarget.getXLenVT();
const uint64_t ModeMaskValue = Subtarget.is64Bit() ? ModeMask64 : ModeMask32;
SDLoc DL(Op);
SDValue Chain = Op->getOperand(0);
SDValue SysRegNo = DAG.getTargetConstant(RISCVSysReg::fcsr, DL, XLenVT);
SDValue ModeMask = DAG.getConstant(ModeMaskValue, DL, XLenVT);

return DAG.getNode(RISCVISD::CLEAR_CSR, DL, MVT::Other, Chain, SysRegNo,
ModeMask);
}

SDValue RISCVTargetLowering::lowerEH_DWARF_CFA(SDValue Op,
SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,9 @@ class RISCVTargetLowering : public TargetLowering {
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 lowerGET_FPMODE(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSET_FPMODE(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerRESET_FPMODE(SDValue Op, SelectionDAG &DAG) const;

SDValue lowerEH_DWARF_CFA(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerCTLZ_CTTZ_ZERO_UNDEF(SDValue Op, SelectionDAG &DAG) const;
Expand Down
54 changes: 54 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,20 @@ def riscv_swap_csr : RVSDNode<"SWAP_CSR",
SDTCisInt<2>]>,
[SDNPHasChain]>;

// Clear bits of CSR. The first operand is the address of the required CSR,
// the second is the bitmask of cleared bits.
def riscv_clear_csr : RVSDNode<"CLEAR_CSR",
SDTypeProfile<0, 2, [SDTCisInt<0>,
SDTCisInt<1>]>,
[SDNPHasChain]>;

// Set bits of CSR. The first operand is the address of the required CSR,
// the second is the bitmask of bits to set.
def riscv_set_csr : RVSDNode<"SET_CSR",
SDTypeProfile<0, 2, [SDTCisInt<0>,
SDTCisInt<1>]>,
[SDNPHasChain]>;

// A read of the 64-bit counter CSR on a 32-bit target (returns (Lo, Hi)).
// It takes a chain operand and another two target constant operands (the
// CSR numbers of the low and high parts of the counter).
Expand Down Expand Up @@ -2038,6 +2052,42 @@ class SwapSysRegImm<SysReg SR, list<Register> Regs>
let Defs = Regs;
}

class ClearSysReg<SysReg SR, list<Register> Regs>
: Pseudo<(outs), (ins GPR:$val),
[(riscv_clear_csr (XLenVT SR.Encoding), (XLenVT GPR:$val))]>,
PseudoInstExpansion<(CSRRC X0, SR.Encoding, GPR:$val)> {
let hasSideEffects = 0;
let Uses = Regs;
let Defs = Regs;
}

class ClearSysRegImm<SysReg SR, list<Register> Regs>
: Pseudo<(outs), (ins uimm5:$val),
[(riscv_clear_csr (XLenVT SR.Encoding), uimm5:$val)]>,
PseudoInstExpansion<(CSRRCI X0, SR.Encoding, uimm5:$val)> {
let hasSideEffects = 0;
let Uses = Regs;
let Defs = Regs;
}

class SetSysReg<SysReg SR, list<Register> Regs>
: Pseudo<(outs), (ins GPR:$val),
[(riscv_set_csr (XLenVT SR.Encoding), (XLenVT GPR:$val))]>,
PseudoInstExpansion<(CSRRS X0, SR.Encoding, GPR:$val)> {
let hasSideEffects = 0;
let Uses = Regs;
let Defs = Regs;
}

class SetSysRegImm<SysReg SR, list<Register> Regs>
: Pseudo<(outs), (ins uimm5:$val),
[(riscv_set_csr (XLenVT SR.Encoding), uimm5:$val)]>,
PseudoInstExpansion<(CSRRSI X0, SR.Encoding, uimm5:$val)> {
let hasSideEffects = 0;
let Uses = Regs;
let Defs = Regs;
}

def ReadFRM : ReadSysReg<SysRegFRM, [FRM]>;
let hasPostISelHook = 1 in {
def WriteFRM : WriteSysReg<SysRegFRM, [FRM]>;
Expand All @@ -2056,6 +2106,10 @@ let hasPostISelHook = 1 in {
def ReadFCSR : ReadSysReg<SysRegFCSR, [FRM, FFLAGS]>;
def WriteFCSR : WriteSysReg<SysRegFCSR, [FRM, FFLAGS]>;
def WriteFCSRImm : WriteSysRegImm<SysRegFCSR, [FRM, FFLAGS]>;
def ClearFCSR : ClearSysReg<SysRegFCSR, [FRM, FFLAGS]>;
def ClearFCSRImm : ClearSysRegImm<SysRegFCSR, [FRM, FFLAGS]>;
def SetFCSR : SetSysReg<SysRegFCSR, [FRM, FFLAGS]>;
def SetFCSRImm : SetSysRegImm<SysRegFCSR, [FRM, FFLAGS]>;
}

/// Other pseudo-instructions
Expand Down
35 changes: 35 additions & 0 deletions llvm/test/CodeGen/RISCV/fpenv-xlen.ll
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,38 @@ entry:
call void @llvm.reset.fpenv()
ret void
}

define iXLen @func_get_fpmode() {
; CHECK-LABEL: func_get_fpmode:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: frcsr a0
; CHECK-NEXT: andi a0, a0, -32
; CHECK-NEXT: ret
entry:
%fpenv = call iXLen @llvm.get.fpmode.iXLen()
ret iXLen %fpenv
}

define void @func_set_fpmode(iXLen %fpmode) {
; CHECK-LABEL: func_set_fpmode:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: li a1, -32
; CHECK-NEXT: csrc fcsr, a1
; CHECK-NEXT: andi a0, a0, -32
; CHECK-NEXT: csrs fcsr, a0
; CHECK-NEXT: ret
entry:
call void @llvm.set.fpmode.iXLen(iXLen %fpmode)
ret void
}

define void @func_reset_fpmode() {
; CHECK-LABEL: func_reset_fpmode:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: li a0, -32
; CHECK-NEXT: csrc fcsr, a0
; CHECK-NEXT: ret
entry:
call void @llvm.reset.fpmode()
ret void
}
Loading