Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / AArch64 / sve2-intrinsics-combine-rshrnb.ll
blob82078ad63d66b3fff71d071a6076c3d27959548f
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve2 < %s | FileCheck %s
4 define 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:    ptrue p0.h
8 ; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
9 ; CHECK-NEXT:    rshrnb z0.b, z0.h, #6
10 ; CHECK-NEXT:    st1b { z0.h }, p0, [x1, x2]
11 ; CHECK-NEXT:    ret
12   %load = load <vscale x 8 x i16>, ptr %ptr, align 2
13   %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 %index
17   store <vscale x 8 x i8> %3, ptr %4, align 1
18   ret void
21 define 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:    ptrue p0.h
25 ; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
26 ; CHECK-NEXT:    add z0.h, z0.h, #1 // =0x1
27 ; CHECK-NEXT:    lsr z0.h, z0.h, #6
28 ; CHECK-NEXT:    st1b { z0.h }, p0, [x1, x2]
29 ; CHECK-NEXT:    ret
30   %load = load <vscale x 8 x i16>, ptr %ptr, align 2
31   %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 %index
35   store <vscale x 8 x i8> %3, ptr %4, align 1
36   ret void
39 define 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:    ptrue p0.h
43 ; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
44 ; CHECK-NEXT:    rshrnb z0.b, z0.h, #7
45 ; CHECK-NEXT:    st1b { z0.h }, p0, [x1, x2]
46 ; CHECK-NEXT:    ret
47   %load = load <vscale x 8 x i16>, ptr %ptr, align 2
48   %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 %index
52   store <vscale x 8 x i8> %3, ptr %4, align 1
53   ret void
56 define 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:    ptrue p0.s
60 ; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
61 ; CHECK-NEXT:    rshrnb z0.h, z0.s, #6
62 ; CHECK-NEXT:    st1h { z0.s }, p0, [x1, x2, lsl #1]
63 ; CHECK-NEXT:    ret
64   %load = load <vscale x 4 x i32>, ptr %ptr, align 2
65   %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 %index
69   store <vscale x 4 x i16> %3, ptr %4, align 1
70   ret void
73 define 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:    ptrue p0.s
77 ; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
78 ; CHECK-NEXT:    rshrnb z0.h, z0.s, #2
79 ; CHECK-NEXT:    st1h { z0.s }, p0, [x1, x2, lsl #1]
80 ; CHECK-NEXT:    ret
81   %load = load <vscale x 4 x i32>, ptr %ptr, align 2
82   %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 %index
86   store <vscale x 4 x i16> %3, ptr %4, align 1
87   ret void
90 define 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:    ret
94   %load = load <vscale x 4 x i32>, ptr %ptr, align 2
95   %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 %index
99   store <vscale x 4 x i16> %3, ptr %4, align 1
100   ret void
103 define void @neg_zero_shift(ptr %ptr, ptr %dst, i64 %index){
104 ; CHECK-LABEL: neg_zero_shift:
105 ; CHECK:       // %bb.0:
106 ; CHECK-NEXT:    ptrue p0.s
107 ; CHECK-NEXT:    ld1w { z0.s }, p0/z, [x0]
108 ; CHECK-NEXT:    add z0.s, z0.s, #1 // =0x1
109 ; CHECK-NEXT:    st1h { z0.s }, p0, [x1, x2, lsl #1]
110 ; CHECK-NEXT:    ret
111   %load = load <vscale x 4 x i32>, ptr %ptr, align 2
112   %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 %index
116   store <vscale x 4 x i16> %3, ptr %4, align 1
117   ret void
120 define 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, #6
124 ; CHECK-NEXT:    rshrnb z0.b, z0.h, #6
125 ; CHECK-NEXT:    ptrue p0.b
126 ; CHECK-NEXT:    ld1b { z2.b }, p0/z, [x0, x1]
127 ; CHECK-NEXT:    uzp1 z0.b, z0.b, z1.b
128 ; CHECK-NEXT:    add z0.b, z2.b, z0.b
129 ; CHECK-NEXT:    st1b { z0.b }, p0, [x0, x1]
130 ; CHECK-NEXT:    ret
131   %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 %index
134   %load = load <vscale x 16 x i8>, ptr %3, align 2
135   %4 = trunc <vscale x 16 x i16> %2 to <vscale x 16 x i8>
136   %5 = add <vscale x 16 x i8> %load, %4
137   store <vscale x 16 x i8> %5, ptr %3, align 2
138   ret void
141 define 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, #6
145 ; CHECK-NEXT:    rshrnb z0.h, z0.s, #6
146 ; CHECK-NEXT:    ptrue p0.h
147 ; CHECK-NEXT:    ld1h { z2.h }, p0/z, [x0, x1, lsl #1]
148 ; CHECK-NEXT:    uzp1 z0.h, z0.h, z1.h
149 ; CHECK-NEXT:    add z0.h, z2.h, z0.h
150 ; CHECK-NEXT:    st1h { z0.h }, p0, [x0, x1, lsl #1]
151 ; CHECK-NEXT:    ret
152   %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 %index
155   %load = load <vscale x 8 x i16>, ptr %3, align 2
156   %4 = trunc <vscale x 8 x i32> %2 to <vscale x 8 x i16>
157   %5 = add <vscale x 8 x i16> %load, %4
158   store <vscale x 8 x i16> %5, ptr %3, align 2
159   ret void
162 define 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, #32
166 ; CHECK-NEXT:    rshrnb z0.s, z0.d, #32
167 ; CHECK-NEXT:    ptrue p0.s
168 ; CHECK-NEXT:    ld1w { z2.s }, p0/z, [x0, x1, lsl #2]
169 ; CHECK-NEXT:    uzp1 z0.s, z0.s, z1.s
170 ; CHECK-NEXT:    add z0.s, z2.s, z0.s
171 ; CHECK-NEXT:    st1w { z0.s }, p0, [x0, x1, lsl #2]
172 ; CHECK-NEXT:    ret
173   %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 %index
176   %load = load <vscale x 4 x i32>, ptr %3, align 4
177   %4 = trunc <vscale x 4 x i64> %2 to <vscale x 4 x i32>
178   %5 = add <vscale x 4 x i32> %load, %4
179   store <vscale x 4 x i32> %5, ptr %3, align 4
180   ret void
183 ; Do not emit rshrnb if the shift amount is larger than the dest eltsize in bits
184 define 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, #0x800000000000
188 ; CHECK-NEXT:    ptrue p0.s
189 ; CHECK-NEXT:    add z0.d, z0.d, z2.d
190 ; CHECK-NEXT:    add z1.d, z1.d, z2.d
191 ; CHECK-NEXT:    ld1w { z2.s }, p0/z, [x0, x1, lsl #2]
192 ; CHECK-NEXT:    lsr z1.d, z1.d, #48
193 ; CHECK-NEXT:    lsr z0.d, z0.d, #48
194 ; CHECK-NEXT:    uzp1 z0.s, z0.s, z1.s
195 ; CHECK-NEXT:    add z0.s, z2.s, z0.s
196 ; CHECK-NEXT:    st1w { z0.s }, p0, [x0, x1, lsl #2]
197 ; CHECK-NEXT:    ret
198   %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 %index
201   %load = load <vscale x 4 x i32>, ptr %3, align 4
202   %4 = trunc <vscale x 4 x i64> %2 to <vscale x 4 x i32>
203   %5 = add <vscale x 4 x i32> %load, %4
204   store <vscale x 4 x i32> %5, ptr %3, align 4
205   ret void
208 define 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:    ptrue p0.h
212 ; CHECK-NEXT:    ld1h { z1.h }, p0/z, [x0]
213 ; CHECK-NEXT:    add z0.h, z1.h, z0.h
214 ; CHECK-NEXT:    lsr z0.h, z0.h, #6
215 ; CHECK-NEXT:    st1b { z0.h }, p0, [x1, x2]
216 ; CHECK-NEXT:    ret
217   %load = load <vscale x 8 x i16>, ptr %ptr, align 2
218   %1 = add <vscale x 8 x i16> %load, %add_op1
219   %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 %index
222   store <vscale x 8 x i8> %3, ptr %4, align 1
223   ret void
226 define 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:    ptrue p0.h
230 ; CHECK-NEXT:    ld1h { z1.h }, p0/z, [x0]
231 ; CHECK-NEXT:    add z1.h, z1.h, #32 // =0x20
232 ; CHECK-NEXT:    lsrr z0.h, p0/m, z0.h, z1.h
233 ; CHECK-NEXT:    st1b { z0.h }, p0, [x1, x2]
234 ; CHECK-NEXT:    ret
235   %load = load <vscale x 8 x i16>, ptr %ptr, align 2
236   %1 = add <vscale x 8 x i16> %load, splat (i16 32)
237   %2 = lshr <vscale x 8 x i16> %1, %lshr_op1
238   %3 = trunc <vscale x 8 x i16> %2 to <vscale x 8 x i8>
239   %4 = getelementptr inbounds i8, ptr %dst, i64 %index
240   store <vscale x 8 x i8> %3, ptr %4, align 1
241   ret void
244 define 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:    ptrue p0.h
248 ; CHECK-NEXT:    ld1h { z0.h }, p0/z, [x0]
249 ; CHECK-NEXT:    add z0.h, z0.h, #32 // =0x20
250 ; CHECK-NEXT:    add z1.h, z0.h, z0.h
251 ; CHECK-NEXT:    lsr z0.h, z0.h, #6
252 ; CHECK-NEXT:    st1h { z1.h }, p0, [x2, x3, lsl #1]
253 ; CHECK-NEXT:    st1b { z0.h }, p0, [x1, x3]
254 ; CHECK-NEXT:    ret
255   %load = load <vscale x 8 x i16>, ptr %ptr, align 2
256   %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, %1
259   %4 = getelementptr inbounds i16, ptr %dst2, i64 %index
260   %5 = trunc <vscale x 8 x i16> %2 to <vscale x 8 x i8>
261   %6 = getelementptr inbounds i8, ptr %dst, i64 %index
262   store <vscale x 8 x i16> %3, ptr %4, align 1
263   store <vscale x 8 x i8> %5, ptr %6, align 1
264   ret void
267 define 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:    ptrue p0.d
271 ; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0]
272 ; CHECK-NEXT:    rshrnb z0.s, z0.d, #6
273 ; CHECK-NEXT:    st1w { z0.d }, p0, [x1, x2, lsl #2]
274 ; CHECK-NEXT:    ret
275   %load = load <vscale x 2 x i64>, ptr %ptr, align 2
276   %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 %index
280   store <vscale x 2 x i32> %3, ptr %4, align 1
281   ret void
284 define 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:    ptrue p0.d
288 ; CHECK-NEXT:    ld1d { z0.d }, p0/z, [x0]
289 ; CHECK-NEXT:    add z0.d, z0.d, #32 // =0x20
290 ; CHECK-NEXT:    lsr z0.d, z0.d, #6
291 ; CHECK-NEXT:    st1h { z0.d }, p0, [x1, x2, lsl #1]
292 ; CHECK-NEXT:    ret
293   %load = load <vscale x 2 x i64>, ptr %ptr, align 2
294   %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 %index
298   store <vscale x 2 x i16> %3, ptr %4, align 1
299   ret void
302 define void @masked_store_rshrnb(ptr %ptr, ptr %dst, i64 %index, <vscale x 8 x i1> %mask) {                             ; preds = %vector.body, %vector.ph
303 ; 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, #6
307 ; CHECK-NEXT:    st1b { z0.h }, p0, [x1, x2]
308 ; CHECK-NEXT:    ret
309   %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 %index
314   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 void
318 declare void @llvm.masked.store.nxv8i8.p0(<vscale x 8 x i8>, ptr, i32, <vscale x 8 x i1>)
319 declare <vscale x 8 x i16> @llvm.masked.load.nxv8i16.p0(ptr, i32, <vscale x 8 x i1>, <vscale x 8 x i16>)