1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
4; Should fold
5;   (%x + %y) u>= %x
6; or
7;   (%x + %y) u>= %y
8; to
9;   @llvm.uadd.with.overflow(%x, %y) + extractvalue + not
10;
11; All tests here have extra uses, to ensure that the pattern isn't perturbed.
12
13declare void @use8(i8)
14declare void @use2x8(<2 x i8>)
15
16define i1 @t0_basic(i8 %x, i8 %y) {
17; CHECK-LABEL: @t0_basic(
18; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
19; CHECK-NEXT:    call void @use8(i8 [[T0]])
20; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[T0]], [[Y]]
21; CHECK-NEXT:    ret i1 [[R]]
22;
23  %t0 = add i8 %x, %y
24  call void @use8(i8 %t0)
25  %r = icmp uge i8 %t0, %y
26  ret i1 %r
27}
28
29define <2 x i1> @t1_vec(<2 x i8> %x, <2 x i8> %y) {
30; CHECK-LABEL: @t1_vec(
31; CHECK-NEXT:    [[T0:%.*]] = add <2 x i8> [[X:%.*]], [[Y:%.*]]
32; CHECK-NEXT:    call void @use2x8(<2 x i8> [[T0]])
33; CHECK-NEXT:    [[R:%.*]] = icmp uge <2 x i8> [[T0]], [[Y]]
34; CHECK-NEXT:    ret <2 x i1> [[R]]
35;
36  %t0 = add <2 x i8> %x, %y
37  call void @use2x8(<2 x i8> %t0)
38  %r = icmp uge <2 x i8> %t0, %y
39  ret <2 x i1> %r
40}
41
42; Commutativity
43
44define i1 @t2_symmetry(i8 %x, i8 %y) {
45; CHECK-LABEL: @t2_symmetry(
46; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
47; CHECK-NEXT:    call void @use8(i8 [[T0]])
48; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[T0]], [[X]]
49; CHECK-NEXT:    ret i1 [[R]]
50;
51  %t0 = add i8 %x, %y
52  call void @use8(i8 %t0)
53  %r = icmp uge i8 %t0, %x ; can check against either of `add` arguments
54  ret i1 %r
55}
56
57declare i8 @gen8()
58
59define i1 @t3_commutative(i8 %x) {
60; CHECK-LABEL: @t3_commutative(
61; CHECK-NEXT:    [[Y:%.*]] = call i8 @gen8()
62; CHECK-NEXT:    [[T0:%.*]] = add i8 [[Y]], [[X:%.*]]
63; CHECK-NEXT:    call void @use8(i8 [[T0]])
64; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[T0]], [[Y]]
65; CHECK-NEXT:    ret i1 [[R]]
66;
67  %y = call i8 @gen8()
68  %t0 = add i8 %y, %x ; swapped
69  call void @use8(i8 %t0)
70  %r = icmp uge i8 %t0, %y
71  ret i1 %r
72}
73
74define i1 @t4_commutative() {
75; CHECK-LABEL: @t4_commutative(
76; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
77; CHECK-NEXT:    [[Y:%.*]] = call i8 @gen8()
78; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X]], [[Y]]
79; CHECK-NEXT:    call void @use8(i8 [[T0]])
80; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[Y]], [[T0]]
81; CHECK-NEXT:    ret i1 [[R]]
82;
83  %x = call i8 @gen8()
84  %y = call i8 @gen8()
85  %t0 = add i8 %x, %y
86  call void @use8(i8 %t0)
87  %r = icmp ule i8 %y, %t0 ; swapped
88  ret i1 %r
89}
90
91define i1 @t5_commutative(i8 %x) {
92; CHECK-LABEL: @t5_commutative(
93; CHECK-NEXT:    [[Y:%.*]] = call i8 @gen8()
94; CHECK-NEXT:    [[T0:%.*]] = add i8 [[Y]], [[X:%.*]]
95; CHECK-NEXT:    call void @use8(i8 [[T0]])
96; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[Y]], [[T0]]
97; CHECK-NEXT:    ret i1 [[R]]
98;
99  %y = call i8 @gen8()
100  %t0 = add i8 %y, %x ; swapped
101  call void @use8(i8 %t0)
102  %r = icmp ule i8 %y, %t0 ; swapped
103  ret i1 %r
104}
105
106; Extra-use tests
107
108define i1 @t6_no_extrause(i8 %x, i8 %y) {
109; CHECK-LABEL: @t6_no_extrause(
110; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
111; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[TMP1]], [[X:%.*]]
112; CHECK-NEXT:    ret i1 [[R]]
113;
114  %t0 = add i8 %x, %y
115  %r = icmp uge i8 %t0, %y
116  ret i1 %r
117}
118
119; Negative tests
120
121define i1 @n7_different_y(i8 %x, i8 %y0, i8 %y1) {
122; CHECK-LABEL: @n7_different_y(
123; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y0:%.*]]
124; CHECK-NEXT:    call void @use8(i8 [[T0]])
125; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[T0]], [[Y1:%.*]]
126; CHECK-NEXT:    ret i1 [[R]]
127;
128  %t0 = add i8 %x, %y0
129  call void @use8(i8 %t0)
130  %r = icmp uge i8 %t0, %y1
131  ret i1 %r
132}
133
134define i1 @n8_wrong_pred0(i8 %x, i8 %y) {
135; CHECK-LABEL: @n8_wrong_pred0(
136; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
137; CHECK-NEXT:    call void @use8(i8 [[T0]])
138; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[T0]], [[Y]]
139; CHECK-NEXT:    ret i1 [[R]]
140;
141  %t0 = add i8 %x, %y
142  call void @use8(i8 %t0)
143  %r = icmp ule i8 %t0, %y
144  ret i1 %r
145}
146
147define i1 @n9_wrong_pred1(i8 %x, i8 %y) {
148; CHECK-LABEL: @n9_wrong_pred1(
149; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
150; CHECK-NEXT:    call void @use8(i8 [[T0]])
151; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[T0]], [[Y]]
152; CHECK-NEXT:    ret i1 [[R]]
153;
154  %t0 = add i8 %x, %y
155  call void @use8(i8 %t0)
156  %r = icmp ugt i8 %t0, %y
157  ret i1 %r
158}
159
160define i1 @n10_wrong_pred2(i8 %x, i8 %y) {
161; CHECK-LABEL: @n10_wrong_pred2(
162; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
163; CHECK-NEXT:    call void @use8(i8 [[T0]])
164; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[X]], 0
165; CHECK-NEXT:    ret i1 [[R]]
166;
167  %t0 = add i8 %x, %y
168  call void @use8(i8 %t0)
169  %r = icmp eq i8 %t0, %y
170  ret i1 %r
171}
172
173define i1 @n11_wrong_pred3(i8 %x, i8 %y) {
174; CHECK-LABEL: @n11_wrong_pred3(
175; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
176; CHECK-NEXT:    call void @use8(i8 [[T0]])
177; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[X]], 0
178; CHECK-NEXT:    ret i1 [[R]]
179;
180  %t0 = add i8 %x, %y
181  call void @use8(i8 %t0)
182  %r = icmp ne i8 %t0, %y
183  ret i1 %r
184}
185
186define i1 @n12_wrong_pred4(i8 %x, i8 %y) {
187; CHECK-LABEL: @n12_wrong_pred4(
188; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
189; CHECK-NEXT:    call void @use8(i8 [[T0]])
190; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[T0]], [[Y]]
191; CHECK-NEXT:    ret i1 [[R]]
192;
193  %t0 = add i8 %x, %y
194  call void @use8(i8 %t0)
195  %r = icmp slt i8 %t0, %y
196  ret i1 %r
197}
198
199define i1 @n13_wrong_pred5(i8 %x, i8 %y) {
200; CHECK-LABEL: @n13_wrong_pred5(
201; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
202; CHECK-NEXT:    call void @use8(i8 [[T0]])
203; CHECK-NEXT:    [[R:%.*]] = icmp sle i8 [[T0]], [[Y]]
204; CHECK-NEXT:    ret i1 [[R]]
205;
206  %t0 = add i8 %x, %y
207  call void @use8(i8 %t0)
208  %r = icmp sle i8 %t0, %y
209  ret i1 %r
210}
211
212define i1 @n14_wrong_pred6(i8 %x, i8 %y) {
213; CHECK-LABEL: @n14_wrong_pred6(
214; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
215; CHECK-NEXT:    call void @use8(i8 [[T0]])
216; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[T0]], [[Y]]
217; CHECK-NEXT:    ret i1 [[R]]
218;
219  %t0 = add i8 %x, %y
220  call void @use8(i8 %t0)
221  %r = icmp sgt i8 %t0, %y
222  ret i1 %r
223}
224
225define i1 @n15_wrong_pred7(i8 %x, i8 %y) {
226; CHECK-LABEL: @n15_wrong_pred7(
227; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
228; CHECK-NEXT:    call void @use8(i8 [[T0]])
229; CHECK-NEXT:    [[R:%.*]] = icmp sge i8 [[T0]], [[Y]]
230; CHECK-NEXT:    ret i1 [[R]]
231;
232  %t0 = add i8 %x, %y
233  call void @use8(i8 %t0)
234  %r = icmp sge i8 %t0, %y
235  ret i1 %r
236}
237