diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -356,6 +356,23 @@ // sub(a, select(mask, mul(b, c), splat(0))) -> mls(a, mask, b, c) (sub node:$op1, (vselect node:$pred, (AArch64mul_p_oneuse (SVEAllActive), node:$op2, node:$op3), (SVEDup0)))]>; + +def AArch64smax_m1 : PatFrags<(ops node:$pg, node:$op1, node:$op2), + [(int_aarch64_sve_smax node:$pg, node:$op1, node:$op2), + (vselect node:$pg, (AArch64smax_p (SVEAllActive), node:$op1, node:$op2), node:$op1)]>; + +def AArch64umax_m1 : PatFrags<(ops node:$pg, node:$op1, node:$op2), + [(int_aarch64_sve_umax node:$pg, node:$op1, node:$op2), + (vselect node:$pg, (AArch64umax_p (SVEAllActive), node:$op1, node:$op2), node:$op1)]>; + +def AArch64smin_m1 : PatFrags<(ops node:$pg, node:$op1, node:$op2), + [(int_aarch64_sve_smin node:$pg, node:$op1, node:$op2), + (vselect node:$pg, (AArch64smin_p (SVEAllActive), node:$op1, node:$op2), node:$op1)]>; + +def AArch64umin_m1 : PatFrags<(ops node:$pg, node:$op1, node:$op2), + [(int_aarch64_sve_umin node:$pg, node:$op1, node:$op2), + (vselect node:$pg, (AArch64umin_p (SVEAllActive), node:$op1, node:$op2), node:$op1)]>; + 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">; @@ -483,10 +500,10 @@ def : Pat<(nxv2i64 (zext (nxv2i1 (AArch64setcc_z (nxv2i1 (SVEAllActive):$Pg), nxv2i64:$Op2, (SVEDup0), SETEQ)))), (CNOT_ZPmZ_D $Op2, $Pg, $Op2)>; - defm SMAX_ZPmZ : sve_int_bin_pred_arit_1<0b000, "smax", "SMAX_ZPZZ", int_aarch64_sve_smax, DestructiveBinaryComm>; - defm UMAX_ZPmZ : sve_int_bin_pred_arit_1<0b001, "umax", "UMAX_ZPZZ", int_aarch64_sve_umax, DestructiveBinaryComm>; - defm SMIN_ZPmZ : sve_int_bin_pred_arit_1<0b010, "smin", "SMIN_ZPZZ", int_aarch64_sve_smin, DestructiveBinaryComm>; - defm UMIN_ZPmZ : sve_int_bin_pred_arit_1<0b011, "umin", "UMIN_ZPZZ", int_aarch64_sve_umin, DestructiveBinaryComm>; + defm SMAX_ZPmZ : sve_int_bin_pred_arit_1<0b000, "smax", "SMAX_ZPZZ", AArch64smax_m1, DestructiveBinaryComm>; + defm UMAX_ZPmZ : sve_int_bin_pred_arit_1<0b001, "umax", "UMAX_ZPZZ", AArch64umax_m1, DestructiveBinaryComm>; + defm SMIN_ZPmZ : sve_int_bin_pred_arit_1<0b010, "smin", "SMIN_ZPZZ", AArch64smin_m1, DestructiveBinaryComm>; + defm UMIN_ZPmZ : sve_int_bin_pred_arit_1<0b011, "umin", "UMIN_ZPZZ", AArch64umin_m1, DestructiveBinaryComm>; defm SABD_ZPmZ : sve_int_bin_pred_arit_1<0b100, "sabd", "SABD_ZPZZ", int_aarch64_sve_sabd, DestructiveBinaryComm>; defm UABD_ZPmZ : sve_int_bin_pred_arit_1<0b101, "uabd", "UABD_ZPZZ", int_aarch64_sve_uabd, DestructiveBinaryComm>; diff --git a/llvm/test/CodeGen/AArch64/sve-min-max-pred.ll b/llvm/test/CodeGen/AArch64/sve-min-max-pred.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sve-min-max-pred.ll @@ -0,0 +1,180 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=aarch64-eabi %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-ISEL +; RUN: llc -mtriple=aarch64-eabi -global-isel %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GLOBAL + + +; These tests just check that the plumbing is in place for @llvm.smax, @llvm.umax, +; @llvm.smin, @llvm.umin. + +; tests for smax: + +define @smax_select_i8( %pg, %a, %b) { +; CHECK-LABEL: smax_i8: +; CHECK: smax z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.smax.nxv16i8( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @smax_select_i16( %pg, %a, %b) { +; CHECK-LABEL: smax_i16: +; CHECK: smax z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.smax.nxv8i16( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @smax_select_i32( %pg, %a, %b) { +; CHECK-LABEL: smax_i32: +; CHECK: smax z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.smax.nxv4i32( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @smax_select_i64( %pg, %a, %b) { +; CHECK-LABEL: smax_i64: +; CHECK: smax z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.smax.nxv2i64( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +; tests for umax: + +define @umax_select_i8( %pg, %a, %b) { +; CHECK-LABEL: umax_i8: +; CHECK: umax z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.umax.nxv16i8( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @umax_select_i16( %pg, %a, %b) { +; CHECK-LABEL: umax_i16: +; CHECK: umaxz0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.umax.nxv8i16( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @umax_select_i32( %pg, %a, %b) { +; CHECK-LABEL: umax_i32: +; CHECK: umax z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.umax.nxv4i32( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @umax_select_i64( %pg, %a, %b) { +; CHECK-LABEL: smax_i64: +; CHECK: umax z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.umax.nxv2i64( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +; tests for smin: + +define @smin_select_i8( %pg, %a, %b) { +; CHECK-LABEL: smin_i8: +; CHECK: smin z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.smin.nxv16i8( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @smin_select_i16( %pg, %a, %b) { +; CHECK-LABEL: smin_i16: +; CHECK: smin z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.smin.nxv8i16( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @smin_select_i32( %pg, %a, %b) { +; CHECK-LABEL: smin_i32: +; CHECK: smin z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.smin.nxv4i32( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @smin_select_i64( %pg, %a, %b) { +; CHECK-LABEL: smin_i64: +; CHECK: smin z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.smin.nxv2i64( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +; tests for umin: + +define @umin_select_i8( %pg, %a, %b) { +; CHECK-LABEL: umin_i8: +; CHECK: umin z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.umin.nxv16i8( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @umin_select_i16( %pg, %a, %b) { +; CHECK-LABEL: umin_i16: +; CHECK: umin z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.umin.nxv8i16( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @umin_select_i32( %pg, %a, %b) { +; CHECK-LABEL: umin_i32: +; CHECK: umin z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.umin.nxv4i32( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + +define @umin_select_i64( %pg, %a, %b) { +; CHECK-LABEL: umin_i64: +; CHECK: umin z0.s, p0/m, z0.s, z1.s +; CHECK-NEXT: ret + %sel = call @llvm.umin.nxv2i64( %a, %b) + %out = select %pg, %sel, %a + ret %out +} + + +declare @llvm.smax.nxv16i8(, ) +declare @llvm.smax.nxv8i16(, ) +declare @llvm.smax.nxv4i32(, ) +declare @llvm.smax.nxv2i64(, ) + +declare @llvm.umax.nxv16i8(, ) +declare @llvm.umax.nxv8i16(, ) +declare @llvm.umax.nxv4i32(, ) +declare @llvm.umax.nxv2i64(, ) + +declare @llvm.smin.nxv16i8(, ) +declare @llvm.smin.nxv8i16(, ) +declare @llvm.smin.nxv4i32(, ) +declare @llvm.smin.nxv2i64(, ) + +declare @llvm.umin.nxv16i8(, ) +declare @llvm.umin.nxv8i16(, ) +declare @llvm.umin.nxv4i32(, ) +declare @llvm.umin.nxv2i64(, )