blob: fd52fd26a62309ad7ec89344f84a2599b0f13eeb [file]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -mtriple=aarch64 < %s | FileCheck %s
; Left slide: {v[0]..v[7]} => {v[1]..v[7], 0}
define <8 x i8> @slide_left_1(<8 x i8> %v) {
; CHECK-LABEL: slide_left_1:
; CHECK: // %bb.0:
; CHECK-NEXT: ushr d0, d0, #8
; CHECK-NEXT: ret
%r = shufflevector <8 x i8> %v, <8 x i8> zeroinitializer,
<8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>
ret <8 x i8> %r
}
; Right slide: {v[0]..v[7]} => {0, v[0]..v[6]}
define <8 x i8> @slide_right_1(<8 x i8> %v) {
; CHECK-LABEL: slide_right_1:
; CHECK: // %bb.0:
; CHECK-NEXT: shl d0, d0, #8
; CHECK-NEXT: ret
%r = shufflevector <8 x i8> zeroinitializer, <8 x i8> %v,
<8 x i32> <i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14>
ret <8 x i8> %r
}
; Commuted left slide: zeros first, then data
define <8 x i8> @slide_left_1_commuted(<8 x i8> %v) {
; CHECK-LABEL: slide_left_1_commuted:
; CHECK: // %bb.0:
; CHECK-NEXT: ushr d0, d0, #8
; CHECK-NEXT: ret
%r = shufflevector <8 x i8> zeroinitializer, <8 x i8> %v,
<8 x i32> <i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0>
ret <8 x i8> %r
}
; Commuted right slide: data first, then zeros
define <8 x i8> @slide_right_1_commuted(<8 x i8> %v) {
; CHECK-LABEL: slide_right_1_commuted:
; CHECK: // %bb.0:
; CHECK-NEXT: shl d0, d0, #8
; CHECK-NEXT: ret
%r = shufflevector <8 x i8> %v, <8 x i8> zeroinitializer,
<8 x i32> <i32 15, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6>
ret <8 x i8> %r
}
; Commuted 128-bit lane-independent
define <16 x i8> @slide_left_v16i8_lane_independent_commuted(<16 x i8> %v) {
; CHECK-LABEL: slide_left_v16i8_lane_independent_commuted:
; CHECK: // %bb.0:
; CHECK-NEXT: ushr v0.2d, v0.2d, #8
; CHECK-NEXT: ret
%r = shufflevector <16 x i8> zeroinitializer, <16 x i8> %v,
<16 x i32> <i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 0,
i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 8>
ret <16 x i8> %r
}
; 64 bit test (with poison)
; Left slide with poison (from issue's Alive2 proof)
define <8 x i8> @slide_left_poison(<8 x i8> %v) {
; CHECK-LABEL: slide_left_poison:
; CHECK: // %bb.0:
; CHECK-NEXT: ushr d0, d0, #8
; CHECK-NEXT: ret
%r = shufflevector <8 x i8> %v, <8 x i8> <i8 0, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison>,
<8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>
ret <8 x i8> %r
}
; Right slide with poison (from issue's Alive2 proof)
define <8 x i8> @slide_right_poison(<8 x i8> %v) {
; CHECK-LABEL: slide_right_poison:
; CHECK: // %bb.0:
; CHECK-NEXT: shl d0, d0, #8
; CHECK-NEXT: ret
%r = shufflevector <8 x i8> <i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 0>, <8 x i8> %v,
<8 x i32> <i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14>
ret <8 x i8> %r
}
; should also optimize 32-bit vectors
; Left slide 32-bit: <4 x i8>
define <4 x i8> @slide_left_v4i8(<4 x i8> %v) {
; CHECK-LABEL: slide_left_v4i8:
; CHECK: // %bb.0:
; CHECK-NEXT: ushr d0, d0, #16
; CHECK-NEXT: ret
%r = shufflevector <4 x i8> %v, <4 x i8> zeroinitializer,
<4 x i32> <i32 1, i32 2, i32 3, i32 4>
ret <4 x i8> %r
}
; Right slide 32-bit: <4 x i8>
define <4 x i8> @slide_right_v4i8(<4 x i8> %v) {
; CHECK-LABEL: slide_right_v4i8:
; CHECK: // %bb.0:
; CHECK-NEXT: shl d0, d0, #16
; CHECK-NEXT: ret
%r = shufflevector <4 x i8> zeroinitializer, <4 x i8> %v,
<4 x i32> <i32 3, i32 4, i32 5, i32 6>
ret <4 x i8> %r
}
; should NOT optimize 128-bit vectors
; Left slide 128-bit: <16 x i8> - must use ext
define <16 x i8> @slide_left_v16i8(<16 x i8> %v) {
; CHECK-LABEL: slide_left_v16i8:
; CHECK: // %bb.0:
; CHECK-NEXT: movi v1.2d, #0000000000000000
; CHECK-NEXT: ext v0.16b, v0.16b, v1.16b, #1
; CHECK-NEXT: ret
%r = shufflevector <16 x i8> %v, <16 x i8> zeroinitializer,
<16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8,
i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>
ret <16 x i8> %r
}
; Right slide 128-bit: <16 x i8> - must use ext
define <16 x i8> @slide_right_v16i8(<16 x i8> %v) {
; CHECK-LABEL: slide_right_v16i8:
; CHECK: // %bb.0:
; CHECK-NEXT: movi v1.2d, #0000000000000000
; CHECK-NEXT: ext v0.16b, v1.16b, v0.16b, #15
; CHECK-NEXT: ret
%r = shufflevector <16 x i8> zeroinitializer, <16 x i8> %v,
<16 x i32> <i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22,
i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30>
ret <16 x i8> %r
}
; 128-bit lane-independent slides (both 64-bit halves slide same amount)
; These CAN be optimized to ushr/shl on v2i64
; Left slide 128-bit lane-independent: each half slides left by 1
define <16 x i8> @slide_left_v16i8_lane_independent(<16 x i8> %v) {
; CHECK-LABEL: slide_left_v16i8_lane_independent:
; CHECK: // %bb.0:
; CHECK-NEXT: ushr v0.2d, v0.2d, #8
; CHECK-NEXT: ret
%r = shufflevector <16 x i8> %v, <16 x i8> zeroinitializer,
<16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16,
i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 24>
ret <16 x i8> %r
}
; Right slide 128-bit lane-independent: each half slides right by 1
define <16 x i8> @slide_right_v16i8_lane_independent(<16 x i8> %v) {
; CHECK-LABEL: slide_right_v16i8_lane_independent:
; CHECK: // %bb.0:
; CHECK-NEXT: shl v0.2d, v0.2d, #8
; CHECK-NEXT: ret
%r = shufflevector <16 x i8> zeroinitializer, <16 x i8> %v,
<16 x i32> <i32 0, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22,
i32 8, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30>
ret <16 x i8> %r
}
; 128-bit i16 lane-independent slide
define <8 x i16> @slide_left_v8i16_lane_independent(<8 x i16> %v) {
; CHECK-LABEL: slide_left_v8i16_lane_independent:
; CHECK: // %bb.0:
; CHECK-NEXT: ushr v0.2d, v0.2d, #16
; CHECK-NEXT: ret
%r = shufflevector <8 x i16> %v, <8 x i16> zeroinitializer,
<8 x i32> <i32 1, i32 2, i32 3, i32 8,
i32 5, i32 6, i32 7, i32 12>
ret <8 x i16> %r
}
; 128-bit i32 lane-independent slide
define <4 x i32> @slide_left_v4i32_lane_independent(<4 x i32> %v) {
; CHECK-LABEL: slide_left_v4i32_lane_independent:
; CHECK: // %bb.0:
; CHECK-NEXT: ushr v0.2d, v0.2d, #32
; CHECK-NEXT: ret
%r = shufflevector <4 x i32> %v, <4 x i32> zeroinitializer,
<4 x i32> <i32 1, i32 4, i32 3, i32 6>
ret <4 x i32> %r
}
; Negative: halves slide different amounts (should NOT optimize to shift)
define <16 x i8> @slide_different_amounts(<16 x i8> %v) {
; CHECK-LABEL: slide_different_amounts:
; CHECK: // %bb.0:
; CHECK-NEXT: adrp x8, .LCPI15_0
; CHECK-NEXT: ldr q1, [x8, :lo12:.LCPI15_0]
; CHECK-NEXT: tbl v0.16b, { v0.16b }, v1.16b
; CHECK-NEXT: ret
%r = shufflevector <16 x i8> %v, <16 x i8> zeroinitializer,
<16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16,
i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 24, i32 25>
ret <16 x i8> %r
}
; Slide by max (N-1 elements)
; Left slide by 7 (max for v8i8)
define <8 x i8> @slide_left_max(<8 x i8> %v) {
; CHECK-LABEL: slide_left_max:
; CHECK: // %bb.0:
; CHECK-NEXT: ushr d0, d0, #56
; CHECK-NEXT: ret
%r = shufflevector <8 x i8> %v, <8 x i8> zeroinitializer,
<8 x i32> <i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14>
ret <8 x i8> %r
}
; Right slide by 7 (max for v8i8): [v0..v7] => [0,0,0,0,0,0,0,v0]
define <8 x i8> @slide_right_max(<8 x i8> %v) {
; CHECK-LABEL: slide_right_max:
; CHECK: // %bb.0:
; CHECK-NEXT: shl d0, d0, #56
; CHECK-NEXT: ret
%r = shufflevector <8 x i8> zeroinitializer, <8 x i8> %v,
<8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 8>
ret <8 x i8> %r
}