xref: /llvm-project/llvm/test/CodeGen/AArch64/typepromotion-overflow.ll (revision 331ba4369ac3cdf2ac2c6f724f9beaf43fb3fea7)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s
3
4define 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
20}
21
22define 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
38}
39
40define 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
56}
57
58define 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
74}
75
76define 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
89}
90
91define 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
105}
106
107define i32 @overflow_add_positive_const_limit(i8 zeroext %a) {
108; CHECK-LABEL: overflow_add_positive_const_limit:
109; CHECK:       // %bb.0:
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
115; CHECK-NEXT:    ret
116  %cmp = icmp slt i8 %a, -1
117  %res = select i1 %cmp, i32 8, i32 16
118  ret i32 %res
119}
120
121define 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
132}
133
134define 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
145}
146
147define 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
160}
161
162define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) {
163; CHECK-LABEL: overflow_sub_negative_const_limit:
164; CHECK:       // %bb.0:
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
170; CHECK-NEXT:    ret
171  %cmp = icmp slt i8 %a, -1
172  %res = select i1 %cmp, i32 8, i32 16
173  ret i32 %res
174}
175
176; This is valid so long as the icmp immediate is sext.
177define 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
190}
191
192define 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
203}
204
205define 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
218}
219
220; This is valid so long as the icmp immediate is sext.
221define 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
234}
235
236define 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
241entry:
242  ret i32 0
243}
244
245define 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
252; CHECK-NEXT:    ret
253entry:
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
258  ret i32 %conv4
259}
260
261define 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
265; CHECK-NEXT:    ret
266entry:
267  ret i32 1
268}
269
270define 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
274; CHECK-NEXT:    ret
275entry:
276  ret i32 1
277}
278
279define i8 @convert_add_order(i8 zeroext %arg) {
280; CHECK-LABEL: convert_add_order:
281; CHECK:       // %bb.0:
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
291; CHECK-NEXT:    ret
292  %shl = or i8 %arg, 1
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
299  ret i8 %res
300}
301
302define i8 @underflow_if_sub(i32 %arg, i8 zeroext %arg1) {
303; CHECK-LABEL: underflow_if_sub:
304; CHECK:       // %bb.0:
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
312; CHECK-NEXT:    ret
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
320  ret i8 %res
321}
322
323define i8 @underflow_if_sub_signext(i32 %arg, i8 signext %arg1) {
324; CHECK-LABEL: underflow_if_sub_signext:
325; CHECK:       // %bb.0:
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
333; CHECK-NEXT:    ret
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
341  ret i8 %res
342}
343