| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 | |
| ; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s --check-prefixes=CHECK,CHECK-SD | |
| ; RUN: llc < %s -mtriple=aarch64-unknown-unknown -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI | |
| define <8 x i8> @inserti8_first(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti8_first: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldr d0, [x0] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti8_first: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-GI-NEXT: ext v0.8b, v0.8b, v0.8b, #7 | |
| ; CHECK-GI-NEXT: ld1 { v0.b }[0], [x0] | |
| ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| %l1 = load <8 x i8>, ptr %q | |
| %l2 = load i8, ptr %p | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 0 | |
| ret <8 x i8> %ins | |
| } | |
| define <8 x i8> @inserti8_last(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti8_last: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti8_last: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldr d0, [x0] | |
| ; CHECK-GI-NEXT: add x8, x0, #8 | |
| ; CHECK-GI-NEXT: ext v0.8b, v0.8b, v0.8b, #1 | |
| ; CHECK-GI-NEXT: ld1 { v0.b }[7], [x8] | |
| ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 8 | |
| %l1 = load <8 x i8>, ptr %p | |
| %l2 = load i8, ptr %q | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 7 | |
| ret <8 x i8> %ins | |
| } | |
| define <8 x i16> @inserti8_first_sext(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti8_first_sext: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldr d0, [x0] | |
| ; CHECK-SD-NEXT: sshll v0.8h, v0.8b, #0 | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti8_first_sext: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-GI-NEXT: ldrsb w8, [x0] | |
| ; CHECK-GI-NEXT: sshll v0.8h, v0.8b, #0 | |
| ; CHECK-GI-NEXT: ext v0.16b, v0.16b, v0.16b, #14 | |
| ; CHECK-GI-NEXT: mov v0.h[0], w8 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| %l1 = load <8 x i8>, ptr %q | |
| %s1 = sext <8 x i8> %l1 to <8 x i16> | |
| %l2 = load i8, ptr %p | |
| %s2 = sext i8 %l2 to i16 | |
| %s = shufflevector <8 x i16> %s1, <8 x i16> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i16> %s, i16 %s2, i32 0 | |
| ret <8 x i16> %ins | |
| } | |
| define <8 x i16> @inserti8_last_sext(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti8_last_sext: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-SD-NEXT: sshll v0.8h, v0.8b, #0 | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti8_last_sext: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldr d0, [x0] | |
| ; CHECK-GI-NEXT: ldrsb w8, [x0, #8] | |
| ; CHECK-GI-NEXT: sshll v0.8h, v0.8b, #0 | |
| ; CHECK-GI-NEXT: ext v0.16b, v0.16b, v0.16b, #2 | |
| ; CHECK-GI-NEXT: mov v0.h[7], w8 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 8 | |
| %l1 = load <8 x i8>, ptr %p | |
| %s1 = sext <8 x i8> %l1 to <8 x i16> | |
| %l2 = load i8, ptr %q | |
| %s2 = sext i8 %l2 to i16 | |
| %s = shufflevector <8 x i16> %s1, <8 x i16> undef, <8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef> | |
| %ins = insertelement <8 x i16> %s, i16 %s2, i32 7 | |
| ret <8 x i16> %ins | |
| } | |
| define <8 x i16> @inserti8_first_zext(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti8_first_zext: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldr d0, [x0] | |
| ; CHECK-SD-NEXT: ushll v0.8h, v0.8b, #0 | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti8_first_zext: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-GI-NEXT: ldrb w8, [x0] | |
| ; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0 | |
| ; CHECK-GI-NEXT: ext v0.16b, v0.16b, v0.16b, #14 | |
| ; CHECK-GI-NEXT: mov v0.h[0], w8 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| %l1 = load <8 x i8>, ptr %q | |
| %s1 = zext <8 x i8> %l1 to <8 x i16> | |
| %l2 = load i8, ptr %p | |
| %s2 = zext i8 %l2 to i16 | |
| %s = shufflevector <8 x i16> %s1, <8 x i16> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i16> %s, i16 %s2, i32 0 | |
| ret <8 x i16> %ins | |
| } | |
| define <8 x i16> @inserti8_last_zext(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti8_last_zext: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-SD-NEXT: ushll v0.8h, v0.8b, #0 | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti8_last_zext: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldr d0, [x0] | |
| ; CHECK-GI-NEXT: ldrb w8, [x0, #8] | |
| ; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0 | |
| ; CHECK-GI-NEXT: ext v0.16b, v0.16b, v0.16b, #2 | |
| ; CHECK-GI-NEXT: mov v0.h[7], w8 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 8 | |
| %l1 = load <8 x i8>, ptr %p | |
| %s1 = zext <8 x i8> %l1 to <8 x i16> | |
| %l2 = load i8, ptr %q | |
| %s2 = zext i8 %l2 to i16 | |
| %s = shufflevector <8 x i16> %s1, <8 x i16> undef, <8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef> | |
| %ins = insertelement <8 x i16> %s, i16 %s2, i32 7 | |
| ret <8 x i16> %ins | |
| } | |
| define <8 x i32> @inserti32_first(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti32_first: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldp q0, q1, [x0] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti32_first: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: mov x8, x0 | |
| ; CHECK-GI-NEXT: ldr q1, [x8, #4]! | |
| ; CHECK-GI-NEXT: ldr q2, [x8, #16] | |
| ; CHECK-GI-NEXT: ext v0.16b, v0.16b, v1.16b, #12 | |
| ; CHECK-GI-NEXT: ext v1.16b, v1.16b, v2.16b, #12 | |
| ; CHECK-GI-NEXT: ld1 { v0.s }[0], [x0] | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 4 | |
| %l1 = load <8 x i32>, ptr %q | |
| %l2 = load i32, ptr %p | |
| %s = shufflevector <8 x i32> %l1, <8 x i32> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i32> %s, i32 %l2, i32 0 | |
| ret <8 x i32> %ins | |
| } | |
| define <8 x i32> @inserti32_last(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti32_last: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldur q0, [x0, #4] | |
| ; CHECK-SD-NEXT: ldur q1, [x0, #20] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti32_last: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldp q2, q0, [x0] | |
| ; CHECK-GI-NEXT: add x8, x0, #32 | |
| ; CHECK-GI-NEXT: ext v1.16b, v0.16b, v0.16b, #4 | |
| ; CHECK-GI-NEXT: ext v0.16b, v2.16b, v0.16b, #4 | |
| ; CHECK-GI-NEXT: ld1 { v1.s }[3], [x8] | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 32 | |
| %l1 = load <8 x i32>, ptr %p | |
| %l2 = load i32, ptr %q | |
| %s = shufflevector <8 x i32> %l1, <8 x i32> undef, <8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef> | |
| %ins = insertelement <8 x i32> %s, i32 %l2, i32 7 | |
| ret <8 x i32> %ins | |
| } | |
| define <8 x i32> @inserti32_first_multiuse(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti32_first_multiuse: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldp q3, q2, [x0] | |
| ; CHECK-SD-NEXT: ldur q1, [x0, #20] | |
| ; CHECK-SD-NEXT: ldur q0, [x0, #4] | |
| ; CHECK-SD-NEXT: add v0.4s, v0.4s, v3.4s | |
| ; CHECK-SD-NEXT: add v1.4s, v1.4s, v2.4s | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti32_first_multiuse: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: mov x8, x0 | |
| ; CHECK-GI-NEXT: ldr q0, [x8, #4]! | |
| ; CHECK-GI-NEXT: ldr q1, [x8, #16] | |
| ; CHECK-GI-NEXT: ext v2.16b, v0.16b, v0.16b, #12 | |
| ; CHECK-GI-NEXT: ext v3.16b, v0.16b, v1.16b, #12 | |
| ; CHECK-GI-NEXT: ld1 { v2.s }[0], [x0] | |
| ; CHECK-GI-NEXT: add v1.4s, v1.4s, v3.4s | |
| ; CHECK-GI-NEXT: add v0.4s, v0.4s, v2.4s | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 4 | |
| %l1 = load <8 x i32>, ptr %q | |
| %l2 = load i32, ptr %p | |
| %s = shufflevector <8 x i32> %l1, <8 x i32> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i32> %s, i32 %l2, i32 0 | |
| %a = add <8 x i32> %l1, %ins | |
| ret <8 x i32> %a | |
| } | |
| define <8 x i32> @inserti32_last_multiuse(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti32_last_multiuse: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldp q0, q1, [x0] | |
| ; CHECK-SD-NEXT: ldur q2, [x0, #20] | |
| ; CHECK-SD-NEXT: ldur q3, [x0, #4] | |
| ; CHECK-SD-NEXT: add v0.4s, v0.4s, v3.4s | |
| ; CHECK-SD-NEXT: add v1.4s, v1.4s, v2.4s | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti32_last_multiuse: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldr q1, [x0, #16] | |
| ; CHECK-GI-NEXT: add x8, x0, #32 | |
| ; CHECK-GI-NEXT: ext v2.16b, v1.16b, v0.16b, #4 | |
| ; CHECK-GI-NEXT: ldr q0, [x0] | |
| ; CHECK-GI-NEXT: ext v3.16b, v0.16b, v1.16b, #4 | |
| ; CHECK-GI-NEXT: ld1 { v2.s }[3], [x8] | |
| ; CHECK-GI-NEXT: add v0.4s, v0.4s, v3.4s | |
| ; CHECK-GI-NEXT: add v1.4s, v1.4s, v2.4s | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 32 | |
| %l1 = load <8 x i32>, ptr %p | |
| %l2 = load i32, ptr %q | |
| %s = shufflevector <8 x i32> %l1, <8 x i32> undef, <8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef> | |
| %ins = insertelement <8 x i32> %s, i32 %l2, i32 7 | |
| %a = add <8 x i32> %l1, %ins | |
| ret <8 x i32> %a | |
| } | |
| define <4 x float> @insertf32_first(ptr %p) { | |
| ; CHECK-SD-LABEL: insertf32_first: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldr q0, [x0] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: insertf32_first: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldur q0, [x0, #4] | |
| ; CHECK-GI-NEXT: ext v0.16b, v0.16b, v0.16b, #12 | |
| ; CHECK-GI-NEXT: ld1 { v0.s }[0], [x0] | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 4 | |
| %l1 = load <4 x float>, ptr %q | |
| %l2 = load float, ptr %p | |
| %s = shufflevector <4 x float> %l1, <4 x float> undef, <4 x i32> <i32 undef, i32 0, i32 1, i32 2> | |
| %ins = insertelement <4 x float> %s, float %l2, i32 0 | |
| ret <4 x float> %ins | |
| } | |
| define <4 x float> @insertf32_last(ptr %p) { | |
| ; CHECK-SD-LABEL: insertf32_last: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldur q0, [x0, #4] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: insertf32_last: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldr q0, [x0] | |
| ; CHECK-GI-NEXT: add x8, x0, #16 | |
| ; CHECK-GI-NEXT: ext v0.16b, v0.16b, v0.16b, #4 | |
| ; CHECK-GI-NEXT: ld1 { v0.s }[3], [x8] | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 16 | |
| %l1 = load <4 x float>, ptr %p | |
| %l2 = load float, ptr %q | |
| %s = shufflevector <4 x float> %l1, <4 x float> undef, <4 x i32> <i32 1, i32 2, i32 3, i32 undef> | |
| %ins = insertelement <4 x float> %s, float %l2, i32 3 | |
| ret <4 x float> %ins | |
| } | |
| define <2 x i64> @inserti64_first(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti64_first: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldr q0, [x0] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti64_first: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: add x8, x0, #8 | |
| ; CHECK-GI-NEXT: ld1r { v0.2d }, [x8] | |
| ; CHECK-GI-NEXT: ld1 { v0.d }[0], [x0] | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 8 | |
| %l1 = load <2 x i64>, ptr %q | |
| %l2 = load i64, ptr %p | |
| %s = shufflevector <2 x i64> %l1, <2 x i64> undef, <2 x i32> <i32 undef, i32 0> | |
| %ins = insertelement <2 x i64> %s, i64 %l2, i32 0 | |
| ret <2 x i64> %ins | |
| } | |
| define <2 x i64> @inserti64_last(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti64_last: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldur q0, [x0, #8] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti64_last: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldr q0, [x0] | |
| ; CHECK-GI-NEXT: add x8, x0, #16 | |
| ; CHECK-GI-NEXT: dup v0.2d, v0.d[1] | |
| ; CHECK-GI-NEXT: ld1 { v0.d }[1], [x8] | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 16 | |
| %l1 = load <2 x i64>, ptr %p | |
| %l2 = load i64, ptr %q | |
| %s = shufflevector <2 x i64> %l1, <2 x i64> undef, <2 x i32> <i32 1, i32 undef> | |
| %ins = insertelement <2 x i64> %s, i64 %l2, i32 1 | |
| ret <2 x i64> %ins | |
| } | |
| define <8 x i8> @inserti8_first_undef(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti8_first_undef: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldr d0, [x0] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti8_first_undef: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-GI-NEXT: ext v0.8b, v0.8b, v0.8b, #7 | |
| ; CHECK-GI-NEXT: ld1 { v0.b }[0], [x0] | |
| ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| %l1 = load <8 x i8>, ptr %q | |
| %l2 = load i8, ptr %p | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 undef, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 0 | |
| ret <8 x i8> %ins | |
| } | |
| define <8 x i8> @inserti8_last_undef(ptr %p) { | |
| ; CHECK-SD-LABEL: inserti8_last_undef: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: inserti8_last_undef: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldr d0, [x0] | |
| ; CHECK-GI-NEXT: add x8, x0, #8 | |
| ; CHECK-GI-NEXT: dup v0.8b, v0.b[1] | |
| ; CHECK-GI-NEXT: ld1 { v0.b }[7], [x8] | |
| ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 8 | |
| %l1 = load <8 x i8>, ptr %p | |
| %l2 = load i8, ptr %q | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 1, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 7 | |
| ret <8 x i8> %ins | |
| } | |
| define <8 x i16> @wrong_zextandsext(ptr %p) { | |
| ; CHECK-LABEL: wrong_zextandsext: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-NEXT: ldrsb w8, [x0] | |
| ; CHECK-NEXT: ushll v0.8h, v0.8b, #0 | |
| ; CHECK-NEXT: ext v0.16b, v0.16b, v0.16b, #14 | |
| ; CHECK-NEXT: mov v0.h[0], w8 | |
| ; CHECK-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| %l1 = load <8 x i8>, ptr %q | |
| %s1 = zext <8 x i8> %l1 to <8 x i16> | |
| %l2 = load i8, ptr %p | |
| %s2 = sext i8 %l2 to i16 | |
| %s = shufflevector <8 x i16> %s1, <8 x i16> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i16> %s, i16 %s2, i32 0 | |
| ret <8 x i16> %ins | |
| } | |
| define <8 x i8> @wrongidx_first(ptr %p) { | |
| ; CHECK-LABEL: wrongidx_first: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-NEXT: ext v0.8b, v0.8b, v0.8b, #7 | |
| ; CHECK-NEXT: ld1 { v0.b }[7], [x0] | |
| ; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| %l1 = load <8 x i8>, ptr %q | |
| %l2 = load i8, ptr %p | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 7 | |
| ret <8 x i8> %ins | |
| } | |
| define <8 x i8> @wrong_last(ptr %p) { | |
| ; CHECK-LABEL: wrong_last: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: ldr d0, [x0] | |
| ; CHECK-NEXT: add x8, x0, #8 | |
| ; CHECK-NEXT: ext v0.8b, v0.8b, v0.8b, #1 | |
| ; CHECK-NEXT: ld1 { v0.b }[0], [x8] | |
| ; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 8 | |
| %l1 = load <8 x i8>, ptr %p | |
| %l2 = load i8, ptr %q | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 0 | |
| ret <8 x i8> %ins | |
| } | |
| define <8 x i8> @wrong_shuffle(ptr %p) { | |
| ; CHECK-SD-LABEL: wrong_shuffle: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-SD-NEXT: adrp x8, .LCPI19_0 | |
| ; CHECK-SD-NEXT: ldr d1, [x8, :lo12:.LCPI19_0] | |
| ; CHECK-SD-NEXT: mov v0.d[1], v0.d[0] | |
| ; CHECK-SD-NEXT: tbl v0.8b, { v0.16b }, v1.8b | |
| ; CHECK-SD-NEXT: ld1 { v0.b }[0], [x0] | |
| ; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: wrong_shuffle: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-GI-NEXT: adrp x8, .LCPI19_0 | |
| ; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI19_0] | |
| ; CHECK-GI-NEXT: mov v0.d[1], v0.d[0] | |
| ; CHECK-GI-NEXT: tbl v0.16b, { v0.16b }, v1.16b | |
| ; CHECK-GI-NEXT: ld1 { v0.b }[0], [x0] | |
| ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| %l1 = load <8 x i8>, ptr %q | |
| %l2 = load i8, ptr %p | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 3, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 0 | |
| ret <8 x i8> %ins | |
| } | |
| define <8 x i16> @wrong_exttype(ptr %p) { | |
| ; CHECK-LABEL: wrong_exttype: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-NEXT: sshll v0.8h, v0.8b, #0 | |
| ; CHECK-NEXT: ext v0.16b, v0.16b, v0.16b, #14 | |
| ; CHECK-NEXT: ld1 { v0.h }[0], [x0] | |
| ; CHECK-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| %l1 = load <8 x i8>, ptr %q | |
| %s1 = sext <8 x i8> %l1 to <8 x i16> | |
| %l2 = load i16, ptr %p | |
| %s = shufflevector <8 x i16> %s1, <8 x i16> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i16> %s, i16 %l2, i32 0 | |
| ret <8 x i16> %ins | |
| } | |
| define <4 x i32> @wrong_exttype2(ptr %p) { | |
| ; CHECK-SD-LABEL: wrong_exttype2: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldur s0, [x0, #1] | |
| ; CHECK-SD-NEXT: ldrsh w8, [x0] | |
| ; CHECK-SD-NEXT: sshll v0.8h, v0.8b, #0 | |
| ; CHECK-SD-NEXT: sshll v0.4s, v0.4h, #0 | |
| ; CHECK-SD-NEXT: ext v0.16b, v0.16b, v0.16b, #12 | |
| ; CHECK-SD-NEXT: mov v0.s[0], w8 | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: wrong_exttype2: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldur w8, [x0, #1] | |
| ; CHECK-GI-NEXT: fmov s0, w8 | |
| ; CHECK-GI-NEXT: sxtb w8, w8 | |
| ; CHECK-GI-NEXT: mov b1, v0.b[2] | |
| ; CHECK-GI-NEXT: mov b2, v0.b[1] | |
| ; CHECK-GI-NEXT: mov b3, v0.b[3] | |
| ; CHECK-GI-NEXT: fmov s0, w8 | |
| ; CHECK-GI-NEXT: ldrsh w8, [x0] | |
| ; CHECK-GI-NEXT: fmov w9, s1 | |
| ; CHECK-GI-NEXT: fmov w10, s2 | |
| ; CHECK-GI-NEXT: fmov w11, s3 | |
| ; CHECK-GI-NEXT: sxtb w9, w9 | |
| ; CHECK-GI-NEXT: sxtb w10, w10 | |
| ; CHECK-GI-NEXT: sxtb w11, w11 | |
| ; CHECK-GI-NEXT: fmov s1, w9 | |
| ; CHECK-GI-NEXT: mov v0.h[1], w10 | |
| ; CHECK-GI-NEXT: mov v1.h[1], w11 | |
| ; CHECK-GI-NEXT: sshll v0.4s, v0.4h, #0 | |
| ; CHECK-GI-NEXT: sshll v1.4s, v1.4h, #0 | |
| ; CHECK-GI-NEXT: mov v0.d[1], v1.d[0] | |
| ; CHECK-GI-NEXT: ext v0.16b, v0.16b, v0.16b, #12 | |
| ; CHECK-GI-NEXT: mov v0.s[0], w8 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| %l1 = load <4 x i8>, ptr %q | |
| %s1 = sext <4 x i8> %l1 to <4 x i32> | |
| %l2 = load i16, ptr %p | |
| %s2 = sext i16 %l2 to i32 | |
| %s = shufflevector <4 x i32> %s1, <4 x i32> undef, <4 x i32> <i32 undef, i32 0, i32 1, i32 2> | |
| %ins = insertelement <4 x i32> %s, i32 %s2, i32 0 | |
| ret <4 x i32> %ins | |
| } | |
| define <8 x i8> @wrong_offsetfirst(ptr %p) { | |
| ; CHECK-LABEL: wrong_offsetfirst: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: ldur d0, [x0, #-1] | |
| ; CHECK-NEXT: ext v0.8b, v0.8b, v0.8b, #7 | |
| ; CHECK-NEXT: ld1 { v0.b }[0], [x0] | |
| ; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 -1 | |
| %l1 = load <8 x i8>, ptr %q | |
| %l2 = load i8, ptr %p | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 0 | |
| ret <8 x i8> %ins | |
| } | |
| define <8 x i8> @wrong_offsetlast(ptr %p) { | |
| ; CHECK-LABEL: wrong_offsetlast: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: ldr d0, [x0] | |
| ; CHECK-NEXT: add x8, x0, #7 | |
| ; CHECK-NEXT: ext v0.8b, v0.8b, v0.8b, #1 | |
| ; CHECK-NEXT: ld1 { v0.b }[7], [x8] | |
| ; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 7 | |
| %l1 = load <8 x i8>, ptr %p | |
| %l2 = load i8, ptr %q | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 undef> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 7 | |
| ret <8 x i8> %ins | |
| } | |
| define <8 x i8> @storebetween(ptr %p, ptr %r) { | |
| ; CHECK-LABEL: storebetween: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-NEXT: strb wzr, [x1] | |
| ; CHECK-NEXT: ext v0.8b, v0.8b, v0.8b, #7 | |
| ; CHECK-NEXT: ld1 { v0.b }[0], [x0] | |
| ; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| %l1 = load <8 x i8>, ptr %q | |
| store i8 0, ptr %r | |
| %l2 = load i8, ptr %p | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 0 | |
| ret <8 x i8> %ins | |
| } | |
| define <8 x i8> @storebefore(ptr %p, ptr %r) { | |
| ; CHECK-SD-LABEL: storebefore: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: strb wzr, [x1] | |
| ; CHECK-SD-NEXT: ldr d0, [x0] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: storebefore: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: strb wzr, [x1] | |
| ; CHECK-GI-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-GI-NEXT: ext v0.8b, v0.8b, v0.8b, #7 | |
| ; CHECK-GI-NEXT: ld1 { v0.b }[0], [x0] | |
| ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| store i8 0, ptr %r | |
| %l1 = load <8 x i8>, ptr %q | |
| %l2 = load i8, ptr %p | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 0 | |
| ret <8 x i8> %ins | |
| } | |
| define <8 x i8> @storeafter(ptr %p, ptr %r) { | |
| ; CHECK-SD-LABEL: storeafter: | |
| ; CHECK-SD: // %bb.0: | |
| ; CHECK-SD-NEXT: ldr d0, [x0] | |
| ; CHECK-SD-NEXT: strb wzr, [x1] | |
| ; CHECK-SD-NEXT: ret | |
| ; | |
| ; CHECK-GI-LABEL: storeafter: | |
| ; CHECK-GI: // %bb.0: | |
| ; CHECK-GI-NEXT: ldur d0, [x0, #1] | |
| ; CHECK-GI-NEXT: ldr b1, [x0] | |
| ; CHECK-GI-NEXT: strb wzr, [x1] | |
| ; CHECK-GI-NEXT: ext v0.8b, v0.8b, v0.8b, #7 | |
| ; CHECK-GI-NEXT: mov v0.b[0], v1.b[0] | |
| ; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0 | |
| ; CHECK-GI-NEXT: ret | |
| %q = getelementptr inbounds i8, ptr %p, i32 1 | |
| %l1 = load <8 x i8>, ptr %q | |
| %l2 = load i8, ptr %p | |
| store i8 0, ptr %r | |
| %s = shufflevector <8 x i8> %l1, <8 x i8> undef, <8 x i32> <i32 undef, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6> | |
| %ins = insertelement <8 x i8> %s, i8 %l2, i32 0 | |
| ret <8 x i8> %ins | |
| } |