xref: /llvm-project/llvm/test/CodeGen/RISCV/typepromotion-overflow.ll (revision 6657d4bd70523e6852f07f64711fb15bdf7b347a)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv64 -mattr=+m %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 a0, a1, a0
8; CHECK-NEXT:    ori a0, a0, 1
9; CHECK-NEXT:    slli a0, a0, 48
10; CHECK-NEXT:    srli a0, a0, 48
11; CHECK-NEXT:    li a1, 1024
12; CHECK-NEXT:    bltu a1, a0, .LBB0_2
13; CHECK-NEXT:  # %bb.1:
14; CHECK-NEXT:    li a0, 5
15; CHECK-NEXT:    ret
16; CHECK-NEXT:  .LBB0_2:
17; CHECK-NEXT:    li a0, 2
18; CHECK-NEXT:    ret
19  %add = add i16 %b, %a
20  %or = or i16 %add, 1
21  %cmp = icmp ugt i16 %or, 1024
22  %res = select i1 %cmp, i16 2, i16 5
23  ret i16 %res
24}
25
26define zeroext i16 @overflow_sub(i16 zeroext %a, i16 zeroext %b) {
27; CHECK-LABEL: overflow_sub:
28; CHECK:       # %bb.0:
29; CHECK-NEXT:    subw a0, a0, a1
30; CHECK-NEXT:    ori a0, a0, 1
31; CHECK-NEXT:    slli a0, a0, 48
32; CHECK-NEXT:    srli a0, a0, 48
33; CHECK-NEXT:    li a1, 1024
34; CHECK-NEXT:    bltu a1, a0, .LBB1_2
35; CHECK-NEXT:  # %bb.1:
36; CHECK-NEXT:    li a0, 5
37; CHECK-NEXT:    ret
38; CHECK-NEXT:  .LBB1_2:
39; CHECK-NEXT:    li a0, 2
40; CHECK-NEXT:    ret
41  %add = sub i16 %a, %b
42  %or = or i16 %add, 1
43  %cmp = icmp ugt i16 %or, 1024
44  %res = select i1 %cmp, i16 2, i16 5
45  ret i16 %res
46}
47
48define zeroext i16 @overflow_mul(i16 zeroext %a, i16 zeroext %b) {
49; CHECK-LABEL: overflow_mul:
50; CHECK:       # %bb.0:
51; CHECK-NEXT:    mul a0, a1, a0
52; CHECK-NEXT:    ori a0, a0, 1
53; CHECK-NEXT:    slli a0, a0, 48
54; CHECK-NEXT:    srli a0, a0, 48
55; CHECK-NEXT:    li a1, 1024
56; CHECK-NEXT:    bltu a1, a0, .LBB2_2
57; CHECK-NEXT:  # %bb.1:
58; CHECK-NEXT:    li a0, 5
59; CHECK-NEXT:    ret
60; CHECK-NEXT:  .LBB2_2:
61; CHECK-NEXT:    li a0, 2
62; CHECK-NEXT:    ret
63  %add = mul i16 %b, %a
64  %or = or i16 %add, 1
65  %cmp = icmp ugt i16 %or, 1024
66  %res = select i1 %cmp, i16 2, i16 5
67  ret i16 %res
68}
69
70define zeroext i16 @overflow_shl(i16 zeroext %a, i16 zeroext %b) {
71; CHECK-LABEL: overflow_shl:
72; CHECK:       # %bb.0:
73; CHECK-NEXT:    sll a0, a0, a1
74; CHECK-NEXT:    ori a0, a0, 1
75; CHECK-NEXT:    slli a0, a0, 48
76; CHECK-NEXT:    srli a0, a0, 48
77; CHECK-NEXT:    li a1, 1024
78; CHECK-NEXT:    bltu a1, a0, .LBB3_2
79; CHECK-NEXT:  # %bb.1:
80; CHECK-NEXT:    li a0, 5
81; CHECK-NEXT:    ret
82; CHECK-NEXT:  .LBB3_2:
83; CHECK-NEXT:    li a0, 2
84; CHECK-NEXT:    ret
85  %add = shl i16 %a, %b
86  %or = or i16 %add, 1
87  %cmp = icmp ugt i16 %or, 1024
88  %res = select i1 %cmp, i16 2, i16 5
89  ret i16 %res
90}
91
92define i32 @overflow_add_no_consts(i8 zeroext %a, i8 zeroext %b, i8 zeroext %limit) {
93; CHECK-LABEL: overflow_add_no_consts:
94; CHECK:       # %bb.0:
95; CHECK-NEXT:    add a0, a1, a0
96; CHECK-NEXT:    andi a0, a0, 255
97; CHECK-NEXT:    bltu a2, a0, .LBB4_2
98; CHECK-NEXT:  # %bb.1:
99; CHECK-NEXT:    li a0, 16
100; CHECK-NEXT:    ret
101; CHECK-NEXT:  .LBB4_2:
102; CHECK-NEXT:    li a0, 8
103; CHECK-NEXT:    ret
104  %add = add i8 %b, %a
105  %cmp = icmp ugt i8 %add, %limit
106  %res = select i1 %cmp, i32 8, i32 16
107  ret i32 %res
108}
109
110define i32 @overflow_add_const_limit(i8 zeroext %a, i8 zeroext %b) {
111; CHECK-LABEL: overflow_add_const_limit:
112; CHECK:       # %bb.0:
113; CHECK-NEXT:    add a0, a1, a0
114; CHECK-NEXT:    andi a0, a0, 255
115; CHECK-NEXT:    li a1, 128
116; CHECK-NEXT:    bltu a1, a0, .LBB5_2
117; CHECK-NEXT:  # %bb.1:
118; CHECK-NEXT:    li a0, 16
119; CHECK-NEXT:    ret
120; CHECK-NEXT:  .LBB5_2:
121; CHECK-NEXT:    li a0, 8
122; CHECK-NEXT:    ret
123  %add = add i8 %b, %a
124  %cmp = icmp ugt i8 %add, -128
125  %res = select i1 %cmp, i32 8, i32 16
126  ret i32 %res
127}
128
129define i32 @overflow_add_positive_const_limit(i8 zeroext %a) {
130; CHECK-LABEL: overflow_add_positive_const_limit:
131; CHECK:       # %bb.0:
132; CHECK-NEXT:    slli a0, a0, 56
133; CHECK-NEXT:    srai a0, a0, 56
134; CHECK-NEXT:    li a1, -1
135; CHECK-NEXT:    blt a0, a1, .LBB6_2
136; CHECK-NEXT:  # %bb.1:
137; CHECK-NEXT:    li a0, 16
138; CHECK-NEXT:    ret
139; CHECK-NEXT:  .LBB6_2:
140; CHECK-NEXT:    li a0, 8
141; CHECK-NEXT:    ret
142  %cmp = icmp slt i8 %a, -1
143  %res = select i1 %cmp, i32 8, i32 16
144  ret i32 %res
145}
146
147define i32 @unsafe_add_underflow(i8 zeroext %a) {
148; CHECK-LABEL: unsafe_add_underflow:
149; CHECK:       # %bb.0:
150; CHECK-NEXT:    li a1, 1
151; CHECK-NEXT:    beq a0, a1, .LBB7_2
152; CHECK-NEXT:  # %bb.1:
153; CHECK-NEXT:    li a0, 16
154; CHECK-NEXT:    ret
155; CHECK-NEXT:  .LBB7_2:
156; CHECK-NEXT:    li a0, 8
157; CHECK-NEXT:    ret
158  %cmp = icmp eq i8 %a, 1
159  %res = select i1 %cmp, i32 8, i32 16
160  ret i32 %res
161}
162
163define i32 @safe_add_underflow(i8 zeroext %a) {
164; CHECK-LABEL: safe_add_underflow:
165; CHECK:       # %bb.0:
166; CHECK-NEXT:    beqz a0, .LBB8_2
167; CHECK-NEXT:  # %bb.1:
168; CHECK-NEXT:    li a0, 16
169; CHECK-NEXT:    ret
170; CHECK-NEXT:  .LBB8_2:
171; CHECK-NEXT:    li a0, 8
172; CHECK-NEXT:    ret
173  %cmp = icmp eq i8 %a, 0
174  %res = select i1 %cmp, i32 8, i32 16
175  ret i32 %res
176}
177
178define i32 @safe_add_underflow_neg(i8 zeroext %a) {
179; CHECK-LABEL: safe_add_underflow_neg:
180; CHECK:       # %bb.0:
181; CHECK-NEXT:    addi a0, a0, -2
182; CHECK-NEXT:    li a1, 251
183; CHECK-NEXT:    bltu a0, a1, .LBB9_2
184; CHECK-NEXT:  # %bb.1:
185; CHECK-NEXT:    li a0, 16
186; CHECK-NEXT:    ret
187; CHECK-NEXT:  .LBB9_2:
188; CHECK-NEXT:    li a0, 8
189; CHECK-NEXT:    ret
190  %add = add i8 %a, -2
191  %cmp = icmp ult i8 %add, -5
192  %res = select i1 %cmp, i32 8, i32 16
193  ret i32 %res
194}
195
196define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) {
197; CHECK-LABEL: overflow_sub_negative_const_limit:
198; CHECK:       # %bb.0:
199; CHECK-NEXT:    slli a0, a0, 56
200; CHECK-NEXT:    srai a0, a0, 56
201; CHECK-NEXT:    li a1, -1
202; CHECK-NEXT:    blt a0, a1, .LBB10_2
203; CHECK-NEXT:  # %bb.1:
204; CHECK-NEXT:    li a0, 16
205; CHECK-NEXT:    ret
206; CHECK-NEXT:  .LBB10_2:
207; CHECK-NEXT:    li a0, 8
208; CHECK-NEXT:    ret
209  %cmp = icmp slt i8 %a, -1
210  %res = select i1 %cmp, i32 8, i32 16
211  ret i32 %res
212}
213
214; This is valid so long as the icmp immediate is sext.
215define i32 @sext_sub_underflow(i8 zeroext %a) {
216; CHECK-LABEL: sext_sub_underflow:
217; CHECK:       # %bb.0:
218; CHECK-NEXT:    addi a0, a0, -6
219; CHECK-NEXT:    li a1, -6
220; CHECK-NEXT:    bltu a1, a0, .LBB11_2
221; CHECK-NEXT:  # %bb.1:
222; CHECK-NEXT:    li a0, 16
223; CHECK-NEXT:    ret
224; CHECK-NEXT:  .LBB11_2:
225; CHECK-NEXT:    li a0, 8
226; CHECK-NEXT:    ret
227  %sub = add i8 %a, -6
228  %cmp = icmp ugt i8 %sub, -6
229  %res = select i1 %cmp, i32 8, i32 16
230  ret i32 %res
231}
232
233define i32 @safe_sub_underflow(i8 zeroext %a) {
234; CHECK-LABEL: safe_sub_underflow:
235; CHECK:       # %bb.0:
236; CHECK-NEXT:    beqz a0, .LBB12_2
237; CHECK-NEXT:  # %bb.1:
238; CHECK-NEXT:    li a0, 8
239; CHECK-NEXT:    ret
240; CHECK-NEXT:  .LBB12_2:
241; CHECK-NEXT:    li a0, 16
242; CHECK-NEXT:    ret
243  %cmp.not = icmp eq i8 %a, 0
244  %res = select i1 %cmp.not, i32 16, i32 8
245  ret i32 %res
246}
247
248define i32 @safe_sub_underflow_neg(i8 zeroext %a) {
249; CHECK-LABEL: safe_sub_underflow_neg:
250; CHECK:       # %bb.0:
251; CHECK-NEXT:    addi a0, a0, -4
252; CHECK-NEXT:    li a1, 250
253; CHECK-NEXT:    bltu a1, a0, .LBB13_2
254; CHECK-NEXT:  # %bb.1:
255; CHECK-NEXT:    li a0, 16
256; CHECK-NEXT:    ret
257; CHECK-NEXT:  .LBB13_2:
258; CHECK-NEXT:    li a0, 8
259; CHECK-NEXT:    ret
260  %sub = add i8 %a, -4
261  %cmp = icmp ugt i8 %sub, -6
262  %res = select i1 %cmp, i32 8, i32 16
263  ret i32 %res
264}
265
266; This is valid so long as the icmp immediate is sext.
267define i32 @sext_sub_underflow_neg(i8 zeroext %a) {
268; CHECK-LABEL: sext_sub_underflow_neg:
269; CHECK:       # %bb.0:
270; CHECK-NEXT:    addi a0, a0, -4
271; CHECK-NEXT:    li a1, -3
272; CHECK-NEXT:    bltu a0, a1, .LBB14_2
273; CHECK-NEXT:  # %bb.1:
274; CHECK-NEXT:    li a0, 16
275; CHECK-NEXT:    ret
276; CHECK-NEXT:  .LBB14_2:
277; CHECK-NEXT:    li a0, 8
278; CHECK-NEXT:    ret
279  %sub = add i8 %a, -4
280  %cmp = icmp ult i8 %sub, -3
281  %res = select i1 %cmp, i32 8, i32 16
282  ret i32 %res
283}
284
285define i32 @safe_sub_imm_var(ptr nocapture readonly %b) local_unnamed_addr #1 {
286; CHECK-LABEL: safe_sub_imm_var:
287; CHECK:       # %bb.0: # %entry
288; CHECK-NEXT:    li a0, 0
289; CHECK-NEXT:    ret
290entry:
291  ret i32 0
292}
293
294define i32 @safe_sub_var_imm(ptr nocapture readonly %b) local_unnamed_addr #1 {
295; CHECK-LABEL: safe_sub_var_imm:
296; CHECK:       # %bb.0: # %entry
297; CHECK-NEXT:    lbu a0, 0(a0)
298; CHECK-NEXT:    addi a0, a0, -248
299; CHECK-NEXT:    sltiu a0, a0, -3
300; CHECK-NEXT:    xori a0, a0, 1
301; CHECK-NEXT:    ret
302entry:
303  %0 = load i8, ptr %b, align 1
304  %sub = add nsw i8 %0, 8
305  %cmp = icmp ugt i8 %sub, -4
306  %conv4 = zext i1 %cmp to i32
307  ret i32 %conv4
308}
309
310define i32 @safe_add_imm_var(ptr nocapture readnone %b) {
311; CHECK-LABEL: safe_add_imm_var:
312; CHECK:       # %bb.0: # %entry
313; CHECK-NEXT:    li a0, 1
314; CHECK-NEXT:    ret
315entry:
316  ret i32 1
317}
318
319define i32 @safe_add_var_imm(ptr nocapture readnone %b) {
320; CHECK-LABEL: safe_add_var_imm:
321; CHECK:       # %bb.0: # %entry
322; CHECK-NEXT:    li a0, 1
323; CHECK-NEXT:    ret
324entry:
325  ret i32 1
326}
327
328define i8 @convert_add_order(i8 zeroext %arg) {
329; CHECK-LABEL: convert_add_order:
330; CHECK:       # %bb.0:
331; CHECK-NEXT:    ori a1, a0, 1
332; CHECK-NEXT:    li a2, 50
333; CHECK-NEXT:    bltu a1, a2, .LBB19_2
334; CHECK-NEXT:  # %bb.1:
335; CHECK-NEXT:    li a1, 255
336; CHECK-NEXT:    and a0, a1, a0
337; CHECK-NEXT:    ret
338; CHECK-NEXT:  .LBB19_2:
339; CHECK-NEXT:    addi a1, a1, -40
340; CHECK-NEXT:    sltiu a1, a1, 20
341; CHECK-NEXT:    li a2, 2
342; CHECK-NEXT:    sub a1, a2, a1
343; CHECK-NEXT:    and a0, a1, a0
344; CHECK-NEXT:    ret
345  %shl = or i8 %arg, 1
346  %cmp.0 = icmp ult i8 %shl, 50
347  %sub = add nsw i8 %shl, -40
348  %cmp.1 = icmp ult i8 %sub, 20
349  %mask.sel.v = select i1 %cmp.1, i8 1, i8 2
350  %mask.sel = select i1 %cmp.0, i8 %mask.sel.v, i8 -1
351  %res = and i8 %mask.sel, %arg
352  ret i8 %res
353}
354
355define i8 @underflow_if_sub(i32 %arg, i8 zeroext %arg1) {
356; CHECK-LABEL: underflow_if_sub:
357; CHECK:       # %bb.0:
358; CHECK-NEXT:    sext.w a2, a0
359; CHECK-NEXT:    sgtz a2, a2
360; CHECK-NEXT:    and a0, a2, a0
361; CHECK-NEXT:    addi a0, a0, 245
362; CHECK-NEXT:    bltu a0, a1, .LBB20_2
363; CHECK-NEXT:  # %bb.1:
364; CHECK-NEXT:    li a0, 100
365; CHECK-NEXT:  .LBB20_2:
366; CHECK-NEXT:    ret
367  %cmp = icmp sgt i32 %arg, 0
368  %conv = zext i1 %cmp to i32
369  %and = and i32 %conv, %arg
370  %trunc = trunc i32 %and to i8
371  %conv1 = add nuw nsw i8 %trunc, -11
372  %cmp.1 = icmp ult i8 %conv1, %arg1
373  %res = select i1 %cmp.1, i8 %conv1, i8 100
374  ret i8 %res
375}
376
377define i8 @underflow_if_sub_signext(i32 %arg, i8 signext %arg1) {
378; CHECK-LABEL: underflow_if_sub_signext:
379; CHECK:       # %bb.0:
380; CHECK-NEXT:    sext.w a2, a0
381; CHECK-NEXT:    andi a1, a1, 255
382; CHECK-NEXT:    sgtz a2, a2
383; CHECK-NEXT:    and a0, a2, a0
384; CHECK-NEXT:    addi a0, a0, 245
385; CHECK-NEXT:    bltu a0, a1, .LBB21_2
386; CHECK-NEXT:  # %bb.1:
387; CHECK-NEXT:    li a0, 100
388; CHECK-NEXT:  .LBB21_2:
389; CHECK-NEXT:    ret
390  %cmp = icmp sgt i32 %arg, 0
391  %conv = zext i1 %cmp to i32
392  %and = and i32 %conv, %arg
393  %trunc = trunc i32 %and to i8
394  %conv1 = add nuw nsw i8 %trunc, -11
395  %cmp.1 = icmp ult i8 %conv1, %arg1
396  %res = select i1 %cmp.1, i8 %conv1, i8 100
397  ret i8 %res
398}
399