[X86] combineTargetShuffle - commute VPERMV3 shuffles so any load is on the RHS
[llvm-project.git] / llvm / test / CodeGen / SystemZ / spill-01.ll
blobb243765c425008eb968674990a12be362219e4a5
1 ; Test spilling using MVC.  The tests here assume z10 register pressure,
2 ; without the high words being available.
4 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -verify-machineinstrs | FileCheck %s
6 declare void @foo()
8 @g0 = dso_local global i32 0
9 @g1 = dso_local global i32 1
10 @g2 = dso_local global i32 2
11 @g3 = dso_local global i32 3
12 @g4 = dso_local global i32 4
13 @g5 = dso_local global i32 5
14 @g6 = dso_local global i32 6
15 @g7 = dso_local global i32 7
16 @g8 = dso_local global i32 8
17 @g9 = dso_local global i32 9
19 @h0 = dso_local global i64 0
20 @h1 = dso_local global i64 1
21 @h2 = dso_local global i64 2
22 @h3 = dso_local global i64 3
23 @h4 = dso_local global i64 4
24 @h5 = dso_local global i64 5
25 @h6 = dso_local global i64 6
26 @h7 = dso_local global i64 7
27 @h8 = dso_local global i64 8
28 @h9 = dso_local global i64 9
30 ; This function shouldn't spill anything
31 define dso_local void @f1(ptr %ptr0) {
32 ; CHECK-LABEL: f1:
33 ; CHECK: stmg
34 ; CHECK: aghi %r15, -160
35 ; CHECK-NOT: %r15
36 ; CHECK: brasl %r14, foo@PLT
37 ; CHECK-NOT: %r15
38 ; CHECK: lmg
39 ; CHECK: br %r14
40   %ptr1 = getelementptr i32, ptr %ptr0, i32 2
41   %ptr2 = getelementptr i32, ptr %ptr0, i32 4
42   %ptr3 = getelementptr i32, ptr %ptr0, i32 6
43   %ptr4 = getelementptr i32, ptr %ptr0, i32 8
44   %ptr5 = getelementptr i32, ptr %ptr0, i32 10
45   %ptr6 = getelementptr i32, ptr %ptr0, i32 12
47   %val0 = load i32, ptr %ptr0
48   %val1 = load i32, ptr %ptr1
49   %val2 = load i32, ptr %ptr2
50   %val3 = load i32, ptr %ptr3
51   %val4 = load i32, ptr %ptr4
52   %val5 = load i32, ptr %ptr5
53   %val6 = load i32, ptr %ptr6
55   call void @foo()
57   store i32 %val0, ptr %ptr0
58   store i32 %val1, ptr %ptr1
59   store i32 %val2, ptr %ptr2
60   store i32 %val3, ptr %ptr3
61   store i32 %val4, ptr %ptr4
62   store i32 %val5, ptr %ptr5
63   store i32 %val6, ptr %ptr6
65   ret void
68 ; Test a case where at least one i32 load and at least one i32 store
69 ; need spills.
70 define dso_local void @f2(ptr %ptr0) {
71 ; CHECK-LABEL: f2:
72 ; CHECK: mvc [[OFFSET1:16[04]]](4,%r15), [[OFFSET2:[0-9]+]]({{%r[0-9]+}})
73 ; CHECK: brasl %r14, foo@PLT
74 ; CHECK: mvc [[OFFSET2]](4,{{%r[0-9]+}}), [[OFFSET1]](%r15)
75 ; CHECK: br %r14
76   %ptr1 = getelementptr i32, ptr %ptr0, i64 2
77   %ptr2 = getelementptr i32, ptr %ptr0, i64 4
78   %ptr3 = getelementptr i32, ptr %ptr0, i64 6
79   %ptr4 = getelementptr i32, ptr %ptr0, i64 8
80   %ptr5 = getelementptr i32, ptr %ptr0, i64 10
81   %ptr6 = getelementptr i32, ptr %ptr0, i64 12
82   %ptr7 = getelementptr i32, ptr %ptr0, i64 14
83   %ptr8 = getelementptr i32, ptr %ptr0, i64 16
85   %val0 = load i32, ptr %ptr0
86   %val1 = load i32, ptr %ptr1
87   %val2 = load i32, ptr %ptr2
88   %val3 = load i32, ptr %ptr3
89   %val4 = load i32, ptr %ptr4
90   %val5 = load i32, ptr %ptr5
91   %val6 = load i32, ptr %ptr6
92   %val7 = load i32, ptr %ptr7
93   %val8 = load i32, ptr %ptr8
95   call void @foo()
97   store i32 %val0, ptr %ptr0
98   store i32 %val1, ptr %ptr1
99   store i32 %val2, ptr %ptr2
100   store i32 %val3, ptr %ptr3
101   store i32 %val4, ptr %ptr4
102   store i32 %val5, ptr %ptr5
103   store i32 %val6, ptr %ptr6
104   store i32 %val7, ptr %ptr7
105   store i32 %val8, ptr %ptr8
107   ret void
110 ; Test a case where at least one i64 load and at least one i64 store
111 ; need spills.
112 define dso_local void @f3(ptr %ptr0) {
113 ; CHECK-LABEL: f3:
114 ; CHECK: mvc 160(8,%r15), [[OFFSET:[0-9]+]]({{%r[0-9]+}})
115 ; CHECK: brasl %r14, foo@PLT
116 ; CHECK: mvc [[OFFSET]](8,{{%r[0-9]+}}), 160(%r15)
117 ; CHECK: br %r14
118   %ptr1 = getelementptr i64, ptr %ptr0, i64 2
119   %ptr2 = getelementptr i64, ptr %ptr0, i64 4
120   %ptr3 = getelementptr i64, ptr %ptr0, i64 6
121   %ptr4 = getelementptr i64, ptr %ptr0, i64 8
122   %ptr5 = getelementptr i64, ptr %ptr0, i64 10
123   %ptr6 = getelementptr i64, ptr %ptr0, i64 12
124   %ptr7 = getelementptr i64, ptr %ptr0, i64 14
125   %ptr8 = getelementptr i64, ptr %ptr0, i64 16
127   %val0 = load i64, ptr %ptr0
128   %val1 = load i64, ptr %ptr1
129   %val2 = load i64, ptr %ptr2
130   %val3 = load i64, ptr %ptr3
131   %val4 = load i64, ptr %ptr4
132   %val5 = load i64, ptr %ptr5
133   %val6 = load i64, ptr %ptr6
134   %val7 = load i64, ptr %ptr7
135   %val8 = load i64, ptr %ptr8
137   call void @foo()
139   store i64 %val0, ptr %ptr0
140   store i64 %val1, ptr %ptr1
141   store i64 %val2, ptr %ptr2
142   store i64 %val3, ptr %ptr3
143   store i64 %val4, ptr %ptr4
144   store i64 %val5, ptr %ptr5
145   store i64 %val6, ptr %ptr6
146   store i64 %val7, ptr %ptr7
147   store i64 %val8, ptr %ptr8
149   ret void
153 ; Test a case where at least at least one f32 load and at least one f32 store
154 ; need spills.  The 8 call-saved FPRs could be used for 8 of the %vals
155 ; (and are at the time of writing), but it would really be better to use
156 ; MVC for all 10.
157 define dso_local void @f4(ptr %ptr0) {
158 ; CHECK-LABEL: f4:
159 ; CHECK: mvc [[OFFSET1:16[04]]](4,%r15), [[OFFSET2:[0-9]+]]({{%r[0-9]+}})
160 ; CHECK: brasl %r14, foo@PLT
161 ; CHECK: mvc [[OFFSET2]](4,{{%r[0-9]+}}), [[OFFSET1]](%r15)
162 ; CHECK: br %r14
163   %ptr1 = getelementptr float, ptr %ptr0, i64 2
164   %ptr2 = getelementptr float, ptr %ptr0, i64 4
165   %ptr3 = getelementptr float, ptr %ptr0, i64 6
166   %ptr4 = getelementptr float, ptr %ptr0, i64 8
167   %ptr5 = getelementptr float, ptr %ptr0, i64 10
168   %ptr6 = getelementptr float, ptr %ptr0, i64 12
169   %ptr7 = getelementptr float, ptr %ptr0, i64 14
170   %ptr8 = getelementptr float, ptr %ptr0, i64 16
171   %ptr9 = getelementptr float, ptr %ptr0, i64 18
173   %val0 = load float, ptr %ptr0
174   %val1 = load float, ptr %ptr1
175   %val2 = load float, ptr %ptr2
176   %val3 = load float, ptr %ptr3
177   %val4 = load float, ptr %ptr4
178   %val5 = load float, ptr %ptr5
179   %val6 = load float, ptr %ptr6
180   %val7 = load float, ptr %ptr7
181   %val8 = load float, ptr %ptr8
182   %val9 = load float, ptr %ptr9
184   call void @foo()
186   store float %val0, ptr %ptr0
187   store float %val1, ptr %ptr1
188   store float %val2, ptr %ptr2
189   store float %val3, ptr %ptr3
190   store float %val4, ptr %ptr4
191   store float %val5, ptr %ptr5
192   store float %val6, ptr %ptr6
193   store float %val7, ptr %ptr7
194   store float %val8, ptr %ptr8
195   store float %val9, ptr %ptr9
197   ret void
200 ; Similarly for f64.
201 define dso_local void @f5(ptr %ptr0) {
202 ; CHECK-LABEL: f5:
203 ; CHECK: mvc 160(8,%r15), [[OFFSET:[0-9]+]]({{%r[0-9]+}})
204 ; CHECK: brasl %r14, foo@PLT
205 ; CHECK: mvc [[OFFSET]](8,{{%r[0-9]+}}), 160(%r15)
206 ; CHECK: br %r14
207   %ptr1 = getelementptr double, ptr %ptr0, i64 2
208   %ptr2 = getelementptr double, ptr %ptr0, i64 4
209   %ptr3 = getelementptr double, ptr %ptr0, i64 6
210   %ptr4 = getelementptr double, ptr %ptr0, i64 8
211   %ptr5 = getelementptr double, ptr %ptr0, i64 10
212   %ptr6 = getelementptr double, ptr %ptr0, i64 12
213   %ptr7 = getelementptr double, ptr %ptr0, i64 14
214   %ptr8 = getelementptr double, ptr %ptr0, i64 16
215   %ptr9 = getelementptr double, ptr %ptr0, i64 18
217   %val0 = load double, ptr %ptr0
218   %val1 = load double, ptr %ptr1
219   %val2 = load double, ptr %ptr2
220   %val3 = load double, ptr %ptr3
221   %val4 = load double, ptr %ptr4
222   %val5 = load double, ptr %ptr5
223   %val6 = load double, ptr %ptr6
224   %val7 = load double, ptr %ptr7
225   %val8 = load double, ptr %ptr8
226   %val9 = load double, ptr %ptr9
228   call void @foo()
230   store double %val0, ptr %ptr0
231   store double %val1, ptr %ptr1
232   store double %val2, ptr %ptr2
233   store double %val3, ptr %ptr3
234   store double %val4, ptr %ptr4
235   store double %val5, ptr %ptr5
236   store double %val6, ptr %ptr6
237   store double %val7, ptr %ptr7
238   store double %val8, ptr %ptr8
239   store double %val9, ptr %ptr9
241   ret void
244 ; Repeat f2 with atomic accesses.  We shouldn't use MVC here.
245 define dso_local void @f6(ptr %ptr0) {
246 ; CHECK-LABEL: f6:
247 ; CHECK-NOT: mvc
248 ; CHECK: br %r14
249   %ptr1 = getelementptr i32, ptr %ptr0, i64 2
250   %ptr2 = getelementptr i32, ptr %ptr0, i64 4
251   %ptr3 = getelementptr i32, ptr %ptr0, i64 6
252   %ptr4 = getelementptr i32, ptr %ptr0, i64 8
253   %ptr5 = getelementptr i32, ptr %ptr0, i64 10
254   %ptr6 = getelementptr i32, ptr %ptr0, i64 12
255   %ptr7 = getelementptr i32, ptr %ptr0, i64 14
256   %ptr8 = getelementptr i32, ptr %ptr0, i64 16
258   %val0 = load atomic i32, ptr %ptr0 unordered, align 4
259   %val1 = load atomic i32, ptr %ptr1 unordered, align 4
260   %val2 = load atomic i32, ptr %ptr2 unordered, align 4
261   %val3 = load atomic i32, ptr %ptr3 unordered, align 4
262   %val4 = load atomic i32, ptr %ptr4 unordered, align 4
263   %val5 = load atomic i32, ptr %ptr5 unordered, align 4
264   %val6 = load atomic i32, ptr %ptr6 unordered, align 4
265   %val7 = load atomic i32, ptr %ptr7 unordered, align 4
266   %val8 = load atomic i32, ptr %ptr8 unordered, align 4
268   call void @foo()
270   store atomic i32 %val0, ptr %ptr0 unordered, align 4
271   store atomic i32 %val1, ptr %ptr1 unordered, align 4
272   store atomic i32 %val2, ptr %ptr2 unordered, align 4
273   store atomic i32 %val3, ptr %ptr3 unordered, align 4
274   store atomic i32 %val4, ptr %ptr4 unordered, align 4
275   store atomic i32 %val5, ptr %ptr5 unordered, align 4
276   store atomic i32 %val6, ptr %ptr6 unordered, align 4
277   store atomic i32 %val7, ptr %ptr7 unordered, align 4
278   store atomic i32 %val8, ptr %ptr8 unordered, align 4
280   ret void
283 ; ...likewise volatile accesses.
284 define dso_local void @f7(ptr %ptr0) {
285 ; CHECK-LABEL: f7:
286 ; CHECK-NOT: mvc
287 ; CHECK: br %r14
288   %ptr1 = getelementptr i32, ptr %ptr0, i64 2
289   %ptr2 = getelementptr i32, ptr %ptr0, i64 4
290   %ptr3 = getelementptr i32, ptr %ptr0, i64 6
291   %ptr4 = getelementptr i32, ptr %ptr0, i64 8
292   %ptr5 = getelementptr i32, ptr %ptr0, i64 10
293   %ptr6 = getelementptr i32, ptr %ptr0, i64 12
294   %ptr7 = getelementptr i32, ptr %ptr0, i64 14
295   %ptr8 = getelementptr i32, ptr %ptr0, i64 16
297   %val0 = load volatile i32, ptr %ptr0
298   %val1 = load volatile i32, ptr %ptr1
299   %val2 = load volatile i32, ptr %ptr2
300   %val3 = load volatile i32, ptr %ptr3
301   %val4 = load volatile i32, ptr %ptr4
302   %val5 = load volatile i32, ptr %ptr5
303   %val6 = load volatile i32, ptr %ptr6
304   %val7 = load volatile i32, ptr %ptr7
305   %val8 = load volatile i32, ptr %ptr8
307   call void @foo()
309   store volatile i32 %val0, ptr %ptr0
310   store volatile i32 %val1, ptr %ptr1
311   store volatile i32 %val2, ptr %ptr2
312   store volatile i32 %val3, ptr %ptr3
313   store volatile i32 %val4, ptr %ptr4
314   store volatile i32 %val5, ptr %ptr5
315   store volatile i32 %val6, ptr %ptr6
316   store volatile i32 %val7, ptr %ptr7
317   store volatile i32 %val8, ptr %ptr8
319   ret void
322 ; Check that LRL and STRL are not converted.
323 define dso_local void @f8() {
324 ; CHECK-LABEL: f8:
325 ; CHECK-NOT: mvc
326 ; CHECK: br %r14
327   %val0 = load i32, ptr@g0
328   %val1 = load i32, ptr@g1
329   %val2 = load i32, ptr@g2
330   %val3 = load i32, ptr@g3
331   %val4 = load i32, ptr@g4
332   %val5 = load i32, ptr@g5
333   %val6 = load i32, ptr@g6
334   %val7 = load i32, ptr@g7
335   %val8 = load i32, ptr@g8
336   %val9 = load i32, ptr@g9
338   call void @foo()
340   store i32 %val0, ptr@g0
341   store i32 %val1, ptr@g1
342   store i32 %val2, ptr@g2
343   store i32 %val3, ptr@g3
344   store i32 %val4, ptr@g4
345   store i32 %val5, ptr@g5
346   store i32 %val6, ptr@g6
347   store i32 %val7, ptr@g7
348   store i32 %val8, ptr@g8
349   store i32 %val9, ptr@g9
351   ret void
354 ; Likewise LGRL and STGRL.
355 define dso_local void @f9() {
356 ; CHECK-LABEL: f9:
357 ; CHECK-NOT: mvc
358 ; CHECK: br %r14
359   %val0 = load i64, ptr@h0
360   %val1 = load i64, ptr@h1
361   %val2 = load i64, ptr@h2
362   %val3 = load i64, ptr@h3
363   %val4 = load i64, ptr@h4
364   %val5 = load i64, ptr@h5
365   %val6 = load i64, ptr@h6
366   %val7 = load i64, ptr@h7
367   %val8 = load i64, ptr@h8
368   %val9 = load i64, ptr@h9
370   call void @foo()
372   store i64 %val0, ptr@h0
373   store i64 %val1, ptr@h1
374   store i64 %val2, ptr@h2
375   store i64 %val3, ptr@h3
376   store i64 %val4, ptr@h4
377   store i64 %val5, ptr@h5
378   store i64 %val6, ptr@h6
379   store i64 %val7, ptr@h7
380   store i64 %val8, ptr@h8
381   store i64 %val9, ptr@h9
383   ret void
386 ; This showed a problem with the way stack coloring updated instructions.
387 ; The copy from %val9 to %newval8 can be done using an MVC, which then
388 ; has two frame index operands.  Stack coloring chose a valid renumbering
389 ; [FI0, FI1] -> [FI1, FI2], but applied it in the form FI0 -> FI1 -> FI2,
390 ; so that both operands ended up being the same.
391 define dso_local void @f10() {
392 ; CHECK-LABEL: f10:
393 ; CHECK: lgrl [[REG:%r[0-9]+]], h9
394 ; CHECK: stg [[REG]], [[VAL9:[0-9]+]](%r15)
395 ; CHECK: brasl %r14, foo@PLT
396 ; CHECK: brasl %r14, foo@PLT
397 ; CHECK: mvc [[NEWVAL8:[0-9]+]](8,%r15), [[VAL9]](%r15)
398 ; CHECK: brasl %r14, foo@PLT
399 ; CHECK: lg [[REG:%r[0-9]+]], [[NEWVAL8]](%r15)
400 ; CHECK: stgrl [[REG]], h8
401 ; CHECK: br %r14
402 entry:
403   %val8 = load volatile i64, ptr@h8
404   %val0 = load volatile i64, ptr@h0
405   %val1 = load volatile i64, ptr@h1
406   %val2 = load volatile i64, ptr@h2
407   %val3 = load volatile i64, ptr@h3
408   %val4 = load volatile i64, ptr@h4
409   %val5 = load volatile i64, ptr@h5
410   %val6 = load volatile i64, ptr@h6
411   %val7 = load volatile i64, ptr@h7
412   %val9 = load volatile i64, ptr@h9
414   call void @foo()
416   store volatile i64 %val0, ptr@h0
417   store volatile i64 %val1, ptr@h1
418   store volatile i64 %val2, ptr@h2
419   store volatile i64 %val3, ptr@h3
420   store volatile i64 %val4, ptr@h4
421   store volatile i64 %val5, ptr@h5
422   store volatile i64 %val6, ptr@h6
423   store volatile i64 %val7, ptr@h7
425   %check = load volatile i64, ptr@h0
426   %cond = icmp eq i64 %check, 0
427   br i1 %cond, label %skip, label %fallthru
429 fallthru:
430   call void @foo()
432   store volatile i64 %val0, ptr@h0
433   store volatile i64 %val1, ptr@h1
434   store volatile i64 %val2, ptr@h2
435   store volatile i64 %val3, ptr@h3
436   store volatile i64 %val4, ptr@h4
437   store volatile i64 %val5, ptr@h5
438   store volatile i64 %val6, ptr@h6
439   store volatile i64 %val7, ptr@h7
440   store volatile i64 %val8, ptr@h8
441   br label %skip
443 skip:
444   %newval8 = phi i64 [ %val8, %entry ], [ %val9, %fallthru ]
445   call void @foo()
447   store volatile i64 %val0, ptr@h0
448   store volatile i64 %val1, ptr@h1
449   store volatile i64 %val2, ptr@h2
450   store volatile i64 %val3, ptr@h3
451   store volatile i64 %val4, ptr@h4
452   store volatile i64 %val5, ptr@h5
453   store volatile i64 %val6, ptr@h6
454   store volatile i64 %val7, ptr@h7
455   store volatile i64 %newval8, ptr@h8
456   store volatile i64 %val9, ptr@h9
458   ret void
461 ; This used to generate a no-op MVC.  It is very sensitive to spill heuristics.
462 define dso_local void @f11() {
463 ; CHECK-LABEL: f11:
464 ; CHECK-NOT: mvc [[OFFSET:[0-9]+]](8,%r15), [[OFFSET]](%r15)
465 ; CHECK: br %r14
466 entry:
467   %val0 = load volatile i64, ptr@h0
468   %val1 = load volatile i64, ptr@h1
469   %val2 = load volatile i64, ptr@h2
470   %val3 = load volatile i64, ptr@h3
471   %val4 = load volatile i64, ptr@h4
472   %val5 = load volatile i64, ptr@h5
473   %val6 = load volatile i64, ptr@h6
474   %val7 = load volatile i64, ptr@h7
476   %altval0 = load volatile i64, ptr@h0
477   %altval1 = load volatile i64, ptr@h1
479   call void @foo()
481   store volatile i64 %val0, ptr@h0
482   store volatile i64 %val1, ptr@h1
483   store volatile i64 %val2, ptr@h2
484   store volatile i64 %val3, ptr@h3
485   store volatile i64 %val4, ptr@h4
486   store volatile i64 %val5, ptr@h5
487   store volatile i64 %val6, ptr@h6
488   store volatile i64 %val7, ptr@h7
490   %check = load volatile i64, ptr@h0
491   %cond = icmp eq i64 %check, 0
492   br i1 %cond, label %a1, label %b1
495   call void @foo()
496   br label %join1
499   call void @foo()
500   br label %join1
502 join1:
503   %newval0 = phi i64 [ %val0, %a1 ], [ %altval0, %b1 ]
505   call void @foo()
507   store volatile i64 %val1, ptr@h1
508   store volatile i64 %val2, ptr@h2
509   store volatile i64 %val3, ptr@h3
510   store volatile i64 %val4, ptr@h4
511   store volatile i64 %val5, ptr@h5
512   store volatile i64 %val6, ptr@h6
513   store volatile i64 %val7, ptr@h7
514   br i1 %cond, label %a2, label %b2
517   call void @foo()
518   br label %join2
521   call void @foo()
522   br label %join2
524 join2:
525   %newval1 = phi i64 [ %val1, %a2 ], [ %altval1, %b2 ]
527   call void @foo()
529   store volatile i64 %val2, ptr@h2
530   store volatile i64 %val3, ptr@h3
531   store volatile i64 %val4, ptr@h4
532   store volatile i64 %val5, ptr@h5
533   store volatile i64 %val6, ptr@h6
534   store volatile i64 %val7, ptr@h7
536   call void @foo()
538   store volatile i64 %newval0, ptr@h0
539   store volatile i64 %newval1, ptr@h1
540   store volatile i64 %val2, ptr@h2
541   store volatile i64 %val3, ptr@h3
542   store volatile i64 %val4, ptr@h4
543   store volatile i64 %val5, ptr@h5
544   store volatile i64 %val6, ptr@h6
545   store volatile i64 %val7, ptr@h7
547   ret void