diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -2435,10 +2435,14 @@ case ISD::FP_TO_UINT: ExpandIntRes_FP_TO_UINT(N, Lo, Hi); break; case ISD::FP_TO_SINT_SAT: case ISD::FP_TO_UINT_SAT: ExpandIntRes_FP_TO_XINT_SAT(N, Lo, Hi); break; + case ISD::STRICT_LROUND: + case ISD::STRICT_LRINT: + case ISD::LROUND: + case ISD::LRINT: case ISD::STRICT_LLROUND: case ISD::STRICT_LLRINT: case ISD::LLROUND: - case ISD::LLRINT: ExpandIntRes_LLROUND_LLRINT(N, Lo, Hi); break; + case ISD::LLRINT: ExpandIntRes_XROUND_XRINT(N, Lo, Hi); break; case ISD::LOAD: ExpandIntRes_LOAD(cast(N), Lo, Hi); break; case ISD::MUL: ExpandIntRes_MUL(N, Lo, Hi); break; case ISD::READCYCLECOUNTER: ExpandIntRes_READCYCLECOUNTER(N, Lo, Hi); break; @@ -3474,8 +3478,8 @@ SplitInteger(Res, Lo, Hi); } -void DAGTypeLegalizer::ExpandIntRes_LLROUND_LLRINT(SDNode *N, SDValue &Lo, - SDValue &Hi) { +void DAGTypeLegalizer::ExpandIntRes_XROUND_XRINT(SDNode *N, SDValue &Lo, + SDValue &Hi) { SDLoc dl(N); bool IsStrict = N->isStrictFPOpcode(); SDValue Op = N->getOperand(IsStrict ? 1 : 0); @@ -3498,7 +3502,33 @@ } RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; - if (N->getOpcode() == ISD::LLROUND || + if (N->getOpcode() == ISD::LROUND || + N->getOpcode() == ISD::STRICT_LROUND) { + if (VT == MVT::f32) + LC = RTLIB::LROUND_F32; + else if (VT == MVT::f64) + LC = RTLIB::LROUND_F64; + else if (VT == MVT::f80) + LC = RTLIB::LROUND_F80; + else if (VT == MVT::f128) + LC = RTLIB::LROUND_F128; + else if (VT == MVT::ppcf128) + LC = RTLIB::LROUND_PPCF128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected lround input type!"); + } else if (N->getOpcode() == ISD::LRINT || + N->getOpcode() == ISD::STRICT_LRINT) { + if (VT == MVT::f32) + LC = RTLIB::LRINT_F32; + else if (VT == MVT::f64) + LC = RTLIB::LRINT_F64; + else if (VT == MVT::f80) + LC = RTLIB::LRINT_F80; + else if (VT == MVT::f128) + LC = RTLIB::LRINT_F128; + else if (VT == MVT::ppcf128) + LC = RTLIB::LRINT_PPCF128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected lrint input type!"); + } else if (N->getOpcode() == ISD::LLROUND || N->getOpcode() == ISD::STRICT_LLROUND) { if (VT == MVT::f32) LC = RTLIB::LLROUND_F32; diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -441,7 +441,7 @@ void ExpandIntRes_FP_TO_SINT (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandIntRes_FP_TO_UINT (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandIntRes_FP_TO_XINT_SAT (SDNode *N, SDValue &Lo, SDValue &Hi); - void ExpandIntRes_LLROUND_LLRINT (SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandIntRes_XROUND_XRINT (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandIntRes_Logical (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandIntRes_ADDSUB (SDNode *N, SDValue &Lo, SDValue &Hi); diff --git a/llvm/test/CodeGen/AVR/llrint.ll b/llvm/test/CodeGen/AVR/llrint.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AVR/llrint.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=avr -mcpu=atmega328p | FileCheck %s + +define i64 @testmsxs_builtin(float %x) { +; CHECK-LABEL: testmsxs_builtin: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call llrintf +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.llrint.f32(float %x) + ret i64 %0 +} + +define i64 @testmsxd_builtin(double %x) { +; CHECK-LABEL: testmsxd_builtin: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call llrint +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.llrint.f64(double %x) + ret i64 %0 +} + +declare i64 @llvm.llrint.f32(float) nounwind readnone +declare i64 @llvm.llrint.f64(double) nounwind readnone diff --git a/llvm/test/CodeGen/AVR/llround-conv.ll b/llvm/test/CodeGen/AVR/llround-conv.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AVR/llround-conv.ll @@ -0,0 +1,51 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=avr -mcpu=atmega328p | FileCheck %s + +define signext i32 @testmsws(float %x) { +; CHECK-LABEL: testmsws: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call llroundf +; CHECK-NEXT: movw r22, r18 +; CHECK-NEXT: movw r24, r20 +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.llround.i64.f32(float %x) + %conv = trunc i64 %0 to i32 + ret i32 %conv +} + +define i64 @testmsxs(float %x) { +; CHECK-LABEL: testmsxs: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call llroundf +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.llround.i64.f32(float %x) + ret i64 %0 +} + +define signext i32 @testmswd(double %x) { +; CHECK-LABEL: testmswd: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call llround +; CHECK-NEXT: movw r22, r18 +; CHECK-NEXT: movw r24, r20 +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.llround.i64.f64(double %x) + %conv = trunc i64 %0 to i32 + ret i32 %conv +} + +define i64 @testmsxd(double %x) { +; CHECK-LABEL: testmsxd: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call llround +; CHECK-NEXT: ret +entry: + %0 = tail call i64 @llvm.llround.i64.f64(double %x) + ret i64 %0 +} + +declare i64 @llvm.llround.i64.f32(float) nounwind readnone +declare i64 @llvm.llround.i64.f64(double) nounwind readnone diff --git a/llvm/test/CodeGen/AVR/lrint.ll b/llvm/test/CodeGen/AVR/lrint.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AVR/lrint.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=avr -mcpu=atmega328p | FileCheck %s + +define i32 @testmsws_builtin(float %x) { +; CHECK-LABEL: testmsws_builtin: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call lrintf +; CHECK-NEXT: ret +entry: + %0 = tail call i32 @llvm.lrint.i32.f32(float %x) + ret i32 %0 +} + +define i32 @testmswd_builtin(double %x) { +; CHECK-LABEL: testmswd_builtin: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call lrint +; CHECK-NEXT: ret +entry: + %0 = tail call i32 @llvm.lrint.i32.f64(double %x) + ret i32 %0 +} + +declare i32 @llvm.lrint.i32.f32(float) nounwind readnone +declare i32 @llvm.lrint.i32.f64(double) nounwind readnone diff --git a/llvm/test/CodeGen/AVR/lround-conv.ll b/llvm/test/CodeGen/AVR/lround-conv.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AVR/lround-conv.ll @@ -0,0 +1,49 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=avr -mcpu=atmega328p | FileCheck %s + +define signext i16 @testmsws(float %x) { +; CHECK-LABEL: testmsws: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call lroundf +; CHECK-NEXT: movw r24, r22 +; CHECK-NEXT: ret +entry: + %0 = tail call i32 @llvm.lround.i32.f32(float %x) + %conv = trunc i32 %0 to i16 + ret i16 %conv +} + +define i32 @testmsxs(float %x) { +; CHECK-LABEL: testmsxs: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call lroundf +; CHECK-NEXT: ret +entry: + %0 = tail call i32 @llvm.lround.i32.f32(float %x) + ret i32 %0 +} + +define signext i16 @testmswd(double %x) { +; CHECK-LABEL: testmswd: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call lround +; CHECK-NEXT: movw r24, r22 +; CHECK-NEXT: ret +entry: + %0 = tail call i32 @llvm.lround.i32.f64(double %x) + %conv = trunc i32 %0 to i16 + ret i16 %conv +} + +define i32 @testmsxd(double %x) { +; CHECK-LABEL: testmsxd: +; CHECK: ; %bb.0: ; %entry +; CHECK-NEXT: call lround +; CHECK-NEXT: ret +entry: + %0 = tail call i32 @llvm.lround.i32.f64(double %x) + ret i32 %0 +} + +declare i32 @llvm.lround.i32.f32(float) nounwind readnone +declare i32 @llvm.lround.i32.f64(double) nounwind readnone