[MachineVerifier] Analyze MachineMemOperands for mem-to-mem moves.
[oota-llvm.git] / test / CodeGen / SystemZ / spill-01.ll
1 ; Test spilling using MVC.  The tests here assume z10 register pressure,
2 ; without the high words being available.
3 ;
4 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -verify-machineinstrs | FileCheck %s
5
6 declare void @foo()
7
8 @g0 = global i32 0
9 @g1 = global i32 1
10 @g2 = global i32 2
11 @g3 = global i32 3
12 @g4 = global i32 4
13 @g5 = global i32 5
14 @g6 = global i32 6
15 @g7 = global i32 7
16 @g8 = global i32 8
17 @g9 = global i32 9
18
19 @h0 = global i64 0
20 @h1 = global i64 1
21 @h2 = global i64 2
22 @h3 = global i64 3
23 @h4 = global i64 4
24 @h5 = global i64 5
25 @h6 = global i64 6
26 @h7 = global i64 7
27 @h8 = global i64 8
28 @h9 = global i64 9
29
30 ; This function shouldn't spill anything
31 define void @f1(i32 *%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, i32 *%ptr0, i32 2
41   %ptr2 = getelementptr i32, i32 *%ptr0, i32 4
42   %ptr3 = getelementptr i32, i32 *%ptr0, i32 6
43   %ptr4 = getelementptr i32, i32 *%ptr0, i32 8
44   %ptr5 = getelementptr i32, i32 *%ptr0, i32 10
45   %ptr6 = getelementptr i32, i32 *%ptr0, i32 12
46
47   %val0 = load i32 , i32 *%ptr0
48   %val1 = load i32 , i32 *%ptr1
49   %val2 = load i32 , i32 *%ptr2
50   %val3 = load i32 , i32 *%ptr3
51   %val4 = load i32 , i32 *%ptr4
52   %val5 = load i32 , i32 *%ptr5
53   %val6 = load i32 , i32 *%ptr6
54
55   call void @foo()
56
57   store i32 %val0, i32 *%ptr0
58   store i32 %val1, i32 *%ptr1
59   store i32 %val2, i32 *%ptr2
60   store i32 %val3, i32 *%ptr3
61   store i32 %val4, i32 *%ptr4
62   store i32 %val5, i32 *%ptr5
63   store i32 %val6, i32 *%ptr6
64
65   ret void
66 }
67
68 ; Test a case where at least one i32 load and at least one i32 store
69 ; need spills.
70 define void @f2(i32 *%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, i32 *%ptr0, i64 2
77   %ptr2 = getelementptr i32, i32 *%ptr0, i64 4
78   %ptr3 = getelementptr i32, i32 *%ptr0, i64 6
79   %ptr4 = getelementptr i32, i32 *%ptr0, i64 8
80   %ptr5 = getelementptr i32, i32 *%ptr0, i64 10
81   %ptr6 = getelementptr i32, i32 *%ptr0, i64 12
82   %ptr7 = getelementptr i32, i32 *%ptr0, i64 14
83   %ptr8 = getelementptr i32, i32 *%ptr0, i64 16
84
85   %val0 = load i32 , i32 *%ptr0
86   %val1 = load i32 , i32 *%ptr1
87   %val2 = load i32 , i32 *%ptr2
88   %val3 = load i32 , i32 *%ptr3
89   %val4 = load i32 , i32 *%ptr4
90   %val5 = load i32 , i32 *%ptr5
91   %val6 = load i32 , i32 *%ptr6
92   %val7 = load i32 , i32 *%ptr7
93   %val8 = load i32 , i32 *%ptr8
94
95   call void @foo()
96
97   store i32 %val0, i32 *%ptr0
98   store i32 %val1, i32 *%ptr1
99   store i32 %val2, i32 *%ptr2
100   store i32 %val3, i32 *%ptr3
101   store i32 %val4, i32 *%ptr4
102   store i32 %val5, i32 *%ptr5
103   store i32 %val6, i32 *%ptr6
104   store i32 %val7, i32 *%ptr7
105   store i32 %val8, i32 *%ptr8
106
107   ret void
108 }
109
110 ; Test a case where at least one i64 load and at least one i64 store
111 ; need spills.
112 define void @f3(i64 *%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, i64 *%ptr0, i64 2
119   %ptr2 = getelementptr i64, i64 *%ptr0, i64 4
120   %ptr3 = getelementptr i64, i64 *%ptr0, i64 6
121   %ptr4 = getelementptr i64, i64 *%ptr0, i64 8
122   %ptr5 = getelementptr i64, i64 *%ptr0, i64 10
123   %ptr6 = getelementptr i64, i64 *%ptr0, i64 12
124   %ptr7 = getelementptr i64, i64 *%ptr0, i64 14
125   %ptr8 = getelementptr i64, i64 *%ptr0, i64 16
126
127   %val0 = load i64 , i64 *%ptr0
128   %val1 = load i64 , i64 *%ptr1
129   %val2 = load i64 , i64 *%ptr2
130   %val3 = load i64 , i64 *%ptr3
131   %val4 = load i64 , i64 *%ptr4
132   %val5 = load i64 , i64 *%ptr5
133   %val6 = load i64 , i64 *%ptr6
134   %val7 = load i64 , i64 *%ptr7
135   %val8 = load i64 , i64 *%ptr8
136
137   call void @foo()
138
139   store i64 %val0, i64 *%ptr0
140   store i64 %val1, i64 *%ptr1
141   store i64 %val2, i64 *%ptr2
142   store i64 %val3, i64 *%ptr3
143   store i64 %val4, i64 *%ptr4
144   store i64 %val5, i64 *%ptr5
145   store i64 %val6, i64 *%ptr6
146   store i64 %val7, i64 *%ptr7
147   store i64 %val8, i64 *%ptr8
148
149   ret void
150 }
151
152
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 void @f4(float *%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, float *%ptr0, i64 2
164   %ptr2 = getelementptr float, float *%ptr0, i64 4
165   %ptr3 = getelementptr float, float *%ptr0, i64 6
166   %ptr4 = getelementptr float, float *%ptr0, i64 8
167   %ptr5 = getelementptr float, float *%ptr0, i64 10
168   %ptr6 = getelementptr float, float *%ptr0, i64 12
169   %ptr7 = getelementptr float, float *%ptr0, i64 14
170   %ptr8 = getelementptr float, float *%ptr0, i64 16
171   %ptr9 = getelementptr float, float *%ptr0, i64 18
172
173   %val0 = load float , float *%ptr0
174   %val1 = load float , float *%ptr1
175   %val2 = load float , float *%ptr2
176   %val3 = load float , float *%ptr3
177   %val4 = load float , float *%ptr4
178   %val5 = load float , float *%ptr5
179   %val6 = load float , float *%ptr6
180   %val7 = load float , float *%ptr7
181   %val8 = load float , float *%ptr8
182   %val9 = load float , float *%ptr9
183
184   call void @foo()
185
186   store float %val0, float *%ptr0
187   store float %val1, float *%ptr1
188   store float %val2, float *%ptr2
189   store float %val3, float *%ptr3
190   store float %val4, float *%ptr4
191   store float %val5, float *%ptr5
192   store float %val6, float *%ptr6
193   store float %val7, float *%ptr7
194   store float %val8, float *%ptr8
195   store float %val9, float *%ptr9
196
197   ret void
198 }
199
200 ; Similarly for f64.
201 define void @f5(double *%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, double *%ptr0, i64 2
208   %ptr2 = getelementptr double, double *%ptr0, i64 4
209   %ptr3 = getelementptr double, double *%ptr0, i64 6
210   %ptr4 = getelementptr double, double *%ptr0, i64 8
211   %ptr5 = getelementptr double, double *%ptr0, i64 10
212   %ptr6 = getelementptr double, double *%ptr0, i64 12
213   %ptr7 = getelementptr double, double *%ptr0, i64 14
214   %ptr8 = getelementptr double, double *%ptr0, i64 16
215   %ptr9 = getelementptr double, double *%ptr0, i64 18
216
217   %val0 = load double , double *%ptr0
218   %val1 = load double , double *%ptr1
219   %val2 = load double , double *%ptr2
220   %val3 = load double , double *%ptr3
221   %val4 = load double , double *%ptr4
222   %val5 = load double , double *%ptr5
223   %val6 = load double , double *%ptr6
224   %val7 = load double , double *%ptr7
225   %val8 = load double , double *%ptr8
226   %val9 = load double , double *%ptr9
227
228   call void @foo()
229
230   store double %val0, double *%ptr0
231   store double %val1, double *%ptr1
232   store double %val2, double *%ptr2
233   store double %val3, double *%ptr3
234   store double %val4, double *%ptr4
235   store double %val5, double *%ptr5
236   store double %val6, double *%ptr6
237   store double %val7, double *%ptr7
238   store double %val8, double *%ptr8
239   store double %val9, double *%ptr9
240
241   ret void
242 }
243
244 ; Repeat f2 with atomic accesses.  We shouldn't use MVC here.
245 define void @f6(i32 *%ptr0) {
246 ; CHECK-LABEL: f6:
247 ; CHECK-NOT: mvc
248 ; CHECK: br %r14
249   %ptr1 = getelementptr i32, i32 *%ptr0, i64 2
250   %ptr2 = getelementptr i32, i32 *%ptr0, i64 4
251   %ptr3 = getelementptr i32, i32 *%ptr0, i64 6
252   %ptr4 = getelementptr i32, i32 *%ptr0, i64 8
253   %ptr5 = getelementptr i32, i32 *%ptr0, i64 10
254   %ptr6 = getelementptr i32, i32 *%ptr0, i64 12
255   %ptr7 = getelementptr i32, i32 *%ptr0, i64 14
256   %ptr8 = getelementptr i32, i32 *%ptr0, i64 16
257
258   %val0 = load atomic i32 , i32 *%ptr0 unordered, align 4
259   %val1 = load atomic i32 , i32 *%ptr1 unordered, align 4
260   %val2 = load atomic i32 , i32 *%ptr2 unordered, align 4
261   %val3 = load atomic i32 , i32 *%ptr3 unordered, align 4
262   %val4 = load atomic i32 , i32 *%ptr4 unordered, align 4
263   %val5 = load atomic i32 , i32 *%ptr5 unordered, align 4
264   %val6 = load atomic i32 , i32 *%ptr6 unordered, align 4
265   %val7 = load atomic i32 , i32 *%ptr7 unordered, align 4
266   %val8 = load atomic i32 , i32 *%ptr8 unordered, align 4
267
268   call void @foo()
269
270   store atomic i32 %val0, i32 *%ptr0 unordered, align 4
271   store atomic i32 %val1, i32 *%ptr1 unordered, align 4
272   store atomic i32 %val2, i32 *%ptr2 unordered, align 4
273   store atomic i32 %val3, i32 *%ptr3 unordered, align 4
274   store atomic i32 %val4, i32 *%ptr4 unordered, align 4
275   store atomic i32 %val5, i32 *%ptr5 unordered, align 4
276   store atomic i32 %val6, i32 *%ptr6 unordered, align 4
277   store atomic i32 %val7, i32 *%ptr7 unordered, align 4
278   store atomic i32 %val8, i32 *%ptr8 unordered, align 4
279
280   ret void
281 }
282
283 ; ...likewise volatile accesses.
284 define void @f7(i32 *%ptr0) {
285 ; CHECK-LABEL: f7:
286 ; CHECK-NOT: mvc
287 ; CHECK: br %r14
288   %ptr1 = getelementptr i32, i32 *%ptr0, i64 2
289   %ptr2 = getelementptr i32, i32 *%ptr0, i64 4
290   %ptr3 = getelementptr i32, i32 *%ptr0, i64 6
291   %ptr4 = getelementptr i32, i32 *%ptr0, i64 8
292   %ptr5 = getelementptr i32, i32 *%ptr0, i64 10
293   %ptr6 = getelementptr i32, i32 *%ptr0, i64 12
294   %ptr7 = getelementptr i32, i32 *%ptr0, i64 14
295   %ptr8 = getelementptr i32, i32 *%ptr0, i64 16
296
297   %val0 = load volatile i32 , i32 *%ptr0
298   %val1 = load volatile i32 , i32 *%ptr1
299   %val2 = load volatile i32 , i32 *%ptr2
300   %val3 = load volatile i32 , i32 *%ptr3
301   %val4 = load volatile i32 , i32 *%ptr4
302   %val5 = load volatile i32 , i32 *%ptr5
303   %val6 = load volatile i32 , i32 *%ptr6
304   %val7 = load volatile i32 , i32 *%ptr7
305   %val8 = load volatile i32 , i32 *%ptr8
306
307   call void @foo()
308
309   store volatile i32 %val0, i32 *%ptr0
310   store volatile i32 %val1, i32 *%ptr1
311   store volatile i32 %val2, i32 *%ptr2
312   store volatile i32 %val3, i32 *%ptr3
313   store volatile i32 %val4, i32 *%ptr4
314   store volatile i32 %val5, i32 *%ptr5
315   store volatile i32 %val6, i32 *%ptr6
316   store volatile i32 %val7, i32 *%ptr7
317   store volatile i32 %val8, i32 *%ptr8
318
319   ret void
320 }
321
322 ; Check that LRL and STRL are not converted.
323 define void @f8() {
324 ; CHECK-LABEL: f8:
325 ; CHECK-NOT: mvc
326 ; CHECK: br %r14
327   %val0 = load i32 , i32 *@g0
328   %val1 = load i32 , i32 *@g1
329   %val2 = load i32 , i32 *@g2
330   %val3 = load i32 , i32 *@g3
331   %val4 = load i32 , i32 *@g4
332   %val5 = load i32 , i32 *@g5
333   %val6 = load i32 , i32 *@g6
334   %val7 = load i32 , i32 *@g7
335   %val8 = load i32 , i32 *@g8
336   %val9 = load i32 , i32 *@g9
337
338   call void @foo()
339
340   store i32 %val0, i32 *@g0
341   store i32 %val1, i32 *@g1
342   store i32 %val2, i32 *@g2
343   store i32 %val3, i32 *@g3
344   store i32 %val4, i32 *@g4
345   store i32 %val5, i32 *@g5
346   store i32 %val6, i32 *@g6
347   store i32 %val7, i32 *@g7
348   store i32 %val8, i32 *@g8
349   store i32 %val9, i32 *@g9
350
351   ret void
352 }
353
354 ; Likewise LGRL and STGRL.
355 define void @f9() {
356 ; CHECK-LABEL: f9:
357 ; CHECK-NOT: mvc
358 ; CHECK: br %r14
359   %val0 = load i64 , i64 *@h0
360   %val1 = load i64 , i64 *@h1
361   %val2 = load i64 , i64 *@h2
362   %val3 = load i64 , i64 *@h3
363   %val4 = load i64 , i64 *@h4
364   %val5 = load i64 , i64 *@h5
365   %val6 = load i64 , i64 *@h6
366   %val7 = load i64 , i64 *@h7
367   %val8 = load i64 , i64 *@h8
368   %val9 = load i64 , i64 *@h9
369
370   call void @foo()
371
372   store i64 %val0, i64 *@h0
373   store i64 %val1, i64 *@h1
374   store i64 %val2, i64 *@h2
375   store i64 %val3, i64 *@h3
376   store i64 %val4, i64 *@h4
377   store i64 %val5, i64 *@h5
378   store i64 %val6, i64 *@h6
379   store i64 %val7, i64 *@h7
380   store i64 %val8, i64 *@h8
381   store i64 %val9, i64 *@h9
382
383   ret void
384 }
385
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 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 , i64 *@h8
404   %val0 = load volatile i64 , i64 *@h0
405   %val1 = load volatile i64 , i64 *@h1
406   %val2 = load volatile i64 , i64 *@h2
407   %val3 = load volatile i64 , i64 *@h3
408   %val4 = load volatile i64 , i64 *@h4
409   %val5 = load volatile i64 , i64 *@h5
410   %val6 = load volatile i64 , i64 *@h6
411   %val7 = load volatile i64 , i64 *@h7
412   %val9 = load volatile i64 , i64 *@h9
413
414   call void @foo()
415
416   store volatile i64 %val0, i64 *@h0
417   store volatile i64 %val1, i64 *@h1
418   store volatile i64 %val2, i64 *@h2
419   store volatile i64 %val3, i64 *@h3
420   store volatile i64 %val4, i64 *@h4
421   store volatile i64 %val5, i64 *@h5
422   store volatile i64 %val6, i64 *@h6
423   store volatile i64 %val7, i64 *@h7
424
425   %check = load volatile i64 , i64 *@h0
426   %cond = icmp eq i64 %check, 0
427   br i1 %cond, label %skip, label %fallthru
428
429 fallthru:
430   call void @foo()
431
432   store volatile i64 %val0, i64 *@h0
433   store volatile i64 %val1, i64 *@h1
434   store volatile i64 %val2, i64 *@h2
435   store volatile i64 %val3, i64 *@h3
436   store volatile i64 %val4, i64 *@h4
437   store volatile i64 %val5, i64 *@h5
438   store volatile i64 %val6, i64 *@h6
439   store volatile i64 %val7, i64 *@h7
440   store volatile i64 %val8, i64 *@h8
441   br label %skip
442
443 skip:
444   %newval8 = phi i64 [ %val8, %entry ], [ %val9, %fallthru ]
445   call void @foo()
446
447   store volatile i64 %val0, i64 *@h0
448   store volatile i64 %val1, i64 *@h1
449   store volatile i64 %val2, i64 *@h2
450   store volatile i64 %val3, i64 *@h3
451   store volatile i64 %val4, i64 *@h4
452   store volatile i64 %val5, i64 *@h5
453   store volatile i64 %val6, i64 *@h6
454   store volatile i64 %val7, i64 *@h7
455   store volatile i64 %newval8, i64 *@h8
456   store volatile i64 %val9, i64 *@h9
457
458   ret void
459 }
460
461 ; This used to generate a no-op MVC.  It is very sensitive to spill heuristics.
462 define 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 , i64 *@h0
468   %val1 = load volatile i64 , i64 *@h1
469   %val2 = load volatile i64 , i64 *@h2
470   %val3 = load volatile i64 , i64 *@h3
471   %val4 = load volatile i64 , i64 *@h4
472   %val5 = load volatile i64 , i64 *@h5
473   %val6 = load volatile i64 , i64 *@h6
474   %val7 = load volatile i64 , i64 *@h7
475
476   %altval0 = load volatile i64 , i64 *@h0
477   %altval1 = load volatile i64 , i64 *@h1
478
479   call void @foo()
480
481   store volatile i64 %val0, i64 *@h0
482   store volatile i64 %val1, i64 *@h1
483   store volatile i64 %val2, i64 *@h2
484   store volatile i64 %val3, i64 *@h3
485   store volatile i64 %val4, i64 *@h4
486   store volatile i64 %val5, i64 *@h5
487   store volatile i64 %val6, i64 *@h6
488   store volatile i64 %val7, i64 *@h7
489
490   %check = load volatile i64 , i64 *@h0
491   %cond = icmp eq i64 %check, 0
492   br i1 %cond, label %a1, label %b1
493
494 a1:
495   call void @foo()
496   br label %join1
497
498 b1:
499   call void @foo()
500   br label %join1
501
502 join1:
503   %newval0 = phi i64 [ %val0, %a1 ], [ %altval0, %b1 ]
504
505   call void @foo()
506
507   store volatile i64 %val1, i64 *@h1
508   store volatile i64 %val2, i64 *@h2
509   store volatile i64 %val3, i64 *@h3
510   store volatile i64 %val4, i64 *@h4
511   store volatile i64 %val5, i64 *@h5
512   store volatile i64 %val6, i64 *@h6
513   store volatile i64 %val7, i64 *@h7
514   br i1 %cond, label %a2, label %b2
515
516 a2:
517   call void @foo()
518   br label %join2
519
520 b2:
521   call void @foo()
522   br label %join2
523
524 join2:
525   %newval1 = phi i64 [ %val1, %a2 ], [ %altval1, %b2 ]
526
527   call void @foo()
528
529   store volatile i64 %val2, i64 *@h2
530   store volatile i64 %val3, i64 *@h3
531   store volatile i64 %val4, i64 *@h4
532   store volatile i64 %val5, i64 *@h5
533   store volatile i64 %val6, i64 *@h6
534   store volatile i64 %val7, i64 *@h7
535
536   call void @foo()
537
538   store volatile i64 %newval0, i64 *@h0
539   store volatile i64 %newval1, i64 *@h1
540   store volatile i64 %val2, i64 *@h2
541   store volatile i64 %val3, i64 *@h3
542   store volatile i64 %val4, i64 *@h4
543   store volatile i64 %val5, i64 *@h5
544   store volatile i64 %val6, i64 *@h6
545   store volatile i64 %val7, i64 *@h7
546
547   ret void
548 }