1 ; Test spilling using MVC.
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
29 ; This function shouldn't spill anything
30 define void @f1(i32 *%ptr0) {
33 ; CHECK: aghi %r15, -160
35 ; CHECK: brasl %r14, foo@PLT
39 %ptr1 = getelementptr i32 *%ptr0, i32 2
40 %ptr2 = getelementptr i32 *%ptr0, i32 4
41 %ptr3 = getelementptr i32 *%ptr0, i32 6
42 %ptr4 = getelementptr i32 *%ptr0, i32 8
43 %ptr5 = getelementptr i32 *%ptr0, i32 10
44 %ptr6 = getelementptr i32 *%ptr0, i32 12
46 %val0 = load i32 *%ptr0
47 %val1 = load i32 *%ptr1
48 %val2 = load i32 *%ptr2
49 %val3 = load i32 *%ptr3
50 %val4 = load i32 *%ptr4
51 %val5 = load i32 *%ptr5
52 %val6 = load i32 *%ptr6
56 store i32 %val0, i32 *%ptr0
57 store i32 %val1, i32 *%ptr1
58 store i32 %val2, i32 *%ptr2
59 store i32 %val3, i32 *%ptr3
60 store i32 %val4, i32 *%ptr4
61 store i32 %val5, i32 *%ptr5
62 store i32 %val6, i32 *%ptr6
67 ; Test a case where at least one i32 load and at least one i32 store
69 define void @f2(i32 *%ptr0) {
71 ; CHECK: mvc [[OFFSET1:16[04]]](4,%r15), [[OFFSET2:[0-9]+]]({{%r[0-9]+}})
72 ; CHECK: brasl %r14, foo@PLT
73 ; CHECK: mvc [[OFFSET2]](4,{{%r[0-9]+}}), [[OFFSET1]](%r15)
75 %ptr1 = getelementptr i32 *%ptr0, i64 2
76 %ptr2 = getelementptr i32 *%ptr0, i64 4
77 %ptr3 = getelementptr i32 *%ptr0, i64 6
78 %ptr4 = getelementptr i32 *%ptr0, i64 8
79 %ptr5 = getelementptr i32 *%ptr0, i64 10
80 %ptr6 = getelementptr i32 *%ptr0, i64 12
81 %ptr7 = getelementptr i32 *%ptr0, i64 14
82 %ptr8 = getelementptr i32 *%ptr0, i64 16
84 %val0 = load i32 *%ptr0
85 %val1 = load i32 *%ptr1
86 %val2 = load i32 *%ptr2
87 %val3 = load i32 *%ptr3
88 %val4 = load i32 *%ptr4
89 %val5 = load i32 *%ptr5
90 %val6 = load i32 *%ptr6
91 %val7 = load i32 *%ptr7
92 %val8 = load i32 *%ptr8
96 store i32 %val0, i32 *%ptr0
97 store i32 %val1, i32 *%ptr1
98 store i32 %val2, i32 *%ptr2
99 store i32 %val3, i32 *%ptr3
100 store i32 %val4, i32 *%ptr4
101 store i32 %val5, i32 *%ptr5
102 store i32 %val6, i32 *%ptr6
103 store i32 %val7, i32 *%ptr7
104 store i32 %val8, i32 *%ptr8
109 ; Test a case where at least one i64 load and at least one i64 store
111 define void @f3(i64 *%ptr0) {
113 ; CHECK: mvc 160(8,%r15), [[OFFSET:[0-9]+]]({{%r[0-9]+}})
114 ; CHECK: brasl %r14, foo@PLT
115 ; CHECK: mvc [[OFFSET]](8,{{%r[0-9]+}}), 160(%r15)
117 %ptr1 = getelementptr i64 *%ptr0, i64 2
118 %ptr2 = getelementptr i64 *%ptr0, i64 4
119 %ptr3 = getelementptr i64 *%ptr0, i64 6
120 %ptr4 = getelementptr i64 *%ptr0, i64 8
121 %ptr5 = getelementptr i64 *%ptr0, i64 10
122 %ptr6 = getelementptr i64 *%ptr0, i64 12
123 %ptr7 = getelementptr i64 *%ptr0, i64 14
124 %ptr8 = getelementptr i64 *%ptr0, i64 16
126 %val0 = load i64 *%ptr0
127 %val1 = load i64 *%ptr1
128 %val2 = load i64 *%ptr2
129 %val3 = load i64 *%ptr3
130 %val4 = load i64 *%ptr4
131 %val5 = load i64 *%ptr5
132 %val6 = load i64 *%ptr6
133 %val7 = load i64 *%ptr7
134 %val8 = load i64 *%ptr8
138 store i64 %val0, i64 *%ptr0
139 store i64 %val1, i64 *%ptr1
140 store i64 %val2, i64 *%ptr2
141 store i64 %val3, i64 *%ptr3
142 store i64 %val4, i64 *%ptr4
143 store i64 %val5, i64 *%ptr5
144 store i64 %val6, i64 *%ptr6
145 store i64 %val7, i64 *%ptr7
146 store i64 %val8, i64 *%ptr8
152 ; Test a case where at least at least one f32 load and at least one f32 store
153 ; need spills. The 8 call-saved FPRs could be used for 8 of the %vals
154 ; (and are at the time of writing), but it would really be better to use
156 define void @f4(float *%ptr0) {
158 ; CHECK: mvc [[OFFSET1:16[04]]](4,%r15), [[OFFSET2:[0-9]+]]({{%r[0-9]+}})
159 ; CHECK: brasl %r14, foo@PLT
160 ; CHECK: mvc [[OFFSET2]](4,{{%r[0-9]+}}), [[OFFSET1]](%r15)
162 %ptr1 = getelementptr float *%ptr0, i64 2
163 %ptr2 = getelementptr float *%ptr0, i64 4
164 %ptr3 = getelementptr float *%ptr0, i64 6
165 %ptr4 = getelementptr float *%ptr0, i64 8
166 %ptr5 = getelementptr float *%ptr0, i64 10
167 %ptr6 = getelementptr float *%ptr0, i64 12
168 %ptr7 = getelementptr float *%ptr0, i64 14
169 %ptr8 = getelementptr float *%ptr0, i64 16
170 %ptr9 = getelementptr float *%ptr0, i64 18
172 %val0 = load float *%ptr0
173 %val1 = load float *%ptr1
174 %val2 = load float *%ptr2
175 %val3 = load float *%ptr3
176 %val4 = load float *%ptr4
177 %val5 = load float *%ptr5
178 %val6 = load float *%ptr6
179 %val7 = load float *%ptr7
180 %val8 = load float *%ptr8
181 %val9 = load float *%ptr9
185 store float %val0, float *%ptr0
186 store float %val1, float *%ptr1
187 store float %val2, float *%ptr2
188 store float %val3, float *%ptr3
189 store float %val4, float *%ptr4
190 store float %val5, float *%ptr5
191 store float %val6, float *%ptr6
192 store float %val7, float *%ptr7
193 store float %val8, float *%ptr8
194 store float %val9, float *%ptr9
200 define void @f5(double *%ptr0) {
202 ; CHECK: mvc 160(8,%r15), [[OFFSET:[0-9]+]]({{%r[0-9]+}})
203 ; CHECK: brasl %r14, foo@PLT
204 ; CHECK: mvc [[OFFSET]](8,{{%r[0-9]+}}), 160(%r15)
206 %ptr1 = getelementptr double *%ptr0, i64 2
207 %ptr2 = getelementptr double *%ptr0, i64 4
208 %ptr3 = getelementptr double *%ptr0, i64 6
209 %ptr4 = getelementptr double *%ptr0, i64 8
210 %ptr5 = getelementptr double *%ptr0, i64 10
211 %ptr6 = getelementptr double *%ptr0, i64 12
212 %ptr7 = getelementptr double *%ptr0, i64 14
213 %ptr8 = getelementptr double *%ptr0, i64 16
214 %ptr9 = getelementptr double *%ptr0, i64 18
216 %val0 = load double *%ptr0
217 %val1 = load double *%ptr1
218 %val2 = load double *%ptr2
219 %val3 = load double *%ptr3
220 %val4 = load double *%ptr4
221 %val5 = load double *%ptr5
222 %val6 = load double *%ptr6
223 %val7 = load double *%ptr7
224 %val8 = load double *%ptr8
225 %val9 = load double *%ptr9
229 store double %val0, double *%ptr0
230 store double %val1, double *%ptr1
231 store double %val2, double *%ptr2
232 store double %val3, double *%ptr3
233 store double %val4, double *%ptr4
234 store double %val5, double *%ptr5
235 store double %val6, double *%ptr6
236 store double %val7, double *%ptr7
237 store double %val8, double *%ptr8
238 store double %val9, double *%ptr9
243 ; Repeat f2 with atomic accesses. We shouldn't use MVC here.
244 define void @f6(i32 *%ptr0) {
248 %ptr1 = getelementptr i32 *%ptr0, i64 2
249 %ptr2 = getelementptr i32 *%ptr0, i64 4
250 %ptr3 = getelementptr i32 *%ptr0, i64 6
251 %ptr4 = getelementptr i32 *%ptr0, i64 8
252 %ptr5 = getelementptr i32 *%ptr0, i64 10
253 %ptr6 = getelementptr i32 *%ptr0, i64 12
254 %ptr7 = getelementptr i32 *%ptr0, i64 14
255 %ptr8 = getelementptr i32 *%ptr0, i64 16
257 %val0 = load atomic i32 *%ptr0 unordered, align 4
258 %val1 = load atomic i32 *%ptr1 unordered, align 4
259 %val2 = load atomic i32 *%ptr2 unordered, align 4
260 %val3 = load atomic i32 *%ptr3 unordered, align 4
261 %val4 = load atomic i32 *%ptr4 unordered, align 4
262 %val5 = load atomic i32 *%ptr5 unordered, align 4
263 %val6 = load atomic i32 *%ptr6 unordered, align 4
264 %val7 = load atomic i32 *%ptr7 unordered, align 4
265 %val8 = load atomic i32 *%ptr8 unordered, align 4
269 store atomic i32 %val0, i32 *%ptr0 unordered, align 4
270 store atomic i32 %val1, i32 *%ptr1 unordered, align 4
271 store atomic i32 %val2, i32 *%ptr2 unordered, align 4
272 store atomic i32 %val3, i32 *%ptr3 unordered, align 4
273 store atomic i32 %val4, i32 *%ptr4 unordered, align 4
274 store atomic i32 %val5, i32 *%ptr5 unordered, align 4
275 store atomic i32 %val6, i32 *%ptr6 unordered, align 4
276 store atomic i32 %val7, i32 *%ptr7 unordered, align 4
277 store atomic i32 %val8, i32 *%ptr8 unordered, align 4
282 ; ...likewise volatile accesses.
283 define void @f7(i32 *%ptr0) {
287 %ptr1 = getelementptr i32 *%ptr0, i64 2
288 %ptr2 = getelementptr i32 *%ptr0, i64 4
289 %ptr3 = getelementptr i32 *%ptr0, i64 6
290 %ptr4 = getelementptr i32 *%ptr0, i64 8
291 %ptr5 = getelementptr i32 *%ptr0, i64 10
292 %ptr6 = getelementptr i32 *%ptr0, i64 12
293 %ptr7 = getelementptr i32 *%ptr0, i64 14
294 %ptr8 = getelementptr i32 *%ptr0, i64 16
296 %val0 = load volatile i32 *%ptr0
297 %val1 = load volatile i32 *%ptr1
298 %val2 = load volatile i32 *%ptr2
299 %val3 = load volatile i32 *%ptr3
300 %val4 = load volatile i32 *%ptr4
301 %val5 = load volatile i32 *%ptr5
302 %val6 = load volatile i32 *%ptr6
303 %val7 = load volatile i32 *%ptr7
304 %val8 = load volatile i32 *%ptr8
308 store volatile i32 %val0, i32 *%ptr0
309 store volatile i32 %val1, i32 *%ptr1
310 store volatile i32 %val2, i32 *%ptr2
311 store volatile i32 %val3, i32 *%ptr3
312 store volatile i32 %val4, i32 *%ptr4
313 store volatile i32 %val5, i32 *%ptr5
314 store volatile i32 %val6, i32 *%ptr6
315 store volatile i32 %val7, i32 *%ptr7
316 store volatile i32 %val8, i32 *%ptr8
321 ; Check that LRL and STRL are not converted.
326 %val0 = load i32 *@g0
327 %val1 = load i32 *@g1
328 %val2 = load i32 *@g2
329 %val3 = load i32 *@g3
330 %val4 = load i32 *@g4
331 %val5 = load i32 *@g5
332 %val6 = load i32 *@g6
333 %val7 = load i32 *@g7
334 %val8 = load i32 *@g8
335 %val9 = load i32 *@g9
339 store i32 %val0, i32 *@g0
340 store i32 %val1, i32 *@g1
341 store i32 %val2, i32 *@g2
342 store i32 %val3, i32 *@g3
343 store i32 %val4, i32 *@g4
344 store i32 %val5, i32 *@g5
345 store i32 %val6, i32 *@g6
346 store i32 %val7, i32 *@g7
347 store i32 %val8, i32 *@g8
348 store i32 %val9, i32 *@g9
353 ; Likewise LGRL and STGRL.
358 %val0 = load i64 *@h0
359 %val1 = load i64 *@h1
360 %val2 = load i64 *@h2
361 %val3 = load i64 *@h3
362 %val4 = load i64 *@h4
363 %val5 = load i64 *@h5
364 %val6 = load i64 *@h6
365 %val7 = load i64 *@h7
366 %val8 = load i64 *@h8
367 %val9 = load i64 *@h9
371 store i64 %val0, i64 *@h0
372 store i64 %val1, i64 *@h1
373 store i64 %val2, i64 *@h2
374 store i64 %val3, i64 *@h3
375 store i64 %val4, i64 *@h4
376 store i64 %val5, i64 *@h5
377 store i64 %val6, i64 *@h6
378 store i64 %val7, i64 *@h7
379 store i64 %val8, i64 *@h8
380 store i64 %val9, i64 *@h9
385 ; This showed a problem with the way stack coloring updated instructions.
386 ; The copy from %val9 to %newval8 can be done using an MVC, which then
387 ; has two frame index operands. Stack coloring chose a valid renumbering
388 ; [FI0, FI1] -> [FI1, FI2], but applied it in the form FI0 -> FI1 -> FI2,
389 ; so that both operands ended up being the same.
392 ; CHECK: lgrl [[REG:%r[0-9]+]], h9
393 ; CHECK: stg [[REG]], [[VAL9:[0-9]+]](%r15)
394 ; CHECK: brasl %r14, foo@PLT
395 ; CHECK: brasl %r14, foo@PLT
396 ; CHECK: mvc [[NEWVAL8:[0-9]+]](8,%r15), [[VAL9]](%r15)
397 ; CHECK: brasl %r14, foo@PLT
398 ; CHECK: lg [[REG:%r[0-9]+]], [[NEWVAL8]](%r15)
399 ; CHECK: stgrl [[REG]], h8
402 %val0 = load volatile i64 *@h0
403 %val1 = load volatile i64 *@h1
404 %val2 = load volatile i64 *@h2
405 %val3 = load volatile i64 *@h3
406 %val4 = load volatile i64 *@h4
407 %val5 = load volatile i64 *@h5
408 %val6 = load volatile i64 *@h6
409 %val7 = load volatile i64 *@h7
410 %val8 = load volatile i64 *@h8
411 %val9 = load volatile i64 *@h9
415 store volatile i64 %val0, i64 *@h0
416 store volatile i64 %val1, i64 *@h1
417 store volatile i64 %val2, i64 *@h2
418 store volatile i64 %val3, i64 *@h3
419 store volatile i64 %val4, i64 *@h4
420 store volatile i64 %val5, i64 *@h5
421 store volatile i64 %val6, i64 *@h6
422 store volatile i64 %val7, i64 *@h7
424 %check = load volatile i64 *@h0
425 %cond = icmp eq i64 %check, 0
426 br i1 %cond, label %skip, label %fallthru
431 store volatile i64 %val0, i64 *@h0
432 store volatile i64 %val1, i64 *@h1
433 store volatile i64 %val2, i64 *@h2
434 store volatile i64 %val3, i64 *@h3
435 store volatile i64 %val4, i64 *@h4
436 store volatile i64 %val5, i64 *@h5
437 store volatile i64 %val6, i64 *@h6
438 store volatile i64 %val7, i64 *@h7
439 store volatile i64 %val8, i64 *@h8
443 %newval8 = phi i64 [ %val8, %entry ], [ %val9, %fallthru ]
446 store volatile i64 %val0, i64 *@h0
447 store volatile i64 %val1, i64 *@h1
448 store volatile i64 %val2, i64 *@h2
449 store volatile i64 %val3, i64 *@h3
450 store volatile i64 %val4, i64 *@h4
451 store volatile i64 %val5, i64 *@h5
452 store volatile i64 %val6, i64 *@h6
453 store volatile i64 %val7, i64 *@h7
454 store volatile i64 %newval8, i64 *@h8
455 store volatile i64 %val9, i64 *@h9
460 ; This used to generate a no-op MVC. It is very sensitive to spill heuristics.
463 ; CHECK-NOT: mvc [[OFFSET:[0-9]+]](8,%r15), [[OFFSET]](%r15)
466 %val0 = load volatile i64 *@h0
467 %val1 = load volatile i64 *@h1
468 %val2 = load volatile i64 *@h2
469 %val3 = load volatile i64 *@h3
470 %val4 = load volatile i64 *@h4
471 %val5 = load volatile i64 *@h5
472 %val6 = load volatile i64 *@h6
473 %val7 = load volatile i64 *@h7
475 %altval0 = load volatile i64 *@h0
476 %altval1 = load volatile i64 *@h1
480 store volatile i64 %val0, i64 *@h0
481 store volatile i64 %val1, i64 *@h1
482 store volatile i64 %val2, i64 *@h2
483 store volatile i64 %val3, i64 *@h3
484 store volatile i64 %val4, i64 *@h4
485 store volatile i64 %val5, i64 *@h5
486 store volatile i64 %val6, i64 *@h6
487 store volatile i64 %val7, i64 *@h7
489 %check = load volatile i64 *@h0
490 %cond = icmp eq i64 %check, 0
491 br i1 %cond, label %a1, label %b1
502 %newval0 = phi i64 [ %val0, %a1 ], [ %altval0, %b1 ]
506 store volatile i64 %val1, i64 *@h1
507 store volatile i64 %val2, i64 *@h2
508 store volatile i64 %val3, i64 *@h3
509 store volatile i64 %val4, i64 *@h4
510 store volatile i64 %val5, i64 *@h5
511 store volatile i64 %val6, i64 *@h6
512 store volatile i64 %val7, i64 *@h7
513 br i1 %cond, label %a2, label %b2
524 %newval1 = phi i64 [ %val1, %a2 ], [ %altval1, %b2 ]
528 store volatile i64 %val2, i64 *@h2
529 store volatile i64 %val3, i64 *@h3
530 store volatile i64 %val4, i64 *@h4
531 store volatile i64 %val5, i64 *@h5
532 store volatile i64 %val6, i64 *@h6
533 store volatile i64 %val7, i64 *@h7
537 store volatile i64 %newval0, i64 *@h0
538 store volatile i64 %newval1, i64 *@h1
539 store volatile i64 %val2, i64 *@h2
540 store volatile i64 %val3, i64 *@h3
541 store volatile i64 %val4, i64 *@h4
542 store volatile i64 %val5, i64 *@h5
543 store volatile i64 %val6, i64 *@h6
544 store volatile i64 %val7, i64 *@h7