• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
6declare 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
31define 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.
70define 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.
112define 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.
157define 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.
201define 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.
245define 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.
284define 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.
323define 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.
355define 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.
391define 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
402entry:
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
429fallthru:
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
443skip:
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.
462define void @f11() {
463; CHECK-LABEL: f11:
464; CHECK-NOT: mvc [[OFFSET:[0-9]+]](8,%r15), [[OFFSET]](%r15)
465; CHECK: br %r14
466entry:
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
494a1:
495  call void @foo()
496  br label %join1
497
498b1:
499  call void @foo()
500  br label %join1
501
502join1:
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
516a2:
517  call void @foo()
518  br label %join2
519
520b2:
521  call void @foo()
522  br label %join2
523
524join2:
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}
549