[NFC][RemoveDIs] Prefer iterators over inst-pointers in InstCombine
[llvm-project.git] / llvm / test / CodeGen / AArch64 / typepromotion-overflow.ll
blobccfbf456693d7a690e13ed9651a38a8731a2baed
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s
4 define zeroext i16 @overflow_add(i16 zeroext %a, i16 zeroext %b) {
5 ; CHECK-LABEL: overflow_add:
6 ; CHECK:       // %bb.0:
7 ; CHECK-NEXT:    add w9, w1, w0
8 ; CHECK-NEXT:    mov w8, #5 // =0x5
9 ; CHECK-NEXT:    orr w9, w9, #0x1
10 ; CHECK-NEXT:    and w9, w9, #0xffff
11 ; CHECK-NEXT:    cmp w9, #1024
12 ; CHECK-NEXT:    mov w9, #2 // =0x2
13 ; CHECK-NEXT:    csel w0, w9, w8, hi
14 ; CHECK-NEXT:    ret
15   %add = add i16 %b, %a
16   %or = or i16 %add, 1
17   %cmp = icmp ugt i16 %or, 1024
18   %res = select i1 %cmp, i16 2, i16 5
19   ret i16 %res
22 define zeroext i16 @overflow_sub(i16 zeroext %a, i16 zeroext %b) {
23 ; CHECK-LABEL: overflow_sub:
24 ; CHECK:       // %bb.0:
25 ; CHECK-NEXT:    sub w9, w0, w1
26 ; CHECK-NEXT:    mov w8, #5 // =0x5
27 ; CHECK-NEXT:    orr w9, w9, #0x1
28 ; CHECK-NEXT:    and w9, w9, #0xffff
29 ; CHECK-NEXT:    cmp w9, #1024
30 ; CHECK-NEXT:    mov w9, #2 // =0x2
31 ; CHECK-NEXT:    csel w0, w9, w8, hi
32 ; CHECK-NEXT:    ret
33   %add = sub i16 %a, %b
34   %or = or i16 %add, 1
35   %cmp = icmp ugt i16 %or, 1024
36   %res = select i1 %cmp, i16 2, i16 5
37   ret i16 %res
40 define zeroext i16 @overflow_mul(i16 zeroext %a, i16 zeroext %b) {
41 ; CHECK-LABEL: overflow_mul:
42 ; CHECK:       // %bb.0:
43 ; CHECK-NEXT:    mul w9, w1, w0
44 ; CHECK-NEXT:    mov w8, #5 // =0x5
45 ; CHECK-NEXT:    orr w9, w9, #0x1
46 ; CHECK-NEXT:    and w9, w9, #0xffff
47 ; CHECK-NEXT:    cmp w9, #1024
48 ; CHECK-NEXT:    mov w9, #2 // =0x2
49 ; CHECK-NEXT:    csel w0, w9, w8, hi
50 ; CHECK-NEXT:    ret
51   %add = mul i16 %b, %a
52   %or = or i16 %add, 1
53   %cmp = icmp ugt i16 %or, 1024
54   %res = select i1 %cmp, i16 2, i16 5
55   ret i16 %res
58 define zeroext i16 @overflow_shl(i16 zeroext %a, i16 zeroext %b) {
59 ; CHECK-LABEL: overflow_shl:
60 ; CHECK:       // %bb.0:
61 ; CHECK-NEXT:    lsl w9, w0, w1
62 ; CHECK-NEXT:    mov w8, #5 // =0x5
63 ; CHECK-NEXT:    orr w9, w9, #0x1
64 ; CHECK-NEXT:    and w9, w9, #0xffff
65 ; CHECK-NEXT:    cmp w9, #1024
66 ; CHECK-NEXT:    mov w9, #2 // =0x2
67 ; CHECK-NEXT:    csel w0, w9, w8, hi
68 ; CHECK-NEXT:    ret
69   %add = shl i16 %a, %b
70   %or = or i16 %add, 1
71   %cmp = icmp ugt i16 %or, 1024
72   %res = select i1 %cmp, i16 2, i16 5
73   ret i16 %res
76 define i32 @overflow_add_no_consts(i8 zeroext %a, i8 zeroext %b, i8 zeroext %limit) {
77 ; CHECK-LABEL: overflow_add_no_consts:
78 ; CHECK:       // %bb.0:
79 ; CHECK-NEXT:    add w8, w1, w0
80 ; CHECK-NEXT:    mov w9, #8 // =0x8
81 ; CHECK-NEXT:    cmp w2, w8, uxtb
82 ; CHECK-NEXT:    mov w8, #16 // =0x10
83 ; CHECK-NEXT:    csel w0, w9, w8, lo
84 ; CHECK-NEXT:    ret
85   %add = add i8 %b, %a
86   %cmp = icmp ugt i8 %add, %limit
87   %res = select i1 %cmp, i32 8, i32 16
88   ret i32 %res
91 define i32 @overflow_add_const_limit(i8 zeroext %a, i8 zeroext %b) {
92 ; CHECK-LABEL: overflow_add_const_limit:
93 ; CHECK:       // %bb.0:
94 ; CHECK-NEXT:    add w9, w1, w0
95 ; CHECK-NEXT:    mov w8, #16 // =0x10
96 ; CHECK-NEXT:    and w9, w9, #0xff
97 ; CHECK-NEXT:    cmp w9, #128
98 ; CHECK-NEXT:    mov w9, #8 // =0x8
99 ; CHECK-NEXT:    csel w0, w9, w8, hi
100 ; CHECK-NEXT:    ret
101   %add = add i8 %b, %a
102   %cmp = icmp ugt i8 %add, -128
103   %res = select i1 %cmp, i32 8, i32 16
104   ret i32 %res
107 define i32 @overflow_add_positive_const_limit(i8 zeroext %a) {
108 ; CHECK-LABEL: overflow_add_positive_const_limit:
109 ; CHECK:       // %bb.0:
110 ; CHECK-NEXT:    mov w8, #-1 // =0xffffffff
111 ; CHECK-NEXT:    mov w9, #8 // =0x8
112 ; CHECK-NEXT:    cmp w8, w0, sxtb
113 ; CHECK-NEXT:    mov w8, #16 // =0x10
114 ; CHECK-NEXT:    csel w0, w9, w8, gt
115 ; CHECK-NEXT:    ret
116   %cmp = icmp slt i8 %a, -1
117   %res = select i1 %cmp, i32 8, i32 16
118   ret i32 %res
121 define i32 @unsafe_add_underflow(i8 zeroext %a) {
122 ; CHECK-LABEL: unsafe_add_underflow:
123 ; CHECK:       // %bb.0:
124 ; CHECK-NEXT:    mov w8, #16 // =0x10
125 ; CHECK-NEXT:    cmp w0, #1
126 ; CHECK-NEXT:    mov w9, #8 // =0x8
127 ; CHECK-NEXT:    csel w0, w9, w8, eq
128 ; CHECK-NEXT:    ret
129   %cmp = icmp eq i8 %a, 1
130   %res = select i1 %cmp, i32 8, i32 16
131   ret i32 %res
134 define i32 @safe_add_underflow(i8 zeroext %a) {
135 ; CHECK-LABEL: safe_add_underflow:
136 ; CHECK:       // %bb.0:
137 ; CHECK-NEXT:    mov w8, #16 // =0x10
138 ; CHECK-NEXT:    cmp w0, #0
139 ; CHECK-NEXT:    mov w9, #8 // =0x8
140 ; CHECK-NEXT:    csel w0, w9, w8, eq
141 ; CHECK-NEXT:    ret
142   %cmp = icmp eq i8 %a, 0
143   %res = select i1 %cmp, i32 8, i32 16
144   ret i32 %res
147 define i32 @safe_add_underflow_neg(i8 zeroext %a) {
148 ; CHECK-LABEL: safe_add_underflow_neg:
149 ; CHECK:       // %bb.0:
150 ; CHECK-NEXT:    sub w9, w0, #2
151 ; CHECK-NEXT:    mov w8, #16 // =0x10
152 ; CHECK-NEXT:    cmp w9, #251
153 ; CHECK-NEXT:    mov w9, #8 // =0x8
154 ; CHECK-NEXT:    csel w0, w9, w8, lo
155 ; CHECK-NEXT:    ret
156   %add = add i8 %a, -2
157   %cmp = icmp ult i8 %add, -5
158   %res = select i1 %cmp, i32 8, i32 16
159   ret i32 %res
162 define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) {
163 ; CHECK-LABEL: overflow_sub_negative_const_limit:
164 ; CHECK:       // %bb.0:
165 ; CHECK-NEXT:    mov w8, #-1 // =0xffffffff
166 ; CHECK-NEXT:    mov w9, #8 // =0x8
167 ; CHECK-NEXT:    cmp w8, w0, sxtb
168 ; CHECK-NEXT:    mov w8, #16 // =0x10
169 ; CHECK-NEXT:    csel w0, w9, w8, gt
170 ; CHECK-NEXT:    ret
171   %cmp = icmp slt i8 %a, -1
172   %res = select i1 %cmp, i32 8, i32 16
173   ret i32 %res
176 ; This is valid so long as the icmp immediate is sext.
177 define i32 @sext_sub_underflow(i8 zeroext %a) {
178 ; CHECK-LABEL: sext_sub_underflow:
179 ; CHECK:       // %bb.0:
180 ; CHECK-NEXT:    sub w9, w0, #6
181 ; CHECK-NEXT:    mov w8, #16 // =0x10
182 ; CHECK-NEXT:    cmn w9, #6
183 ; CHECK-NEXT:    mov w9, #8 // =0x8
184 ; CHECK-NEXT:    csel w0, w9, w8, hi
185 ; CHECK-NEXT:    ret
186   %sub = add i8 %a, -6
187   %cmp = icmp ugt i8 %sub, -6
188   %res = select i1 %cmp, i32 8, i32 16
189   ret i32 %res
192 define i32 @safe_sub_underflow(i8 zeroext %a) {
193 ; CHECK-LABEL: safe_sub_underflow:
194 ; CHECK:       // %bb.0:
195 ; CHECK-NEXT:    mov w8, #8 // =0x8
196 ; CHECK-NEXT:    cmp w0, #0
197 ; CHECK-NEXT:    mov w9, #16 // =0x10
198 ; CHECK-NEXT:    csel w0, w9, w8, eq
199 ; CHECK-NEXT:    ret
200   %cmp.not = icmp eq i8 %a, 0
201   %res = select i1 %cmp.not, i32 16, i32 8
202   ret i32 %res
205 define i32 @safe_sub_underflow_neg(i8 zeroext %a) {
206 ; CHECK-LABEL: safe_sub_underflow_neg:
207 ; CHECK:       // %bb.0:
208 ; CHECK-NEXT:    sub w9, w0, #4
209 ; CHECK-NEXT:    mov w8, #16 // =0x10
210 ; CHECK-NEXT:    cmp w9, #250
211 ; CHECK-NEXT:    mov w9, #8 // =0x8
212 ; CHECK-NEXT:    csel w0, w9, w8, hi
213 ; CHECK-NEXT:    ret
214   %sub = add i8 %a, -4
215   %cmp = icmp ugt i8 %sub, -6
216   %res = select i1 %cmp, i32 8, i32 16
217   ret i32 %res
220 ; This is valid so long as the icmp immediate is sext.
221 define i32 @sext_sub_underflow_neg(i8 zeroext %a) {
222 ; CHECK-LABEL: sext_sub_underflow_neg:
223 ; CHECK:       // %bb.0:
224 ; CHECK-NEXT:    sub w9, w0, #4
225 ; CHECK-NEXT:    mov w8, #16 // =0x10
226 ; CHECK-NEXT:    cmn w9, #3
227 ; CHECK-NEXT:    mov w9, #8 // =0x8
228 ; CHECK-NEXT:    csel w0, w9, w8, lo
229 ; CHECK-NEXT:    ret
230   %sub = add i8 %a, -4
231   %cmp = icmp ult i8 %sub, -3
232   %res = select i1 %cmp, i32 8, i32 16
233   ret i32 %res
236 define i32 @safe_sub_imm_var(ptr nocapture readonly %b) local_unnamed_addr #1 {
237 ; CHECK-LABEL: safe_sub_imm_var:
238 ; CHECK:       // %bb.0: // %entry
239 ; CHECK-NEXT:    mov w0, wzr
240 ; CHECK-NEXT:    ret
241 entry:
242   ret i32 0
245 define i32 @safe_sub_var_imm(ptr nocapture readonly %b) local_unnamed_addr #1 {
246 ; CHECK-LABEL: safe_sub_var_imm:
247 ; CHECK:       // %bb.0: // %entry
248 ; CHECK-NEXT:    ldrb w8, [x0]
249 ; CHECK-NEXT:    add w8, w8, #8
250 ; CHECK-NEXT:    and w8, w8, #0xff
251 ; CHECK-NEXT:    cmp w8, #252
252 ; CHECK-NEXT:    cset w0, hi
253 ; CHECK-NEXT:    ret
254 entry:
255   %0 = load i8, ptr %b, align 1
256   %sub = add nsw i8 %0, 8
257   %cmp = icmp ugt i8 %sub, -4
258   %conv4 = zext i1 %cmp to i32
259   ret i32 %conv4
262 define i32 @safe_add_imm_var(ptr nocapture readnone %b) {
263 ; CHECK-LABEL: safe_add_imm_var:
264 ; CHECK:       // %bb.0: // %entry
265 ; CHECK-NEXT:    mov w0, #1 // =0x1
266 ; CHECK-NEXT:    ret
267 entry:
268   ret i32 1
271 define i32 @safe_add_var_imm(ptr nocapture readnone %b) {
272 ; CHECK-LABEL: safe_add_var_imm:
273 ; CHECK:       // %bb.0: // %entry
274 ; CHECK-NEXT:    mov w0, #1 // =0x1
275 ; CHECK-NEXT:    ret
276 entry:
277   ret i32 1
280 define i8 @convert_add_order(i8 zeroext %arg) {
281 ; CHECK-LABEL: convert_add_order:
282 ; CHECK:       // %bb.0:
283 ; CHECK-NEXT:    orr w9, w0, #0x1
284 ; CHECK-NEXT:    mov w8, #1 // =0x1
285 ; CHECK-NEXT:    sub w10, w9, #40
286 ; CHECK-NEXT:    cmp w10, #20
287 ; CHECK-NEXT:    cinc w8, w8, hs
288 ; CHECK-NEXT:    cmp w9, #50
289 ; CHECK-NEXT:    mov w9, #255 // =0xff
290 ; CHECK-NEXT:    csel w8, w8, w9, lo
291 ; CHECK-NEXT:    and w0, w8, w0
292 ; CHECK-NEXT:    ret
293   %shl = or i8 %arg, 1
294   %cmp.0 = icmp ult i8 %shl, 50
295   %sub = add nsw i8 %shl, -40
296   %cmp.1 = icmp ult i8 %sub, 20
297   %mask.sel.v = select i1 %cmp.1, i8 1, i8 2
298   %mask.sel = select i1 %cmp.0, i8 %mask.sel.v, i8 -1
299   %res = and i8 %mask.sel, %arg
300   ret i8 %res
303 define i8 @underflow_if_sub(i32 %arg, i8 zeroext %arg1) {
304 ; CHECK-LABEL: underflow_if_sub:
305 ; CHECK:       // %bb.0:
306 ; CHECK-NEXT:    cmp w0, #0
307 ; CHECK-NEXT:    mov w8, #100 // =0x64
308 ; CHECK-NEXT:    cset w9, gt
309 ; CHECK-NEXT:    and w9, w9, w0
310 ; CHECK-NEXT:    add w9, w9, #245
311 ; CHECK-NEXT:    cmp w9, w1
312 ; CHECK-NEXT:    csel w0, w9, w8, lo
313 ; CHECK-NEXT:    ret
314   %cmp = icmp sgt i32 %arg, 0
315   %conv = zext i1 %cmp to i32
316   %and = and i32 %conv, %arg
317   %trunc = trunc i32 %and to i8
318   %conv1 = add nuw nsw i8 %trunc, -11
319   %cmp.1 = icmp ult i8 %conv1, %arg1
320   %res = select i1 %cmp.1, i8 %conv1, i8 100
321   ret i8 %res
324 define i8 @underflow_if_sub_signext(i32 %arg, i8 signext %arg1) {
325 ; CHECK-LABEL: underflow_if_sub_signext:
326 ; CHECK:       // %bb.0:
327 ; CHECK-NEXT:    cmp w0, #0
328 ; CHECK-NEXT:    mov w8, #100 // =0x64
329 ; CHECK-NEXT:    cset w9, gt
330 ; CHECK-NEXT:    and w9, w9, w0
331 ; CHECK-NEXT:    add w9, w9, #245
332 ; CHECK-NEXT:    cmp w9, w1, uxtb
333 ; CHECK-NEXT:    csel w0, w9, w8, lo
334 ; CHECK-NEXT:    ret
335   %cmp = icmp sgt i32 %arg, 0
336   %conv = zext i1 %cmp to i32
337   %and = and i32 %conv, %arg
338   %trunc = trunc i32 %and to i8
339   %conv1 = add nuw nsw i8 %trunc, -11
340   %cmp.1 = icmp ult i8 %conv1, %arg1
341   %res = select i1 %cmp.1, i8 %conv1, i8 100
342   ret i8 %res