diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 6bee00d1ce382..9c21b8695b3cc 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -143,6 +143,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, setOperationAction(ISD::BITREVERSE, MVT::i32, Custom); setOperationAction(ISD::BSWAP, MVT::i32, Custom); setOperationAction({ISD::UDIV, ISD::UREM}, MVT::i32, Custom); + setOperationAction(ISD::LROUND, MVT::i32, Custom); } // Set operations for LA32 only. @@ -3103,6 +3104,18 @@ void LoongArchTargetLowering::ReplaceNodeResults( replaceINTRINSIC_WO_CHAINResults(N, Results, DAG, Subtarget); break; } + case ISD::LROUND: { + SDValue Op0 = N->getOperand(0); + EVT OpVT = Op0.getValueType(); + RTLIB::Libcall LC = + OpVT == MVT::f64 ? RTLIB::LROUND_F64 : RTLIB::LROUND_F32; + MakeLibCallOptions CallOptions; + CallOptions.setTypeListBeforeSoften(OpVT, MVT::i64, true); + SDValue Result = makeLibCall(DAG, LC, MVT::i64, Op0, CallOptions, DL).first; + Result = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Result); + Results.push_back(Result); + break; + } } } diff --git a/llvm/test/CodeGen/LoongArch/double-lround.ll b/llvm/test/CodeGen/LoongArch/double-lround.ll new file mode 100644 index 0000000000000..1b7791d683973 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/double-lround.ll @@ -0,0 +1,18 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc --mtriple=loongarch64 %s -o - | FileCheck %s + +declare i32 @llvm.lround.i32.f64(double) + +;; We support lround with i32 as return type on LoongArch64. This is needed by flang. +define i32 @lround_i32_f64(double %a) nounwind { +; CHECK-LABEL: lround_i32_f64: +; CHECK: # %bb.0: +; CHECK-NEXT: addi.d $sp, $sp, -16 +; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; CHECK-NEXT: bl %plt(lround) +; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 16 +; CHECK-NEXT: ret + %1 = call i32 @llvm.lround.i32.f64(double %a) + ret i32 %1 +} diff --git a/llvm/test/CodeGen/LoongArch/float-lround.ll b/llvm/test/CodeGen/LoongArch/float-lround.ll new file mode 100644 index 0000000000000..a129aa27a3e3e --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/float-lround.ll @@ -0,0 +1,18 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc --mtriple=loongarch64 %s -o - | FileCheck %s + +declare i32 @llvm.lround.i32.f32(float) + +;; We support lround with i32 as return type on LoongArch64. This is needed by flang. +define i32 @lround_i32_f32(float %a) nounwind { +; CHECK-LABEL: lround_i32_f32: +; CHECK: # %bb.0: +; CHECK-NEXT: addi.d $sp, $sp, -16 +; CHECK-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill +; CHECK-NEXT: bl %plt(lroundf) +; CHECK-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload +; CHECK-NEXT: addi.d $sp, $sp, 16 +; CHECK-NEXT: ret + %1 = call i32 @llvm.lround.i32.f32(float %a) + ret i32 %1 +}