Index: llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -335,8 +335,16 @@ (and node:$op1, (xor node:$op2, (SVEAllActive))), (AArch64bic_node node:$op1, node:$op2)]>; -def AArch64subr : PatFrag<(ops node:$op1, node:$op2), - (sub node:$op2, node:$op1)>; +def AArch64subr_imm : PatFrag<(ops node:$op1, node:$op2), + (sub node:$op2, node:$op1)>; +def AArch64subr : PatFrag<(ops node:$pred, node:$op1, node:$op2), + (int_aarch64_sve_subr node:$pred, node:$op1, node:$op2)>; +def AArch64add : PatFrags<(ops node:$pred, node:$op1, node:$op2), + [(int_aarch64_sve_add node:$pred, node:$op1, node:$op2), + (add node:$op1, (vselect node:$pred, node:$op2, (SVEDup0)))]>; +def AArch64sub : PatFrags<(ops node:$pred, node:$op1, node:$op2), + [(int_aarch64_sve_sub node:$pred, node:$op1, node:$op2), + (sub node:$op1, (vselect node:$pred, node:$op2, (SVEDup0)))]>; let Predicates = [HasSVE] in { defm RDFFR_PPz : sve_int_rdffr_pred<0b0, "rdffr", int_aarch64_sve_rdffr_z>; @@ -359,9 +367,9 @@ defm EOR_ZZZ : sve_int_bin_cons_log<0b10, "eor", xor>; defm BIC_ZZZ : sve_int_bin_cons_log<0b11, "bic", AArch64bic>; - defm ADD_ZPmZ : sve_int_bin_pred_arit_0<0b000, "add", "ADD_ZPZZ", int_aarch64_sve_add, DestructiveBinaryComm>; - defm SUB_ZPmZ : sve_int_bin_pred_arit_0<0b001, "sub", "SUB_ZPZZ", int_aarch64_sve_sub, DestructiveBinaryCommWithRev, "SUBR_ZPmZ">; - defm SUBR_ZPmZ : sve_int_bin_pred_arit_0<0b011, "subr", "SUBR_ZPZZ", int_aarch64_sve_subr, DestructiveBinaryCommWithRev, "SUB_ZPmZ", /*isReverseInstr*/ 1>; + defm ADD_ZPmZ : sve_int_bin_pred_arit_0<0b000, "add", "ADD_ZPZZ", AArch64add, DestructiveBinaryComm>; + defm SUB_ZPmZ : sve_int_bin_pred_arit_0<0b001, "sub", "SUB_ZPZZ", AArch64sub, DestructiveBinaryCommWithRev, "SUBR_ZPmZ">; + defm SUBR_ZPmZ : sve_int_bin_pred_arit_0<0b011, "subr", "SUBR_ZPZZ", AArch64subr, DestructiveBinaryCommWithRev, "SUB_ZPmZ", /*isReverseInstr*/ 1>; defm ORR_ZPmZ : sve_int_bin_pred_log<0b000, "orr", "ORR_ZPZZ", int_aarch64_sve_orr, DestructiveBinaryComm>; defm EOR_ZPmZ : sve_int_bin_pred_log<0b001, "eor", "EOR_ZPZZ", int_aarch64_sve_eor, DestructiveBinaryComm>; @@ -383,7 +391,7 @@ let Predicates = [HasSVEorSME] in { defm ADD_ZI : sve_int_arith_imm0<0b000, "add", add>; defm SUB_ZI : sve_int_arith_imm0<0b001, "sub", sub>; - defm SUBR_ZI : sve_int_arith_imm0<0b011, "subr", AArch64subr>; + defm SUBR_ZI : sve_int_arith_imm0<0b011, "subr", AArch64subr_imm>; defm SQADD_ZI : sve_int_arith_imm0<0b100, "sqadd", saddsat>; defm UQADD_ZI : sve_int_arith_imm0<0b101, "uqadd", uaddsat>; defm SQSUB_ZI : sve_int_arith_imm0<0b110, "sqsub", ssubsat>; Index: llvm/test/CodeGen/AArch64/sve-masked-add-sub.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/sve-masked-add-sub.ll @@ -0,0 +1,90 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64--linux-gnu -mattr=+sve < %s | FileCheck %s + +; +; Masked Additions +; + +define @masked_add_nxv16i8( %a, %b, %mask) { +; CHECK-LABEL: masked_add_nxv16i8: +; CHECK: // %bb.0: +; CHECK-NEXT: add z0.b, p0/m, z0.b, z1.b +; CHECK-NEXT: ret + %select = select %mask, %b, zeroinitializer + %ret = add %a, %select + ret %ret +} + +define @masked_add_nxv8i16( %a, %b, %mask) { +; CHECK-LABEL: masked_add_nxv8i16: +; CHECK: // %bb.0: +; CHECK-NEXT: add z0.h, p0/m, z0.h, z1.h +; CHECK-NEXT: ret + %select = select %mask, %b, zeroinitializer + %ret = add %a, %select + ret %ret +} + +define @masked_add_nxv4i32( %a, %b, %mask) { +; CHECK-LABEL: masked_add_nxv4i32: +; CHECK: // %bb.0: +; CHECK-NEXT: add z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %select = select %mask, %b, zeroinitializer + %ret = add %a, %select + ret %ret +} + +define @masked_add_nxv2i64( %a, %b, %mask) { +; CHECK-LABEL: masked_add_nxv2i64: +; CHECK: // %bb.0: +; CHECK-NEXT: add z0.d, p0/m, z0.d, z1.d +; CHECK-NEXT: ret + %select = select %mask, %b, zeroinitializer + %ret = add %a, %select + ret %ret +} + +; +; Masked Subtractions +; + +define @masked_sub_nxv16i8( %a, %b, %mask) { +; CHECK-LABEL: masked_sub_nxv16i8: +; CHECK: // %bb.0: +; CHECK-NEXT: sub z0.b, p0/m, z0.b, z1.b +; CHECK-NEXT: ret + %select = select %mask, %b, zeroinitializer + %ret = sub %a, %select + ret %ret +} + +define @masked_sub_nxv8i16( %a, %b, %mask) { +; CHECK-LABEL: masked_sub_nxv8i16: +; CHECK: // %bb.0: +; CHECK-NEXT: sub z0.h, p0/m, z0.h, z1.h +; CHECK-NEXT: ret + %select = select %mask, %b, zeroinitializer + %ret = sub %a, %select + ret %ret +} + +define @masked_sub_nxv4i32( %a, %b, %mask) { +; CHECK-LABEL: masked_sub_nxv4i32: +; CHECK: // %bb.0: +; CHECK-NEXT: sub z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %select = select %mask, %b, zeroinitializer + %ret = sub %a, %select + ret %ret +} + +define @masked_sub_nxv2i64( %a, %b, %mask) { +; CHECK-LABEL: masked_sub_nxv2i64: +; CHECK: // %bb.0: +; CHECK-NEXT: sub z0.d, p0/m, z0.d, z1.d +; CHECK-NEXT: ret + %select = select %mask, %b, zeroinitializer + %ret = sub %a, %select + ret %ret +}