[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / SystemZ / frame-15.ll
blob0595b5403b05c56cb73cf1d05d8e9690236cdfdf
1 ; Test the handling of base + index + 12-bit displacement addresses for
2 ; large frames, in cases where no 20-bit form exists.  The tests here
3 ; assume z10 register pressure, without the high words being available.
5 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | \
6 ; RUN:   FileCheck -check-prefix=CHECK-NOFP %s
7 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -frame-pointer=all | \
8 ; RUN:   FileCheck -check-prefix=CHECK-FP %s
10 declare void @foo(float *%ptr1, float *%ptr2)
12 ; This file tests what happens when a displacement is converted from
13 ; being relative to the start of a frame object to being relative to
14 ; the frame itself.  In some cases the test is only possible if two
15 ; objects are allocated.
17 ; Rather than rely on a particular order for those objects, the tests
18 ; instead allocate two objects of the same size and apply the test to
19 ; both of them.  For consistency, all tests follow this model, even if
20 ; one object would actually be enough.
22 ; First check the highest in-range offset after conversion, which is 4092
23 ; for word-addressing instructions like LDEB.
25 ; The last in-range doubleword offset is 4088.  Since the frame has two
26 ; emergency spill slots at 160(%r15), the amount that we need to allocate
27 ; in order to put another object at offset 4088 is (4088 - 176) / 4 = 978
28 ; words.
29 define void @f1(double *%dst) {
30 ; CHECK-NOFP-LABEL: f1:
31 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4092(%r15)
32 ; CHECK-NOFP: br %r14
34 ; CHECK-FP-LABEL: f1:
35 ; CHECK-FP: ldeb {{%f[0-7]}}, 4092(%r11)
36 ; CHECK-FP: br %r14
37   %region1 = alloca [978 x float], align 8
38   %region2 = alloca [978 x float], align 8
39   %start1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 0
40   %start2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 0
41   call void @foo(float *%start1, float *%start2)
42   %ptr1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 1
43   %ptr2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 1
44   %float1 = load float, float *%ptr1
45   %float2 = load float, float *%ptr2
46   %double1 = fpext float %float1 to double
47   %double2 = fpext float %float2 to double
48   store volatile double %double1, double *%dst
49   store volatile double %double2, double *%dst
50   ret void
53 ; Test the first out-of-range offset.
54 define void @f2(double *%dst) {
55 ; CHECK-NOFP-LABEL: f2:
56 ; CHECK-NOFP: lghi %r1, 4096
57 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 0(%r1,%r15)
58 ; CHECK-NOFP: br %r14
60 ; CHECK-FP-LABEL: f2:
61 ; CHECK-FP: lghi %r1, 4096
62 ; CHECK-FP: ldeb {{%f[0-7]}}, 0(%r1,%r11)
63 ; CHECK-FP: br %r14
64   %region1 = alloca [978 x float], align 8
65   %region2 = alloca [978 x float], align 8
66   %start1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 0
67   %start2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 0
68   call void @foo(float *%start1, float *%start2)
69   %ptr1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 2
70   %ptr2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 2
71   %float1 = load float, float *%ptr1
72   %float2 = load float, float *%ptr2
73   %double1 = fpext float %float1 to double
74   %double2 = fpext float %float2 to double
75   store volatile double %double1, double *%dst
76   store volatile double %double2, double *%dst
77   ret void
80 ; Test the next offset after that.
81 define void @f3(double *%dst) {
82 ; CHECK-NOFP-LABEL: f3:
83 ; CHECK-NOFP: lghi %r1, 4096
84 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4(%r1,%r15)
85 ; CHECK-NOFP: br %r14
87 ; CHECK-FP-LABEL: f3:
88 ; CHECK-FP: lghi %r1, 4096
89 ; CHECK-FP: ldeb {{%f[0-7]}}, 4(%r1,%r11)
90 ; CHECK-FP: br %r14
91   %region1 = alloca [978 x float], align 8
92   %region2 = alloca [978 x float], align 8
93   %start1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 0
94   %start2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 0
95   call void @foo(float *%start1, float *%start2)
96   %ptr1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 3
97   %ptr2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 3
98   %float1 = load float, float *%ptr1
99   %float2 = load float, float *%ptr2
100   %double1 = fpext float %float1 to double
101   %double2 = fpext float %float2 to double
102   store volatile double %double1, double *%dst
103   store volatile double %double2, double *%dst
104   ret void
107 ; Add 4096 bytes (1024 words) to the size of each object and repeat.
108 define void @f4(double *%dst) {
109 ; CHECK-NOFP-LABEL: f4:
110 ; CHECK-NOFP: lghi %r1, 4096
111 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4092(%r1,%r15)
112 ; CHECK-NOFP: br %r14
114 ; CHECK-FP-LABEL: f4:
115 ; CHECK-FP: lghi %r1, 4096
116 ; CHECK-FP: ldeb {{%f[0-7]}}, 4092(%r1,%r11)
117 ; CHECK-FP: br %r14
118   %region1 = alloca [2002 x float], align 8
119   %region2 = alloca [2002 x float], align 8
120   %start1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 0
121   %start2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 0
122   call void @foo(float *%start1, float *%start2)
123   %ptr1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 1
124   %ptr2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 1
125   %float1 = load float, float *%ptr1
126   %float2 = load float, float *%ptr2
127   %double1 = fpext float %float1 to double
128   %double2 = fpext float %float2 to double
129   store volatile double %double1, double *%dst
130   store volatile double %double2, double *%dst
131   ret void
134 ; ...as above.
135 define void @f5(double *%dst) {
136 ; CHECK-NOFP-LABEL: f5:
137 ; CHECK-NOFP: lghi %r1, 8192
138 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 0(%r1,%r15)
139 ; CHECK-NOFP: br %r14
141 ; CHECK-FP-LABEL: f5:
142 ; CHECK-FP: lghi %r1, 8192
143 ; CHECK-FP: ldeb {{%f[0-7]}}, 0(%r1,%r11)
144 ; CHECK-FP: br %r14
145   %region1 = alloca [2002 x float], align 8
146   %region2 = alloca [2002 x float], align 8
147   %start1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 0
148   %start2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 0
149   call void @foo(float *%start1, float *%start2)
150   %ptr1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 2
151   %ptr2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 2
152   %float1 = load float, float *%ptr1
153   %float2 = load float, float *%ptr2
154   %double1 = fpext float %float1 to double
155   %double2 = fpext float %float2 to double
156   store volatile double %double1, double *%dst
157   store volatile double %double2, double *%dst
158   ret void
161 ; ...as above.
162 define void @f6(double *%dst) {
163 ; CHECK-NOFP-LABEL: f6:
164 ; CHECK-NOFP: lghi %r1, 8192
165 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4(%r1,%r15)
166 ; CHECK-NOFP: br %r14
168 ; CHECK-FP-LABEL: f6:
169 ; CHECK-FP: lghi %r1, 8192
170 ; CHECK-FP: ldeb {{%f[0-7]}}, 4(%r1,%r11)
171 ; CHECK-FP: br %r14
172   %region1 = alloca [2002 x float], align 8
173   %region2 = alloca [2002 x float], align 8
174   %start1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 0
175   %start2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 0
176   call void @foo(float *%start1, float *%start2)
177   %ptr1 = getelementptr inbounds [2002 x float], [2002 x float]* %region1, i64 0, i64 3
178   %ptr2 = getelementptr inbounds [2002 x float], [2002 x float]* %region2, i64 0, i64 3
179   %float1 = load float, float *%ptr1
180   %float2 = load float, float *%ptr2
181   %double1 = fpext float %float1 to double
182   %double2 = fpext float %float2 to double
183   store volatile double %double1, double *%dst
184   store volatile double %double2, double *%dst
185   ret void
188 ; Now try an offset of 4092 from the start of the object, with the object
189 ; being at offset 8192.  This time we need objects of (8192 - 168) / 4 = 2004
190 ; words.
191 define void @f7(double *%dst) {
192 ; CHECK-NOFP-LABEL: f7:
193 ; CHECK-NOFP: lghi %r1, 8192
194 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4092(%r1,%r15)
195 ; CHECK-NOFP: br %r14
197 ; CHECK-FP-LABEL: f7:
198 ; CHECK-FP: lghi %r1, 8192
199 ; CHECK-FP: ldeb {{%f[0-7]}}, 4092(%r1,%r11)
200 ; CHECK-FP: br %r14
201   %region1 = alloca [2004 x float], align 8
202   %region2 = alloca [2004 x float], align 8
203   %start1 = getelementptr inbounds [2004 x float], [2004 x float]* %region1, i64 0, i64 0
204   %start2 = getelementptr inbounds [2004 x float], [2004 x float]* %region2, i64 0, i64 0
205   call void @foo(float *%start1, float *%start2)
206   %ptr1 = getelementptr inbounds [2004 x float], [2004 x float]* %region1, i64 0, i64 1023
207   %ptr2 = getelementptr inbounds [2004 x float], [2004 x float]* %region2, i64 0, i64 1023
208   %float1 = load float, float *%ptr1
209   %float2 = load float, float *%ptr2
210   %double1 = fpext float %float1 to double
211   %double2 = fpext float %float2 to double
212   store volatile double %double1, double *%dst
213   store volatile double %double2, double *%dst
214   ret void
217 ; Keep the object-relative offset the same but bump the size of the
218 ; objects by one doubleword.
219 define void @f8(double *%dst) {
220 ; CHECK-NOFP-LABEL: f8:
221 ; CHECK-NOFP: lghi %r1, 12288
222 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 4(%r1,%r15)
223 ; CHECK-NOFP: br %r14
225 ; CHECK-FP-LABEL: f8:
226 ; CHECK-FP: lghi %r1, 12288
227 ; CHECK-FP: ldeb {{%f[0-7]}}, 4(%r1,%r11)
228 ; CHECK-FP: br %r14
229   %region1 = alloca [2006 x float], align 8
230   %region2 = alloca [2006 x float], align 8
231   %start1 = getelementptr inbounds [2006 x float], [2006 x float]* %region1, i64 0, i64 0
232   %start2 = getelementptr inbounds [2006 x float], [2006 x float]* %region2, i64 0, i64 0
233   call void @foo(float *%start1, float *%start2)
234   %ptr1 = getelementptr inbounds [2006 x float], [2006 x float]* %region1, i64 0, i64 1023
235   %ptr2 = getelementptr inbounds [2006 x float], [2006 x float]* %region2, i64 0, i64 1023
236   %float1 = load float, float *%ptr1
237   %float2 = load float, float *%ptr2
238   %double1 = fpext float %float1 to double
239   %double2 = fpext float %float2 to double
240   store volatile double %double1, double *%dst
241   store volatile double %double2, double *%dst
242   ret void
245 ; Check a case where the original displacement is out of range.  The backend
246 ; should force an LAY from the outset.  We don't yet do any kind of anchor
247 ; optimization, so there should be no offset on the LDEB itself.
248 define void @f9(double *%dst) {
249 ; CHECK-NOFP-LABEL: f9:
250 ; CHECK-NOFP: lay %r1, 12296(%r15)
251 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 0(%r1)
252 ; CHECK-NOFP: br %r14
254 ; CHECK-FP-LABEL: f9:
255 ; CHECK-FP: lay %r1, 12296(%r11)
256 ; CHECK-FP: ldeb {{%f[0-7]}}, 0(%r1)
257 ; CHECK-FP: br %r14
258   %region1 = alloca [2006 x float], align 8
259   %region2 = alloca [2006 x float], align 8
260   %start1 = getelementptr inbounds [2006 x float], [2006 x float]* %region1, i64 0, i64 0
261   %start2 = getelementptr inbounds [2006 x float], [2006 x float]* %region2, i64 0, i64 0
262   call void @foo(float *%start1, float *%start2)
263   %ptr1 = getelementptr inbounds [2006 x float], [2006 x float]* %region1, i64 0, i64 1024
264   %ptr2 = getelementptr inbounds [2006 x float], [2006 x float]* %region2, i64 0, i64 1024
265   %float1 = load float, float *%ptr1
266   %float2 = load float, float *%ptr2
267   %double1 = fpext float %float1 to double
268   %double2 = fpext float %float2 to double
269   store volatile double %double1, double *%dst
270   store volatile double %double2, double *%dst
271   ret void
274 ; Repeat f2 in a case that needs the emergency spill slots, because all
275 ; call-clobbered and allocated call-saved registers are live.  Note that
276 ; %vptr and %dst are copied to call-saved registers, freeing up %r2 and
277 ; %r3 during the main test.
278 define void @f10(i32 *%vptr, double *%dst) {
279 ; CHECK-NOFP-LABEL: f10:
280 ; CHECK-NOFP: stg [[REGISTER:%r[1-9][0-4]?]], [[OFFSET:160|168]](%r15)
281 ; CHECK-NOFP: lghi [[REGISTER]], 4096
282 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r15)
283 ; CHECK-NOFP: lg [[REGISTER]], [[OFFSET]](%r15)
284 ; CHECK-NOFP: br %r14
286 ; CHECK-FP-LABEL: f10:
287 ; CHECK-FP: stg [[REGISTER:%r[1-9][0-4]?]], [[OFFSET:160|168]](%r11)
288 ; CHECK-FP: lghi [[REGISTER]], 4096
289 ; CHECK-FP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r11)
290 ; CHECK-FP: lg [[REGISTER]], [[OFFSET]](%r11)
291 ; CHECK-FP: br %r14
292   %region1 = alloca [978 x float], align 8
293   %region2 = alloca [978 x float], align 8
294   %start1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 0
295   %start2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 0
296   call void @foo(float *%start1, float *%start2)
297   %ptr1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 2
298   %ptr2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 2
299   %i0 = load volatile i32, i32 *%vptr
300   %i1 = load volatile i32, i32 *%vptr
301   %i2 = load volatile i32, i32 *%vptr
302   %i3 = load volatile i32, i32 *%vptr
303   %i4 = load volatile i32, i32 *%vptr
304   %i5 = load volatile i32, i32 *%vptr
305   %i14 = load volatile i32, i32 *%vptr
306   %float1 = load float, float *%ptr1
307   %float2 = load float, float *%ptr2
308   %double1 = fpext float %float1 to double
309   %double2 = fpext float %float2 to double
310   store volatile double %double1, double *%dst
311   store volatile double %double2, double *%dst
312   store volatile i32 %i0, i32 *%vptr
313   store volatile i32 %i1, i32 *%vptr
314   store volatile i32 %i2, i32 *%vptr
315   store volatile i32 %i3, i32 *%vptr
316   store volatile i32 %i4, i32 *%vptr
317   store volatile i32 %i5, i32 *%vptr
318   store volatile i32 %i14, i32 *%vptr
319   ret void
322 ; Repeat f2 in a case where the index register is already occupied.
323 define void @f11(double *%dst, i64 %index) {
324 ; CHECK-NOFP-LABEL: f11:
325 ; CHECK-NOFP: lgr [[REGISTER:%r[1-9][0-5]?]], %r3
326 ; CHECK-NOFP: lay %r1, 4096(%r15)
327 ; CHECK-NOFP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r1)
328 ; CHECK-NOFP: br %r14
330 ; CHECK-FP-LABEL: f11:
331 ; CHECK-FP: lgr [[REGISTER:%r[1-9][0-5]?]], %r3
332 ; CHECK-FP: lay %r1, 4096(%r11)
333 ; CHECK-FP: ldeb {{%f[0-7]}}, 0([[REGISTER]],%r1)
334 ; CHECK-FP: br %r14
335   %region1 = alloca [978 x float], align 8
336   %region2 = alloca [978 x float], align 8
337   %start1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 0
338   %start2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 0
339   call void @foo(float *%start1, float *%start2)
340   %elem1 = getelementptr inbounds [978 x float], [978 x float]* %region1, i64 0, i64 2
341   %elem2 = getelementptr inbounds [978 x float], [978 x float]* %region2, i64 0, i64 2
342   %base1 = ptrtoint float *%elem1 to i64
343   %base2 = ptrtoint float *%elem2 to i64
344   %addr1 = add i64 %base1, %index
345   %addr2 = add i64 %base2, %index
346   %ptr1 = inttoptr i64 %addr1 to float *
347   %ptr2 = inttoptr i64 %addr2 to float *
348   %float1 = load float, float *%ptr1
349   %float2 = load float, float *%ptr2
350   %double1 = fpext float %float1 to double
351   %double2 = fpext float %float2 to double
352   store volatile double %double1, double *%dst
353   store volatile double %double2, double *%dst
354   ret void