Index: llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp +++ llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp @@ -425,6 +425,7 @@ // so the Destructive Operand must be unique. bool DOPRegIsUnique = false; switch (DType) { + case AArch64::DestructiveBinary: case AArch64::DestructiveBinaryComm: case AArch64::DestructiveBinaryCommWithRev: DOPRegIsUnique = @@ -502,6 +503,7 @@ .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)); switch (DType) { + case AArch64::DestructiveBinary: case AArch64::DestructiveBinaryImm: case AArch64::DestructiveBinaryComm: case AArch64::DestructiveBinaryCommWithRev: Index: llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -271,7 +271,7 @@ defm FMAX_ZPmZ : sve_fp_2op_p_zds<0b0110, "fmax", "FMAX_ZPZZ", int_aarch64_sve_fmax, DestructiveBinaryComm>; defm FMIN_ZPmZ : sve_fp_2op_p_zds<0b0111, "fmin", "FMIN_ZPZZ", int_aarch64_sve_fmin, DestructiveBinaryComm>; defm FABD_ZPmZ : sve_fp_2op_p_zds<0b1000, "fabd", "FABD_ZPZZ", int_aarch64_sve_fabd, DestructiveBinaryComm>; - defm FSCALE_ZPmZ : sve_fp_2op_p_zds_fscale<0b1001, "fscale", int_aarch64_sve_fscale>; + defm FSCALE_ZPmZ : sve_fp_2op_p_zds_fscale<0b1001, "fscale", "FSCALE_ZPZZ", 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", 0>; defm FDIV_ZPmZ : sve_fp_2op_p_zds<0b1101, "fdiv", "FDIV_ZPZZ", int_aarch64_sve_fdiv, DestructiveBinaryCommWithRev, "FDIVR_ZPmZ", 1>; @@ -285,6 +285,7 @@ defm FMAX_ZPZZ : sve_fp_2op_p_zds_zx; defm FMIN_ZPZZ : sve_fp_2op_p_zds_zx; defm FABD_ZPZZ : sve_fp_2op_p_zds_zx; + defm FSCALE_ZPZZ : sve_fp_2op_p_zds_fscale_zx; defm FMULX_ZPZZ : sve_fp_2op_p_zds_zx; defm FDIVR_ZPZZ : sve_fp_2op_p_zds_zx; defm FDIV_ZPZZ : sve_fp_2op_p_zds_zx; Index: llvm/lib/Target/AArch64/SVEInstrFormats.td =================================================================== --- llvm/lib/Target/AArch64/SVEInstrFormats.td +++ llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -446,6 +446,14 @@ Pseudo<(outs zprty:$Zd), (ins PPR3bAny:$Pg, zprty:$Zs1, immty:$imm), []> { let FalseLanes = flags; } + + class PredTwoOpConstrainedPseudo + : SVEPseudo2Instr, + Pseudo<(outs zprty:$Zd), (ins PPR3bAny:$Pg, zprty:$Zs1, zprty:$Zs2), []> { + let Constraints = "$Zd = $Zs1"; + let FalseLanes = flags; + } } //===----------------------------------------------------------------------===// @@ -1559,16 +1567,28 @@ } multiclass sve_fp_2op_p_zds_fscale opc, string asm, - SDPatternOperator op> { - def _H : sve_fp_2op_p_zds<0b01, opc, asm, ZPR16>; - def _S : sve_fp_2op_p_zds<0b10, opc, asm, ZPR32>; - def _D : sve_fp_2op_p_zds<0b11, opc, asm, ZPR64>; + string Ps, SDPatternOperator op> { + let DestructiveInstType = DestructiveBinary in { + def _H : SVEPseudo2Instr, sve_fp_2op_p_zds<0b01, opc, asm, ZPR16>; + def _S : SVEPseudo2Instr, sve_fp_2op_p_zds<0b10, opc, asm, ZPR32>; + def _D : SVEPseudo2Instr, sve_fp_2op_p_zds<0b11, opc, asm, ZPR64>; + } def : SVE_3_Op_Pat(NAME # _H)>; def : SVE_3_Op_Pat(NAME # _S)>; def : SVE_3_Op_Pat(NAME # _D)>; } +multiclass sve_fp_2op_p_zds_fscale_zx { + def _ZERO_H : PredTwoOpConstrainedPseudo; + def _ZERO_S : PredTwoOpConstrainedPseudo; + def _ZERO_D : PredTwoOpConstrainedPseudo; + + def : SVE_3_Op_Pat_SelZero(NAME # _ZERO_H)>; + def : SVE_3_Op_Pat_SelZero(NAME # _ZERO_S)>; + def : SVE_3_Op_Pat_SelZero(NAME # _ZERO_D)>; +} + multiclass sve_fp_2op_p_zds_zx { def _ZERO_H : PredTwoOpPseudo; def _ZERO_S : PredTwoOpPseudo; Index: llvm/test/CodeGen/AArch64/sve-intrinsics-fp-arith-merging.ll =================================================================== --- llvm/test/CodeGen/AArch64/sve-intrinsics-fp-arith-merging.ll +++ llvm/test/CodeGen/AArch64/sve-intrinsics-fp-arith-merging.ll @@ -240,6 +240,46 @@ ret %out } +; +; FSCALE +; + +define @fscale_h( %pg, %a, %b) { +; CHECK-LABEL: fscale_h: +; CHECK: movprfx z0.h, p0/z, z0.h +; CHECK-NEXT: fscale z0.h, p0/m, z0.h, z1.h +; CHECK-NEXT: ret + %a_z = select %pg, %a, zeroinitializer + %out = call @llvm.aarch64.sve.fscale.nxv8f16( %pg, + %a_z, + %b) + ret %out +} + +define @fscale_s( %pg, %a, %b) { +; CHECK-LABEL: fscale_s: +; CHECK: movprfx z0.s, p0/z, z0.s +; CHECK-NEXT: fscale z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %a_z = select %pg, %a, zeroinitializer + %out = call @llvm.aarch64.sve.fscale.nxv4f32( %pg, + %a_z, + %b) + ret %out +} + +define @fscale_d( %pg, %a, %b) { +; CHECK-LABEL: fscale_d: +; CHECK: movprfx z0.d, p0/z, z0.d +; CHECK-NEXT: fscale z0.d, p0/m, z0.d, z1.d +; CHECK-NEXT: ret + %a_z = select %pg, %a, zeroinitializer + %out = call @llvm.aarch64.sve.fscale.nxv2f64( %pg, + %a_z, + %b) + ret %out +} + ; ; FSUB ; @@ -360,6 +400,10 @@ declare @llvm.aarch64.sve.fmulx.nxv4f32(, , ) declare @llvm.aarch64.sve.fmulx.nxv2f64(, , ) +declare @llvm.aarch64.sve.fscale.nxv8f16(, , ) +declare @llvm.aarch64.sve.fscale.nxv4f32(, , ) +declare @llvm.aarch64.sve.fscale.nxv2f64(, , ) + declare @llvm.aarch64.sve.fsub.nxv8f16(, , ) declare @llvm.aarch64.sve.fsub.nxv4f32(, , ) declare @llvm.aarch64.sve.fsub.nxv2f64(, , )