diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 16bceacfaa222..bb6800a8493cd 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -1669,16 +1669,19 @@ SDValue LoongArchTargetLowering::lowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); + SDValue Op0 = Op.getOperand(0); + + if (Op0.getValueType() == MVT::f16) + Op0 = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Op0); if (Op.getValueSizeInBits() > 32 && Subtarget.hasBasicF() && !Subtarget.hasBasicD()) { - SDValue Dst = - DAG.getNode(LoongArchISD::FTINT, DL, MVT::f32, Op.getOperand(0)); + SDValue Dst = DAG.getNode(LoongArchISD::FTINT, DL, MVT::f32, Op0); return DAG.getNode(LoongArchISD::MOVFR2GR_S_LA64, DL, MVT::i64, Dst); } EVT FPTy = EVT::getFloatingPointVT(Op.getValueSizeInBits()); - SDValue Trunc = DAG.getNode(LoongArchISD::FTINT, DL, FPTy, Op.getOperand(0)); + SDValue Trunc = DAG.getNode(LoongArchISD::FTINT, DL, FPTy, Op0); return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Trunc); } @@ -2872,6 +2875,8 @@ void LoongArchTargetLowering::ReplaceNodeResults( EVT FVT = EVT::getFloatingPointVT(N->getValueSizeInBits(0)); if (getTypeAction(*DAG.getContext(), Src.getValueType()) != TargetLowering::TypeSoftenFloat) { + if (Src.getValueType() == MVT::f16) + Src = DAG.getNode(ISD::FP_EXTEND, DL, MVT::f32, Src); SDValue Dst = DAG.getNode(LoongArchISD::FTINT, DL, FVT, Src); Results.push_back(DAG.getNode(ISD::BITCAST, DL, VT, Dst)); return; diff --git a/llvm/test/CodeGen/LoongArch/fp16-promote.ll b/llvm/test/CodeGen/LoongArch/fp16-promote.ll index 03965ac81f376..c5a27a7011278 100644 --- a/llvm/test/CodeGen/LoongArch/fp16-promote.ll +++ b/llvm/test/CodeGen/LoongArch/fp16-promote.ll @@ -378,3 +378,84 @@ define half @freeze_half_poison(half %maybe.poison) nounwind { %t1 = fadd half %y1, %y1 ret half %t1 } + +define signext i32 @test_half_to_s32(half %a) nounwind { +; LA32-LABEL: test_half_to_s32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: addi.w $sp, $sp, -16 +; LA32-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill +; LA32-NEXT: bl %plt(__gnu_h2f_ieee) +; LA32-NEXT: ftintrz.w.s $fa0, $fa0 +; LA32-NEXT: movfr2gr.s $a0, $fa0 +; LA32-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload +; LA32-NEXT: addi.w $sp, $sp, 16 +; LA32-NEXT: ret +; +; LA64-LABEL: test_half_to_s32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: addi.d $sp, $sp, -16 +; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64-NEXT: bl %plt(__gnu_h2f_ieee) +; LA64-NEXT: ftintrz.w.s $fa0, $fa0 +; LA64-NEXT: movfr2gr.s $a0, $fa0 +; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 16 +; LA64-NEXT: ret +entry: + %conv = fptosi half %a to i32 + ret i32 %conv +} + +define zeroext i32 @test_half_to_s32_u32(half %a) nounwind { +; LA32-LABEL: test_half_to_s32_u32: +; LA32: # %bb.0: # %entry +; LA32-NEXT: addi.w $sp, $sp, -16 +; LA32-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill +; LA32-NEXT: bl %plt(__gnu_h2f_ieee) +; LA32-NEXT: ftintrz.w.s $fa0, $fa0 +; LA32-NEXT: movfr2gr.s $a0, $fa0 +; LA32-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload +; LA32-NEXT: addi.w $sp, $sp, 16 +; LA32-NEXT: ret +; +; LA64-LABEL: test_half_to_s32_u32: +; LA64: # %bb.0: # %entry +; LA64-NEXT: addi.d $sp, $sp, -16 +; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64-NEXT: bl %plt(__gnu_h2f_ieee) +; LA64-NEXT: ftintrz.w.s $fa0, $fa0 +; LA64-NEXT: movfr2gr.s $a0, $fa0 +; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 16 +; LA64-NEXT: ret +entry: + %conv = fptosi half %a to i32 + ret i32 %conv +} + +define i64 @test_half_to_i64(half %a) nounwind { +; LA32-LABEL: test_half_to_i64: +; LA32: # %bb.0: # %entry +; LA32-NEXT: addi.w $sp, $sp, -16 +; LA32-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill +; LA32-NEXT: bl %plt(__gnu_h2f_ieee) +; LA32-NEXT: bl %plt(__fixsfdi) +; LA32-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload +; LA32-NEXT: addi.w $sp, $sp, 16 +; LA32-NEXT: ret +; +; LA64-LABEL: test_half_to_i64: +; LA64: # %bb.0: # %entry +; LA64-NEXT: addi.d $sp, $sp, -16 +; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64-NEXT: bl %plt(__gnu_h2f_ieee) +; LA64-NEXT: ftintrz.l.s $fa0, $fa0 +; LA64-NEXT: movfr2gr.d $a0, $fa0 +; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 16 +; LA64-NEXT: ret +entry: + %conv = fptosi half %a to i64 + ret i64 %conv +}