Skip to content

Commit

Permalink
[RISCV] Custom lowering of llvm.is.fpclass
Browse files Browse the repository at this point in the history
This patch supports FCLASS.S, FCLASS.H and FCLASS.D.

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D149063
  • Loading branch information
ChunyuLiao committed Apr 26, 2023
1 parent e80da0f commit 5b869f3
Show file tree
Hide file tree
Showing 9 changed files with 570 additions and 0 deletions.
42 changes: 42 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(FPRndMode, MVT::f16,
Subtarget.hasStdExtZfa() ? Legal : Custom);
setOperationAction(ISD::SELECT, MVT::f16, Custom);
setOperationAction(ISD::IS_FPCLASS, MVT::f16, Custom);
} else {
static const unsigned ZfhminPromoteOps[] = {
ISD::FMINNUM, ISD::FMAXNUM, ISD::FADD,
Expand Down Expand Up @@ -417,6 +418,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(FPOpToExpand, MVT::f32, Expand);
setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);
setTruncStoreAction(MVT::f32, MVT::f16, Expand);
setOperationAction(ISD::IS_FPCLASS, MVT::f32, Custom);

if (Subtarget.hasStdExtZfa())
setOperationAction(ISD::FNEARBYINT, MVT::f32, Legal);
Expand Down Expand Up @@ -450,6 +452,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(FPOpToExpand, MVT::f64, Expand);
setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);
setTruncStoreAction(MVT::f64, MVT::f16, Expand);
setOperationAction(ISD::IS_FPCLASS, MVT::f64, Custom);
}

if (Subtarget.is64Bit()) {
Expand Down Expand Up @@ -4168,6 +4171,42 @@ static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG,
return Op;
}

static SDValue LowerIS_FPCLASS(SDValue Op, SelectionDAG &DAG,
const RISCVSubtarget &Subtarget) {
SDLoc DL(Op);
MVT VT = Op.getSimpleValueType();
MVT XLenVT = Subtarget.getXLenVT();
auto CNode = cast<ConstantSDNode>(Op.getOperand(1));
unsigned Check = CNode->getZExtValue();
unsigned TDCMask = 0;
if (Check & fcSNan)
TDCMask |= RISCV::FPMASK_Signaling_NaN;
if (Check & fcQNan)
TDCMask |= RISCV::FPMASK_Quiet_NaN;
if (Check & fcPosInf)
TDCMask |= RISCV::FPMASK_Positive_Infinity;
if (Check & fcNegInf)
TDCMask |= RISCV::FPMASK_Negative_Infinity;
if (Check & fcPosNormal)
TDCMask |= RISCV::FPMASK_Positive_Normal;
if (Check & fcNegNormal)
TDCMask |= RISCV::FPMASK_Negative_Normal;
if (Check & fcPosSubnormal)
TDCMask |= RISCV::FPMASK_Positive_Subnormal;
if (Check & fcNegSubnormal)
TDCMask |= RISCV::FPMASK_Negative_Subnormal;
if (Check & fcPosZero)
TDCMask |= RISCV::FPMASK_Positive_Zero;
if (Check & fcNegZero)
TDCMask |= RISCV::FPMASK_Negative_Zero;

SDValue TDCMaskV = DAG.getConstant(TDCMask, DL, XLenVT);
SDValue FPCLASS = DAG.getNode(RISCVISD::FPCLASS, DL, VT, Op.getOperand(0));
SDValue AND = DAG.getNode(ISD::AND, DL, VT, FPCLASS, TDCMaskV);
return DAG.getSetCC(DL, VT, AND, DAG.getConstant(0, DL, XLenVT),
ISD::CondCode::SETNE);
}

SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
SelectionDAG &DAG) const {
switch (Op.getOpcode()) {
Expand Down Expand Up @@ -4279,6 +4318,8 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
return LowerINTRINSIC_W_CHAIN(Op, DAG);
case ISD::INTRINSIC_VOID:
return LowerINTRINSIC_VOID(Op, DAG);
case ISD::IS_FPCLASS:
return LowerIS_FPCLASS(Op, DAG, Subtarget);
case ISD::BITREVERSE: {
MVT VT = Op.getSimpleValueType();
SDLoc DL(Op);
Expand Down Expand Up @@ -14609,6 +14650,7 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
NODE_NAME_CASE(STRICT_FCVT_W_RV64)
NODE_NAME_CASE(STRICT_FCVT_WU_RV64)
NODE_NAME_CASE(FROUND)
NODE_NAME_CASE(FPCLASS)
NODE_NAME_CASE(READ_CYCLE_WIDE)
NODE_NAME_CASE(BREV8)
NODE_NAME_CASE(ORC_B)
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/RISCVISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ enum NodeType : unsigned {
// inserter.
FROUND,

FPCLASS,
// READ_CYCLE_WIDE - A read of the 64-bit cycle CSR on a 32-bit target
// (returns (Lo, Hi)). It takes a chain operand.
READ_CYCLE_WIDE,
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,17 @@ bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2);
// Special immediate for AVL operand of V pseudo instructions to indicate VLMax.
static constexpr int64_t VLMaxSentinel = -1LL;

// Mask assignments for floating-point
static constexpr unsigned FPMASK_Negative_Infinity = 0x001;
static constexpr unsigned FPMASK_Negative_Normal = 0x002;
static constexpr unsigned FPMASK_Negative_Subnormal = 0x004;
static constexpr unsigned FPMASK_Negative_Zero = 0x008;
static constexpr unsigned FPMASK_Positive_Zero = 0x010;
static constexpr unsigned FPMASK_Positive_Subnormal = 0x020;
static constexpr unsigned FPMASK_Positive_Normal = 0x040;
static constexpr unsigned FPMASK_Positive_Infinity = 0x080;
static constexpr unsigned FPMASK_Signaling_NaN = 0x100;
static constexpr unsigned FPMASK_Quiet_NaN = 0x200;
} // namespace RISCV

namespace RISCVVPseudosTable {
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoD.td
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ def : Pat<(any_fsqrt FPR64:$rs1), (FSQRT_D FPR64:$rs1, FRM_DYN)>;
def : Pat<(fneg FPR64:$rs1), (FSGNJN_D $rs1, $rs1)>;
def : Pat<(fabs FPR64:$rs1), (FSGNJX_D $rs1, $rs1)>;

def : Pat<(riscv_fpclass FPR64:$rs1), (FCLASS_D $rs1)>;

def : PatFprFpr<fcopysign, FSGNJ_D, FPR64>;
def : Pat<(fcopysign FPR64:$rs1, (fneg FPR64:$rs2)), (FSGNJN_D $rs1, $rs2)>;
def : Pat<(fcopysign FPR64:$rs1, FPR32:$rs2), (FSGNJ_D $rs1, (FCVT_D_S $rs2))>;
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoF.td
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ def SDT_RISCVFCVT_X
def SDT_RISCVFROUND
: SDTypeProfile<1, 3, [SDTCisFP<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
SDTCisVT<3, XLenVT>]>;
def SDT_RISCVFPCLASS
: SDTypeProfile<1, 1, [SDTCisVT<0, XLenVT>, SDTCisFP<1>]>;

def riscv_fpclass
: SDNode<"RISCVISD::FPCLASS", SDT_RISCVFPCLASS>;

def riscv_fround
: SDNode<"RISCVISD::FROUND", SDT_RISCVFROUND>;
Expand Down Expand Up @@ -475,6 +480,8 @@ def : Pat<(any_fsqrt FPR32:$rs1), (FSQRT_S FPR32:$rs1, FRM_DYN)>;
def : Pat<(fneg FPR32:$rs1), (FSGNJN_S $rs1, $rs1)>;
def : Pat<(fabs FPR32:$rs1), (FSGNJX_S $rs1, $rs1)>;

def : Pat<(riscv_fpclass FPR32:$rs1), (FCLASS_S $rs1)>;

def : PatFprFpr<fcopysign, FSGNJ_S, FPR32>;
def : Pat<(fcopysign FPR32:$rs1, (fneg FPR32:$rs2)), (FSGNJN_S $rs1, $rs2)>;

Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfoZfh.td
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ def : Pat<(any_fsqrt FPR16:$rs1), (FSQRT_H FPR16:$rs1, FRM_DYN)>;
def : Pat<(fneg FPR16:$rs1), (FSGNJN_H $rs1, $rs1)>;
def : Pat<(fabs FPR16:$rs1), (FSGNJX_H $rs1, $rs1)>;

def : Pat<(riscv_fpclass FPR16:$rs1), (FCLASS_H $rs1)>;

def : PatFprFpr<fcopysign, FSGNJ_H, FPR16>;
def : Pat<(fcopysign FPR16:$rs1, (fneg FPR16:$rs2)), (FSGNJN_H $rs1, $rs2)>;
def : Pat<(fcopysign FPR16:$rs1, FPR32:$rs2),
Expand Down
34 changes: 34 additions & 0 deletions llvm/test/CodeGen/RISCV/double-intrinsics.ll
Original file line number Diff line number Diff line change
Expand Up @@ -1044,3 +1044,37 @@ define i64 @llround_f64(double %a) nounwind {
%1 = call i64 @llvm.llround.i64.f64(double %a)
ret i64 %1
}

declare i1 @llvm.is.fpclass.f64(double, i32)
define i1 @isnan_d_fpclass(double %x) {
; CHECKIFD-LABEL: isnan_d_fpclass:
; CHECKIFD: # %bb.0:
; CHECKIFD-NEXT: fclass.d a0, fa0
; CHECKIFD-NEXT: andi a0, a0, 768
; CHECKIFD-NEXT: snez a0, a0
; CHECKIFD-NEXT: ret
;
; RV32I-LABEL: isnan_d_fpclass:
; RV32I: # %bb.0:
; RV32I-NEXT: slli a1, a1, 1
; RV32I-NEXT: srli a1, a1, 1
; RV32I-NEXT: lui a2, 524032
; RV32I-NEXT: beq a1, a2, .LBB29_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: slt a0, a2, a1
; RV32I-NEXT: ret
; RV32I-NEXT: .LBB29_2:
; RV32I-NEXT: snez a0, a0
; RV32I-NEXT: ret
;
; RV64I-LABEL: isnan_d_fpclass:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a0, a0, 1
; RV64I-NEXT: srli a0, a0, 1
; RV64I-NEXT: li a1, 2047
; RV64I-NEXT: slli a1, a1, 52
; RV64I-NEXT: slt a0, a1, a0
; RV64I-NEXT: ret
%1 = call i1 @llvm.is.fpclass.f64(double %x, i32 3) ; nan
ret i1 %1
}

0 comments on commit 5b869f3

Please sign in to comment.