; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 ; RUN: llc -mtriple=aarch64--linux-gnu -mattr=+sve < %s | FileCheck %s define @sload_nxv2i8(ptr %src) { ; CHECK-LABEL: sload_nxv2i8: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sb { z0.d }, p0/z, [x0] ; CHECK-NEXT: ret %load = load , ptr %src, align 1 %ext = sext %load to ret %ext } define @sload_nxv2i16(ptr %src) { ; CHECK-LABEL: sload_nxv2i16: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sh { z0.d }, p0/z, [x0] ; CHECK-NEXT: ret %load = load , ptr %src, align 2 %ext = sext %load to ret %ext } define @sload_nxv2i32(ptr %src) { ; CHECK-LABEL: sload_nxv2i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sw { z0.d }, p0/z, [x0] ; CHECK-NEXT: ret %load = load , ptr %src, align 4 %ext = sext %load to ret %ext } define @sload_nxv4i8(ptr %src) { ; CHECK-LABEL: sload_nxv4i8: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: ld1sb { z0.s }, p0/z, [x0] ; CHECK-NEXT: ret %load = load , ptr %src, align 1 %ext = sext %load to ret %ext } define @sload_nxv4i16(ptr %src) { ; CHECK-LABEL: sload_nxv4i16: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: ld1sh { z0.s }, p0/z, [x0] ; CHECK-NEXT: ret %load = load , ptr %src, align 2 %ext = sext %load to ret %ext } define @sload_nxv8i8(ptr %src) { ; CHECK-LABEL: sload_nxv8i8: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.h ; CHECK-NEXT: ld1sb { z0.h }, p0/z, [x0] ; CHECK-NEXT: ret %load = load , ptr %src, align 1 %ext = sext %load to ret %ext } ; Return type requires splitting define @sload_nxv8i16(ptr %a) { ; CHECK-LABEL: sload_nxv8i16: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sh { z0.d }, p0/z, [x0] ; CHECK-NEXT: ld1sh { z1.d }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ld1sh { z2.d }, p0/z, [x0, #2, mul vl] ; CHECK-NEXT: ld1sh { z3.d }, p0/z, [x0, #3, mul vl] ; CHECK-NEXT: ret %load = load , ptr %a, align 2 %ext = sext %load to ret %ext } define @sload_nxv8i8_nxv8i32(ptr %a) { ; CHECK-LABEL: sload_nxv8i8_nxv8i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: ld1sb { z0.s }, p0/z, [x0] ; CHECK-NEXT: ld1sb { z1.s }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ret %load = load , ptr %a, align 1 %ext = sext %load to ret %ext } ; load requires promotion define @sload_2i16_2f64(ptr noalias %in) { ; CHECK-LABEL: sload_2i16_2f64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sh { z0.d }, p0/z, [x0] ; CHECK-NEXT: ucvtf z0.d, p0/m, z0.s ; CHECK-NEXT: ret %load = load , ptr %in, align 2 %sext = sext %load to %res = uitofp %sext to ret %res } ; Extending loads from unpacked to wide illegal types define @sload_4i8_4i64(ptr %a) { ; CHECK-LABEL: sload_4i8_4i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sb { z0.d }, p0/z, [x0] ; CHECK-NEXT: ld1sb { z1.d }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ret %aval = load , ptr %a, align 1 %aext = sext %aval to ret %aext } define @sload_4i16_4i64(ptr %a) { ; CHECK-LABEL: sload_4i16_4i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sh { z0.d }, p0/z, [x0] ; CHECK-NEXT: ld1sh { z1.d }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ret %aval = load , ptr %a, align 2 %aext = sext %aval to ret %aext } define @sload_8i8_8i32(ptr %a) { ; CHECK-LABEL: sload_8i8_8i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: ld1sb { z0.s }, p0/z, [x0] ; CHECK-NEXT: ld1sb { z1.s }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ret %aval = load , ptr %a, align 1 %aext = sext %aval to ret %aext } define @sload_8i8_8i64(ptr %a) { ; CHECK-LABEL: sload_8i8_8i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sb { z0.d }, p0/z, [x0] ; CHECK-NEXT: ld1sb { z1.d }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ld1sb { z2.d }, p0/z, [x0, #2, mul vl] ; CHECK-NEXT: ld1sb { z3.d }, p0/z, [x0, #3, mul vl] ; CHECK-NEXT: ret %aval = load , ptr %a, align 1 %aext = sext %aval to ret %aext } define @sload_x2_4i8_4i64(ptr %a, ptr %b) { ; CHECK-LABEL: sload_x2_4i8_4i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sb { z1.d }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ld1sb { z0.d }, p0/z, [x0] ; CHECK-NEXT: ld1sb { z2.d }, p0/z, [x1, #1, mul vl] ; CHECK-NEXT: ld1sb { z3.d }, p0/z, [x1] ; CHECK-NEXT: add z1.d, z1.d, z2.d ; CHECK-NEXT: add z0.d, z0.d, z3.d ; CHECK-NEXT: ret %aval = load , ptr %a, align 1 %bval = load , ptr %b, align 1 %aext = sext %aval to %bext = sext %bval to %res = add %aext, %bext ret %res } define @sload_x2_4i16_4i64(ptr %a, ptr %b) { ; CHECK-LABEL: sload_x2_4i16_4i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sh { z1.d }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ld1sh { z0.d }, p0/z, [x0] ; CHECK-NEXT: ld1sh { z2.d }, p0/z, [x1, #1, mul vl] ; CHECK-NEXT: ld1sh { z3.d }, p0/z, [x1] ; CHECK-NEXT: add z1.d, z1.d, z2.d ; CHECK-NEXT: add z0.d, z0.d, z3.d ; CHECK-NEXT: ret %aval = load , ptr %a, align 2 %bval = load , ptr %b, align 2 %aext = sext %aval to %bext = sext %bval to %res = add %aext, %bext ret %res } define @sload_x2_8i8_8i32(ptr %a, ptr %b) { ; CHECK-LABEL: sload_x2_8i8_8i32: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: ld1sb { z1.s }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ld1sb { z0.s }, p0/z, [x0] ; CHECK-NEXT: ld1sb { z2.s }, p0/z, [x1, #1, mul vl] ; CHECK-NEXT: ld1sb { z3.s }, p0/z, [x1] ; CHECK-NEXT: add z1.s, z1.s, z2.s ; CHECK-NEXT: add z0.s, z0.s, z3.s ; CHECK-NEXT: ret %aval = load , ptr %a, align 1 %bval = load , ptr %b, align 1 %aext = sext %aval to %bext = sext %bval to %res = add %aext, %bext ret %res } define @sload_x2_8i8_8i64(ptr %a, ptr %b) { ; CHECK-LABEL: sload_x2_8i8_8i64: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sb { z3.d }, p0/z, [x0, #3, mul vl] ; CHECK-NEXT: ld1sb { z2.d }, p0/z, [x0, #2, mul vl] ; CHECK-NEXT: ld1sb { z1.d }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ld1sb { z0.d }, p0/z, [x0] ; CHECK-NEXT: ld1sb { z4.d }, p0/z, [x1] ; CHECK-NEXT: ld1sb { z5.d }, p0/z, [x1, #3, mul vl] ; CHECK-NEXT: ld1sb { z6.d }, p0/z, [x1, #2, mul vl] ; CHECK-NEXT: ld1sb { z7.d }, p0/z, [x1, #1, mul vl] ; CHECK-NEXT: add z0.d, z0.d, z4.d ; CHECK-NEXT: add z3.d, z3.d, z5.d ; CHECK-NEXT: add z1.d, z1.d, z7.d ; CHECK-NEXT: add z2.d, z2.d, z6.d ; CHECK-NEXT: ret %aval = load , ptr %a, align 1 %bval = load , ptr %b, align 1 %aext = sext %aval to %bext = sext %bval to %res = add %aext, %bext ret %res } define @load_frozen_before_sext(ptr %src) { ; CHECK-LABEL: load_frozen_before_sext: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1sb { z0.d }, p0/z, [x0] ; CHECK-NEXT: ret %load = load , ptr %src %load.frozen = freeze %load %ext = sext %load.frozen to ret %ext } define @load_frozen_before_sext_needs_splitting(ptr %src) { ; CHECK-LABEL: load_frozen_before_sext_needs_splitting: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.s ; CHECK-NEXT: ld1sb { z0.s }, p0/z, [x0] ; CHECK-NEXT: ld1sb { z1.s }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ret %load = load , ptr %src %load.frozen = freeze %load %ext = sext %load.frozen to ret %ext } ; A multi-use freeze in this example effectively means the load is also multi-use. define @load_frozen_before_sext_multiuse(ptr %src) { ; CHECK-LABEL: load_frozen_before_sext_multiuse: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1b { z1.d }, p0/z, [x0] ; CHECK-NEXT: movprfx z0, z1 ; CHECK-NEXT: sxtb z0.d, p0/m, z1.d ; CHECK-NEXT: // fake_use: $z1 ; CHECK-NEXT: ret %load = load , ptr %src, align 1 %load.frozen = freeze %load %ext = sext %load.frozen to call void (...) @llvm.fake.use( %load.frozen) ret %ext } ; In this example the freeze is used twice and the load used once. define @load_frozen_before_sext_multiuse2(ptr %src) { ; CHECK-LABEL: load_frozen_before_sext_multiuse2: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1b { z0.d }, p0/z, [x0] ; CHECK-NEXT: movprfx z1, z0 ; CHECK-NEXT: mul z1.d, z1.d, #13 ; CHECK-NEXT: sxtb z0.d, p0/m, z0.d ; CHECK-NEXT: and z1.d, z1.d, #0xff ; CHECK-NEXT: add z0.d, z0.d, z1.d ; CHECK-NEXT: ret %load = load , ptr %src, align 1 %load.frozen = freeze %load %ext = sext %load.frozen to %mul = mul %load.frozen, splat (i8 13) %mul.ext = zext %mul to %res = add %ext, %mul.ext ret %res } ; In this example the freeze is used 3 times and the load used twice via the chain. define @load_frozen_before_sext_multiuse3(ptr %src, ptr %dst1, ptr %dst2) { ; CHECK-LABEL: load_frozen_before_sext_multiuse3: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: ld1b { z0.d }, p0/z, [x0] ; CHECK-NEXT: movprfx z1, z0 ; CHECK-NEXT: and z1.d, z1.d, #0xff ; CHECK-NEXT: sxtb z0.d, p0/m, z0.d ; CHECK-NEXT: movprfx z2, z1 ; CHECK-NEXT: mul z2.d, z2.d, #49 ; CHECK-NEXT: mul z1.d, z1.d, #33 ; CHECK-NEXT: add z0.d, z0.d, z2.d ; CHECK-NEXT: st1w { z1.d }, p0, [x1] ; CHECK-NEXT: st1h { z2.d }, p0, [x2] ; CHECK-NEXT: ret %load = load , ptr %src, align 1 %load.frozen = freeze %load %sext64 = sext %load.frozen to %zext32 = zext %load.frozen to %zext16 = zext %load.frozen to %mul32 = mul %zext32, splat (i32 33) %mul16 = mul %zext16, splat (i16 49) store %mul32, ptr %dst1, align 4 store %mul16, ptr %dst2, align 2 %mul32.ext64 = sext %mul16 to %res = add %sext64, %mul32.ext64 ret %res } ; In this example the freeze is used twice - once for the sign-extend and ; once for the icmp (or SETCC) define @load_frozen_before_sext_multiuse4(ptr %src1, ptr %src2, ptr %dst1) { ; CHECK-LABEL: load_frozen_before_sext_multiuse4: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov w8, #1234 // =0x4d2 ; CHECK-NEXT: mov z3.d, #27 // =0x1b ; CHECK-NEXT: ld1b { z0.d }, p0/z, [x0] ; CHECK-NEXT: ld1b { z2.d }, p0/z, [x1] ; CHECK-NEXT: movprfx z1, z0 ; CHECK-NEXT: and z1.d, z1.d, #0xff ; CHECK-NEXT: sxtb z0.d, p0/m, z0.d ; CHECK-NEXT: cmpeq p1.d, p0/z, z1.d, #3 ; CHECK-NEXT: mov z1.d, x8 ; CHECK-NEXT: add z0.d, z0.d, z1.d ; CHECK-NEXT: sel z1.d, p1, z2.d, z3.d ; CHECK-NEXT: st1b { z1.d }, p0, [x2] ; CHECK-NEXT: ret %load = load , ptr %src1, align 1 %load.frozen = freeze %load %sext64 = sext %load.frozen to %cmp = icmp eq %load.frozen, splat (i8 3) %load2 = load , ptr %src2, align 1 %sel = select %cmp, %load2, splat (i8 27) store %sel, ptr %dst1, align 1 %res = add %sext64, splat (i64 1234) ret %res } ; In the following 3 variants is one use of the freeze, and there are ; multiple uses of the load via the chain. Each variant tests a different ; case: ; 1. Dest type is illegal, source is legal. ; 2. Dest type is legal, source is illegal. ; 3. Both dest and source types are illegal.o define @load_frozen_before_zext_multiuse5_dst_illegal(ptr %src, ptr %dst) { ; CHECK-LABEL: load_frozen_before_zext_multiuse5_dst_illegal: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov z24.d, #3 // =0x3 ; CHECK-NEXT: ld1sb { z0.d }, p0/z, [x0] ; CHECK-NEXT: ld1sb { z1.d }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: ld1sb { z2.d }, p0/z, [x0, #2, mul vl] ; CHECK-NEXT: ld1sb { z3.d }, p0/z, [x0, #3, mul vl] ; CHECK-NEXT: ld1sb { z4.d }, p0/z, [x0, #4, mul vl] ; CHECK-NEXT: ld1sb { z5.d }, p0/z, [x0, #5, mul vl] ; CHECK-NEXT: ld1sb { z6.d }, p0/z, [x0, #6, mul vl] ; CHECK-NEXT: ld1sb { z7.d }, p0/z, [x0, #7, mul vl] ; CHECK-NEXT: str z24, [x1, #6, mul vl] ; CHECK-NEXT: str z24, [x1, #7, mul vl] ; CHECK-NEXT: str z24, [x1, #4, mul vl] ; CHECK-NEXT: str z24, [x1, #5, mul vl] ; CHECK-NEXT: str z24, [x1, #2, mul vl] ; CHECK-NEXT: str z24, [x1, #3, mul vl] ; CHECK-NEXT: str z24, [x1] ; CHECK-NEXT: str z24, [x1, #1, mul vl] ; CHECK-NEXT: ret %load = load , ptr %src, align 1 %load.frozen = freeze %load %ext = sext %load.frozen to store splat (i64 3), ptr %dst, align 8 ret %ext } define @load_frozen_before_sext_multiuse5_src_illegal(ptr %src, ptr %dst) { ; CHECK-LABEL: load_frozen_before_sext_multiuse5_src_illegal: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov z1.d, #3 // =0x3 ; CHECK-NEXT: ld1sb { z0.d }, p0/z, [x0] ; CHECK-NEXT: str z1, [x1] ; CHECK-NEXT: ret %load = load , ptr %src, align 1 %load.frozen = freeze %load %ext = sext %load.frozen to store splat (i64 3), ptr %dst, align 8 ret %ext } define @load_frozen_before_sext_multiuse5_both_illegal(ptr %src, ptr %dst) { ; CHECK-LABEL: load_frozen_before_sext_multiuse5_both_illegal: ; CHECK: // %bb.0: ; CHECK-NEXT: ptrue p0.d ; CHECK-NEXT: mov z2.d, #3 // =0x3 ; CHECK-NEXT: ld1sb { z0.d }, p0/z, [x0] ; CHECK-NEXT: ld1sb { z1.d }, p0/z, [x0, #1, mul vl] ; CHECK-NEXT: str z2, [x1, #1, mul vl] ; CHECK-NEXT: str z2, [x1] ; CHECK-NEXT: ret %load = load , ptr %src, align 1 %load.frozen = freeze %load %ext = sext %load.frozen to store splat (i64 3), ptr %dst, align 8 ret %ext }