Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / test / CodeGen / SystemZ / vec-intrinsics-02.ll
blobb93a610aa0b1a37810ddff83fd3a0c90a880cbc9
1 ; Test vector intrinsics added with z14.
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s
5 declare <2 x i64> @llvm.s390.vbperm(<16 x i8>, <16 x i8>)
6 declare <16 x i8> @llvm.s390.vmslg(<2 x i64>, <2 x i64>, <16 x i8>, i32)
7 declare <16 x i8> @llvm.s390.vlrl(i32, ptr)
8 declare void @llvm.s390.vstrl(<16 x i8>, i32, ptr)
10 declare {<4 x i32>, i32} @llvm.s390.vfcesbs(<4 x float>, <4 x float>)
11 declare {<4 x i32>, i32} @llvm.s390.vfchsbs(<4 x float>, <4 x float>)
12 declare {<4 x i32>, i32} @llvm.s390.vfchesbs(<4 x float>, <4 x float>)
13 declare {<4 x i32>, i32} @llvm.s390.vftcisb(<4 x float>, i32)
14 declare <4 x float> @llvm.s390.vfisb(<4 x float>, i32, i32)
16 declare <2 x double> @llvm.s390.vfmaxdb(<2 x double>, <2 x double>, i32)
17 declare <2 x double> @llvm.s390.vfmindb(<2 x double>, <2 x double>, i32)
18 declare <4 x float> @llvm.s390.vfmaxsb(<4 x float>, <4 x float>, i32)
19 declare <4 x float> @llvm.s390.vfminsb(<4 x float>, <4 x float>, i32)
21 ; VBPERM.
22 define <2 x i64> @test_vbperm(<16 x i8> %a, <16 x i8> %b) {
23 ; CHECK-LABEL: test_vbperm:
24 ; CHECK: vbperm %v24, %v24, %v26
25 ; CHECK: br %r14
26   %res = call <2 x i64> @llvm.s390.vbperm(<16 x i8> %a, <16 x i8> %b)
27   ret <2 x i64> %res
30 ; VMSLG with no shifts.
31 define <16 x i8> @test_vmslg1(<2 x i64> %a, <2 x i64> %b, <16 x i8> %c) {
32 ; CHECK-LABEL: test_vmslg1:
33 ; CHECK: vmslg %v24, %v24, %v26, %v28, 0
34 ; CHECK: br %r14
35   %res = call <16 x i8> @llvm.s390.vmslg(<2 x i64> %a, <2 x i64> %b, <16 x i8> %c, i32 0)
36   ret <16 x i8> %res
39 ; VMSLG with both shifts.
40 define <16 x i8> @test_vmslg2(<2 x i64> %a, <2 x i64> %b, <16 x i8> %c) {
41 ; CHECK-LABEL: test_vmslg2:
42 ; CHECK: vmslg %v24, %v24, %v26, %v28, 12
43 ; CHECK: br %r14
44   %res = call <16 x i8> @llvm.s390.vmslg(<2 x i64> %a, <2 x i64> %b, <16 x i8> %c, i32 12)
45   ret <16 x i8> %res
48 ; VLRLR with the lowest in-range displacement.
49 define <16 x i8> @test_vlrlr1(ptr %ptr, i32 %length) {
50 ; CHECK-LABEL: test_vlrlr1:
51 ; CHECK: vlrlr %v24, %r3, 0(%r2)
52 ; CHECK: br %r14
53   %res = call <16 x i8> @llvm.s390.vlrl(i32 %length, ptr %ptr)
54   ret <16 x i8> %res
57 ; VLRLR with the highest in-range displacement.
58 define <16 x i8> @test_vlrlr2(ptr %base, i32 %length) {
59 ; CHECK-LABEL: test_vlrlr2:
60 ; CHECK: vlrlr %v24, %r3, 4095(%r2)
61 ; CHECK: br %r14
62   %ptr = getelementptr i8, ptr %base, i64 4095
63   %res = call <16 x i8> @llvm.s390.vlrl(i32 %length, ptr %ptr)
64   ret <16 x i8> %res
67 ; VLRLR with an out-of-range displacement.
68 define <16 x i8> @test_vlrlr3(ptr %base, i32 %length) {
69 ; CHECK-LABEL: test_vlrlr3:
70 ; CHECK: vlrlr %v24, %r3, 0({{%r[1-5]}})
71 ; CHECK: br %r14
72   %ptr = getelementptr i8, ptr %base, i64 4096
73   %res = call <16 x i8> @llvm.s390.vlrl(i32 %length, ptr %ptr)
74   ret <16 x i8> %res
77 ; Check that VLRLR doesn't allow an index.
78 define <16 x i8> @test_vlrlr4(ptr %base, i64 %index, i32 %length) {
79 ; CHECK-LABEL: test_vlrlr4:
80 ; CHECK: vlrlr %v24, %r4, 0({{%r[1-5]}})
81 ; CHECK: br %r14
82   %ptr = getelementptr i8, ptr %base, i64 %index
83   %res = call <16 x i8> @llvm.s390.vlrl(i32 %length, ptr %ptr)
84   ret <16 x i8> %res
87 ; VLRL with the lowest in-range displacement.
88 define <16 x i8> @test_vlrl1(ptr %ptr) {
89 ; CHECK-LABEL: test_vlrl1:
90 ; CHECK: vlrl %v24, 0(%r2), 0
91 ; CHECK: br %r14
92   %res = call <16 x i8> @llvm.s390.vlrl(i32 0, ptr %ptr)
93   ret <16 x i8> %res
96 ; VLRL with the highest in-range displacement.
97 define <16 x i8> @test_vlrl2(ptr %base) {
98 ; CHECK-LABEL: test_vlrl2:
99 ; CHECK: vlrl %v24, 4095(%r2), 0
100 ; CHECK: br %r14
101   %ptr = getelementptr i8, ptr %base, i64 4095
102   %res = call <16 x i8> @llvm.s390.vlrl(i32 0, ptr %ptr)
103   ret <16 x i8> %res
106 ; VLRL with an out-of-range displacement.
107 define <16 x i8> @test_vlrl3(ptr %base) {
108 ; CHECK-LABEL: test_vlrl3:
109 ; CHECK: vlrl %v24, 0({{%r[1-5]}}), 0
110 ; CHECK: br %r14
111   %ptr = getelementptr i8, ptr %base, i64 4096
112   %res = call <16 x i8> @llvm.s390.vlrl(i32 0, ptr %ptr)
113   ret <16 x i8> %res
116 ; Check that VLRL doesn't allow an index.
117 define <16 x i8> @test_vlrl4(ptr %base, i64 %index) {
118 ; CHECK-LABEL: test_vlrl4:
119 ; CHECK: vlrl %v24, 0({{%r[1-5]}}), 0
120 ; CHECK: br %r14
121   %ptr = getelementptr i8, ptr %base, i64 %index
122   %res = call <16 x i8> @llvm.s390.vlrl(i32 0, ptr %ptr)
123   ret <16 x i8> %res
126 ; VLRL with length >= 15 should become VL.
127 define <16 x i8> @test_vlrl5(ptr %ptr) {
128 ; CHECK-LABEL: test_vlrl5:
129 ; CHECK: vl %v24, 0({{%r[1-5]}})
130 ; CHECK: br %r14
131   %res = call <16 x i8> @llvm.s390.vlrl(i32 15, ptr %ptr)
132   ret <16 x i8> %res
135 ; VSTRLR with the lowest in-range displacement.
136 define void @test_vstrlr1(<16 x i8> %vec, ptr %ptr, i32 %length) {
137 ; CHECK-LABEL: test_vstrlr1:
138 ; CHECK: vstrlr %v24, %r3, 0(%r2)
139 ; CHECK: br %r14
140   call void @llvm.s390.vstrl(<16 x i8> %vec, i32 %length, ptr %ptr)
141   ret void
144 ; VSTRLR with the highest in-range displacement.
145 define void @test_vstrlr2(<16 x i8> %vec, ptr %base, i32 %length) {
146 ; CHECK-LABEL: test_vstrlr2:
147 ; CHECK: vstrlr %v24, %r3, 4095(%r2)
148 ; CHECK: br %r14
149   %ptr = getelementptr i8, ptr %base, i64 4095
150   call void @llvm.s390.vstrl(<16 x i8> %vec, i32 %length, ptr %ptr)
151   ret void
154 ; VSTRLR with an out-of-range displacement.
155 define void @test_vstrlr3(<16 x i8> %vec, ptr %base, i32 %length) {
156 ; CHECK-LABEL: test_vstrlr3:
157 ; CHECK: vstrlr %v24, %r3, 0({{%r[1-5]}})
158 ; CHECK: br %r14
159   %ptr = getelementptr i8, ptr %base, i64 4096
160   call void @llvm.s390.vstrl(<16 x i8> %vec, i32 %length, ptr %ptr)
161   ret void
164 ; Check that VSTRLR doesn't allow an index.
165 define void @test_vstrlr4(<16 x i8> %vec, ptr %base, i64 %index, i32 %length) {
166 ; CHECK-LABEL: test_vstrlr4:
167 ; CHECK: vstrlr %v24, %r4, 0({{%r[1-5]}})
168 ; CHECK: br %r14
169   %ptr = getelementptr i8, ptr %base, i64 %index
170   call void @llvm.s390.vstrl(<16 x i8> %vec, i32 %length, ptr %ptr)
171   ret void
174 ; VSTRL with the lowest in-range displacement.
175 define void @test_vstrl1(<16 x i8> %vec, ptr %ptr) {
176 ; CHECK-LABEL: test_vstrl1:
177 ; CHECK: vstrl %v24, 0(%r2), 8
178 ; CHECK: br %r14
179   call void @llvm.s390.vstrl(<16 x i8> %vec, i32 8, ptr %ptr)
180   ret void
183 ; VSTRL with the highest in-range displacement.
184 define void @test_vstrl2(<16 x i8> %vec, ptr %base) {
185 ; CHECK-LABEL: test_vstrl2:
186 ; CHECK: vstrl %v24, 4095(%r2), 8
187 ; CHECK: br %r14
188   %ptr = getelementptr i8, ptr %base, i64 4095
189   call void @llvm.s390.vstrl(<16 x i8> %vec, i32 8, ptr %ptr)
190   ret void
193 ; VSTRL with an out-of-range displacement.
194 define void @test_vstrl3(<16 x i8> %vec, ptr %base) {
195 ; CHECK-LABEL: test_vstrl3:
196 ; CHECK: vstrl %v24, 0({{%r[1-5]}}), 8
197 ; CHECK: br %r14
198   %ptr = getelementptr i8, ptr %base, i64 4096
199   call void @llvm.s390.vstrl(<16 x i8> %vec, i32 8, ptr %ptr)
200   ret void
203 ; Check that VSTRL doesn't allow an index.
204 define void @test_vstrl4(<16 x i8> %vec, ptr %base, i64 %index) {
205 ; CHECK-LABEL: test_vstrl4:
206 ; CHECK: vstrl %v24, 0({{%r[1-5]}}), 8
207 ; CHECK: br %r14
208   %ptr = getelementptr i8, ptr %base, i64 %index
209   call void @llvm.s390.vstrl(<16 x i8> %vec, i32 8, ptr %ptr)
210   ret void
213 ; VSTRL with length >= 15 should become VST.
214 define void @test_vstrl5(<16 x i8> %vec, ptr %ptr) {
215 ; CHECK-LABEL: test_vstrl5:
216 ; CHECK: vst %v24, 0({{%r[1-5]}})
217 ; CHECK: br %r14
218   call void @llvm.s390.vstrl(<16 x i8> %vec, i32 15, ptr %ptr)
219   ret void
222 ; VFCESBS with no processing of the result.
223 define i32 @test_vfcesbs(<4 x float> %a, <4 x float> %b) {
224 ; CHECK-LABEL: test_vfcesbs:
225 ; CHECK: vfcesbs {{%v[0-9]+}}, %v24, %v26
226 ; CHECK: ipm %r2
227 ; CHECK: srl %r2, 28
228 ; CHECK: br %r14
229   %call = call {<4 x i32>, i32} @llvm.s390.vfcesbs(<4 x float> %a,
230                                                    <4 x float> %b)
231   %res = extractvalue {<4 x i32>, i32} %call, 1
232   ret i32 %res
235 ; VFCESBS, returning 1 if any elements are equal (CC != 3).
236 define i32 @test_vfcesbs_any_bool(<4 x float> %a, <4 x float> %b) {
237 ; CHECK-LABEL: test_vfcesbs_any_bool:
238 ; CHECK: vfcesbs {{%v[0-9]+}}, %v24, %v26
239 ; CHECK: lhi %r2, 0
240 ; CHECK: lochile %r2, 1
241 ; CHECK: br %r14
242   %call = call {<4 x i32>, i32} @llvm.s390.vfcesbs(<4 x float> %a,
243                                                    <4 x float> %b)
244   %res = extractvalue {<4 x i32>, i32} %call, 1
245   %cmp = icmp ne i32 %res, 3
246   %ext = zext i1 %cmp to i32
247   ret i32 %ext
250 ; VFCESBS, storing to %ptr if any elements are equal.
251 define <4 x i32> @test_vfcesbs_any_store(<4 x float> %a, <4 x float> %b,
252                                          ptr %ptr) {
253 ; CHECK-LABEL: test_vfcesbs_any_store:
254 ; CHECK-NOT: %r
255 ; CHECK: vfcesbs %v24, %v24, %v26
256 ; CHECK-NEXT: {{bor|bnler}} %r14
257 ; CHECK: mvhi 0(%r2), 0
258 ; CHECK: br %r14
259   %call = call {<4 x i32>, i32} @llvm.s390.vfcesbs(<4 x float> %a,
260                                                    <4 x float> %b)
261   %res = extractvalue {<4 x i32>, i32} %call, 0
262   %cc = extractvalue {<4 x i32>, i32} %call, 1
263   %cmp = icmp ule i32 %cc, 2
264   br i1 %cmp, label %store, label %exit
266 store:
267   store i32 0, ptr %ptr
268   br label %exit
270 exit:
271   ret <4 x i32> %res
274 ; VFCHSBS with no processing of the result.
275 define i32 @test_vfchsbs(<4 x float> %a, <4 x float> %b) {
276 ; CHECK-LABEL: test_vfchsbs:
277 ; CHECK: vfchsbs {{%v[0-9]+}}, %v24, %v26
278 ; CHECK: ipm %r2
279 ; CHECK: srl %r2, 28
280 ; CHECK: br %r14
281   %call = call {<4 x i32>, i32} @llvm.s390.vfchsbs(<4 x float> %a,
282                                                    <4 x float> %b)
283   %res = extractvalue {<4 x i32>, i32} %call, 1
284   ret i32 %res
287 ; VFCHSBS, returning 1 if not all elements are higher.
288 define i32 @test_vfchsbs_notall_bool(<4 x float> %a, <4 x float> %b) {
289 ; CHECK-LABEL: test_vfchsbs_notall_bool:
290 ; CHECK: vfchsbs {{%v[0-9]+}}, %v24, %v26
291 ; CHECK: lhi %r2, 0
292 ; CHECK: lochinhe %r2, 1
293 ; CHECK: br %r14
294   %call = call {<4 x i32>, i32} @llvm.s390.vfchsbs(<4 x float> %a,
295                                                    <4 x float> %b)
296   %res = extractvalue {<4 x i32>, i32} %call, 1
297   %cmp = icmp sge i32 %res, 1
298   %ext = zext i1 %cmp to i32
299   ret i32 %ext
302 ; VFCHSBS, storing to %ptr if not all elements are higher.
303 define <4 x i32> @test_vfchsbs_notall_store(<4 x float> %a, <4 x float> %b,
304                                             ptr %ptr) {
305 ; CHECK-LABEL: test_vfchsbs_notall_store:
306 ; CHECK-NOT: %r
307 ; CHECK: vfchsbs %v24, %v24, %v26
308 ; CHECK-NEXT: {{bher|ber}} %r14
309 ; CHECK: mvhi 0(%r2), 0
310 ; CHECK: br %r14
311   %call = call {<4 x i32>, i32} @llvm.s390.vfchsbs(<4 x float> %a,
312                                                    <4 x float> %b)
313   %res = extractvalue {<4 x i32>, i32} %call, 0
314   %cc = extractvalue {<4 x i32>, i32} %call, 1
315   %cmp = icmp ugt i32 %cc, 0
316   br i1 %cmp, label %store, label %exit
318 store:
319   store i32 0, ptr %ptr
320   br label %exit
322 exit:
323   ret <4 x i32> %res
326 ; VFCHESBS with no processing of the result.
327 define i32 @test_vfchesbs(<4 x float> %a, <4 x float> %b) {
328 ; CHECK-LABEL: test_vfchesbs:
329 ; CHECK: vfchesbs {{%v[0-9]+}}, %v24, %v26
330 ; CHECK: ipm %r2
331 ; CHECK: srl %r2, 28
332 ; CHECK: br %r14
333   %call = call {<4 x i32>, i32} @llvm.s390.vfchesbs(<4 x float> %a,
334                                                     <4 x float> %b)
335   %res = extractvalue {<4 x i32>, i32} %call, 1
336   ret i32 %res
339 ; VFCHESBS, returning 1 if neither element is higher or equal.
340 define i32 @test_vfchesbs_none_bool(<4 x float> %a, <4 x float> %b) {
341 ; CHECK-LABEL: test_vfchesbs_none_bool:
342 ; CHECK: vfchesbs {{%v[0-9]+}}, %v24, %v26
343 ; CHECK: lhi %r2, 0
344 ; CHECK: lochio %r2, 1
345 ; CHECK: br %r14
346   %call = call {<4 x i32>, i32} @llvm.s390.vfchesbs(<4 x float> %a,
347                                                     <4 x float> %b)
348   %res = extractvalue {<4 x i32>, i32} %call, 1
349   %cmp = icmp eq i32 %res, 3
350   %ext = zext i1 %cmp to i32
351   ret i32 %ext
354 ; VFCHESBS, storing to %ptr if neither element is higher or equal.
355 define <4 x i32> @test_vfchesbs_none_store(<4 x float> %a, <4 x float> %b,
356                                            ptr %ptr) {
357 ; CHECK-LABEL: test_vfchesbs_none_store:
358 ; CHECK-NOT: %r
359 ; CHECK: vfchesbs %v24, %v24, %v26
360 ; CHECK-NEXT: {{bnor|bler}} %r14
361 ; CHECK: mvhi 0(%r2), 0
362 ; CHECK: br %r14
363   %call = call {<4 x i32>, i32} @llvm.s390.vfchesbs(<4 x float> %a,
364                                                     <4 x float> %b)
365   %res = extractvalue {<4 x i32>, i32} %call, 0
366   %cc = extractvalue {<4 x i32>, i32} %call, 1
367   %cmp = icmp uge i32 %cc, 3
368   br i1 %cmp, label %store, label %exit
370 store:
371   store i32 0, ptr %ptr
372   br label %exit
374 exit:
375   ret <4 x i32> %res
378 ; VFTCISB with the lowest useful class selector and no processing of the result.
379 define i32 @test_vftcisb(<4 x float> %a) {
380 ; CHECK-LABEL: test_vftcisb:
381 ; CHECK: vftcisb {{%v[0-9]+}}, %v24, 1
382 ; CHECK: ipm %r2
383 ; CHECK: srl %r2, 28
384 ; CHECK: br %r14
385   %call = call {<4 x i32>, i32} @llvm.s390.vftcisb(<4 x float> %a, i32 1)
386   %res = extractvalue {<4 x i32>, i32} %call, 1
387   ret i32 %res
390 ; VFTCISB with the highest useful class selector, returning 1 if all elements
391 ; have the right class (CC == 0).
392 define i32 @test_vftcisb_all_bool(<4 x float> %a) {
393 ; CHECK-LABEL: test_vftcisb_all_bool:
394 ; CHECK: vftcisb {{%v[0-9]+}}, %v24, 4094
395 ; CHECK: lhi %r2, 0
396 ; CHECK: lochie %r2, 1
397 ; CHECK: br %r14
398   %call = call {<4 x i32>, i32} @llvm.s390.vftcisb(<4 x float> %a, i32 4094)
399   %res = extractvalue {<4 x i32>, i32} %call, 1
400   %cmp = icmp eq i32 %res, 0
401   %ext = zext i1 %cmp to i32
402   ret i32 %ext
405 ; VFISB with a rounding mode not usable via standard intrinsics.
406 define <4 x float> @test_vfisb_0_4(<4 x float> %a) {
407 ; CHECK-LABEL: test_vfisb_0_4:
408 ; CHECK: vfisb %v24, %v24, 0, 4
409 ; CHECK: br %r14
410   %res = call <4 x float> @llvm.s390.vfisb(<4 x float> %a, i32 0, i32 4)
411   ret <4 x float> %res
414 ; VFISB with IEEE-inexact exception suppressed.
415 define <4 x float> @test_vfisb_4_0(<4 x float> %a) {
416 ; CHECK-LABEL: test_vfisb_4_0:
417 ; CHECK: vfisb %v24, %v24, 4, 0
418 ; CHECK: br %r14
419   %res = call <4 x float> @llvm.s390.vfisb(<4 x float> %a, i32 4, i32 0)
420   ret <4 x float> %res
423 ; VFMAXDB.
424 define <2 x double> @test_vfmaxdb(<2 x double> %a, <2 x double> %b) {
425 ; CHECK-LABEL: test_vfmaxdb:
426 ; CHECK: vfmaxdb %v24, %v24, %v26, 4
427 ; CHECK: br %r14
428   %res = call <2 x double> @llvm.s390.vfmaxdb(<2 x double> %a, <2 x double> %b, i32 4)
429   ret <2 x double> %res
432 ; VFMINDB.
433 define <2 x double> @test_vfmindb(<2 x double> %a, <2 x double> %b) {
434 ; CHECK-LABEL: test_vfmindb:
435 ; CHECK: vfmindb %v24, %v24, %v26, 4
436 ; CHECK: br %r14
437   %res = call <2 x double> @llvm.s390.vfmindb(<2 x double> %a, <2 x double> %b, i32 4)
438   ret <2 x double> %res
441 ; VFMAXSB.
442 define <4 x float> @test_vfmaxsb(<4 x float> %a, <4 x float> %b) {
443 ; CHECK-LABEL: test_vfmaxsb:
444 ; CHECK: vfmaxsb %v24, %v24, %v26, 4
445 ; CHECK: br %r14
446   %res = call <4 x float> @llvm.s390.vfmaxsb(<4 x float> %a, <4 x float> %b, i32 4)
447   ret <4 x float> %res
450 ; VFMINSB.
451 define <4 x float> @test_vfminsb(<4 x float> %a, <4 x float> %b) {
452 ; CHECK-LABEL: test_vfminsb:
453 ; CHECK: vfminsb %v24, %v24, %v26, 4
454 ; CHECK: br %r14
455   %res = call <4 x float> @llvm.s390.vfminsb(<4 x float> %a, <4 x float> %b, i32 4)
456   ret <4 x float> %res