diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -544,8 +544,24 @@ "Unexpected custom legalisation"); SDValue Src = N->getOperand(0); EVT VT = EVT::getFloatingPointVT(N->getValueSizeInBits(0)); - SDValue Dst = DAG.getNode(LoongArchISD::FTINT, DL, VT, Src); - Results.push_back(DAG.getNode(ISD::BITCAST, DL, N->getValueType(0), Dst)); + if (getTypeAction(*DAG.getContext(), Src.getValueType()) != + TargetLowering::TypeSoftenFloat) { + SDValue Dst = DAG.getNode(LoongArchISD::FTINT, DL, VT, Src); + Results.push_back(DAG.getNode(ISD::BITCAST, DL, N->getValueType(0), Dst)); + 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'. + RTLIB::Libcall LC; + LC = RTLIB::getFPTOSINT(Src.getValueType(), N->getValueType(0)); + MakeLibCallOptions CallOptions; + EVT OpVT = Src.getValueType(); + CallOptions.setTypeListBeforeSoften(OpVT, N->getValueType(0), true); + SDValue Chain = SDValue(); + SDValue Result; + std::tie(Result, Chain) = + makeLibCall(DAG, LC, N->getValueType(0), Src, CallOptions, DL, Chain); + Results.push_back(Result); break; } case ISD::BITCAST: { diff --git a/llvm/test/CodeGen/LoongArch/soft-fp-to-int.ll b/llvm/test/CodeGen/LoongArch/soft-fp-to-int.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/soft-fp-to-int.ll @@ -0,0 +1,155 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefix=LA32 +; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefix=LA64 + +define i32 @fptosi_i32_fp128(fp128 %X) nounwind { +; LA32-LABEL: fptosi_i32_fp128: +; LA32: # %bb.0: +; LA32-NEXT: addi.w $sp, $sp, -32 +; LA32-NEXT: st.w $ra, $sp, 28 # 4-byte Folded Spill +; LA32-NEXT: ld.w $a1, $a0, 12 +; LA32-NEXT: st.w $a1, $sp, 20 +; LA32-NEXT: ld.w $a1, $a0, 8 +; LA32-NEXT: st.w $a1, $sp, 16 +; LA32-NEXT: ld.w $a1, $a0, 4 +; LA32-NEXT: st.w $a1, $sp, 12 +; LA32-NEXT: ld.w $a0, $a0, 0 +; LA32-NEXT: st.w $a0, $sp, 8 +; LA32-NEXT: addi.w $a0, $sp, 8 +; LA32-NEXT: bl %plt(__fixtfsi) +; LA32-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload +; LA32-NEXT: addi.w $sp, $sp, 32 +; LA32-NEXT: ret +; +; LA64-LABEL: fptosi_i32_fp128: +; LA64: # %bb.0: +; LA64-NEXT: addi.d $sp, $sp, -16 +; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64-NEXT: bl %plt(__fixtfsi) +; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 16 +; LA64-NEXT: ret + %tmp = fptosi fp128 %X to i32 + ret i32 %tmp +} + +define i32 @fptosi_i32_double(double %X) nounwind { +; LA32-LABEL: fptosi_i32_double: +; LA32: # %bb.0: +; LA32-NEXT: addi.w $sp, $sp, -16 +; LA32-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill +; LA32-NEXT: bl %plt(__fixdfsi) +; LA32-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload +; LA32-NEXT: addi.w $sp, $sp, 16 +; LA32-NEXT: ret +; +; LA64-LABEL: fptosi_i32_double: +; LA64: # %bb.0: +; LA64-NEXT: addi.d $sp, $sp, -16 +; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64-NEXT: bl %plt(__fixdfsi) +; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 16 +; LA64-NEXT: ret + %tmp = fptosi double %X to i32 + ret i32 %tmp +} + +define i32 @fptosi_i32_float(float %X) nounwind { +; LA32-LABEL: fptosi_i32_float: +; LA32: # %bb.0: +; LA32-NEXT: addi.w $sp, $sp, -16 +; LA32-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill +; LA32-NEXT: bl %plt(__fixsfsi) +; LA32-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload +; LA32-NEXT: addi.w $sp, $sp, 16 +; LA32-NEXT: ret +; +; LA64-LABEL: fptosi_i32_float: +; LA64: # %bb.0: +; LA64-NEXT: addi.d $sp, $sp, -16 +; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: bl %plt(__fixsfsi) +; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 16 +; LA64-NEXT: ret + %tmp = fptosi float %X to i32 + ret i32 %tmp +} + +define i64 @fptosi_i64_fp128(fp128 %X) nounwind { +; LA32-LABEL: fptosi_i64_fp128: +; LA32: # %bb.0: +; LA32-NEXT: addi.w $sp, $sp, -32 +; LA32-NEXT: st.w $ra, $sp, 28 # 4-byte Folded Spill +; LA32-NEXT: ld.w $a1, $a0, 12 +; LA32-NEXT: st.w $a1, $sp, 12 +; LA32-NEXT: ld.w $a1, $a0, 8 +; LA32-NEXT: st.w $a1, $sp, 8 +; LA32-NEXT: ld.w $a1, $a0, 4 +; LA32-NEXT: st.w $a1, $sp, 4 +; LA32-NEXT: ld.w $a0, $a0, 0 +; LA32-NEXT: st.w $a0, $sp, 0 +; LA32-NEXT: addi.w $a0, $sp, 0 +; LA32-NEXT: bl %plt(__fixtfdi) +; LA32-NEXT: ld.w $ra, $sp, 28 # 4-byte Folded Reload +; LA32-NEXT: addi.w $sp, $sp, 32 +; LA32-NEXT: ret +; +; LA64-LABEL: fptosi_i64_fp128: +; LA64: # %bb.0: +; LA64-NEXT: addi.d $sp, $sp, -16 +; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64-NEXT: bl %plt(__fixtfdi) +; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 16 +; LA64-NEXT: ret + %tmp = fptosi fp128 %X to i64 + ret i64 %tmp +} + +define i64 @fptosi_i64_double(double %X) nounwind { +; LA32-LABEL: fptosi_i64_double: +; LA32: # %bb.0: +; LA32-NEXT: addi.w $sp, $sp, -16 +; LA32-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill +; LA32-NEXT: bl %plt(__fixdfdi) +; LA32-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload +; LA32-NEXT: addi.w $sp, $sp, 16 +; LA32-NEXT: ret +; +; LA64-LABEL: fptosi_i64_double: +; LA64: # %bb.0: +; LA64-NEXT: addi.d $sp, $sp, -16 +; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64-NEXT: bl %plt(__fixdfdi) +; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 16 +; LA64-NEXT: ret + %tmp = fptosi double %X to i64 + ret i64 %tmp +} + +define i64 @fptosi_i64_float(float %X) nounwind { +; LA32-LABEL: fptosi_i64_float: +; LA32: # %bb.0: +; LA32-NEXT: addi.w $sp, $sp, -16 +; LA32-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill +; 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: fptosi_i64_float: +; LA64: # %bb.0: +; LA64-NEXT: addi.d $sp, $sp, -16 +; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 +; LA64-NEXT: bl %plt(__fixsfdi) +; LA64-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; LA64-NEXT: addi.d $sp, $sp, 16 +; LA64-NEXT: ret + %tmp = fptosi float %X to i64 + ret i64 %tmp +}