1 ; Test 64-bit subtractions of constants from memory.
3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
7 ; Check subtraction of 1.
8 define zeroext i1 @f1(i64 *%ptr) {
10 ; CHECK: algsi 0(%r2), -1
11 ; CHECK: ipm [[REG:%r[0-5]]]
12 ; CHECK: afi [[REG]], -536870912
13 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
15 %a = load i64, i64 *%ptr
16 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
17 %val = extractvalue {i64, i1} %t, 0
18 %obit = extractvalue {i64, i1} %t, 1
19 store i64 %val, i64 *%ptr
23 ; Check the high end of the constant range.
24 define zeroext i1 @f2(i64 *%ptr) {
26 ; CHECK: algsi 0(%r2), -128
27 ; CHECK: ipm [[REG:%r[0-5]]]
28 ; CHECK: afi [[REG]], -536870912
29 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
31 %a = load i64, i64 *%ptr
32 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 128)
33 %val = extractvalue {i64, i1} %t, 0
34 %obit = extractvalue {i64, i1} %t, 1
35 store i64 %val, i64 *%ptr
39 ; Check the next constant up, which must use an addition and a store.
40 define zeroext i1 @f3(i64 %dummy, i64 *%ptr) {
42 ; CHECK: lg [[VAL:%r[0-5]]], 0(%r3)
43 ; CHECK: slgfi [[VAL]], 129
44 ; CHECK-DAG: stg [[VAL]], 0(%r3)
45 ; CHECK-DAG: ipm [[REG:%r[0-5]]]
46 ; CHECK-DAG: afi [[REG]], -536870912
47 ; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
49 %a = load i64, i64 *%ptr
50 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 129)
51 %val = extractvalue {i64, i1} %t, 0
52 %obit = extractvalue {i64, i1} %t, 1
53 store i64 %val, i64 *%ptr
57 ; Check the low end of the constant range.
58 define zeroext i1 @f4(i64 *%ptr) {
60 ; CHECK: algsi 0(%r2), 127
61 ; CHECK: ipm [[REG:%r[0-5]]]
62 ; CHECK: afi [[REG]], -536870912
63 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
65 %a = load i64, i64 *%ptr
66 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 -127)
67 %val = extractvalue {i64, i1} %t, 0
68 %obit = extractvalue {i64, i1} %t, 1
69 store i64 %val, i64 *%ptr
73 ; Check the next value down, with the same comment as f3.
74 define zeroext i1 @f5(i64 %dummy, i64 *%ptr) {
76 ; CHECK: lg [[VAL1:%r[0-5]]], 0(%r3)
77 ; CHECK: lghi [[VAL2:%r[0-9]+]], -128
78 ; CHECK: slgr [[VAL1]], [[VAL2]]
79 ; CHECK-DAG: stg [[VAL1]], 0(%r3)
80 ; CHECK-DAG: ipm [[REG:%r[0-5]]]
81 ; CHECK-DAG: afi [[REG]], -536870912
82 ; CHECK-DAG: risbg %r2, [[REG]], 63, 191, 33
84 %a = load i64, i64 *%ptr
85 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 -128)
86 %val = extractvalue {i64, i1} %t, 0
87 %obit = extractvalue {i64, i1} %t, 1
88 store i64 %val, i64 *%ptr
92 ; Check the high end of the aligned ALGSI range.
93 define zeroext i1 @f6(i64 *%base) {
95 ; CHECK: algsi 524280(%r2), -1
96 ; CHECK: ipm [[REG:%r[0-5]]]
97 ; CHECK: afi [[REG]], -536870912
98 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
100 %ptr = getelementptr i64, i64 *%base, i64 65535
101 %a = load i64, i64 *%ptr
102 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
103 %val = extractvalue {i64, i1} %t, 0
104 %obit = extractvalue {i64, i1} %t, 1
105 store i64 %val, i64 *%ptr
109 ; Check the next word up, which must use separate address logic.
110 ; Other sequences besides this one would be OK.
111 define zeroext i1 @f7(i64 *%base) {
113 ; CHECK: agfi %r2, 524288
114 ; CHECK: algsi 0(%r2), -1
115 ; CHECK: ipm [[REG:%r[0-5]]]
116 ; CHECK: afi [[REG]], -536870912
117 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
119 %ptr = getelementptr i64, i64 *%base, i64 65536
120 %a = load i64, i64 *%ptr
121 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
122 %val = extractvalue {i64, i1} %t, 0
123 %obit = extractvalue {i64, i1} %t, 1
124 store i64 %val, i64 *%ptr
128 ; Check the low end of the ALGSI range.
129 define zeroext i1 @f8(i64 *%base) {
131 ; CHECK: algsi -524288(%r2), -1
132 ; CHECK: ipm [[REG:%r[0-5]]]
133 ; CHECK: afi [[REG]], -536870912
134 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
136 %ptr = getelementptr i64, i64 *%base, i64 -65536
137 %a = load i64, i64 *%ptr
138 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
139 %val = extractvalue {i64, i1} %t, 0
140 %obit = extractvalue {i64, i1} %t, 1
141 store i64 %val, i64 *%ptr
145 ; Check the next word down, which must use separate address logic.
146 ; Other sequences besides this one would be OK.
147 define zeroext i1 @f9(i64 *%base) {
149 ; CHECK: agfi %r2, -524296
150 ; CHECK: algsi 0(%r2), -1
151 ; CHECK: ipm [[REG:%r[0-5]]]
152 ; CHECK: afi [[REG]], -536870912
153 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
155 %ptr = getelementptr i64, i64 *%base, i64 -65537
156 %a = load i64, i64 *%ptr
157 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
158 %val = extractvalue {i64, i1} %t, 0
159 %obit = extractvalue {i64, i1} %t, 1
160 store i64 %val, i64 *%ptr
164 ; Check that ALGSI does not allow indices.
165 define zeroext i1 @f10(i64 %base, i64 %index) {
167 ; CHECK: agr %r2, %r3
168 ; CHECK: algsi 8(%r2), -1
169 ; CHECK: ipm [[REG:%r[0-5]]]
170 ; CHECK: afi [[REG]], -536870912
171 ; CHECK: risbg %r2, [[REG]], 63, 191, 33
173 %add1 = add i64 %base, %index
174 %add2 = add i64 %add1, 8
175 %ptr = inttoptr i64 %add2 to i64 *
176 %a = load i64, i64 *%ptr
177 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
178 %val = extractvalue {i64, i1} %t, 0
179 %obit = extractvalue {i64, i1} %t, 1
180 store i64 %val, i64 *%ptr
184 ; Check that subtracting 128 from a spilled value can use ALGSI.
185 define zeroext i1 @f11(i64 *%ptr, i64 %sel) {
187 ; CHECK: algsi {{[0-9]+}}(%r15), -128
190 %val0 = load volatile i64, i64 *%ptr
191 %val1 = load volatile i64, i64 *%ptr
192 %val2 = load volatile i64, i64 *%ptr
193 %val3 = load volatile i64, i64 *%ptr
194 %val4 = load volatile i64, i64 *%ptr
195 %val5 = load volatile i64, i64 *%ptr
196 %val6 = load volatile i64, i64 *%ptr
197 %val7 = load volatile i64, i64 *%ptr
198 %val8 = load volatile i64, i64 *%ptr
199 %val9 = load volatile i64, i64 *%ptr
200 %val10 = load volatile i64, i64 *%ptr
201 %val11 = load volatile i64, i64 *%ptr
202 %val12 = load volatile i64, i64 *%ptr
203 %val13 = load volatile i64, i64 *%ptr
204 %val14 = load volatile i64, i64 *%ptr
205 %val15 = load volatile i64, i64 *%ptr
207 %test = icmp ne i64 %sel, 0
208 br i1 %test, label %add, label %store
211 %t0 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val0, i64 128)
212 %add0 = extractvalue {i64, i1} %t0, 0
213 %obit0 = extractvalue {i64, i1} %t0, 1
214 %t1 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val1, i64 128)
215 %add1 = extractvalue {i64, i1} %t1, 0
216 %obit1 = extractvalue {i64, i1} %t1, 1
217 %res1 = or i1 %obit0, %obit1
218 %t2 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val2, i64 128)
219 %add2 = extractvalue {i64, i1} %t2, 0
220 %obit2 = extractvalue {i64, i1} %t2, 1
221 %res2 = or i1 %res1, %obit2
222 %t3 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val3, i64 128)
223 %add3 = extractvalue {i64, i1} %t3, 0
224 %obit3 = extractvalue {i64, i1} %t3, 1
225 %res3 = or i1 %res2, %obit3
226 %t4 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val4, i64 128)
227 %add4 = extractvalue {i64, i1} %t4, 0
228 %obit4 = extractvalue {i64, i1} %t4, 1
229 %res4 = or i1 %res3, %obit4
230 %t5 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val5, i64 128)
231 %add5 = extractvalue {i64, i1} %t5, 0
232 %obit5 = extractvalue {i64, i1} %t5, 1
233 %res5 = or i1 %res4, %obit5
234 %t6 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val6, i64 128)
235 %add6 = extractvalue {i64, i1} %t6, 0
236 %obit6 = extractvalue {i64, i1} %t6, 1
237 %res6 = or i1 %res5, %obit6
238 %t7 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val7, i64 128)
239 %add7 = extractvalue {i64, i1} %t7, 0
240 %obit7 = extractvalue {i64, i1} %t7, 1
241 %res7 = or i1 %res6, %obit7
242 %t8 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val8, i64 128)
243 %add8 = extractvalue {i64, i1} %t8, 0
244 %obit8 = extractvalue {i64, i1} %t8, 1
245 %res8 = or i1 %res7, %obit8
246 %t9 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val9, i64 128)
247 %add9 = extractvalue {i64, i1} %t9, 0
248 %obit9 = extractvalue {i64, i1} %t9, 1
249 %res9 = or i1 %res8, %obit9
250 %t10 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val10, i64 128)
251 %add10 = extractvalue {i64, i1} %t10, 0
252 %obit10 = extractvalue {i64, i1} %t10, 1
253 %res10 = or i1 %res9, %obit10
254 %t11 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val11, i64 128)
255 %add11 = extractvalue {i64, i1} %t11, 0
256 %obit11 = extractvalue {i64, i1} %t11, 1
257 %res11 = or i1 %res10, %obit11
258 %t12 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val12, i64 128)
259 %add12 = extractvalue {i64, i1} %t12, 0
260 %obit12 = extractvalue {i64, i1} %t12, 1
261 %res12 = or i1 %res11, %obit12
262 %t13 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val13, i64 128)
263 %add13 = extractvalue {i64, i1} %t13, 0
264 %obit13 = extractvalue {i64, i1} %t13, 1
265 %res13 = or i1 %res12, %obit13
266 %t14 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val14, i64 128)
267 %add14 = extractvalue {i64, i1} %t14, 0
268 %obit14 = extractvalue {i64, i1} %t14, 1
269 %res14 = or i1 %res13, %obit14
270 %t15 = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val15, i64 128)
271 %add15 = extractvalue {i64, i1} %t15, 0
272 %obit15 = extractvalue {i64, i1} %t15, 1
273 %res15 = or i1 %res14, %obit15
278 %new0 = phi i64 [ %val0, %entry ], [ %add0, %add ]
279 %new1 = phi i64 [ %val1, %entry ], [ %add1, %add ]
280 %new2 = phi i64 [ %val2, %entry ], [ %add2, %add ]
281 %new3 = phi i64 [ %val3, %entry ], [ %add3, %add ]
282 %new4 = phi i64 [ %val4, %entry ], [ %add4, %add ]
283 %new5 = phi i64 [ %val5, %entry ], [ %add5, %add ]
284 %new6 = phi i64 [ %val6, %entry ], [ %add6, %add ]
285 %new7 = phi i64 [ %val7, %entry ], [ %add7, %add ]
286 %new8 = phi i64 [ %val8, %entry ], [ %add8, %add ]
287 %new9 = phi i64 [ %val9, %entry ], [ %add9, %add ]
288 %new10 = phi i64 [ %val10, %entry ], [ %add10, %add ]
289 %new11 = phi i64 [ %val11, %entry ], [ %add11, %add ]
290 %new12 = phi i64 [ %val12, %entry ], [ %add12, %add ]
291 %new13 = phi i64 [ %val13, %entry ], [ %add13, %add ]
292 %new14 = phi i64 [ %val14, %entry ], [ %add14, %add ]
293 %new15 = phi i64 [ %val15, %entry ], [ %add15, %add ]
294 %res = phi i1 [ 0, %entry ], [ %res15, %add ]
296 store volatile i64 %new0, i64 *%ptr
297 store volatile i64 %new1, i64 *%ptr
298 store volatile i64 %new2, i64 *%ptr
299 store volatile i64 %new3, i64 *%ptr
300 store volatile i64 %new4, i64 *%ptr
301 store volatile i64 %new5, i64 *%ptr
302 store volatile i64 %new6, i64 *%ptr
303 store volatile i64 %new7, i64 *%ptr
304 store volatile i64 %new8, i64 *%ptr
305 store volatile i64 %new9, i64 *%ptr
306 store volatile i64 %new10, i64 *%ptr
307 store volatile i64 %new11, i64 *%ptr
308 store volatile i64 %new12, i64 *%ptr
309 store volatile i64 %new13, i64 *%ptr
310 store volatile i64 %new14, i64 *%ptr
311 store volatile i64 %new15, i64 *%ptr
316 ; Check using the overflow result for a branch.
317 define void @f12(i64 *%ptr) {
319 ; CHECK: algsi 0(%r2), -1
320 ; CHECK: jgle foo@PLT
322 %a = load i64, i64 *%ptr
323 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
324 %val = extractvalue {i64, i1} %t, 0
325 %obit = extractvalue {i64, i1} %t, 1
326 store i64 %val, i64 *%ptr
327 br i1 %obit, label %call, label %exit
337 ; ... and the same with the inverted direction.
338 define void @f13(i64 *%ptr) {
340 ; CHECK: algsi 0(%r2), -1
341 ; CHECK: jgnle foo@PLT
343 %a = load i64, i64 *%ptr
344 %t = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 1)
345 %val = extractvalue {i64, i1} %t, 0
346 %obit = extractvalue {i64, i1} %t, 1
347 store i64 %val, i64 *%ptr
348 br i1 %obit, label %exit, label %call
358 declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) nounwind readnone