Index: llvm/include/llvm/Target/TargetSelectionDAG.td =================================================================== --- llvm/include/llvm/Target/TargetSelectionDAG.td +++ llvm/include/llvm/Target/TargetSelectionDAG.td @@ -450,6 +450,9 @@ def fnearbyint : SDNode<"ISD::FNEARBYINT" , SDTFPUnaryOp>; def fround : SDNode<"ISD::FROUND" , SDTFPUnaryOp>; +def lround : SDNode<"ISD::LROUND" , SDTFPToIntOp>; +def llround : SDNode<"ISD::LLROUND" , SDTFPToIntOp>; + def fpround : SDNode<"ISD::FP_ROUND" , SDTFPRoundOp>; def fpextend : SDNode<"ISD::FP_EXTEND" , SDTFPExtendOp>; def fcopysign : SDNode<"ISD::FCOPYSIGN" , SDTFPSignOp>; Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -765,6 +765,10 @@ } setTruncStoreAction(MVT::v4i16, MVT::v4i8, Custom); + + setOperationAction(ISD::LROUND, MVT::i32, Legal); + setOperationAction(ISD::LROUND, MVT::i64, Legal); + setOperationAction(ISD::LLROUND, MVT::i64, Legal); } PredictableSelectIsExpensive = Subtarget->predictableSelectIsExpensive(); Index: llvm/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -3073,6 +3073,15 @@ defm : FPToIntegerPats; defm : FPToIntegerPats; +def : Pat<(i64 (lround f32:$Rn)), + (!cast(FCVTASUXSr) f32:$Rn)>; +def : Pat<(i64 (lround f64:$Rn)), + (!cast(FCVTASUXDr) f64:$Rn)>; +def : Pat<(i64 (llround f32:$Rn)), + (!cast(FCVTASUXSr) f32:$Rn)>; +def : Pat<(i64 (llround f64:$Rn)), + (!cast(FCVTASUXDr) f64:$Rn)>; + //===----------------------------------------------------------------------===// // Scaled integer to floating point conversion instructions. //===----------------------------------------------------------------------===// Index: llvm/test/CodeGen/AArch64/llround-conv.ll =================================================================== --- llvm/test/CodeGen/AArch64/llround-conv.ll +++ llvm/test/CodeGen/AArch64/llround-conv.ll @@ -68,5 +68,83 @@ ret i64 %call } +; CHECK-LABEL: testmsws_builtin: +; CHECK: fcvtas x0, s0 +; CHECK: ret +define i32 @testmsws_builtin(float %x) { +entry: + %0 = tail call i64 @llvm.llround.f32(float %x) + %conv = trunc i64 %0 to i32 + ret i32 %conv +} + +; CHECK-LABEL: testmsxs_builtin: +; CHECK: fcvtas x0, s0 +; CHECK-NEXT: ret +define i64 @testmsxs_builtin(float %x) { +entry: + %0 = tail call i64 @llvm.llround.f32(float %x) + ret i64 %0 +} + +; CHECK-LABEL: testmswd_builtin: +; CHECK: fcvtas x0, d0 +; CHECK: ret +define i32 @testmswd_builtin(double %x) { +entry: + %0 = tail call i64 @llvm.llround.f64(double %x) + %conv = trunc i64 %0 to i32 + ret i32 %conv +} + +; CHECK-LABEL: testmsxd_builtin: +; CHECK: fcvtas x0, d0 +; CHECK-NEXT: ret +define i64 @testmsxd_builtin(double %x) { +entry: + %0 = tail call i64 @llvm.llround.f64(double %x) + ret i64 %0 +} + +; CHECK-LABEL: testmuws_builtin: +; CHECK: fcvtas x0, s0 +; CHECK: ret +define i32 @testmuws_builtin(float %x) { +entry: + %0 = tail call i64 @llvm.llround.f32(float %x) + %conv = trunc i64 %0 to i32 + ret i32 %conv +} + +; CHECK-LABEL: testmuxs_builtin: +; CHECK: fcvtas x0, s0 +; CHECK-NEXT: ret +define i64 @testmuxs_builtin(float %x) { +entry: + %0 = tail call i64 @llvm.llround.f32(float %x) + ret i64 %0 +} + +; CHECK-LABEL: testmuwd_builtin: +; CHECK: fcvtas x0, d0 +; CHECK: ret +define i32 @testmuwd_builtin(double %x) { +entry: + %0 = tail call i64 @llvm.llround.f64(double %x) + %conv = trunc i64 %0 to i32 + ret i32 %conv +} + +; CHECK-LABEL: testmuxd_builtin: +; XCHECK: fcvtas x0, d0 +; XCHECK-NEXT: ret +define i64 @testmuxd_builtin(double %x) { +entry: + %0 = tail call i64 @llvm.llround.f64(double %x) + ret i64 %0 +} + declare i64 @llroundf(float) nounwind declare i64 @llround(double) nounwind +declare i64 @llvm.llround.f32(float) nounwind readnone +declare i64 @llvm.llround.f64(double) nounwind readnone Index: llvm/test/CodeGen/AArch64/lround-conv.ll =================================================================== --- llvm/test/CodeGen/AArch64/lround-conv.ll +++ llvm/test/CodeGen/AArch64/lround-conv.ll @@ -68,5 +68,83 @@ ret i64 %call } +; CHECK-LABEL: testmsws_builtin: +; CHECK: fcvtas x0, s0 +; CHECK: ret +define i32 @testmsws_builtin(float %x) { +entry: + %0 = tail call i64 @llvm.lround.i64.f32(float %x) + %conv = trunc i64 %0 to i32 + ret i32 %conv +} + +; CHECK-LABEL: testmsxs_builtin: +; CHECK: fcvtas x0, s0 +; CHECK-NEXT: ret +define i64 @testmsxs_builtin(float %x) { +entry: + %0 = tail call i64 @llvm.lround.i64.f32(float %x) + ret i64 %0 +} + +; CHECK-LABEL: testmswd_builtin: +; CHECK: fcvtas x0, d0 +; CHECK: ret +define i32 @testmswd_builtin(double %x) { +entry: + %0 = tail call i64 @llvm.lround.i64.f64(double %x) + %conv = trunc i64 %0 to i32 + ret i32 %conv +} + +; CHECK-LABEL: testmsxd_builtin: +; CHECK: fcvtas x0, d0 +; CHECK-NEXT: ret +define i64 @testmsxd_builtin(double %x) { +entry: + %0 = tail call i64 @llvm.lround.i64.f64(double %x) + ret i64 %0 +} + +; CHECK-LABEL: testmuws_builtin: +; CHECK: fcvtas x0, s0 +; CHECK: ret +define i32 @testmuws_builtin(float %x) { +entry: + %0 = tail call i64 @llvm.lround.i64.f32(float %x) + %conv = trunc i64 %0 to i32 + ret i32 %conv +} + +; CHECK-LABEL: testmuxs_builtin: +; CHECK: fcvtas x0, s0 +; CHECK-NEXT: ret +define i64 @testmuxs_builtin(float %x) { +entry: + %0 = tail call i64 @llvm.lround.i64.f32(float %x) + ret i64 %0 +} + +; CHECK-LABEL: testmuwd_builtin: +; CHECK: fcvtas x0, d0 +; CHECK: ret +define i32 @testmuwd_builtin(double %x) { +entry: + %0 = tail call i64 @llvm.lround.i64.f64(double %x) + %conv = trunc i64 %0 to i32 + ret i32 %conv +} + +; CHECK-LABEL: testmuxd_builtin: +; CHECK: fcvtas x0, d0 +; CHECK-NEXT: ret +define i64 @testmuxd_builtin(double %x) { +entry: + %0 = tail call i64 @llvm.lround.i64.f64(double %x) + ret i64 %0 +} + declare i64 @lroundf(float) nounwind declare i64 @lround(double) nounwind +declare i64 @llvm.lround.i64.f32(float) nounwind readnone +declare i64 @llvm.lround.i64.f64(double) nounwind readnone