blob: 4fc4e73a71fd02d5f2f94e6a77d34772bd792ddc [file]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mattr=+sve2,+dotprod < %s | FileCheck %s --check-prefixes=CHECK,SVE2
; RUN: llc -mattr=+sve2p3,+dotprod < %s | FileCheck %s --check-prefixes=CHECK,SVE2p3
target triple = "aarch64-unknown-linux-gnu"
define <vscale x 16 x i8> @sabs_nxv16i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b) {
; CHECK-LABEL: sabs_nxv16i8:
; CHECK: // %bb.0:
; CHECK-NEXT: ptrue p0.b
; CHECK-NEXT: sabd z0.b, p0/m, z0.b, z1.b
; CHECK-NEXT: ret
%smax = tail call <vscale x 16 x i8> @llvm.smax.nxv16i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
%smin = tail call <vscale x 16 x i8> @llvm.smin.nxv16i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
%sabs = sub <vscale x 16 x i8> %smax, %smin
ret <vscale x 16 x i8> %sabs
}
define <vscale x 16 x i8> @uabs_nxv16i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b) {
; CHECK-LABEL: uabs_nxv16i8:
; CHECK: // %bb.0:
; CHECK-NEXT: ptrue p0.b
; CHECK-NEXT: uabd z0.b, p0/m, z0.b, z1.b
; CHECK-NEXT: ret
%umax = tail call <vscale x 16 x i8> @llvm.umax.nxv16i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
%umin = tail call <vscale x 16 x i8> @llvm.umin.nxv16i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
%uabs = sub <vscale x 16 x i8> %umax, %umin
ret <vscale x 16 x i8> %uabs
}
define <vscale x 8 x i16> @sabs_nxv16i8_wide_add(<vscale x 8 x i16> %acc, <vscale x 16 x i8> %a, <vscale x 16 x i8> %b) {
; SVE2-LABEL: sabs_nxv16i8_wide_add:
; SVE2: // %bb.0:
; SVE2-NEXT: ptrue p0.b
; SVE2-NEXT: sabd z1.b, p0/m, z1.b, z2.b
; SVE2-NEXT: uadalp z0.h, p0/m, z1.b
; SVE2-NEXT: ret
;
; SVE2p3-LABEL: sabs_nxv16i8_wide_add:
; SVE2p3: // %bb.0:
; SVE2p3-NEXT: sabal z0.h, z1.b, z2.b
; SVE2p3-NEXT: ret
%smax = tail call <vscale x 16 x i8> @llvm.smax(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
%smin = tail call <vscale x 16 x i8> @llvm.smin(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
%sabs = sub <vscale x 16 x i8> %smax, %smin
%ext = zext <vscale x 16 x i8> %sabs to <vscale x 16 x i16>
%reduce = call <vscale x 8 x i16> @llvm.vector.partial.reduce.add(<vscale x 8 x i16> %acc, <vscale x 16 x i16> %ext)
ret <vscale x 8 x i16> %reduce
}
define <vscale x 4 x i32> @sabs_nxv8i16_wide_add(<vscale x 4 x i32> %acc, <vscale x 8 x i16> %a, <vscale x 8 x i16> %b) {
; SVE2-LABEL: sabs_nxv8i16_wide_add:
; SVE2: // %bb.0:
; SVE2-NEXT: ptrue p0.h
; SVE2-NEXT: sabd z1.h, p0/m, z1.h, z2.h
; SVE2-NEXT: uadalp z0.s, p0/m, z1.h
; SVE2-NEXT: ret
;
; SVE2p3-LABEL: sabs_nxv8i16_wide_add:
; SVE2p3: // %bb.0:
; SVE2p3-NEXT: sabal z0.s, z1.h, z2.h
; SVE2p3-NEXT: ret
%smax = tail call <vscale x 8 x i16> @llvm.smax(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b)
%smin = tail call <vscale x 8 x i16> @llvm.smin(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b)
%sabs = sub <vscale x 8 x i16> %smax, %smin
%ext = zext <vscale x 8 x i16> %sabs to <vscale x 8 x i32>
%reduce = call <vscale x 4 x i32> @llvm.vector.partial.reduce.add(<vscale x 4 x i32> %acc, <vscale x 8 x i32> %ext)
ret <vscale x 4 x i32> %reduce
}
define <vscale x 2 x i64> @sabs_nxv4i32_wide_add(<vscale x 2 x i64> %acc, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
; SVE2-LABEL: sabs_nxv4i32_wide_add:
; SVE2: // %bb.0:
; SVE2-NEXT: ptrue p0.s
; SVE2-NEXT: sabd z1.s, p0/m, z1.s, z2.s
; SVE2-NEXT: uadalp z0.d, p0/m, z1.s
; SVE2-NEXT: ret
;
; SVE2p3-LABEL: sabs_nxv4i32_wide_add:
; SVE2p3: // %bb.0:
; SVE2p3-NEXT: sabal z0.d, z1.s, z2.s
; SVE2p3-NEXT: ret
%smax = tail call <vscale x 4 x i32> @llvm.smax(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b)
%smin = tail call <vscale x 4 x i32> @llvm.smin(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b)
%sabs = sub <vscale x 4 x i32> %smax, %smin
%ext = zext <vscale x 4 x i32> %sabs to <vscale x 4 x i64>
%reduce = call <vscale x 2 x i64> @llvm.vector.partial.reduce.add(<vscale x 2 x i64> %acc, <vscale x 4 x i64> %ext)
ret <vscale x 2 x i64> %reduce
}
define <vscale x 4 x i32> @sabs_nxv16i8_dot(<vscale x 4 x i32> %acc, <vscale x 16 x i8> %a, <vscale x 16 x i8> %b) {
; CHECK-LABEL: sabs_nxv16i8_dot:
; CHECK: // %bb.0:
; CHECK-NEXT: ptrue p0.b
; CHECK-NEXT: sabd z1.b, p0/m, z1.b, z2.b
; CHECK-NEXT: mov z2.b, #1 // =0x1
; CHECK-NEXT: udot z0.s, z1.b, z2.b
; CHECK-NEXT: ret
%smax = tail call <vscale x 16 x i8> @llvm.smax.nxv16i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
%smin = tail call <vscale x 16 x i8> @llvm.smin.nxv16i8(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
%sabs = sub <vscale x 16 x i8> %smax, %smin
%ext = zext <vscale x 16 x i8> %sabs to <vscale x 16 x i32>
%dot = call <vscale x 4 x i32> @llvm.vector.partial.reduce.add.v4i32.v16i32(<vscale x 4 x i32> %acc, <vscale x 16 x i32> %ext)
ret <vscale x 4 x i32> %dot
}
define <16 x i8> @sabs_v16i8(<16 x i8> %a, <16 x i8> %b) {
; CHECK-LABEL: sabs_v16i8:
; CHECK: // %bb.0:
; CHECK-NEXT: sabd v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
%smax = tail call <16 x i8> @llvm.smax.v16i8(<16 x i8> %a, <16 x i8> %b)
%smin = tail call <16 x i8> @llvm.smin.v16i8(<16 x i8> %a, <16 x i8> %b)
%sabs = sub <16 x i8> %smax, %smin
ret <16 x i8> %sabs
}
define <16 x i8> @uabs_v16i8(<16 x i8> %a, <16 x i8> %b) {
; CHECK-LABEL: uabs_v16i8:
; CHECK: // %bb.0:
; CHECK-NEXT: uabd v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
%umax = tail call <16 x i8> @llvm.umax.v16i8(<16 x i8> %a, <16 x i8> %b)
%umin = tail call <16 x i8> @llvm.umin.v16i8(<16 x i8> %a, <16 x i8> %b)
%uabs = sub <16 x i8> %umax, %umin
ret <16 x i8> %uabs
}
define <vscale x 8 x i16> @uabs_nxv16i8_wide_add(<vscale x 8 x i16> %acc, <vscale x 16 x i8> %a, <vscale x 16 x i8> %b) {
; SVE2-LABEL: uabs_nxv16i8_wide_add:
; SVE2: // %bb.0:
; SVE2-NEXT: ptrue p0.b
; SVE2-NEXT: uabd z1.b, p0/m, z1.b, z2.b
; SVE2-NEXT: uadalp z0.h, p0/m, z1.b
; SVE2-NEXT: ret
;
; SVE2p3-LABEL: uabs_nxv16i8_wide_add:
; SVE2p3: // %bb.0:
; SVE2p3-NEXT: uabal z0.h, z1.b, z2.b
; SVE2p3-NEXT: ret
%umax = tail call <vscale x 16 x i8> @llvm.umax(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
%umin = tail call <vscale x 16 x i8> @llvm.umin(<vscale x 16 x i8> %a, <vscale x 16 x i8> %b)
%uabs = sub <vscale x 16 x i8> %umax, %umin
%ext = zext <vscale x 16 x i8> %uabs to <vscale x 16 x i16>
%reduce = call <vscale x 8 x i16> @llvm.vector.partial.reduce.add(<vscale x 8 x i16> %acc, <vscale x 16 x i16> %ext)
ret <vscale x 8 x i16> %reduce
}
define <vscale x 4 x i32> @uabs_nxv8i16_wide_add(<vscale x 4 x i32> %acc, <vscale x 8 x i16> %a, <vscale x 8 x i16> %b) {
; SVE2-LABEL: uabs_nxv8i16_wide_add:
; SVE2: // %bb.0:
; SVE2-NEXT: ptrue p0.h
; SVE2-NEXT: uabd z1.h, p0/m, z1.h, z2.h
; SVE2-NEXT: uadalp z0.s, p0/m, z1.h
; SVE2-NEXT: ret
;
; SVE2p3-LABEL: uabs_nxv8i16_wide_add:
; SVE2p3: // %bb.0:
; SVE2p3-NEXT: uabal z0.s, z1.h, z2.h
; SVE2p3-NEXT: ret
%umax = tail call <vscale x 8 x i16> @llvm.umax(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b)
%umin = tail call <vscale x 8 x i16> @llvm.umin(<vscale x 8 x i16> %a, <vscale x 8 x i16> %b)
%uabs = sub <vscale x 8 x i16> %umax, %umin
%ext = zext <vscale x 8 x i16> %uabs to <vscale x 8 x i32>
%reduce = call <vscale x 4 x i32> @llvm.vector.partial.reduce.add(<vscale x 4 x i32> %acc, <vscale x 8 x i32> %ext)
ret <vscale x 4 x i32> %reduce
}
define <vscale x 2 x i64> @uabs_nxv4i32_wide_add(<vscale x 2 x i64> %acc, <vscale x 4 x i32> %a, <vscale x 4 x i32> %b) {
; SVE2-LABEL: uabs_nxv4i32_wide_add:
; SVE2: // %bb.0:
; SVE2-NEXT: ptrue p0.s
; SVE2-NEXT: uabd z1.s, p0/m, z1.s, z2.s
; SVE2-NEXT: uadalp z0.d, p0/m, z1.s
; SVE2-NEXT: ret
;
; SVE2p3-LABEL: uabs_nxv4i32_wide_add:
; SVE2p3: // %bb.0:
; SVE2p3-NEXT: uabal z0.d, z1.s, z2.s
; SVE2p3-NEXT: ret
%umax = tail call <vscale x 4 x i32> @llvm.umax(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b)
%umin = tail call <vscale x 4 x i32> @llvm.umin(<vscale x 4 x i32> %a, <vscale x 4 x i32> %b)
%uabs = sub <vscale x 4 x i32> %umax, %umin
%ext = zext <vscale x 4 x i32> %uabs to <vscale x 4 x i64>
%reduce = call <vscale x 2 x i64> @llvm.vector.partial.reduce.add(<vscale x 2 x i64> %acc, <vscale x 4 x i64> %ext)
ret <vscale x 2 x i64> %reduce
}
define <4 x i32> @uabs_v16i8_dot(<4 x i32> %acc, <16 x i8> %a, <16 x i8> %b) {
; CHECK-LABEL: uabs_v16i8_dot:
; CHECK: // %bb.0:
; CHECK-NEXT: mov z3.b, #1 // =0x1
; CHECK-NEXT: uabd v1.16b, v1.16b, v2.16b
; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0
; CHECK-NEXT: udot z0.s, z1.b, z3.b
; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0
; CHECK-NEXT: ret
%umax = tail call <16 x i8> @llvm.umax.v16i8(<16 x i8> %a, <16 x i8> %b)
%umin = tail call <16 x i8> @llvm.umin.v16i8(<16 x i8> %a, <16 x i8> %b)
%uabs = sub <16 x i8> %umax, %umin
%ext = zext <16 x i8> %uabs to <16 x i32>
%dot = call <4 x i32> @llvm.vector.partial.reduce.add.v4i32.v16i32(<4 x i32> %acc, <16 x i32> %ext)
ret <4 x i32> %dot
}