mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
[RISCV] Custom lower (i32 (fptoui/fptosi X)).
I stumbled onto a case where our (sext_inreg (assertzexti32 (fptoui X)), i32) isel pattern can cause an fcvt.wu and fcvt.lu to be emitted if the assertzexti32 has an additional user. If we add a one use check it would just cause a fcvt.lu followed by a sext.w when only need a fcvt.wu to satisfy both users. To mitigate this I've added custom isel and new ISD opcodes for fcvt.wu. This allows us to keep know it started life as a conversion to i32 without needing to match multiple nodes. ComputeNumSignBits has been taught that this new nodes produces 33 sign bits. To prevent regressions when we need to zero extend the result of an (i32 (fptoui X)), I've added a DAG combine to convert it to an (i64 (fptoui X)) before type legalization. In most cases this would happen in InstCombine, but a zero_extend can be created for function returns or arguments. To keep everything consistent I've added new nodes for fptosi as well. Reviewed By: luismarques Differential Revision: https://reviews.llvm.org/D106346
This commit is contained in:
parent
d850d297ea
commit
0a8fb0b4d7
@ -849,6 +849,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
|
||||
setTargetDAGCombine(ISD::OR);
|
||||
setTargetDAGCombine(ISD::XOR);
|
||||
setTargetDAGCombine(ISD::ANY_EXTEND);
|
||||
setTargetDAGCombine(ISD::ZERO_EXTEND);
|
||||
if (Subtarget.hasStdExtV()) {
|
||||
setTargetDAGCombine(ISD::FCOPYSIGN);
|
||||
setTargetDAGCombine(ISD::MGATHER);
|
||||
@ -4859,20 +4860,30 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
|
||||
case ISD::STRICT_FP_TO_UINT:
|
||||
case ISD::FP_TO_SINT:
|
||||
case ISD::FP_TO_UINT: {
|
||||
bool IsStrict = N->isStrictFPOpcode();
|
||||
assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
|
||||
"Unexpected custom legalisation");
|
||||
bool IsStrict = N->isStrictFPOpcode();
|
||||
bool IsSigned = N->getOpcode() == ISD::FP_TO_SINT ||
|
||||
N->getOpcode() == ISD::STRICT_FP_TO_SINT;
|
||||
SDValue Op0 = IsStrict ? N->getOperand(1) : N->getOperand(0);
|
||||
if (getTypeAction(*DAG.getContext(), Op0.getValueType()) !=
|
||||
TargetLowering::TypeSoftenFloat) {
|
||||
// FIXME: Support strict FP.
|
||||
if (IsStrict)
|
||||
return;
|
||||
if (!isTypeLegal(Op0.getValueType()))
|
||||
return;
|
||||
unsigned Opc = IsSigned ? RISCVISD::FCVT_W_RV64 : RISCVISD::FCVT_WU_RV64;
|
||||
SDValue Res = DAG.getNode(Opc, DL, MVT::i64, Op0);
|
||||
Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Res));
|
||||
return;
|
||||
}
|
||||
// If the FP type needs to be softened, emit a library call using the 'si'
|
||||
// version. If we left it to default legalization we'd end up with 'di'. If
|
||||
// the FP type doesn't need to be softened just let generic type
|
||||
// legalization promote the result type.
|
||||
if (getTypeAction(*DAG.getContext(), Op0.getValueType()) !=
|
||||
TargetLowering::TypeSoftenFloat)
|
||||
return;
|
||||
RTLIB::Libcall LC;
|
||||
if (N->getOpcode() == ISD::FP_TO_SINT ||
|
||||
N->getOpcode() == ISD::STRICT_FP_TO_SINT)
|
||||
if (IsSigned)
|
||||
LC = RTLIB::getFPTOSINT(Op0.getValueType(), N->getValueType(0));
|
||||
else
|
||||
LC = RTLIB::getFPTOUINT(Op0.getValueType(), N->getValueType(0));
|
||||
@ -6056,6 +6067,16 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
|
||||
return performXORCombine(N, DCI, Subtarget);
|
||||
case ISD::ANY_EXTEND:
|
||||
return performANY_EXTENDCombine(N, DCI, Subtarget);
|
||||
case ISD::ZERO_EXTEND:
|
||||
// Fold (zero_extend (fp_to_uint X)) to prevent forming fcvt+zexti32 during
|
||||
// type legalization. This is safe because fp_to_uint produces poison if
|
||||
// it overflows.
|
||||
if (N->getValueType(0) == MVT::i64 && Subtarget.is64Bit() &&
|
||||
N->getOperand(0).getOpcode() == ISD::FP_TO_UINT &&
|
||||
isTypeLegal(N->getOperand(0).getOperand(0).getValueType()))
|
||||
return DAG.getNode(ISD::FP_TO_UINT, SDLoc(N), MVT::i64,
|
||||
N->getOperand(0).getOperand(0));
|
||||
return SDValue();
|
||||
case RISCVISD::SELECT_CC: {
|
||||
// Transform
|
||||
SDValue LHS = N->getOperand(0);
|
||||
@ -6586,6 +6607,8 @@ unsigned RISCVTargetLowering::ComputeNumSignBitsForTargetNode(
|
||||
case RISCVISD::UNSHFLW:
|
||||
case RISCVISD::BCOMPRESSW:
|
||||
case RISCVISD::BDECOMPRESSW:
|
||||
case RISCVISD::FCVT_W_RV64:
|
||||
case RISCVISD::FCVT_WU_RV64:
|
||||
// TODO: As the result is sign-extended, this is conservatively correct. A
|
||||
// more precise answer could be calculated for SRAW depending on known
|
||||
// bits in the shift amount.
|
||||
@ -8298,6 +8321,8 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
NODE_NAME_CASE(FMV_X_ANYEXTH)
|
||||
NODE_NAME_CASE(FMV_W_X_RV64)
|
||||
NODE_NAME_CASE(FMV_X_ANYEXTW_RV64)
|
||||
NODE_NAME_CASE(FCVT_W_RV64)
|
||||
NODE_NAME_CASE(FCVT_WU_RV64)
|
||||
NODE_NAME_CASE(READ_CYCLE_WIDE)
|
||||
NODE_NAME_CASE(GREV)
|
||||
NODE_NAME_CASE(GREVW)
|
||||
|
@ -84,6 +84,10 @@ enum NodeType : unsigned {
|
||||
FMV_X_ANYEXTH,
|
||||
FMV_W_X_RV64,
|
||||
FMV_X_ANYEXTW_RV64,
|
||||
// FP to 32 bit int conversions for RV64. These are used to keep track of the
|
||||
// result being sign extended to 64 bit.
|
||||
FCVT_W_RV64,
|
||||
FCVT_WU_RV64,
|
||||
// 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,
|
||||
|
@ -351,12 +351,11 @@ def : Pat<(f64 (fpimm0)), (FMV_D_X (i64 X0))>;
|
||||
def : Pat<(bitconvert (i64 GPR:$rs1)), (FMV_D_X GPR:$rs1)>;
|
||||
def : Pat<(i64 (bitconvert FPR64:$rs1)), (FMV_X_D FPR64:$rs1)>;
|
||||
|
||||
// FP->[u]int32 is mostly handled by the FP->[u]int64 patterns. This is safe
|
||||
// because fpto[u|s]i produce poison if the value can't fit into the target.
|
||||
// We match the single case below because fcvt.wu.d sign-extends its result so
|
||||
// is cheaper than fcvt.lu.d+sext.w.
|
||||
def : Pat<(sext_inreg (assertzexti32 (fp_to_uint FPR64:$rs1)), i32),
|
||||
(FCVT_WU_D $rs1, 0b001)>;
|
||||
// Use target specific isd nodes to help us remember the result is sign
|
||||
// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
|
||||
// duplicated if it has another user that didn't need the sign_extend.
|
||||
def : Pat<(riscv_fcvt_w_rv64 FPR64:$rs1), (FCVT_W_D $rs1, 0b001)>;
|
||||
def : Pat<(riscv_fcvt_wu_rv64 FPR64:$rs1), (FCVT_WU_D $rs1, 0b001)>;
|
||||
|
||||
// [u]int32->fp
|
||||
def : Pat<(sint_to_fp (i64 (sexti32 (i64 GPR:$rs1)))), (FCVT_D_W $rs1)>;
|
||||
|
@ -19,11 +19,17 @@ def SDT_RISCVFMV_W_X_RV64
|
||||
: SDTypeProfile<1, 1, [SDTCisVT<0, f32>, SDTCisVT<1, i64>]>;
|
||||
def SDT_RISCVFMV_X_ANYEXTW_RV64
|
||||
: SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisVT<1, f32>]>;
|
||||
def STD_RISCVFCVT_W_RV64
|
||||
: SDTypeProfile<1, 1, [SDTCisVT<0, i64>, SDTCisFP<1>]>;
|
||||
|
||||
def riscv_fmv_w_x_rv64
|
||||
: SDNode<"RISCVISD::FMV_W_X_RV64", SDT_RISCVFMV_W_X_RV64>;
|
||||
def riscv_fmv_x_anyextw_rv64
|
||||
: SDNode<"RISCVISD::FMV_X_ANYEXTW_RV64", SDT_RISCVFMV_X_ANYEXTW_RV64>;
|
||||
def riscv_fcvt_w_rv64
|
||||
: SDNode<"RISCVISD::FCVT_W_RV64", STD_RISCVFCVT_W_RV64>;
|
||||
def riscv_fcvt_wu_rv64
|
||||
: SDNode<"RISCVISD::FCVT_WU_RV64", STD_RISCVFCVT_W_RV64>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Operand and SDNode transformation definitions.
|
||||
@ -391,12 +397,11 @@ def : Pat<(riscv_fmv_x_anyextw_rv64 FPR32:$src), (FMV_X_W FPR32:$src)>;
|
||||
def : Pat<(sext_inreg (riscv_fmv_x_anyextw_rv64 FPR32:$src), i32),
|
||||
(FMV_X_W FPR32:$src)>;
|
||||
|
||||
// FP->[u]int32 is mostly handled by the FP->[u]int64 patterns. This is safe
|
||||
// because fpto[u|s]i produces poison if the value can't fit into the target.
|
||||
// We match the single case below because fcvt.wu.s sign-extends its result so
|
||||
// is cheaper than fcvt.lu.s+sext.w.
|
||||
def : Pat<(sext_inreg (assertzexti32 (fp_to_uint FPR32:$rs1)), i32),
|
||||
(FCVT_WU_S $rs1, 0b001)>;
|
||||
// Use target specific isd nodes to help us remember the result is sign
|
||||
// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
|
||||
// duplicated if it has another user that didn't need the sign_extend.
|
||||
def : Pat<(riscv_fcvt_w_rv64 FPR32:$rs1), (FCVT_W_S $rs1, 0b001)>;
|
||||
def : Pat<(riscv_fcvt_wu_rv64 FPR32:$rs1), (FCVT_WU_S $rs1, 0b001)>;
|
||||
|
||||
// float->[u]int64. Round-to-zero must be used.
|
||||
def : Pat<(i64 (fp_to_sint FPR32:$rs1)), (FCVT_L_S $rs1, 0b001)>;
|
||||
|
@ -350,12 +350,11 @@ def : Pat<(uint_to_fp (i32 GPR:$rs1)), (FCVT_H_WU $rs1, 0b111)>;
|
||||
} // Predicates = [HasStdExtZfh, IsRV32]
|
||||
|
||||
let Predicates = [HasStdExtZfh, IsRV64] in {
|
||||
// FP->[u]int32 is mostly handled by the FP->[u]int64 patterns. This is safe
|
||||
// because fpto[u|s]i produces poison if the value can't fit into the target.
|
||||
// We match the single case below because fcvt.wu.s sign-extends its result so
|
||||
// is cheaper than fcvt.lu.h+sext.w.
|
||||
def : Pat<(sext_inreg (assertzexti32 (fp_to_uint FPR16:$rs1)), i32),
|
||||
(FCVT_WU_H $rs1, 0b001)>;
|
||||
// Use target specific isd nodes to help us remember the result is sign
|
||||
// extended. Matching sext_inreg+fptoui/fptosi may cause the conversion to be
|
||||
// duplicated if it has another user that didn't need the sign_extend.
|
||||
def : Pat<(riscv_fcvt_w_rv64 FPR16:$rs1), (FCVT_W_H $rs1, 0b001)>;
|
||||
def : Pat<(riscv_fcvt_wu_rv64 FPR16:$rs1), (FCVT_WU_H $rs1, 0b001)>;
|
||||
|
||||
// half->[u]int64. Round-to-zero must be used.
|
||||
def : Pat<(i64 (fp_to_sint FPR16:$rs1)), (FCVT_L_H $rs1, 0b001)>;
|
||||
|
@ -64,7 +64,7 @@ define i32 @fcvt_w_d(double %a) nounwind {
|
||||
; RV64IFD-LABEL: fcvt_w_d:
|
||||
; RV64IFD: # %bb.0:
|
||||
; RV64IFD-NEXT: fmv.d.x ft0, a0
|
||||
; RV64IFD-NEXT: fcvt.l.d a0, ft0, rtz
|
||||
; RV64IFD-NEXT: fcvt.w.d a0, ft0, rtz
|
||||
; RV64IFD-NEXT: ret
|
||||
%1 = fptosi double %a to i32
|
||||
ret i32 %1
|
||||
@ -133,7 +133,7 @@ define i32 @fcvt_wu_d(double %a) nounwind {
|
||||
; RV64IFD-LABEL: fcvt_wu_d:
|
||||
; RV64IFD: # %bb.0:
|
||||
; RV64IFD-NEXT: fmv.d.x ft0, a0
|
||||
; RV64IFD-NEXT: fcvt.lu.d a0, ft0, rtz
|
||||
; RV64IFD-NEXT: fcvt.wu.d a0, ft0, rtz
|
||||
; RV64IFD-NEXT: ret
|
||||
%1 = fptoui double %a to i32
|
||||
ret i32 %1
|
||||
@ -166,7 +166,7 @@ define i32 @fcvt_wu_d_multiple_use(double %x, i32* %y) {
|
||||
; RV64IFD-NEXT: addi a0, zero, 1
|
||||
; RV64IFD-NEXT: beqz a1, .LBB5_2
|
||||
; RV64IFD-NEXT: # %bb.1:
|
||||
; RV64IFD-NEXT: fcvt.lu.d a0, ft0, rtz
|
||||
; RV64IFD-NEXT: mv a0, a1
|
||||
; RV64IFD-NEXT: .LBB5_2:
|
||||
; RV64IFD-NEXT: ret
|
||||
%a = fptoui double %x to i32
|
||||
|
@ -16,7 +16,7 @@ define i32 @fcvt_w_s(float %a) nounwind {
|
||||
; RV64IF-LABEL: fcvt_w_s:
|
||||
; RV64IF: # %bb.0:
|
||||
; RV64IF-NEXT: fmv.w.x ft0, a0
|
||||
; RV64IF-NEXT: fcvt.l.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: fcvt.w.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: ret
|
||||
%1 = fptosi float %a to i32
|
||||
ret i32 %1
|
||||
@ -102,7 +102,7 @@ define i32 @fcvt_wu_s(float %a) nounwind {
|
||||
; RV64IF-LABEL: fcvt_wu_s:
|
||||
; RV64IF: # %bb.0:
|
||||
; RV64IF-NEXT: fmv.w.x ft0, a0
|
||||
; RV64IF-NEXT: fcvt.lu.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: fcvt.wu.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: ret
|
||||
%1 = fptoui float %a to i32
|
||||
ret i32 %1
|
||||
@ -130,7 +130,7 @@ define i32 @fcvt_wu_s_multiple_use(float %x, i32* %y) {
|
||||
; RV64IF-NEXT: addi a0, zero, 1
|
||||
; RV64IF-NEXT: beqz a1, .LBB3_2
|
||||
; RV64IF-NEXT: # %bb.1:
|
||||
; RV64IF-NEXT: fcvt.lu.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: mv a0, a1
|
||||
; RV64IF-NEXT: .LBB3_2:
|
||||
; RV64IF-NEXT: ret
|
||||
%a = fptoui float %x to i32
|
||||
|
@ -164,7 +164,7 @@ define i32 @fcvt_ui_h_multiple_use(half %x, i32* %y) {
|
||||
; RV64IZFH-NEXT: addi a0, zero, 1
|
||||
; RV64IZFH-NEXT: beqz a1, .LBB3_2
|
||||
; RV64IZFH-NEXT: # %bb.1:
|
||||
; RV64IZFH-NEXT: fcvt.lu.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: mv a0, a1
|
||||
; RV64IZFH-NEXT: .LBB3_2:
|
||||
; RV64IZFH-NEXT: ret
|
||||
;
|
||||
@ -174,7 +174,7 @@ define i32 @fcvt_ui_h_multiple_use(half %x, i32* %y) {
|
||||
; RV64IDZFH-NEXT: addi a0, zero, 1
|
||||
; RV64IDZFH-NEXT: beqz a1, .LBB3_2
|
||||
; RV64IDZFH-NEXT: # %bb.1:
|
||||
; RV64IDZFH-NEXT: fcvt.lu.h a0, fa0, rtz
|
||||
; RV64IDZFH-NEXT: mv a0, a1
|
||||
; RV64IDZFH-NEXT: .LBB3_2:
|
||||
; RV64IDZFH-NEXT: ret
|
||||
%a = fptoui half %x to i32
|
||||
@ -246,12 +246,12 @@ define i32 @fcvt_w_h(half %a) nounwind {
|
||||
;
|
||||
; RV64IZFH-LABEL: fcvt_w_h:
|
||||
; RV64IZFH: # %bb.0:
|
||||
; RV64IZFH-NEXT: fcvt.l.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: fcvt.w.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: ret
|
||||
;
|
||||
; RV64IDZFH-LABEL: fcvt_w_h:
|
||||
; RV64IDZFH: # %bb.0:
|
||||
; RV64IDZFH-NEXT: fcvt.l.h a0, fa0, rtz
|
||||
; RV64IDZFH-NEXT: fcvt.w.h a0, fa0, rtz
|
||||
; RV64IDZFH-NEXT: ret
|
||||
%1 = fptosi half %a to i32
|
||||
ret i32 %1
|
||||
@ -400,12 +400,12 @@ define i32 @fcvt_wu_h(half %a) nounwind {
|
||||
;
|
||||
; RV64IZFH-LABEL: fcvt_wu_h:
|
||||
; RV64IZFH: # %bb.0:
|
||||
; RV64IZFH-NEXT: fcvt.lu.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: fcvt.wu.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: ret
|
||||
;
|
||||
; RV64IDZFH-LABEL: fcvt_wu_h:
|
||||
; RV64IDZFH: # %bb.0:
|
||||
; RV64IDZFH-NEXT: fcvt.lu.h a0, fa0, rtz
|
||||
; RV64IDZFH-NEXT: fcvt.wu.h a0, fa0, rtz
|
||||
; RV64IDZFH-NEXT: ret
|
||||
%1 = fptoui half %a to i32
|
||||
ret i32 %1
|
||||
|
@ -11,7 +11,7 @@ define i32 @aext_fptosi(double %a) nounwind {
|
||||
; RV64ID-LABEL: aext_fptosi:
|
||||
; RV64ID: # %bb.0:
|
||||
; RV64ID-NEXT: fmv.d.x ft0, a0
|
||||
; RV64ID-NEXT: fcvt.l.d a0, ft0, rtz
|
||||
; RV64ID-NEXT: fcvt.w.d a0, ft0, rtz
|
||||
; RV64ID-NEXT: ret
|
||||
%1 = fptosi double %a to i32
|
||||
ret i32 %1
|
||||
@ -21,7 +21,7 @@ define signext i32 @sext_fptosi(double %a) nounwind {
|
||||
; RV64ID-LABEL: sext_fptosi:
|
||||
; RV64ID: # %bb.0:
|
||||
; RV64ID-NEXT: fmv.d.x ft0, a0
|
||||
; RV64ID-NEXT: fcvt.l.d a0, ft0, rtz
|
||||
; RV64ID-NEXT: fcvt.w.d a0, ft0, rtz
|
||||
; RV64ID-NEXT: ret
|
||||
%1 = fptosi double %a to i32
|
||||
ret i32 %1
|
||||
@ -31,7 +31,7 @@ define zeroext i32 @zext_fptosi(double %a) nounwind {
|
||||
; RV64ID-LABEL: zext_fptosi:
|
||||
; RV64ID: # %bb.0:
|
||||
; RV64ID-NEXT: fmv.d.x ft0, a0
|
||||
; RV64ID-NEXT: fcvt.l.d a0, ft0, rtz
|
||||
; RV64ID-NEXT: fcvt.w.d a0, ft0, rtz
|
||||
; RV64ID-NEXT: slli a0, a0, 32
|
||||
; RV64ID-NEXT: srli a0, a0, 32
|
||||
; RV64ID-NEXT: ret
|
||||
@ -43,7 +43,7 @@ define i32 @aext_fptoui(double %a) nounwind {
|
||||
; RV64ID-LABEL: aext_fptoui:
|
||||
; RV64ID: # %bb.0:
|
||||
; RV64ID-NEXT: fmv.d.x ft0, a0
|
||||
; RV64ID-NEXT: fcvt.lu.d a0, ft0, rtz
|
||||
; RV64ID-NEXT: fcvt.wu.d a0, ft0, rtz
|
||||
; RV64ID-NEXT: ret
|
||||
%1 = fptoui double %a to i32
|
||||
ret i32 %1
|
||||
|
@ -11,7 +11,7 @@ define i32 @aext_fptosi(float %a) nounwind {
|
||||
; RV64IF-LABEL: aext_fptosi:
|
||||
; RV64IF: # %bb.0:
|
||||
; RV64IF-NEXT: fmv.w.x ft0, a0
|
||||
; RV64IF-NEXT: fcvt.l.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: fcvt.w.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: ret
|
||||
%1 = fptosi float %a to i32
|
||||
ret i32 %1
|
||||
@ -21,7 +21,7 @@ define signext i32 @sext_fptosi(float %a) nounwind {
|
||||
; RV64IF-LABEL: sext_fptosi:
|
||||
; RV64IF: # %bb.0:
|
||||
; RV64IF-NEXT: fmv.w.x ft0, a0
|
||||
; RV64IF-NEXT: fcvt.l.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: fcvt.w.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: ret
|
||||
%1 = fptosi float %a to i32
|
||||
ret i32 %1
|
||||
@ -31,7 +31,7 @@ define zeroext i32 @zext_fptosi(float %a) nounwind {
|
||||
; RV64IF-LABEL: zext_fptosi:
|
||||
; RV64IF: # %bb.0:
|
||||
; RV64IF-NEXT: fmv.w.x ft0, a0
|
||||
; RV64IF-NEXT: fcvt.l.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: fcvt.w.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: slli a0, a0, 32
|
||||
; RV64IF-NEXT: srli a0, a0, 32
|
||||
; RV64IF-NEXT: ret
|
||||
@ -43,7 +43,7 @@ define i32 @aext_fptoui(float %a) nounwind {
|
||||
; RV64IF-LABEL: aext_fptoui:
|
||||
; RV64IF: # %bb.0:
|
||||
; RV64IF-NEXT: fmv.w.x ft0, a0
|
||||
; RV64IF-NEXT: fcvt.lu.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: fcvt.wu.s a0, ft0, rtz
|
||||
; RV64IF-NEXT: ret
|
||||
%1 = fptoui float %a to i32
|
||||
ret i32 %1
|
||||
|
@ -10,7 +10,7 @@
|
||||
define i32 @aext_fptosi(half %a) nounwind {
|
||||
; RV64IZFH-LABEL: aext_fptosi:
|
||||
; RV64IZFH: # %bb.0:
|
||||
; RV64IZFH-NEXT: fcvt.l.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: fcvt.w.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: ret
|
||||
%1 = fptosi half %a to i32
|
||||
ret i32 %1
|
||||
@ -19,7 +19,7 @@ define i32 @aext_fptosi(half %a) nounwind {
|
||||
define signext i32 @sext_fptosi(half %a) nounwind {
|
||||
; RV64IZFH-LABEL: sext_fptosi:
|
||||
; RV64IZFH: # %bb.0:
|
||||
; RV64IZFH-NEXT: fcvt.l.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: fcvt.w.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: ret
|
||||
%1 = fptosi half %a to i32
|
||||
ret i32 %1
|
||||
@ -28,7 +28,7 @@ define signext i32 @sext_fptosi(half %a) nounwind {
|
||||
define zeroext i32 @zext_fptosi(half %a) nounwind {
|
||||
; RV64IZFH-LABEL: zext_fptosi:
|
||||
; RV64IZFH: # %bb.0:
|
||||
; RV64IZFH-NEXT: fcvt.l.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: fcvt.w.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: slli a0, a0, 32
|
||||
; RV64IZFH-NEXT: srli a0, a0, 32
|
||||
; RV64IZFH-NEXT: ret
|
||||
@ -39,7 +39,7 @@ define zeroext i32 @zext_fptosi(half %a) nounwind {
|
||||
define i32 @aext_fptoui(half %a) nounwind {
|
||||
; RV64IZFH-LABEL: aext_fptoui:
|
||||
; RV64IZFH: # %bb.0:
|
||||
; RV64IZFH-NEXT: fcvt.lu.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: fcvt.wu.h a0, fa0, rtz
|
||||
; RV64IZFH-NEXT: ret
|
||||
%1 = fptoui half %a to i32
|
||||
ret i32 %1
|
||||
|
Loading…
Reference in New Issue
Block a user