Merging r260427:
[oota-llvm.git] / test / CodeGen / SystemZ / cond-store-01.ll
1 ; Test 8-bit conditional stores that are presented as selects.  The volatile
2 ; tests require z10, which use a branch instead of a LOCR.
3 ;
4 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s
5
6 declare void @foo(i8 *)
7
8 ; Test the simple case, with the loaded value first.
9 define void @f1(i8 *%ptr, i8 %alt, i32 %limit) {
10 ; CHECK-LABEL: f1:
11 ; CHECK-NOT: %r2
12 ; CHECK: jl [[LABEL:[^ ]*]]
13 ; CHECK-NOT: %r2
14 ; CHECK: stc %r3, 0(%r2)
15 ; CHECK: [[LABEL]]:
16 ; CHECK: br %r14
17   %cond = icmp ult i32 %limit, 420
18   %orig = load i8 , i8 *%ptr
19   %res = select i1 %cond, i8 %orig, i8 %alt
20   store i8 %res, i8 *%ptr
21   ret void
22 }
23
24 ; ...and with the loaded value second
25 define void @f2(i8 *%ptr, i8 %alt, i32 %limit) {
26 ; CHECK-LABEL: f2:
27 ; CHECK-NOT: %r2
28 ; CHECK: jhe [[LABEL:[^ ]*]]
29 ; CHECK-NOT: %r2
30 ; CHECK: stc %r3, 0(%r2)
31 ; CHECK: [[LABEL]]:
32 ; CHECK: br %r14
33   %cond = icmp ult i32 %limit, 420
34   %orig = load i8 , i8 *%ptr
35   %res = select i1 %cond, i8 %alt, i8 %orig
36   store i8 %res, i8 *%ptr
37   ret void
38 }
39
40 ; Test cases where the value is explicitly sign-extended to 32 bits, with the
41 ; loaded value first.
42 define void @f3(i8 *%ptr, i32 %alt, i32 %limit) {
43 ; CHECK-LABEL: f3:
44 ; CHECK-NOT: %r2
45 ; CHECK: jl [[LABEL:[^ ]*]]
46 ; CHECK-NOT: %r2
47 ; CHECK: stc %r3, 0(%r2)
48 ; CHECK: [[LABEL]]:
49 ; CHECK: br %r14
50   %cond = icmp ult i32 %limit, 420
51   %orig = load i8 , i8 *%ptr
52   %ext = sext i8 %orig to i32
53   %res = select i1 %cond, i32 %ext, i32 %alt
54   %trunc = trunc i32 %res to i8
55   store i8 %trunc, i8 *%ptr
56   ret void
57 }
58
59 ; ...and with the loaded value second
60 define void @f4(i8 *%ptr, i32 %alt, i32 %limit) {
61 ; CHECK-LABEL: f4:
62 ; CHECK-NOT: %r2
63 ; CHECK: jhe [[LABEL:[^ ]*]]
64 ; CHECK-NOT: %r2
65 ; CHECK: stc %r3, 0(%r2)
66 ; CHECK: [[LABEL]]:
67 ; CHECK: br %r14
68   %cond = icmp ult i32 %limit, 420
69   %orig = load i8 , i8 *%ptr
70   %ext = sext i8 %orig to i32
71   %res = select i1 %cond, i32 %alt, i32 %ext
72   %trunc = trunc i32 %res to i8
73   store i8 %trunc, i8 *%ptr
74   ret void
75 }
76
77 ; Test cases where the value is explicitly zero-extended to 32 bits, with the
78 ; loaded value first.
79 define void @f5(i8 *%ptr, i32 %alt, i32 %limit) {
80 ; CHECK-LABEL: f5:
81 ; CHECK-NOT: %r2
82 ; CHECK: jl [[LABEL:[^ ]*]]
83 ; CHECK-NOT: %r2
84 ; CHECK: stc %r3, 0(%r2)
85 ; CHECK: [[LABEL]]:
86 ; CHECK: br %r14
87   %cond = icmp ult i32 %limit, 420
88   %orig = load i8 , i8 *%ptr
89   %ext = zext i8 %orig to i32
90   %res = select i1 %cond, i32 %ext, i32 %alt
91   %trunc = trunc i32 %res to i8
92   store i8 %trunc, i8 *%ptr
93   ret void
94 }
95
96 ; ...and with the loaded value second
97 define void @f6(i8 *%ptr, i32 %alt, i32 %limit) {
98 ; CHECK-LABEL: f6:
99 ; CHECK-NOT: %r2
100 ; CHECK: jhe [[LABEL:[^ ]*]]
101 ; CHECK-NOT: %r2
102 ; CHECK: stc %r3, 0(%r2)
103 ; CHECK: [[LABEL]]:
104 ; CHECK: br %r14
105   %cond = icmp ult i32 %limit, 420
106   %orig = load i8 , i8 *%ptr
107   %ext = zext i8 %orig to i32
108   %res = select i1 %cond, i32 %alt, i32 %ext
109   %trunc = trunc i32 %res to i8
110   store i8 %trunc, i8 *%ptr
111   ret void
112 }
113
114 ; Test cases where the value is explicitly sign-extended to 64 bits, with the
115 ; loaded value first.
116 define void @f7(i8 *%ptr, i64 %alt, i32 %limit) {
117 ; CHECK-LABEL: f7:
118 ; CHECK-NOT: %r2
119 ; CHECK: jl [[LABEL:[^ ]*]]
120 ; CHECK-NOT: %r2
121 ; CHECK: stc %r3, 0(%r2)
122 ; CHECK: [[LABEL]]:
123 ; CHECK: br %r14
124   %cond = icmp ult i32 %limit, 420
125   %orig = load i8 , i8 *%ptr
126   %ext = sext i8 %orig to i64
127   %res = select i1 %cond, i64 %ext, i64 %alt
128   %trunc = trunc i64 %res to i8
129   store i8 %trunc, i8 *%ptr
130   ret void
131 }
132
133 ; ...and with the loaded value second
134 define void @f8(i8 *%ptr, i64 %alt, i32 %limit) {
135 ; CHECK-LABEL: f8:
136 ; CHECK-NOT: %r2
137 ; CHECK: jhe [[LABEL:[^ ]*]]
138 ; CHECK-NOT: %r2
139 ; CHECK: stc %r3, 0(%r2)
140 ; CHECK: [[LABEL]]:
141 ; CHECK: br %r14
142   %cond = icmp ult i32 %limit, 420
143   %orig = load i8 , i8 *%ptr
144   %ext = sext i8 %orig to i64
145   %res = select i1 %cond, i64 %alt, i64 %ext
146   %trunc = trunc i64 %res to i8
147   store i8 %trunc, i8 *%ptr
148   ret void
149 }
150
151 ; Test cases where the value is explicitly zero-extended to 64 bits, with the
152 ; loaded value first.
153 define void @f9(i8 *%ptr, i64 %alt, i32 %limit) {
154 ; CHECK-LABEL: f9:
155 ; CHECK-NOT: %r2
156 ; CHECK: jl [[LABEL:[^ ]*]]
157 ; CHECK-NOT: %r2
158 ; CHECK: stc %r3, 0(%r2)
159 ; CHECK: [[LABEL]]:
160 ; CHECK: br %r14
161   %cond = icmp ult i32 %limit, 420
162   %orig = load i8 , i8 *%ptr
163   %ext = zext i8 %orig to i64
164   %res = select i1 %cond, i64 %ext, i64 %alt
165   %trunc = trunc i64 %res to i8
166   store i8 %trunc, i8 *%ptr
167   ret void
168 }
169
170 ; ...and with the loaded value second
171 define void @f10(i8 *%ptr, i64 %alt, i32 %limit) {
172 ; CHECK-LABEL: f10:
173 ; CHECK-NOT: %r2
174 ; CHECK: jhe [[LABEL:[^ ]*]]
175 ; CHECK-NOT: %r2
176 ; CHECK: stc %r3, 0(%r2)
177 ; CHECK: [[LABEL]]:
178 ; CHECK: br %r14
179   %cond = icmp ult i32 %limit, 420
180   %orig = load i8 , i8 *%ptr
181   %ext = zext i8 %orig to i64
182   %res = select i1 %cond, i64 %alt, i64 %ext
183   %trunc = trunc i64 %res to i8
184   store i8 %trunc, i8 *%ptr
185   ret void
186 }
187
188 ; Check the high end of the STC range.
189 define void @f11(i8 *%base, i8 %alt, i32 %limit) {
190 ; CHECK-LABEL: f11:
191 ; CHECK-NOT: %r2
192 ; CHECK: jl [[LABEL:[^ ]*]]
193 ; CHECK-NOT: %r2
194 ; CHECK: stc %r3, 4095(%r2)
195 ; CHECK: [[LABEL]]:
196 ; CHECK: br %r14
197   %ptr = getelementptr i8, i8 *%base, i64 4095
198   %cond = icmp ult i32 %limit, 420
199   %orig = load i8 , i8 *%ptr
200   %res = select i1 %cond, i8 %orig, i8 %alt
201   store i8 %res, i8 *%ptr
202   ret void
203 }
204
205 ; Check the next byte up, which should use STCY instead of STC.
206 define void @f12(i8 *%base, i8 %alt, i32 %limit) {
207 ; CHECK-LABEL: f12:
208 ; CHECK-NOT: %r2
209 ; CHECK: jl [[LABEL:[^ ]*]]
210 ; CHECK-NOT: %r2
211 ; CHECK: stcy %r3, 4096(%r2)
212 ; CHECK: [[LABEL]]:
213 ; CHECK: br %r14
214   %ptr = getelementptr i8, i8 *%base, i64 4096
215   %cond = icmp ult i32 %limit, 420
216   %orig = load i8 , i8 *%ptr
217   %res = select i1 %cond, i8 %orig, i8 %alt
218   store i8 %res, i8 *%ptr
219   ret void
220 }
221
222 ; Check the high end of the STCY range.
223 define void @f13(i8 *%base, i8 %alt, i32 %limit) {
224 ; CHECK-LABEL: f13:
225 ; CHECK-NOT: %r2
226 ; CHECK: jl [[LABEL:[^ ]*]]
227 ; CHECK-NOT: %r2
228 ; CHECK: stcy %r3, 524287(%r2)
229 ; CHECK: [[LABEL]]:
230 ; CHECK: br %r14
231   %ptr = getelementptr i8, i8 *%base, i64 524287
232   %cond = icmp ult i32 %limit, 420
233   %orig = load i8 , i8 *%ptr
234   %res = select i1 %cond, i8 %orig, i8 %alt
235   store i8 %res, i8 *%ptr
236   ret void
237 }
238
239 ; Check the next byte up, which needs separate address logic.
240 ; Other sequences besides this one would be OK.
241 define void @f14(i8 *%base, i8 %alt, i32 %limit) {
242 ; CHECK-LABEL: f14:
243 ; CHECK-NOT: %r2
244 ; CHECK: jl [[LABEL:[^ ]*]]
245 ; CHECK-NOT: %r2
246 ; CHECK: agfi %r2, 524288
247 ; CHECK: stc %r3, 0(%r2)
248 ; CHECK: [[LABEL]]:
249 ; CHECK: br %r14
250   %ptr = getelementptr i8, i8 *%base, i64 524288
251   %cond = icmp ult i32 %limit, 420
252   %orig = load i8 , i8 *%ptr
253   %res = select i1 %cond, i8 %orig, i8 %alt
254   store i8 %res, i8 *%ptr
255   ret void
256 }
257
258 ; Check the low end of the STCY range.
259 define void @f15(i8 *%base, i8 %alt, i32 %limit) {
260 ; CHECK-LABEL: f15:
261 ; CHECK-NOT: %r2
262 ; CHECK: jl [[LABEL:[^ ]*]]
263 ; CHECK-NOT: %r2
264 ; CHECK: stcy %r3, -524288(%r2)
265 ; CHECK: [[LABEL]]:
266 ; CHECK: br %r14
267   %ptr = getelementptr i8, i8 *%base, i64 -524288
268   %cond = icmp ult i32 %limit, 420
269   %orig = load i8 , i8 *%ptr
270   %res = select i1 %cond, i8 %orig, i8 %alt
271   store i8 %res, i8 *%ptr
272   ret void
273 }
274
275 ; Check the next byte down, which needs separate address logic.
276 ; Other sequences besides this one would be OK.
277 define void @f16(i8 *%base, i8 %alt, i32 %limit) {
278 ; CHECK-LABEL: f16:
279 ; CHECK-NOT: %r2
280 ; CHECK: jl [[LABEL:[^ ]*]]
281 ; CHECK-NOT: %r2
282 ; CHECK: agfi %r2, -524289
283 ; CHECK: stc %r3, 0(%r2)
284 ; CHECK: [[LABEL]]:
285 ; CHECK: br %r14
286   %ptr = getelementptr i8, i8 *%base, i64 -524289
287   %cond = icmp ult i32 %limit, 420
288   %orig = load i8 , i8 *%ptr
289   %res = select i1 %cond, i8 %orig, i8 %alt
290   store i8 %res, i8 *%ptr
291   ret void
292 }
293
294 ; Check that STCY allows an index.
295 define void @f17(i64 %base, i64 %index, i8 %alt, i32 %limit) {
296 ; CHECK-LABEL: f17:
297 ; CHECK-NOT: %r2
298 ; CHECK: jl [[LABEL:[^ ]*]]
299 ; CHECK-NOT: %r2
300 ; CHECK: stcy %r4, 4096(%r3,%r2)
301 ; CHECK: [[LABEL]]:
302 ; CHECK: br %r14
303   %add1 = add i64 %base, %index
304   %add2 = add i64 %add1, 4096
305   %ptr = inttoptr i64 %add2 to i8 *
306   %cond = icmp ult i32 %limit, 420
307   %orig = load i8 , i8 *%ptr
308   %res = select i1 %cond, i8 %orig, i8 %alt
309   store i8 %res, i8 *%ptr
310   ret void
311 }
312
313 ; Check that volatile loads are not matched.
314 define void @f18(i8 *%ptr, i8 %alt, i32 %limit) {
315 ; CHECK-LABEL: f18:
316 ; CHECK: lb {{%r[0-5]}}, 0(%r2)
317 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
318 ; CHECK: [[LABEL]]:
319 ; CHECK: stc {{%r[0-5]}}, 0(%r2)
320 ; CHECK: br %r14
321   %cond = icmp ult i32 %limit, 420
322   %orig = load volatile i8 , i8 *%ptr
323   %res = select i1 %cond, i8 %orig, i8 %alt
324   store i8 %res, i8 *%ptr
325   ret void
326 }
327
328 ; ...likewise stores.  In this case we should have a conditional load into %r3.
329 define void @f19(i8 *%ptr, i8 %alt, i32 %limit) {
330 ; CHECK-LABEL: f19:
331 ; CHECK: jhe [[LABEL:[^ ]*]]
332 ; CHECK: lb %r3, 0(%r2)
333 ; CHECK: [[LABEL]]:
334 ; CHECK: stc %r3, 0(%r2)
335 ; CHECK: br %r14
336   %cond = icmp ult i32 %limit, 420
337   %orig = load i8 , i8 *%ptr
338   %res = select i1 %cond, i8 %orig, i8 %alt
339   store volatile i8 %res, i8 *%ptr
340   ret void
341 }
342
343 ; Check that atomic loads are not matched.  The transformation is OK for
344 ; the "unordered" case tested here, but since we don't try to handle atomic
345 ; operations at all in this context, it seems better to assert that than
346 ; to restrict the test to a stronger ordering.
347 define void @f20(i8 *%ptr, i8 %alt, i32 %limit) {
348 ; FIXME: should use a normal load instead of CS.
349 ; CHECK-LABEL: f20:
350 ; CHECK: lb {{%r[0-9]+}}, 0(%r2)
351 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
352 ; CHECK: [[LABEL]]:
353 ; CHECK: stc {{%r[0-9]+}}, 0(%r2)
354 ; CHECK: br %r14
355   %cond = icmp ult i32 %limit, 420
356   %orig = load atomic i8 , i8 *%ptr unordered, align 1
357   %res = select i1 %cond, i8 %orig, i8 %alt
358   store i8 %res, i8 *%ptr
359   ret void
360 }
361
362 ; ...likewise stores.
363 define void @f21(i8 *%ptr, i8 %alt, i32 %limit) {
364 ; FIXME: should use a normal store instead of CS.
365 ; CHECK-LABEL: f21:
366 ; CHECK: jhe [[LABEL:[^ ]*]]
367 ; CHECK: lb %r3, 0(%r2)
368 ; CHECK: [[LABEL]]:
369 ; CHECK: stc %r3, 0(%r2)
370 ; CHECK: br %r14
371   %cond = icmp ult i32 %limit, 420
372   %orig = load i8 , i8 *%ptr
373   %res = select i1 %cond, i8 %orig, i8 %alt
374   store atomic i8 %res, i8 *%ptr unordered, align 1
375   ret void
376 }
377
378 ; Try a frame index base.
379 define void @f22(i8 %alt, i32 %limit) {
380 ; CHECK-LABEL: f22:
381 ; CHECK: brasl %r14, foo@PLT
382 ; CHECK-NOT: %r15
383 ; CHECK: jl [[LABEL:[^ ]*]]
384 ; CHECK-NOT: %r15
385 ; CHECK: stc {{%r[0-9]+}}, {{[0-9]+}}(%r15)
386 ; CHECK: [[LABEL]]:
387 ; CHECK: brasl %r14, foo@PLT
388 ; CHECK: br %r14
389   %ptr = alloca i8
390   call void @foo(i8 *%ptr)
391   %cond = icmp ult i32 %limit, 420
392   %orig = load i8 , i8 *%ptr
393   %res = select i1 %cond, i8 %orig, i8 %alt
394   store i8 %res, i8 *%ptr
395   call void @foo(i8 *%ptr)
396   ret void
397 }