Index: llvm/lib/Target/AArch64/AArch64ISelLowering.h =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -209,6 +209,7 @@ // Vector bitwise negation NOT, + FDIV, // Vector bitwise insertion BIT, Index: llvm/lib/Target/AArch64/AArch64ISelLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -949,6 +949,7 @@ setOperationAction(ISD::SPLAT_VECTOR, VT, Custom); setOperationAction(ISD::SELECT, VT, Custom); setOperationAction(ISD::FMA, VT, Custom); + setOperationAction(ISD::FDIV, VT, Custom); } } @@ -1602,6 +1603,7 @@ MAKE_CASE(AArch64ISD::STNP) MAKE_CASE(AArch64ISD::DUP_MERGE_PASSTHRU) MAKE_CASE(AArch64ISD::INDEX_VECTOR) + MAKE_CASE(AArch64ISD::FDIV) } #undef MAKE_CASE return nullptr; @@ -3478,7 +3480,10 @@ case ISD::FMA: return LowerToPredicatedOp(Op, DAG, AArch64ISD::FMA_PRED); case ISD::FDIV: - return LowerF128Call(Op, DAG, RTLIB::DIV_F128); + if(Op.getValueType().isScalableVector()) + return LowerToPredicatedOp(Op, DAG, AArch64ISD::FDIV); + else + return LowerF128Call(Op, DAG, RTLIB::DIV_F128); case ISD::FP_ROUND: case ISD::STRICT_FP_ROUND: return LowerFP_ROUND(Op, DAG); @@ -7907,6 +7912,15 @@ return DAG.getNode(ISD::BITCAST, DL, VT, TBL); } +static SDValue combineSVEPredIntrinsic(unsigned Opc, SDNode *N, SelectionDAG &DAG) { + SDLoc DL(N); + EVT VT = N->getValueType(0); + SDValue Vector1 = N->getOperand(1); + SDValue Pred = N->getOperand(2); + SDValue Vector2 = N->getOperand(3); + + return DAG.getNode(Opc, DL, VT, Vector1, Pred, Vector2); +} static bool resolveBuildVector(BuildVectorSDNode *BVN, APInt &CnstBits, APInt &UndefBits) { @@ -12057,6 +12071,8 @@ case Intrinsic::aarch64_sve_ptest_last: return getPTest(DAG, N->getValueType(0), N->getOperand(1), N->getOperand(2), AArch64CC::LAST_ACTIVE); + case Intrinsic::aarch64_sve_fdiv: + return combineSVEPredIntrinsic(AArch64ISD::FDIV, N, DAG); } return SDValue(); } Index: llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -207,6 +207,9 @@ def reinterpret_cast : SDNode<"AArch64ISD::REINTERPRET_CAST", SDTUnaryOp>; +def SDT_AArch64PredBinFp : SDTypeProfile<1, 3, [SDTCisVec<1>, SDTCisVec<2>, SDTCisVec<3>]>; +def AArch64fdiv : SDNode<"AArch64ISD::FDIV", SDT_AArch64PredBinFp>; + let Predicates = [HasSVE] in { defm RDFFR_PPz : sve_int_rdffr_pred<0b0, "rdffr", int_aarch64_sve_rdffr_z>; def RDFFRS_PPz : sve_int_rdffr_pred<0b1, "rdffrs">; @@ -358,7 +361,7 @@ defm FSCALE_ZPmZ : sve_fp_2op_p_zds_fscale<0b1001, "fscale", int_aarch64_sve_fscale>; defm FMULX_ZPmZ : sve_fp_2op_p_zds<0b1010, "fmulx", "FMULX_ZPZZ", int_aarch64_sve_fmulx, DestructiveBinaryComm>; defm FDIVR_ZPmZ : sve_fp_2op_p_zds<0b1100, "fdivr", "FDIVR_ZPZZ", int_aarch64_sve_fdivr, DestructiveBinaryCommWithRev, "FDIV_ZPmZ", /*isReverseInstr*/ 1>; - defm FDIV_ZPmZ : sve_fp_2op_p_zds<0b1101, "fdiv", "FDIV_ZPZZ", int_aarch64_sve_fdiv, DestructiveBinaryCommWithRev, "FDIVR_ZPmZ">; + defm FDIV_ZPmZ : sve_fp_2op_p_zds<0b1101, "fdiv", "FDIV_ZPZZ", AArch64fdiv, DestructiveBinaryCommWithRev, "FDIVR_ZPmZ">; defm FADD_ZPZZ : sve_fp_bin_pred_hfd; @@ -374,7 +377,7 @@ defm FABD_ZPZZ : sve_fp_2op_p_zds_zeroing_hsd; defm FMULX_ZPZZ : sve_fp_2op_p_zds_zeroing_hsd; defm FDIVR_ZPZZ : sve_fp_2op_p_zds_zeroing_hsd; - defm FDIV_ZPZZ : sve_fp_2op_p_zds_zeroing_hsd; + defm FDIV_ZPZZ : sve_fp_2op_p_zds_zeroing_hsd; } defm FADD_ZZZ : sve_fp_3op_u_zd<0b000, "fadd", fadd>; Index: llvm/test/CodeGen/AArch64/sve-fp-unpred-to-pred.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/sve-fp-unpred-to-pred.ll @@ -0,0 +1,28 @@ + +; RUN: llc -mtriple=aarch64--linux-gnu -mattr=+sve < %s | FileCheck %s + +; FDIV + +define @fdiv_h( %a, %b) { +; CHECK-LABEL: fdiv_h: +; CHECK: fdiv z0.h, p0/m, z0.h, z1.h +; CHECK-NEXT: ret + %res = fdiv %a, %b + ret %res +} + +define @fdiv_s( %a, %b) { +; CHECK-LABEL: fdiv_s: +; CHECK: fdiv z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %res = fdiv %a, %b + ret %res +} + +define @fdiv_d( %a, %b) { +; CHECK-LABEL: fdiv_d: +; CHECK: fdiv z0.d, p0/m, z0.d, z1.d +; CHECK-NEXT: ret + %res = fdiv %a, %b + ret %res +}