diff --git a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td index 0e2f57551f334d..3767fc1d793bad 100644 --- a/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchFloat32InstrInfo.td @@ -284,7 +284,11 @@ def : Pat<(loongarch_movgr2fr_w_la64 GPR:$src), (MOVGR2FR_W GPR:$src)>; def : Pat<(loongarch_movfr2gr_s_la64 FPR32:$src), (MOVFR2GR_S FPR32:$src)>; // int -> f32 -def : Pat<(f32 (sint_to_fp GPR:$src)), (FFINT_S_W (MOVGR2FR_W GPR:$src))>; +def : Pat<(f32 (sint_to_fp (i64 (sexti32 (i64 GPR:$src))))), + (FFINT_S_W (MOVGR2FR_W GPR:$src))>; +// uint -> f32 +def : Pat<(f32 (uint_to_fp (i64 (sexti32 (i64 GPR:$src))))), + (FFINT_S_W (MOVGR2FR_W GPR:$src))>; } // Predicates = [HasBasicF, IsLA64] // FP Rounding diff --git a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td index d061b6426e244d..44a80054f0a90e 100644 --- a/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchFloat64InstrInfo.td @@ -288,13 +288,11 @@ def : Pat<(f64 fpimm1), (FCVT_D_S (FFINT_S_W (MOVGR2FR_W (ADDI_W R0, 1))))>; /// Convert int to FP let Predicates = [HasBasicD, IsLA64] in { +def : Pat<(f32 (sint_to_fp GPR:$src)), (FFINT_S_L (MOVGR2FR_D GPR:$src))>; def : Pat<(f64 (sint_to_fp (i64 (sexti32 (i64 GPR:$src))))), (FFINT_D_W (MOVGR2FR_W GPR:$src))>; def : Pat<(f64 (sint_to_fp GPR:$src)), (FFINT_D_L (MOVGR2FR_D GPR:$src))>; -def : Pat<(f64 (uint_to_fp (i64 (zexti32 (i64 GPR:$src))))), - (FFINT_D_W (MOVGR2FR_W GPR:$src))>; - def : Pat<(bitconvert GPR:$src), (MOVGR2FR_D GPR:$src)>; } // Predicates = [HasBasicD, IsLA64] let Predicates = [HasBasicD, IsLA32] in { diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp index 415ca4d871cda0..8ba1f9c1b27f60 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp @@ -213,6 +213,12 @@ bool LoongArchDAGToDAGISel::selectSExti32(SDValue N, SDValue &Val) { Val = N.getOperand(0); return true; } + if (N.getOpcode() == LoongArchISD::BSTRPICK && + N.getConstantOperandVal(1) < UINT64_C(0X1F) && + N.getConstantOperandVal(2) == UINT64_C(0)) { + Val = N; + return true; + } MVT VT = N.getSimpleValueType(); if (CurDAG->ComputeNumSignBits(N) > (VT.getSizeInBits() - 32)) { Val = N; diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 6f477413636a9c..49e8ce02abccd5 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -21,6 +21,7 @@ #include "MCTargetDesc/LoongArchMCTargetDesc.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/ISDOpcodes.h" +#include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicsLoongArch.h" #include "llvm/Support/Debug.h" @@ -160,7 +161,12 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, setLibcallName(RTLIB::MUL_I128, nullptr); setOperationAction(ISD::FP_TO_UINT, GRLenVT, Custom); - setOperationAction(ISD::UINT_TO_FP, GRLenVT, Custom); + setOperationAction(ISD::UINT_TO_FP, GRLenVT, Expand); + if ((Subtarget.is64Bit() && Subtarget.hasBasicF() && + !Subtarget.hasBasicD())) { + setOperationAction(ISD::SINT_TO_FP, GRLenVT, Custom); + setOperationAction(ISD::UINT_TO_FP, GRLenVT, Custom); + } // Compute derived properties from the register classes. computeRegisterProperties(STI.getRegisterInfo()); @@ -220,6 +226,8 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op, return lowerBITCAST(Op, DAG); case ISD::UINT_TO_FP: return lowerUINT_TO_FP(Op, DAG); + case ISD::SINT_TO_FP: + return lowerSINT_TO_FP(Op, DAG); case ISD::VASTART: return lowerVASTART(Op, DAG); case ISD::FRAMEADDR: @@ -302,19 +310,61 @@ SDValue LoongArchTargetLowering::lowerVASTART(SDValue Op, SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const { + assert(Subtarget.is64Bit() && Subtarget.hasBasicF() && + !Subtarget.hasBasicD() && "unexpected target features"); + + SDLoc DL(Op); + SDValue Op0 = Op.getOperand(0); + if (Op0->getOpcode() == ISD::AND) { + auto *C = dyn_cast(Op0.getOperand(1)); + if (C && C->getZExtValue() < UINT64_C(0xFFFFFFFF)) + return Op; + } + + if (Op0->getOpcode() == LoongArchISD::BSTRPICK && + Op0.getConstantOperandVal(1) < UINT64_C(0X1F) && + Op0.getConstantOperandVal(2) == UINT64_C(0)) + return Op; + + if (Op0.getOpcode() == ISD::AssertZext && + dyn_cast(Op0.getOperand(1))->getVT().bitsLT(MVT::i32)) + return Op; + + EVT OpVT = Op0.getValueType(); + EVT RetVT = Op.getValueType(); + RTLIB::Libcall LC = RTLIB::getUINTTOFP(OpVT, RetVT); + MakeLibCallOptions CallOptions; + CallOptions.setTypeListBeforeSoften(OpVT, RetVT, true); + SDValue Chain = SDValue(); + SDValue Result; + std::tie(Result, Chain) = + makeLibCall(DAG, LC, Op.getValueType(), Op0, CallOptions, DL, Chain); + return Result; +} + +SDValue LoongArchTargetLowering::lowerSINT_TO_FP(SDValue Op, + SelectionDAG &DAG) const { + assert(Subtarget.is64Bit() && Subtarget.hasBasicF() && + !Subtarget.hasBasicD() && "unexpected target features"); SDLoc DL(Op); - auto &TLI = DAG.getTargetLoweringInfo(); - SDValue Tmp1, Tmp2; - SDValue Op1 = Op.getOperand(0); - if (Op1->getOpcode() == ISD::AssertZext || - Op1->getOpcode() == ISD::AssertSext) + SDValue Op0 = Op.getOperand(0); + + if ((Op0.getOpcode() == ISD::AssertSext || + Op0.getOpcode() == ISD::SIGN_EXTEND_INREG) && + dyn_cast(Op0.getOperand(1))->getVT().bitsLE(MVT::i32)) return Op; - SDValue Trunc = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Op.getOperand(0)); - SDValue Res = DAG.getNode(ISD::UINT_TO_FP, DL, MVT::f64, Trunc); - SDNode *N = Res.getNode(); - TLI.expandUINT_TO_FP(N, Tmp1, Tmp2, DAG); - return Tmp1; + + EVT OpVT = Op0.getValueType(); + EVT RetVT = Op.getValueType(); + RTLIB::Libcall LC = RTLIB::getSINTTOFP(OpVT, RetVT); + MakeLibCallOptions CallOptions; + CallOptions.setTypeListBeforeSoften(OpVT, RetVT, true); + SDValue Chain = SDValue(); + SDValue Result; + std::tie(Result, Chain) = + makeLibCall(DAG, LC, Op.getValueType(), Op0, CallOptions, DL, Chain); + return Result; } SDValue LoongArchTargetLowering::lowerBITCAST(SDValue Op, diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h index 1e411fb34f7270..358da7feb20b6d 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h @@ -171,6 +171,7 @@ class LoongArchTargetLowering : public TargetLowering { SDValue lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const; SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; SDValue lowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const; SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const; SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll index 070027b6984369..03a126a736efc3 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/double-convert.ll @@ -242,16 +242,9 @@ define double @convert_u32_to_double(i32 %a) nounwind { ; ; LA64-LABEL: convert_u32_to_double: ; LA64: # %bb.0: -; LA64-NEXT: pcalau12i $a1, %pc_hi20(.LCPI12_0) -; LA64-NEXT: addi.d $a1, $a1, %pc_lo12(.LCPI12_0) -; LA64-NEXT: fld.d $fa0, $a1, 0 -; LA64-NEXT: lu52i.d $a1, $zero, 1107 -; LA64-NEXT: movgr2fr.d $fa1, $a1 -; LA64-NEXT: fsub.d $fa0, $fa1, $fa0 -; LA64-NEXT: lu12i.w $a1, 275200 -; LA64-NEXT: bstrins.d $a0, $a1, 63, 32 -; LA64-NEXT: movgr2fr.d $fa1, $a0 -; LA64-NEXT: fadd.d $fa0, $fa1, $fa0 +; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: movgr2fr.d $fa0, $a0 +; LA64-NEXT: ffint.d.l $fa0, $fa0 ; LA64-NEXT: ret %1 = uitofp i32 %a to double ret double %1 diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll index 559206a4db5ac3..a18cb6f756a601 100644 --- a/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/float-convert.ll @@ -376,14 +376,12 @@ define float @convert_i32_to_float(i32 %a) nounwind { ; ; LA64F-LABEL: convert_i32_to_float: ; LA64F: # %bb.0: -; LA64F-NEXT: addi.w $a0, $a0, 0 ; LA64F-NEXT: movgr2fr.w $fa0, $a0 ; LA64F-NEXT: ffint.s.w $fa0, $fa0 ; LA64F-NEXT: ret ; ; LA64D-LABEL: convert_i32_to_float: ; LA64D: # %bb.0: -; LA64D-NEXT: addi.w $a0, $a0, 0 ; LA64D-NEXT: movgr2fr.w $fa0, $a0 ; LA64D-NEXT: ffint.s.w $fa0, $fa0 ; LA64D-NEXT: ret @@ -412,14 +410,17 @@ define float @convert_i64_to_float(i64 %a) nounwind { ; ; LA64F-LABEL: convert_i64_to_float: ; LA64F: # %bb.0: -; LA64F-NEXT: movgr2fr.w $fa0, $a0 -; LA64F-NEXT: ffint.s.w $fa0, $fa0 +; LA64F-NEXT: addi.d $sp, $sp, -16 +; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64F-NEXT: bl %plt(__floatdisf) +; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64F-NEXT: addi.d $sp, $sp, 16 ; LA64F-NEXT: ret ; ; LA64D-LABEL: convert_i64_to_float: ; LA64D: # %bb.0: -; LA64D-NEXT: movgr2fr.w $fa0, $a0 -; LA64D-NEXT: ffint.s.w $fa0, $fa0 +; LA64D-NEXT: movgr2fr.d $fa0, $a0 +; LA64D-NEXT: ffint.s.l $fa0, $fa0 ; LA64D-NEXT: ret %1 = sitofp i64 %a to float ret float %1 @@ -514,34 +515,19 @@ define float @convert_u32_to_float(i32 %a) nounwind { ; ; LA64F-LABEL: convert_u32_to_float: ; LA64F: # %bb.0: -; LA64F-NEXT: bstrpick.d $a1, $a0, 31, 1 -; LA64F-NEXT: andi $a2, $a0, 1 -; LA64F-NEXT: or $a1, $a2, $a1 -; LA64F-NEXT: movgr2fr.w $fa0, $a1 -; LA64F-NEXT: ffint.s.w $fa0, $fa0 -; LA64F-NEXT: fadd.s $fa0, $fa0, $fa0 +; LA64F-NEXT: addi.d $sp, $sp, -16 +; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ; LA64F-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64F-NEXT: slti $a1, $a0, 0 -; LA64F-NEXT: movgr2cf $fcc0, $a1 -; LA64F-NEXT: movgr2fr.w $fa1, $a0 -; LA64F-NEXT: ffint.s.w $fa1, $fa1 -; LA64F-NEXT: fsel $fa0, $fa1, $fa0, $fcc0 +; LA64F-NEXT: bl %plt(__floatundisf) +; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64F-NEXT: addi.d $sp, $sp, 16 ; LA64F-NEXT: ret ; ; LA64D-LABEL: convert_u32_to_float: ; LA64D: # %bb.0: -; LA64D-NEXT: bstrpick.d $a1, $a0, 31, 1 -; LA64D-NEXT: andi $a2, $a0, 1 -; LA64D-NEXT: or $a1, $a2, $a1 -; LA64D-NEXT: movgr2fr.w $fa0, $a1 -; LA64D-NEXT: ffint.s.w $fa0, $fa0 -; LA64D-NEXT: fadd.s $fa0, $fa0, $fa0 ; LA64D-NEXT: bstrpick.d $a0, $a0, 31, 0 -; LA64D-NEXT: slti $a1, $a0, 0 -; LA64D-NEXT: movgr2cf $fcc0, $a1 -; LA64D-NEXT: movgr2fr.w $fa1, $a0 -; LA64D-NEXT: ffint.s.w $fa1, $fa1 -; LA64D-NEXT: fsel $fa0, $fa1, $fa0, $fcc0 +; LA64D-NEXT: movgr2fr.d $fa0, $a0 +; LA64D-NEXT: ffint.s.l $fa0, $fa0 ; LA64D-NEXT: ret %1 = uitofp i32 %a to float ret float %1 @@ -568,17 +554,11 @@ define float @convert_u64_to_float(i64 %a) nounwind { ; ; LA64F-LABEL: convert_u64_to_float: ; LA64F: # %bb.0: -; LA64F-NEXT: srli.d $a1, $a0, 1 -; LA64F-NEXT: andi $a2, $a0, 1 -; LA64F-NEXT: or $a1, $a2, $a1 -; LA64F-NEXT: movgr2fr.w $fa0, $a1 -; LA64F-NEXT: ffint.s.w $fa0, $fa0 -; LA64F-NEXT: fadd.s $fa0, $fa0, $fa0 -; LA64F-NEXT: slti $a1, $a0, 0 -; LA64F-NEXT: movgr2cf $fcc0, $a1 -; LA64F-NEXT: movgr2fr.w $fa1, $a0 -; LA64F-NEXT: ffint.s.w $fa1, $fa1 -; LA64F-NEXT: fsel $fa0, $fa1, $fa0, $fcc0 +; LA64F-NEXT: addi.d $sp, $sp, -16 +; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64F-NEXT: bl %plt(__floatundisf) +; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64F-NEXT: addi.d $sp, $sp, 16 ; LA64F-NEXT: ret ; ; LA64D-LABEL: convert_u64_to_float: @@ -586,13 +566,13 @@ define float @convert_u64_to_float(i64 %a) nounwind { ; LA64D-NEXT: srli.d $a1, $a0, 1 ; LA64D-NEXT: andi $a2, $a0, 1 ; LA64D-NEXT: or $a1, $a2, $a1 -; LA64D-NEXT: movgr2fr.w $fa0, $a1 -; LA64D-NEXT: ffint.s.w $fa0, $fa0 +; LA64D-NEXT: movgr2fr.d $fa0, $a1 +; LA64D-NEXT: ffint.s.l $fa0, $fa0 ; LA64D-NEXT: fadd.s $fa0, $fa0, $fa0 ; LA64D-NEXT: slti $a1, $a0, 0 ; LA64D-NEXT: movgr2cf $fcc0, $a1 -; LA64D-NEXT: movgr2fr.w $fa1, $a0 -; LA64D-NEXT: ffint.s.w $fa1, $fa1 +; LA64D-NEXT: movgr2fr.d $fa1, $a0 +; LA64D-NEXT: ffint.s.l $fa1, $fa1 ; LA64D-NEXT: fsel $fa0, $fa1, $fa0, $fcc0 ; LA64D-NEXT: ret %1 = uitofp i64 %a to float