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