[Stack realignment] Handling of aligned allocas.
[oota-llvm.git] / test / CodeGen / SystemZ / cond-store-04.ll
1 ; Test 64-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(i64 *)
6
7 ; Test with the loaded value first.
8 define void @f1(i64 *%ptr, i64 %alt, i32 %limit) {
9 ; CHECK-LABEL: f1:
10 ; CHECK-NOT: %r2
11 ; CHECK: jl [[LABEL:[^ ]*]]
12 ; CHECK-NOT: %r2
13 ; CHECK: stg %r3, 0(%r2)
14 ; CHECK: [[LABEL]]:
15 ; CHECK: br %r14
16   %cond = icmp ult i32 %limit, 420
17   %orig = load i64 , i64 *%ptr
18   %res = select i1 %cond, i64 %orig, i64 %alt
19   store i64 %res, i64 *%ptr
20   ret void
21 }
22
23 ; ...and with the loaded value second
24 define void @f2(i64 *%ptr, i64 %alt, i32 %limit) {
25 ; CHECK-LABEL: f2:
26 ; CHECK-NOT: %r2
27 ; CHECK: jhe [[LABEL:[^ ]*]]
28 ; CHECK-NOT: %r2
29 ; CHECK: stg %r3, 0(%r2)
30 ; CHECK: [[LABEL]]:
31 ; CHECK: br %r14
32   %cond = icmp ult i32 %limit, 420
33   %orig = load i64 , i64 *%ptr
34   %res = select i1 %cond, i64 %alt, i64 %orig
35   store i64 %res, i64 *%ptr
36   ret void
37 }
38
39 ; Check the high end of the aligned STG range.
40 define void @f3(i64 *%base, i64 %alt, i32 %limit) {
41 ; CHECK-LABEL: f3:
42 ; CHECK-NOT: %r2
43 ; CHECK: jl [[LABEL:[^ ]*]]
44 ; CHECK-NOT: %r2
45 ; CHECK: stg %r3, 524280(%r2)
46 ; CHECK: [[LABEL]]:
47 ; CHECK: br %r14
48   %ptr = getelementptr i64, i64 *%base, i64 65535
49   %cond = icmp ult i32 %limit, 420
50   %orig = load i64 , i64 *%ptr
51   %res = select i1 %cond, i64 %orig, i64 %alt
52   store i64 %res, i64 *%ptr
53   ret void
54 }
55
56 ; Check the next doubleword up, which needs separate address logic.
57 ; Other sequences besides this one would be OK.
58 define void @f4(i64 *%base, i64 %alt, i32 %limit) {
59 ; CHECK-LABEL: f4:
60 ; CHECK-NOT: %r2
61 ; CHECK: jl [[LABEL:[^ ]*]]
62 ; CHECK-NOT: %r2
63 ; CHECK: agfi %r2, 524288
64 ; CHECK: stg %r3, 0(%r2)
65 ; CHECK: [[LABEL]]:
66 ; CHECK: br %r14
67   %ptr = getelementptr i64, i64 *%base, i64 65536
68   %cond = icmp ult i32 %limit, 420
69   %orig = load i64 , i64 *%ptr
70   %res = select i1 %cond, i64 %orig, i64 %alt
71   store i64 %res, i64 *%ptr
72   ret void
73 }
74
75 ; Check the low end of the STG range.
76 define void @f5(i64 *%base, i64 %alt, i32 %limit) {
77 ; CHECK-LABEL: f5:
78 ; CHECK-NOT: %r2
79 ; CHECK: jl [[LABEL:[^ ]*]]
80 ; CHECK-NOT: %r2
81 ; CHECK: stg %r3, -524288(%r2)
82 ; CHECK: [[LABEL]]:
83 ; CHECK: br %r14
84   %ptr = getelementptr i64, i64 *%base, i64 -65536
85   %cond = icmp ult i32 %limit, 420
86   %orig = load i64 , i64 *%ptr
87   %res = select i1 %cond, i64 %orig, i64 %alt
88   store i64 %res, i64 *%ptr
89   ret void
90 }
91
92 ; Check the next doubleword down, which needs separate address logic.
93 ; Other sequences besides this one would be OK.
94 define void @f6(i64 *%base, i64 %alt, i32 %limit) {
95 ; CHECK-LABEL: f6:
96 ; CHECK-NOT: %r2
97 ; CHECK: jl [[LABEL:[^ ]*]]
98 ; CHECK-NOT: %r2
99 ; CHECK: agfi %r2, -524296
100 ; CHECK: stg %r3, 0(%r2)
101 ; CHECK: [[LABEL]]:
102 ; CHECK: br %r14
103   %ptr = getelementptr i64, i64 *%base, i64 -65537
104   %cond = icmp ult i32 %limit, 420
105   %orig = load i64 , i64 *%ptr
106   %res = select i1 %cond, i64 %orig, i64 %alt
107   store i64 %res, i64 *%ptr
108   ret void
109 }
110
111 ; Check that STG allows an index.
112 define void @f7(i64 %base, i64 %index, i64 %alt, i32 %limit) {
113 ; CHECK-LABEL: f7:
114 ; CHECK-NOT: %r2
115 ; CHECK: jl [[LABEL:[^ ]*]]
116 ; CHECK-NOT: %r2
117 ; CHECK: stg %r4, 524287(%r3,%r2)
118 ; CHECK: [[LABEL]]:
119 ; CHECK: br %r14
120   %add1 = add i64 %base, %index
121   %add2 = add i64 %add1, 524287
122   %ptr = inttoptr i64 %add2 to i64 *
123   %cond = icmp ult i32 %limit, 420
124   %orig = load i64 , i64 *%ptr
125   %res = select i1 %cond, i64 %orig, i64 %alt
126   store i64 %res, i64 *%ptr
127   ret void
128 }
129
130 ; Check that volatile loads are not matched.
131 define void @f8(i64 *%ptr, i64 %alt, i32 %limit) {
132 ; CHECK-LABEL: f8:
133 ; CHECK: lg {{%r[0-5]}}, 0(%r2)
134 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
135 ; CHECK: [[LABEL]]:
136 ; CHECK: stg {{%r[0-5]}}, 0(%r2)
137 ; CHECK: br %r14
138   %cond = icmp ult i32 %limit, 420
139   %orig = load volatile i64 , i64 *%ptr
140   %res = select i1 %cond, i64 %orig, i64 %alt
141   store i64 %res, i64 *%ptr
142   ret void
143 }
144
145 ; ...likewise stores.  In this case we should have a conditional load into %r3.
146 define void @f9(i64 *%ptr, i64 %alt, i32 %limit) {
147 ; CHECK-LABEL: f9:
148 ; CHECK: jhe [[LABEL:[^ ]*]]
149 ; CHECK: lg %r3, 0(%r2)
150 ; CHECK: [[LABEL]]:
151 ; CHECK: stg %r3, 0(%r2)
152 ; CHECK: br %r14
153   %cond = icmp ult i32 %limit, 420
154   %orig = load i64 , i64 *%ptr
155   %res = select i1 %cond, i64 %orig, i64 %alt
156   store volatile i64 %res, i64 *%ptr
157   ret void
158 }
159
160 ; Check that atomic loads are not matched.  The transformation is OK for
161 ; the "unordered" case tested here, but since we don't try to handle atomic
162 ; operations at all in this context, it seems better to assert that than
163 ; to restrict the test to a stronger ordering.
164 define void @f10(i64 *%ptr, i64 %alt, i32 %limit) {
165 ; FIXME: should use a normal load instead of CSG.
166 ; CHECK-LABEL: f10:
167 ; CHECK: lg {{%r[0-5]}}, 0(%r2)
168 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]
169 ; CHECK: [[LABEL]]:
170 ; CHECK: stg {{%r[0-5]}}, 0(%r2)
171 ; CHECK: br %r14
172   %cond = icmp ult i32 %limit, 420
173   %orig = load atomic i64 , i64 *%ptr unordered, align 8
174   %res = select i1 %cond, i64 %orig, i64 %alt
175   store i64 %res, i64 *%ptr
176   ret void
177 }
178
179 ; ...likewise stores.
180 define void @f11(i64 *%ptr, i64 %alt, i32 %limit) {
181 ; FIXME: should use a normal store instead of CSG.
182 ; CHECK-LABEL: f11:
183 ; CHECK: jhe [[LABEL:[^ ]*]]
184 ; CHECK: lg %r3, 0(%r2)
185 ; CHECK: [[LABEL]]:
186 ; CHECK: stg %r3, 0(%r2)
187 ; CHECK: br %r14
188   %cond = icmp ult i32 %limit, 420
189   %orig = load i64 , i64 *%ptr
190   %res = select i1 %cond, i64 %orig, i64 %alt
191   store atomic i64 %res, i64 *%ptr unordered, align 8
192   ret void
193 }
194
195 ; Try a frame index base.
196 define void @f12(i64 %alt, i32 %limit) {
197 ; CHECK-LABEL: f12:
198 ; CHECK: brasl %r14, foo@PLT
199 ; CHECK-NOT: %r15
200 ; CHECK: jl [[LABEL:[^ ]*]]
201 ; CHECK-NOT: %r15
202 ; CHECK: stg {{%r[0-9]+}}, {{[0-9]+}}(%r15)
203 ; CHECK: [[LABEL]]:
204 ; CHECK: brasl %r14, foo@PLT
205 ; CHECK: br %r14
206   %ptr = alloca i64
207   call void @foo(i64 *%ptr)
208   %cond = icmp ult i32 %limit, 420
209   %orig = load i64 , i64 *%ptr
210   %res = select i1 %cond, i64 %orig, i64 %alt
211   store i64 %res, i64 *%ptr
212   call void @foo(i64 *%ptr)
213   ret void
214 }