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: sxtb w9, w0
111 ; CHECK-NEXT: mov w8, #16 // =0x10
112 ; CHECK-NEXT: cmn w9, #1
113 ; CHECK-NEXT: mov w9, #8 // =0x8
114 ; CHECK-NEXT: csel w0, w9, w8, lt
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: sxtb w9, w0
166 ; CHECK-NEXT: mov w8, #16 // =0x10
167 ; CHECK-NEXT: cmn w9, #1
168 ; CHECK-NEXT: mov w9, #8 // =0x8
169 ; CHECK-NEXT: csel w0, w9, w8, lt
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: sub w8, w8, #248
250 ; CHECK-NEXT: cmn w8, #4
251 ; CHECK-NEXT: cset w0, hi
254 %0 = load i8, ptr %b, align 1
255 %sub = add nsw i8 %0, 8
256 %cmp = icmp ugt i8 %sub, -4
257 %conv4 = zext i1 %cmp to i32
261 define i32 @safe_add_imm_var(ptr nocapture readnone %b) {
262 ; CHECK-LABEL: safe_add_imm_var:
263 ; CHECK: // %bb.0: // %entry
264 ; CHECK-NEXT: mov w0, #1 // =0x1
270 define i32 @safe_add_var_imm(ptr nocapture readnone %b) {
271 ; CHECK-LABEL: safe_add_var_imm:
272 ; CHECK: // %bb.0: // %entry
273 ; CHECK-NEXT: mov w0, #1 // =0x1
279 define i8 @convert_add_order(i8 zeroext %arg) {
280 ; CHECK-LABEL: convert_add_order:
282 ; CHECK-NEXT: orr w9, w0, #0x1
283 ; CHECK-NEXT: mov w8, #1 // =0x1
284 ; CHECK-NEXT: sub w10, w9, #40
285 ; CHECK-NEXT: cmp w10, #20
286 ; CHECK-NEXT: cinc w8, w8, hs
287 ; CHECK-NEXT: cmp w9, #50
288 ; CHECK-NEXT: mov w9, #255 // =0xff
289 ; CHECK-NEXT: csel w8, w8, w9, lo
290 ; CHECK-NEXT: and w0, w8, w0
293 %cmp.0 = icmp ult i8 %shl, 50
294 %sub = add nsw i8 %shl, -40
295 %cmp.1 = icmp ult i8 %sub, 20
296 %mask.sel.v = select i1 %cmp.1, i8 1, i8 2
297 %mask.sel = select i1 %cmp.0, i8 %mask.sel.v, i8 -1
298 %res = and i8 %mask.sel, %arg
302 define i8 @underflow_if_sub(i32 %arg, i8 zeroext %arg1) {
303 ; CHECK-LABEL: underflow_if_sub:
305 ; CHECK-NEXT: cmp w0, #0
306 ; CHECK-NEXT: mov w8, #100 // =0x64
307 ; CHECK-NEXT: cset w9, gt
308 ; CHECK-NEXT: and w9, w9, w0
309 ; CHECK-NEXT: add w9, w9, #245
310 ; CHECK-NEXT: cmp w9, w1
311 ; CHECK-NEXT: csel w0, w9, w8, lo
313 %cmp = icmp sgt i32 %arg, 0
314 %conv = zext i1 %cmp to i32
315 %and = and i32 %conv, %arg
316 %trunc = trunc i32 %and to i8
317 %conv1 = add nuw nsw i8 %trunc, -11
318 %cmp.1 = icmp ult i8 %conv1, %arg1
319 %res = select i1 %cmp.1, i8 %conv1, i8 100
323 define i8 @underflow_if_sub_signext(i32 %arg, i8 signext %arg1) {
324 ; CHECK-LABEL: underflow_if_sub_signext:
326 ; CHECK-NEXT: cmp w0, #0
327 ; CHECK-NEXT: mov w8, #100 // =0x64
328 ; CHECK-NEXT: cset w9, gt
329 ; CHECK-NEXT: and w9, w9, w0
330 ; CHECK-NEXT: add w9, w9, #245
331 ; CHECK-NEXT: cmp w9, w1, uxtb
332 ; CHECK-NEXT: csel w0, w9, w8, lo
334 %cmp = icmp sgt i32 %arg, 0
335 %conv = zext i1 %cmp to i32
336 %and = and i32 %conv, %arg
337 %trunc = trunc i32 %and to i8
338 %conv1 = add nuw nsw i8 %trunc, -11
339 %cmp.1 = icmp ult i8 %conv1, %arg1
340 %res = select i1 %cmp.1, i8 %conv1, i8 100