This moves the matching of AVGFloor and AVGCeil into a place where demand bit are available, so that it can detect more cases for more folds. It changes the transform to start from a shift, not from a truncate. We match the pattern shr(add(ext(A), ext(B)), 1), transforming to ext(hadd(A, B)). For signed values, because only the bottom bits are demanded llvm will transform the above to use a lshr too, as opposed to ashr. In order to correctly detect the hadd we need to know the demanded bits to turn it back. Depending on whether the shift is signed (ashr) or logical (lshr), and the extensions are signed or unsigned we can create different nodes. If the shift is signed: Needs >= 2 sign bits. https://alive2.llvm.org/ce/z/h4gQAW generating signed rhadd. Needs >= 2 zero bits. https://alive2.llvm.org/ce/z/B64DUA generating unsigned rhadd. If the shift is unsigned: Needs >= 1 zero bits. https://alive2.llvm.org/ce/z/ByD8sj generating unsigned rhadd. Needs 1 demanded bit zero and >= 2 sign bits https://alive2.llvm.org/ce/z/hvPGxX and https://alive2.llvm.org/ce/z/32P5n1 generating signed rhadd. Differential Revision: https://reviews.llvm.org/D119072
674 lines
26 KiB
LLVM
674 lines
26 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mtriple=aarch64-none-eabi | FileCheck %s
|
|
|
|
define <8 x i16> @haddu_base(<8 x i16> %src1, <8 x i16> %src2) {
|
|
; CHECK-LABEL: haddu_base:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: uhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
|
|
%zextsrc2 = zext <8 x i16> %src2 to <8 x i32>
|
|
%add = add <8 x i32> %zextsrc1, %zextsrc2
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_const(<8 x i16> %src1) {
|
|
; CHECK-LABEL: haddu_const:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: uhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
|
|
%add = add <8 x i32> %zextsrc1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_const_lhs(<8 x i16> %src1) {
|
|
; CHECK-LABEL: haddu_const_lhs:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: uhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
|
|
%add = add <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, %zextsrc1
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_const_zero(<8 x i16> %src1) {
|
|
; CHECK-LABEL: haddu_const_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: ushll v1.4s, v0.4h, #0
|
|
; CHECK-NEXT: ushll2 v2.4s, v0.8h, #0
|
|
; CHECK-NEXT: shrn v0.4h, v1.4s, #1
|
|
; CHECK-NEXT: shrn2 v0.8h, v2.4s, #1
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
|
|
%add = add <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>, %zextsrc1
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_const_both() {
|
|
; CHECK-LABEL: haddu_const_both:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v0.8h, #2
|
|
; CHECK-NEXT: ret
|
|
%add = add <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_const_bothhigh() {
|
|
; CHECK-LABEL: haddu_const_bothhigh:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mvni v0.8h, #1
|
|
; CHECK-NEXT: ret
|
|
%ext1 = zext <8 x i16> <i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534> to <8 x i32>
|
|
%ext2 = zext <8 x i16> <i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535> to <8 x i32>
|
|
%add = add <8 x i32> %ext1, %ext2
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_undef(<8 x i16> %src1) {
|
|
; CHECK-LABEL: haddu_undef:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: ushll v1.4s, v0.4h, #0
|
|
; CHECK-NEXT: ushll2 v2.4s, v0.8h, #0
|
|
; CHECK-NEXT: shrn v0.4h, v1.4s, #1
|
|
; CHECK-NEXT: shrn2 v0.8h, v2.4s, #1
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
|
|
%zextsrc2 = zext <8 x i16> undef to <8 x i32>
|
|
%add = add <8 x i32> %zextsrc2, %zextsrc1
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
|
|
|
|
define <8 x i16> @haddu_i_base(<8 x i16> %src1, <8 x i16> %src2) {
|
|
; CHECK-LABEL: haddu_i_base:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: uhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> %src1, <8 x i16> %src2)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_i_const(<8 x i16> %src1) {
|
|
; CHECK-LABEL: haddu_i_const:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: uhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> %src1, <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_i_const_lhs(<8 x i16> %src1) {
|
|
; CHECK-LABEL: haddu_i_const_lhs:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: uhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_i_const_zero(<8 x i16> %src1) {
|
|
; CHECK-LABEL: haddu_i_const_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: ushr v0.8h, v0.8h, #1
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_i_const_both() {
|
|
; CHECK-LABEL: haddu_i_const_both:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v0.8h, #2
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>, <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_i_const_bothhigh() {
|
|
; CHECK-LABEL: haddu_i_const_bothhigh:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mvni v0.8h, #1
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> <i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534>, <8 x i16> <i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @haddu_i_undef(<8 x i16> %t, <8 x i16> %src1) {
|
|
; CHECK-LABEL: haddu_i_undef:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov v0.16b, v1.16b
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> undef, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define <8 x i16> @hadds_base(<8 x i16> %src1, <8 x i16> %src2) {
|
|
; CHECK-LABEL: hadds_base:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: shadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = sext <8 x i16> %src1 to <8 x i32>
|
|
%zextsrc2 = sext <8 x i16> %src2 to <8 x i32>
|
|
%add = add <8 x i32> %zextsrc1, %zextsrc2
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_const(<8 x i16> %src1) {
|
|
; CHECK-LABEL: hadds_const:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: shadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = sext <8 x i16> %src1 to <8 x i32>
|
|
%add = add <8 x i32> %zextsrc1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_const_lhs(<8 x i16> %src1) {
|
|
; CHECK-LABEL: hadds_const_lhs:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: shadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = sext <8 x i16> %src1 to <8 x i32>
|
|
%add = add <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, %zextsrc1
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_const_zero(<8 x i16> %src1) {
|
|
; CHECK-LABEL: hadds_const_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sshll v1.4s, v0.4h, #0
|
|
; CHECK-NEXT: sshll2 v2.4s, v0.8h, #0
|
|
; CHECK-NEXT: shrn v0.4h, v1.4s, #1
|
|
; CHECK-NEXT: shrn2 v0.8h, v2.4s, #1
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = sext <8 x i16> %src1 to <8 x i32>
|
|
%add = add <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>, %zextsrc1
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_const_both() {
|
|
; CHECK-LABEL: hadds_const_both:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v0.8h, #2
|
|
; CHECK-NEXT: ret
|
|
%add = add <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_const_bothhigh() {
|
|
; CHECK-LABEL: hadds_const_bothhigh:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov w8, #32766
|
|
; CHECK-NEXT: dup v0.8h, w8
|
|
; CHECK-NEXT: ret
|
|
%ext1 = sext <8 x i16> <i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766> to <8 x i32>
|
|
%ext2 = sext <8 x i16> <i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767> to <8 x i32>
|
|
%add = add <8 x i32> %ext1, %ext2
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_undef(<8 x i16> %src1) {
|
|
; CHECK-LABEL: hadds_undef:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sshll v1.4s, v0.4h, #0
|
|
; CHECK-NEXT: sshll2 v2.4s, v0.8h, #0
|
|
; CHECK-NEXT: shrn v0.4h, v1.4s, #1
|
|
; CHECK-NEXT: shrn2 v0.8h, v2.4s, #1
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = sext <8 x i16> %src1 to <8 x i32>
|
|
%zextsrc2 = sext <8 x i16> undef to <8 x i32>
|
|
%add = add <8 x i32> %zextsrc2, %zextsrc1
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
|
|
|
|
define <8 x i16> @hadds_i_base(<8 x i16> %src1, <8 x i16> %src2) {
|
|
; CHECK-LABEL: hadds_i_base:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: shadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> %src1, <8 x i16> %src2)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_i_const(<8 x i16> %src1) {
|
|
; CHECK-LABEL: hadds_i_const:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: shadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> %src1, <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_i_const_lhs(<8 x i16> %src1) {
|
|
; CHECK-LABEL: hadds_i_const_lhs:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: shadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_i_const_zero(<8 x i16> %src1) {
|
|
; CHECK-LABEL: hadds_i_const_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sshr v0.8h, v0.8h, #1
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_i_const_both() {
|
|
; CHECK-LABEL: hadds_i_const_both:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v0.8h, #2
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>, <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_i_const_bothhigh() {
|
|
; CHECK-LABEL: hadds_i_const_bothhigh:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov w8, #32766
|
|
; CHECK-NEXT: dup v0.8h, w8
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> <i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766>, <8 x i16> <i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @hadds_i_undef(<8 x i16> %t, <8 x i16> %src1) {
|
|
; CHECK-LABEL: hadds_i_undef:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov v0.16b, v1.16b
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> undef, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define <8 x i16> @rhaddu_base(<8 x i16> %src1, <8 x i16> %src2) {
|
|
; CHECK-LABEL: rhaddu_base:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: urhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
|
|
%zextsrc2 = zext <8 x i16> %src2 to <8 x i32>
|
|
%add1 = add <8 x i32> %zextsrc1, %zextsrc2
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_const(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhaddu_const:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: urhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
|
|
%add1 = add <8 x i32> %zextsrc1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_const_lhs(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhaddu_const_lhs:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: urhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
|
|
%add1 = add <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, %zextsrc1
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_const_zero(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhaddu_const_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: uhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
|
|
%add1 = add <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>, %zextsrc1
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_const_both() {
|
|
; CHECK-LABEL: rhaddu_const_both:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v0.8h, #2
|
|
; CHECK-NEXT: ret
|
|
%add1 = add <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_const_bothhigh() {
|
|
; CHECK-LABEL: rhaddu_const_bothhigh:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v0.2d, #0xffffffffffffffff
|
|
; CHECK-NEXT: ret
|
|
%ext1 = zext <8 x i16> <i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534> to <8 x i32>
|
|
%ext2 = zext <8 x i16> <i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535> to <8 x i32>
|
|
%add1 = add <8 x i32> %ext1, %ext2
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_undef(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhaddu_undef:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: uhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = zext <8 x i16> %src1 to <8 x i32>
|
|
%zextsrc2 = zext <8 x i16> undef to <8 x i32>
|
|
%add1 = add <8 x i32> %zextsrc2, %zextsrc1
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = lshr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
|
|
|
|
define <8 x i16> @rhaddu_i_base(<8 x i16> %src1, <8 x i16> %src2) {
|
|
; CHECK-LABEL: rhaddu_i_base:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: urhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> %src1, <8 x i16> %src2)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_i_const(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhaddu_i_const:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: urhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> %src1, <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_i_const_lhs(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhaddu_i_const_lhs:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: urhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_i_const_zero(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhaddu_i_const_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.2d, #0000000000000000
|
|
; CHECK-NEXT: urhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_i_const_both() {
|
|
; CHECK-LABEL: rhaddu_i_const_both:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v0.8h, #2
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>, <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_i_const_bothhigh() {
|
|
; CHECK-LABEL: rhaddu_i_const_bothhigh:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v0.2d, #0xffffffffffffffff
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> <i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534, i16 65534>, <8 x i16> <i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535, i16 65535>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhaddu_i_undef(<8 x i16> %t, <8 x i16> %src1) {
|
|
; CHECK-LABEL: rhaddu_i_undef:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov v0.16b, v1.16b
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> undef, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
define <8 x i16> @rhadds_base(<8 x i16> %src1, <8 x i16> %src2) {
|
|
; CHECK-LABEL: rhadds_base:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: srhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = sext <8 x i16> %src1 to <8 x i32>
|
|
%zextsrc2 = sext <8 x i16> %src2 to <8 x i32>
|
|
%add1 = add <8 x i32> %zextsrc1, %zextsrc2
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_const(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhadds_const:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: srhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = sext <8 x i16> %src1 to <8 x i32>
|
|
%add1 = add <8 x i32> %zextsrc1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_const_lhs(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhadds_const_lhs:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: srhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = sext <8 x i16> %src1 to <8 x i32>
|
|
%add1 = add <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, %zextsrc1
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_const_zero(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhadds_const_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: shadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = sext <8 x i16> %src1 to <8 x i32>
|
|
%add1 = add <8 x i32> <i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>, %zextsrc1
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_const_both() {
|
|
; CHECK-LABEL: rhadds_const_both:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v0.8h, #2
|
|
; CHECK-NEXT: ret
|
|
%add1 = add <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_const_bothhigh() {
|
|
; CHECK-LABEL: rhadds_const_bothhigh:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mvni v0.8h, #128, lsl #8
|
|
; CHECK-NEXT: ret
|
|
%ext1 = sext <8 x i16> <i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766> to <8 x i32>
|
|
%ext2 = sext <8 x i16> <i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767> to <8 x i32>
|
|
%add1 = add <8 x i32> %ext1, %ext2
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_undef(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhadds_undef:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: shadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%zextsrc1 = sext <8 x i16> %src1 to <8 x i32>
|
|
%zextsrc2 = sext <8 x i16> undef to <8 x i32>
|
|
%add1 = add <8 x i32> %zextsrc2, %zextsrc1
|
|
%add = add <8 x i32> %add1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%resulti16 = ashr <8 x i32> %add, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
|
|
%result = trunc <8 x i32> %resulti16 to <8 x i16>
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
|
|
|
|
define <8 x i16> @rhadds_i_base(<8 x i16> %src1, <8 x i16> %src2) {
|
|
; CHECK-LABEL: rhadds_i_base:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: srhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> %src1, <8 x i16> %src2)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_i_const(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhadds_i_const:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: srhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> %src1, <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_i_const_lhs(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhadds_i_const_lhs:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.8h, #1
|
|
; CHECK-NEXT: srhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_i_const_zero(<8 x i16> %src1) {
|
|
; CHECK-LABEL: rhadds_i_const_zero:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v1.2d, #0000000000000000
|
|
; CHECK-NEXT: srhadd v0.8h, v0.8h, v1.8h
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> <i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0, i16 0>, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_i_const_both() {
|
|
; CHECK-LABEL: rhadds_i_const_both:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: movi v0.8h, #2
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> <i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3, i16 3>, <8 x i16> <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_i_const_bothhigh() {
|
|
; CHECK-LABEL: rhadds_i_const_bothhigh:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mvni v0.8h, #128, lsl #8
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> <i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766, i16 32766>, <8 x i16> <i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767>)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
define <8 x i16> @rhadds_i_undef(<8 x i16> %t, <8 x i16> %src1) {
|
|
; CHECK-LABEL: rhadds_i_undef:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov v0.16b, v1.16b
|
|
; CHECK-NEXT: ret
|
|
%result = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> undef, <8 x i16> %src1)
|
|
ret <8 x i16> %result
|
|
}
|
|
|
|
declare <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16>, <8 x i16>)
|
|
declare <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16>, <8 x i16>)
|
|
declare <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16>, <8 x i16>)
|
|
declare <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16>, <8 x i16>)
|