320 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve2 < %s | FileCheck %s3 4define void @add_lshr_rshrnb_b_6(ptr %ptr, ptr %dst, i64 %index){5; CHECK-LABEL: add_lshr_rshrnb_b_6:6; CHECK: // %bb.0:7; CHECK-NEXT: ldr z0, [x0]8; CHECK-NEXT: ptrue p0.h9; CHECK-NEXT: rshrnb z0.b, z0.h, #610; CHECK-NEXT: st1b { z0.h }, p0, [x1, x2]11; CHECK-NEXT: ret12 %load = load <vscale x 8 x i16>, ptr %ptr, align 213 %1 = add <vscale x 8 x i16> %load, trunc (<vscale x 8 x i32> splat (i32 32) to <vscale x 8 x i16>)14 %2 = lshr <vscale x 8 x i16> %1, trunc (<vscale x 8 x i32> splat (i32 6) to <vscale x 8 x i16>)15 %3 = trunc <vscale x 8 x i16> %2 to <vscale x 8 x i8>16 %4 = getelementptr inbounds i8, ptr %dst, i64 %index17 store <vscale x 8 x i8> %3, ptr %4, align 118 ret void19}20 21define void @neg_add_lshr_rshrnb_b_6(ptr %ptr, ptr %dst, i64 %index){22; CHECK-LABEL: neg_add_lshr_rshrnb_b_6:23; CHECK: // %bb.0:24; CHECK-NEXT: ldr z0, [x0]25; CHECK-NEXT: ptrue p0.h26; CHECK-NEXT: add z0.h, z0.h, #1 // =0x127; CHECK-NEXT: lsr z0.h, z0.h, #628; CHECK-NEXT: st1b { z0.h }, p0, [x1, x2]29; CHECK-NEXT: ret30 %load = load <vscale x 8 x i16>, ptr %ptr, align 231 %1 = add <vscale x 8 x i16> %load, trunc (<vscale x 8 x i32> splat (i32 1) to <vscale x 8 x i16>)32 %2 = lshr <vscale x 8 x i16> %1, trunc (<vscale x 8 x i32> splat (i32 6) to <vscale x 8 x i16>)33 %3 = trunc <vscale x 8 x i16> %2 to <vscale x 8 x i8>34 %4 = getelementptr inbounds i8, ptr %dst, i64 %index35 store <vscale x 8 x i8> %3, ptr %4, align 136 ret void37}38 39define void @add_lshr_rshrnb_h_7(ptr %ptr, ptr %dst, i64 %index){40; CHECK-LABEL: add_lshr_rshrnb_h_7:41; CHECK: // %bb.0:42; CHECK-NEXT: ldr z0, [x0]43; CHECK-NEXT: ptrue p0.h44; CHECK-NEXT: rshrnb z0.b, z0.h, #745; CHECK-NEXT: st1b { z0.h }, p0, [x1, x2]46; CHECK-NEXT: ret47 %load = load <vscale x 8 x i16>, ptr %ptr, align 248 %1 = add <vscale x 8 x i16> %load, trunc (<vscale x 8 x i32> splat (i32 64) to <vscale x 8 x i16>)49 %2 = lshr <vscale x 8 x i16> %1, trunc (<vscale x 8 x i32> splat (i32 7) to <vscale x 8 x i16>)50 %3 = trunc <vscale x 8 x i16> %2 to <vscale x 8 x i8>51 %4 = getelementptr inbounds i8, ptr %dst, i64 %index52 store <vscale x 8 x i8> %3, ptr %4, align 153 ret void54}55 56define void @add_lshr_rshrn_h_6(ptr %ptr, ptr %dst, i64 %index){57; CHECK-LABEL: add_lshr_rshrn_h_6:58; CHECK: // %bb.0:59; CHECK-NEXT: ldr z0, [x0]60; CHECK-NEXT: ptrue p0.s61; CHECK-NEXT: rshrnb z0.h, z0.s, #662; CHECK-NEXT: st1h { z0.s }, p0, [x1, x2, lsl #1]63; CHECK-NEXT: ret64 %load = load <vscale x 4 x i32>, ptr %ptr, align 265 %1 = add <vscale x 4 x i32> %load, trunc (<vscale x 4 x i64> splat (i64 32) to <vscale x 4 x i32>)66 %2 = lshr <vscale x 4 x i32> %1, trunc (<vscale x 4 x i64> splat (i64 6) to <vscale x 4 x i32>)67 %3 = trunc <vscale x 4 x i32> %2 to <vscale x 4 x i16>68 %4 = getelementptr inbounds i16, ptr %dst, i64 %index69 store <vscale x 4 x i16> %3, ptr %4, align 170 ret void71}72 73define void @add_lshr_rshrnb_h_2(ptr %ptr, ptr %dst, i64 %index){74; CHECK-LABEL: add_lshr_rshrnb_h_2:75; CHECK: // %bb.0:76; CHECK-NEXT: ldr z0, [x0]77; CHECK-NEXT: ptrue p0.s78; CHECK-NEXT: rshrnb z0.h, z0.s, #279; CHECK-NEXT: st1h { z0.s }, p0, [x1, x2, lsl #1]80; CHECK-NEXT: ret81 %load = load <vscale x 4 x i32>, ptr %ptr, align 282 %1 = add <vscale x 4 x i32> %load, trunc (<vscale x 4 x i64> splat (i64 2) to <vscale x 4 x i32>)83 %2 = lshr <vscale x 4 x i32> %1, trunc (<vscale x 4 x i64> splat (i64 2) to <vscale x 4 x i32>)84 %3 = trunc <vscale x 4 x i32> %2 to <vscale x 4 x i16>85 %4 = getelementptr inbounds i16, ptr %dst, i64 %index86 store <vscale x 4 x i16> %3, ptr %4, align 187 ret void88}89 90define void @neg_add_lshr_rshrnb_h_0(ptr %ptr, ptr %dst, i64 %index){91; CHECK-LABEL: neg_add_lshr_rshrnb_h_0:92; CHECK: // %bb.0:93; CHECK-NEXT: ret94 %load = load <vscale x 4 x i32>, ptr %ptr, align 295 %1 = add <vscale x 4 x i32> %load, trunc (<vscale x 4 x i64> splat (i64 1) to <vscale x 4 x i32>)96 %2 = lshr <vscale x 4 x i32> %1, trunc (<vscale x 4 x i64> splat (i64 -1) to <vscale x 4 x i32>)97 %3 = trunc <vscale x 4 x i32> %2 to <vscale x 4 x i16>98 %4 = getelementptr inbounds i16, ptr %dst, i64 %index99 store <vscale x 4 x i16> %3, ptr %4, align 1100 ret void101}102 103define void @neg_zero_shift(ptr %ptr, ptr %dst, i64 %index){104; CHECK-LABEL: neg_zero_shift:105; CHECK: // %bb.0:106; CHECK-NEXT: ldr z0, [x0]107; CHECK-NEXT: ptrue p0.s108; CHECK-NEXT: add z0.s, z0.s, #1 // =0x1109; CHECK-NEXT: st1h { z0.s }, p0, [x1, x2, lsl #1]110; CHECK-NEXT: ret111 %load = load <vscale x 4 x i32>, ptr %ptr, align 2112 %1 = add <vscale x 4 x i32> %load, trunc (<vscale x 4 x i64> splat (i64 1) to <vscale x 4 x i32>)113 %2 = lshr <vscale x 4 x i32> %1, trunc (<vscale x 4 x i64> splat (i64 0) to <vscale x 4 x i32>)114 %3 = trunc <vscale x 4 x i32> %2 to <vscale x 4 x i16>115 %4 = getelementptr inbounds i16, ptr %dst, i64 %index116 store <vscale x 4 x i16> %3, ptr %4, align 1117 ret void118}119 120define void @wide_add_shift_add_rshrnb_b(ptr %dest, i64 %index, <vscale x 16 x i16> %arg1){121; CHECK-LABEL: wide_add_shift_add_rshrnb_b:122; CHECK: // %bb.0:123; CHECK-NEXT: rshrnb z1.b, z1.h, #6124; CHECK-NEXT: rshrnb z0.b, z0.h, #6125; CHECK-NEXT: ptrue p0.b126; CHECK-NEXT: ld1b { z2.b }, p0/z, [x0, x1]127; CHECK-NEXT: uzp1 z0.b, z0.b, z1.b128; CHECK-NEXT: add z0.b, z2.b, z0.b129; CHECK-NEXT: st1b { z0.b }, p0, [x0, x1]130; CHECK-NEXT: ret131 %1 = add <vscale x 16 x i16> %arg1, splat (i16 32)132 %2 = lshr <vscale x 16 x i16> %1, splat (i16 6)133 %3 = getelementptr inbounds i8, ptr %dest, i64 %index134 %load = load <vscale x 16 x i8>, ptr %3, align 2135 %4 = trunc <vscale x 16 x i16> %2 to <vscale x 16 x i8>136 %5 = add <vscale x 16 x i8> %load, %4137 store <vscale x 16 x i8> %5, ptr %3, align 2138 ret void139}140 141define void @wide_add_shift_add_rshrnb_h(ptr %dest, i64 %index, <vscale x 8 x i32> %arg1){142; CHECK-LABEL: wide_add_shift_add_rshrnb_h:143; CHECK: // %bb.0:144; CHECK-NEXT: rshrnb z1.h, z1.s, #6145; CHECK-NEXT: rshrnb z0.h, z0.s, #6146; CHECK-NEXT: ptrue p0.h147; CHECK-NEXT: ld1h { z2.h }, p0/z, [x0, x1, lsl #1]148; CHECK-NEXT: uzp1 z0.h, z0.h, z1.h149; CHECK-NEXT: add z0.h, z2.h, z0.h150; CHECK-NEXT: st1h { z0.h }, p0, [x0, x1, lsl #1]151; CHECK-NEXT: ret152 %1 = add <vscale x 8 x i32> %arg1, splat (i32 32)153 %2 = lshr <vscale x 8 x i32> %1, splat (i32 6)154 %3 = getelementptr inbounds i16, ptr %dest, i64 %index155 %load = load <vscale x 8 x i16>, ptr %3, align 2156 %4 = trunc <vscale x 8 x i32> %2 to <vscale x 8 x i16>157 %5 = add <vscale x 8 x i16> %load, %4158 store <vscale x 8 x i16> %5, ptr %3, align 2159 ret void160}161 162define void @wide_add_shift_add_rshrnb_d(ptr %dest, i64 %index, <vscale x 4 x i64> %arg1){163; CHECK-LABEL: wide_add_shift_add_rshrnb_d:164; CHECK: // %bb.0:165; CHECK-NEXT: rshrnb z1.s, z1.d, #32166; CHECK-NEXT: rshrnb z0.s, z0.d, #32167; CHECK-NEXT: ptrue p0.s168; CHECK-NEXT: ld1w { z2.s }, p0/z, [x0, x1, lsl #2]169; CHECK-NEXT: uzp1 z0.s, z0.s, z1.s170; CHECK-NEXT: add z0.s, z2.s, z0.s171; CHECK-NEXT: st1w { z0.s }, p0, [x0, x1, lsl #2]172; CHECK-NEXT: ret173 %1 = add <vscale x 4 x i64> %arg1, splat (i64 2147483648)174 %2 = lshr <vscale x 4 x i64> %1, splat (i64 32)175 %3 = getelementptr inbounds i32, ptr %dest, i64 %index176 %load = load <vscale x 4 x i32>, ptr %3, align 4177 %4 = trunc <vscale x 4 x i64> %2 to <vscale x 4 x i32>178 %5 = add <vscale x 4 x i32> %load, %4179 store <vscale x 4 x i32> %5, ptr %3, align 4180 ret void181}182 183; Do not emit rshrnb if the shift amount is larger than the dest eltsize in bits184define void @neg_wide_add_shift_add_rshrnb_d(ptr %dest, i64 %index, <vscale x 4 x i64> %arg1){185; CHECK-LABEL: neg_wide_add_shift_add_rshrnb_d:186; CHECK: // %bb.0:187; CHECK-NEXT: mov z2.d, #0x800000000000188; CHECK-NEXT: ptrue p0.s189; CHECK-NEXT: add z0.d, z0.d, z2.d190; CHECK-NEXT: add z1.d, z1.d, z2.d191; CHECK-NEXT: ld1w { z2.s }, p0/z, [x0, x1, lsl #2]192; CHECK-NEXT: lsr z1.d, z1.d, #48193; CHECK-NEXT: lsr z0.d, z0.d, #48194; CHECK-NEXT: uzp1 z0.s, z0.s, z1.s195; CHECK-NEXT: add z0.s, z2.s, z0.s196; CHECK-NEXT: st1w { z0.s }, p0, [x0, x1, lsl #2]197; CHECK-NEXT: ret198 %1 = add <vscale x 4 x i64> %arg1, splat (i64 140737488355328)199 %2 = lshr <vscale x 4 x i64> %1, splat (i64 48)200 %3 = getelementptr inbounds i32, ptr %dest, i64 %index201 %load = load <vscale x 4 x i32>, ptr %3, align 4202 %4 = trunc <vscale x 4 x i64> %2 to <vscale x 4 x i32>203 %5 = add <vscale x 4 x i32> %load, %4204 store <vscale x 4 x i32> %5, ptr %3, align 4205 ret void206}207 208define void @neg_trunc_lsr_add_op1_not_splat(ptr %ptr, ptr %dst, i64 %index, <vscale x 8 x i16> %add_op1){209; CHECK-LABEL: neg_trunc_lsr_add_op1_not_splat:210; CHECK: // %bb.0:211; CHECK-NEXT: ldr z1, [x0]212; CHECK-NEXT: ptrue p0.h213; CHECK-NEXT: add z0.h, z1.h, z0.h214; CHECK-NEXT: lsr z0.h, z0.h, #6215; CHECK-NEXT: st1b { z0.h }, p0, [x1, x2]216; CHECK-NEXT: ret217 %load = load <vscale x 8 x i16>, ptr %ptr, align 2218 %1 = add <vscale x 8 x i16> %load, %add_op1219 %2 = lshr <vscale x 8 x i16> %1, splat (i16 6)220 %3 = trunc <vscale x 8 x i16> %2 to <vscale x 8 x i8>221 %4 = getelementptr inbounds i8, ptr %dst, i64 %index222 store <vscale x 8 x i8> %3, ptr %4, align 1223 ret void224}225 226define void @neg_trunc_lsr_op1_not_splat(ptr %ptr, ptr %dst, i64 %index, <vscale x 8 x i16> %lshr_op1){227; CHECK-LABEL: neg_trunc_lsr_op1_not_splat:228; CHECK: // %bb.0:229; CHECK-NEXT: ldr z1, [x0]230; CHECK-NEXT: ptrue p0.h231; CHECK-NEXT: add z1.h, z1.h, #32 // =0x20232; CHECK-NEXT: lsrr z0.h, p0/m, z0.h, z1.h233; CHECK-NEXT: st1b { z0.h }, p0, [x1, x2]234; CHECK-NEXT: ret235 %load = load <vscale x 8 x i16>, ptr %ptr, align 2236 %1 = add <vscale x 8 x i16> %load, splat (i16 32)237 %2 = lshr <vscale x 8 x i16> %1, %lshr_op1238 %3 = trunc <vscale x 8 x i16> %2 to <vscale x 8 x i8>239 %4 = getelementptr inbounds i8, ptr %dst, i64 %index240 store <vscale x 8 x i8> %3, ptr %4, align 1241 ret void242}243 244define void @neg_add_has_two_uses(ptr %ptr, ptr %dst, ptr %dst2, i64 %index){245; CHECK-LABEL: neg_add_has_two_uses:246; CHECK: // %bb.0:247; CHECK-NEXT: ldr z0, [x0]248; CHECK-NEXT: ptrue p0.h249; CHECK-NEXT: add z0.h, z0.h, #32 // =0x20250; CHECK-NEXT: add z1.h, z0.h, z0.h251; CHECK-NEXT: lsr z0.h, z0.h, #6252; CHECK-NEXT: st1h { z1.h }, p0, [x2, x3, lsl #1]253; CHECK-NEXT: st1b { z0.h }, p0, [x1, x3]254; CHECK-NEXT: ret255 %load = load <vscale x 8 x i16>, ptr %ptr, align 2256 %1 = add <vscale x 8 x i16> %load, trunc (<vscale x 8 x i32> splat (i32 32) to <vscale x 8 x i16>)257 %2 = lshr <vscale x 8 x i16> %1, trunc (<vscale x 8 x i32> splat (i32 6) to <vscale x 8 x i16>)258 %3 = add <vscale x 8 x i16> %1, %1259 %4 = getelementptr inbounds i16, ptr %dst2, i64 %index260 %5 = trunc <vscale x 8 x i16> %2 to <vscale x 8 x i8>261 %6 = getelementptr inbounds i8, ptr %dst, i64 %index262 store <vscale x 8 x i16> %3, ptr %4, align 1263 store <vscale x 8 x i8> %5, ptr %6, align 1264 ret void265}266 267define void @add_lshr_rshrnb_s(ptr %ptr, ptr %dst, i64 %index){268; CHECK-LABEL: add_lshr_rshrnb_s:269; CHECK: // %bb.0:270; CHECK-NEXT: ldr z0, [x0]271; CHECK-NEXT: ptrue p0.d272; CHECK-NEXT: rshrnb z0.s, z0.d, #6273; CHECK-NEXT: st1w { z0.d }, p0, [x1, x2, lsl #2]274; CHECK-NEXT: ret275 %load = load <vscale x 2 x i64>, ptr %ptr, align 2276 %1 = add <vscale x 2 x i64> %load, splat (i64 32)277 %2 = lshr <vscale x 2 x i64> %1, splat (i64 6)278 %3 = trunc <vscale x 2 x i64> %2 to <vscale x 2 x i32>279 %4 = getelementptr inbounds i32, ptr %dst, i64 %index280 store <vscale x 2 x i32> %3, ptr %4, align 1281 ret void282}283 284define void @neg_add_lshr_rshrnb_s(ptr %ptr, ptr %dst, i64 %index){285; CHECK-LABEL: neg_add_lshr_rshrnb_s:286; CHECK: // %bb.0:287; CHECK-NEXT: ldr z0, [x0]288; CHECK-NEXT: ptrue p0.d289; CHECK-NEXT: add z0.d, z0.d, #32 // =0x20290; CHECK-NEXT: lsr z0.d, z0.d, #6291; CHECK-NEXT: st1h { z0.d }, p0, [x1, x2, lsl #1]292; CHECK-NEXT: ret293 %load = load <vscale x 2 x i64>, ptr %ptr, align 2294 %1 = add <vscale x 2 x i64> %load, splat (i64 32)295 %2 = lshr <vscale x 2 x i64> %1, splat (i64 6)296 %3 = trunc <vscale x 2 x i64> %2 to <vscale x 2 x i16>297 %4 = getelementptr inbounds i16, ptr %dst, i64 %index298 store <vscale x 2 x i16> %3, ptr %4, align 1299 ret void300}301 302define void @masked_store_rshrnb(ptr %ptr, ptr %dst, i64 %index, <vscale x 8 x i1> %mask) { ; preds = %vector.body, %vector.ph303; CHECK-LABEL: masked_store_rshrnb:304; CHECK: // %bb.0:305; CHECK-NEXT: ld1h { z0.h }, p0/z, [x0]306; CHECK-NEXT: rshrnb z0.b, z0.h, #6307; CHECK-NEXT: st1b { z0.h }, p0, [x1, x2]308; CHECK-NEXT: ret309 %wide.masked.load = tail call <vscale x 8 x i16> @llvm.masked.load.nxv8i16.p0(ptr %ptr, i32 2, <vscale x 8 x i1> %mask, <vscale x 8 x i16> poison)310 %1 = add <vscale x 8 x i16> %wide.masked.load, trunc (<vscale x 8 x i32> splat (i32 32) to <vscale x 8 x i16>)311 %2 = lshr <vscale x 8 x i16> %1, trunc (<vscale x 8 x i32> splat (i32 6) to <vscale x 8 x i16>)312 %3 = trunc <vscale x 8 x i16> %2 to <vscale x 8 x i8>313 %4 = getelementptr inbounds i8, ptr %dst, i64 %index314 tail call void @llvm.masked.store.nxv8i8.p0(<vscale x 8 x i8> %3, ptr %4, i32 1, <vscale x 8 x i1> %mask)315 ret void316}317 318declare void @llvm.masked.store.nxv8i8.p0(<vscale x 8 x i8>, ptr, i32, <vscale x 8 x i1>)319declare <vscale x 8 x i16> @llvm.masked.load.nxv8i16.p0(ptr, i32, <vscale x 8 x i1>, <vscale x 8 x i16>)320