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:
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
17 %cmp = icmp ugt i16 %or, 1024
18 %res = select i1 %cmp, i16 2, i16 5
22 define zeroext i16 @overflow_sub(i16 zeroext %a, i16 zeroext %b) {
23 ; CHECK-LABEL: overflow_sub:
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
35 %cmp = icmp ugt i16 %or, 1024
36 %res = select i1 %cmp, i16 2, i16 5
40 define zeroext i16 @overflow_mul(i16 zeroext %a, i16 zeroext %b) {
41 ; CHECK-LABEL: overflow_mul:
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
53 %cmp = icmp ugt i16 %or, 1024
54 %res = select i1 %cmp, i16 2, i16 5
58 define zeroext i16 @overflow_shl(i16 zeroext %a, i16 zeroext %b) {
59 ; CHECK-LABEL: overflow_shl:
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
71 %cmp = icmp ugt i16 %or, 1024
72 %res = select i1 %cmp, i16 2, i16 5
76 define i32 @overflow_add_no_consts(i8 zeroext %a, i8 zeroext %b, i8 zeroext %limit) {
77 ; CHECK-LABEL: overflow_add_no_consts:
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
86 %cmp = icmp ugt i8 %add, %limit
87 %res = select i1 %cmp, i32 8, i32 16
91 define i32 @overflow_add_const_limit(i8 zeroext %a, i8 zeroext %b) {
92 ; CHECK-LABEL: overflow_add_const_limit:
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
102 %cmp = icmp ugt i8 %add, -128
103 %res = select i1 %cmp, i32 8, i32 16
107 define i32 @overflow_add_positive_const_limit(i8 zeroext %a) {
108 ; CHECK-LABEL: overflow_add_positive_const_limit:
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
116 %cmp = icmp slt i8 %a, -1
117 %res = select i1 %cmp, i32 8, i32 16
121 define i32 @unsafe_add_underflow(i8 zeroext %a) {
122 ; CHECK-LABEL: unsafe_add_underflow:
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
129 %cmp = icmp eq i8 %a, 1
130 %res = select i1 %cmp, i32 8, i32 16
134 define i32 @safe_add_underflow(i8 zeroext %a) {
135 ; CHECK-LABEL: safe_add_underflow:
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
142 %cmp = icmp eq i8 %a, 0
143 %res = select i1 %cmp, i32 8, i32 16
147 define i32 @safe_add_underflow_neg(i8 zeroext %a) {
148 ; CHECK-LABEL: safe_add_underflow_neg:
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
157 %cmp = icmp ult i8 %add, -5
158 %res = select i1 %cmp, i32 8, i32 16
162 define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) {
163 ; CHECK-LABEL: overflow_sub_negative_const_limit:
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
171 %cmp = icmp slt i8 %a, -1
172 %res = select i1 %cmp, i32 8, i32 16
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:
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
187 %cmp = icmp ugt i8 %sub, -6
188 %res = select i1 %cmp, i32 8, i32 16
192 define i32 @safe_sub_underflow(i8 zeroext %a) {
193 ; CHECK-LABEL: safe_sub_underflow:
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
200 %cmp.not = icmp eq i8 %a, 0
201 %res = select i1 %cmp.not, i32 16, i32 8
205 define i32 @safe_sub_underflow_neg(i8 zeroext %a) {
206 ; CHECK-LABEL: safe_sub_underflow_neg:
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
215 %cmp = icmp ugt i8 %sub, -6
216 %res = select i1 %cmp, i32 8, i32 16
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:
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
231 %cmp = icmp ult i8 %sub, -3
232 %res = select i1 %cmp, i32 8, i32 16
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
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
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
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
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
280 define i8 @convert_add_order(i8 zeroext %arg) {
281 ; CHECK-LABEL: convert_add_order:
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
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
303 define i8 @underflow_if_sub(i32 %arg, i8 zeroext %arg1) {
304 ; CHECK-LABEL: underflow_if_sub:
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
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
324 define i8 @underflow_if_sub_signext(i32 %arg, i8 signext %arg1) {
325 ; CHECK-LABEL: underflow_if_sub_signext:
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
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