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.h =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -660,6 +660,7 @@ SDValue LowerVectorFP_TO_INT(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerLROUND(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVectorOR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const; Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -765,6 +765,9 @@ } setTruncStoreAction(MVT::v4i16, MVT::v4i8, Custom); + + setOperationAction(ISD::LROUND, MVT::i64, Custom); + setOperationAction(ISD::LLROUND, MVT::i64, Custom); } PredictableSelectIsExpensive = Subtarget->predictableSelectIsExpensive(); @@ -2474,6 +2477,17 @@ return LowerF128Call(Op, DAG, LC); } +SDValue AArch64TargetLowering::LowerLROUND(SDValue Op, + SelectionDAG &DAG) const { + if (Op.getOperand(0).getValueType() != MVT::f128) { + // It's legal except when f128 is involved. + return Op; + } + + // Default action is to lower to a libcall. + return SDValue(); +} + SDValue AArch64TargetLowering::LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const { // For iOS, we want to call an alternative entry point: __sincos_stret, @@ -2954,6 +2968,9 @@ case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: return LowerFP_TO_INT(Op, DAG); + case ISD::LROUND: + case ISD::LLROUND: + return LowerLROUND(Op, DAG); case ISD::FSINCOS: return LowerFSINCOS(Op, DAG); case ISD::FLT_ROUNDS_: 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 @@ -1,7 +1,8 @@ ; RUN: llc < %s -mtriple=aarch64 -mattr=+neon | FileCheck %s ; CHECK-LABEL: testmsws: -; CHECK: bl llroundf +; CHECK: fcvtas x0, s0 +; CHECK: ret define i32 @testmsws(float %x) { entry: %0 = tail call i64 @llvm.llround.f32(float %x) @@ -10,7 +11,8 @@ } ; CHECK-LABEL: testmsxs: -; CHECK: b llroundf +; CHECK: fcvtas x0, s0 +; CHECK-NEXT: ret define i64 @testmsxs(float %x) { entry: %0 = tail call i64 @llvm.llround.f32(float %x) @@ -18,7 +20,8 @@ } ; CHECK-LABEL: testmswd: -; CHECK: bl llround +; CHECK: fcvtas x0, d0 +; CHECK: ret define i32 @testmswd(double %x) { entry: %0 = tail call i64 @llvm.llround.f64(double %x) @@ -27,7 +30,8 @@ } ; CHECK-LABEL: testmsxd: -; CHECK: b llround +; CHECK: fcvtas x0, d0 +; CHECK-NEXT: ret define i64 @testmsxd(double %x) { entry: %0 = tail call i64 @llvm.llround.f64(double %x) Index: llvm/test/CodeGen/AArch64/lround-conv.ll =================================================================== --- llvm/test/CodeGen/AArch64/lround-conv.ll +++ llvm/test/CodeGen/AArch64/lround-conv.ll @@ -1,7 +1,8 @@ ; RUN: llc < %s -mtriple=aarch64 -mattr=+neon | FileCheck %s ; CHECK-LABEL: testmsws: -; CHECK: bl lroundf +; CHECK: fcvtas x0, s0 +; CHECK: ret define i32 @testmsws(float %x) { entry: %0 = tail call i64 @llvm.lround.i64.f32(float %x) @@ -10,7 +11,8 @@ } ; CHECK-LABEL: testmsxs: -; CHECK: b lroundf +; CHECK: fcvtas x0, s0 +; CHECK-NEXT: ret define i64 @testmsxs(float %x) { entry: %0 = tail call i64 @llvm.lround.i64.f32(float %x) @@ -18,7 +20,8 @@ } ; CHECK-LABEL: testmswd: -; CHECK: bl lround +; CHECK: fcvtas x0, d0 +; CHECK: ret define i32 @testmswd(double %x) { entry: %0 = tail call i64 @llvm.lround.i64.f64(double %x) @@ -27,7 +30,8 @@ } ; CHECK-LABEL: testmsxd: -; CHECK: b lround +; CHECK: fcvtas x0, d0 +; CHECK-NEXT: ret define i64 @testmsxd(double %x) { entry: %0 = tail call i64 @llvm.lround.i64.f64(double %x)