| ; 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 |
| } |