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
10
11define i1 @t0_basic(i8 %x, i8 %y) {
12; CHECK-LABEL: @t0_basic(
13; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
14; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[TMP1]], [[X:%.*]]
15; CHECK-NEXT:    ret i1 [[R]]
16;
17  %t0 = add i8 %x, %y
18  %r = icmp ult i8 %t0, %y
19  ret i1 %r
20}
21
22define <2 x i1> @t1_vec(<2 x i8> %x, <2 x i8> %y) {
23; CHECK-LABEL: @t1_vec(
24; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i8> [[Y:%.*]], <i8 -1, i8 -1>
25; CHECK-NEXT:    [[R:%.*]] = icmp ult <2 x i8> [[TMP1]], [[X:%.*]]
26; CHECK-NEXT:    ret <2 x i1> [[R]]
27;
28  %t0 = add <2 x i8> %x, %y
29  %r = icmp ult <2 x i8> %t0, %y
30  ret <2 x i1> %r
31}
32
33; Commutativity
34
35define i1 @t2_symmetry(i8 %x, i8 %y) {
36; CHECK-LABEL: @t2_symmetry(
37; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[X:%.*]], -1
38; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[TMP1]], [[Y:%.*]]
39; CHECK-NEXT:    ret i1 [[R]]
40;
41  %t0 = add i8 %x, %y
42  %r = icmp ult i8 %t0, %x ; can check against either of `add` arguments
43  ret i1 %r
44}
45
46declare i8 @gen8()
47
48define i1 @t3_commutative(i8 %x) {
49; CHECK-LABEL: @t3_commutative(
50; CHECK-NEXT:    [[Y:%.*]] = call i8 @gen8()
51; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y]], -1
52; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[TMP1]], [[X:%.*]]
53; CHECK-NEXT:    ret i1 [[R]]
54;
55  %y = call i8 @gen8()
56  %t0 = add i8 %y, %x ; swapped
57  %r = icmp ult i8 %t0, %y
58  ret i1 %r
59}
60
61define i1 @t4_commutative(i8 %x, i8 %y) {
62; CHECK-LABEL: @t4_commutative(
63; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
64; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[TMP1]], [[X:%.*]]
65; CHECK-NEXT:    ret i1 [[R]]
66;
67  %t0 = add i8 %x, %y
68  %r = icmp ugt i8 %y, %t0 ; swapped
69  ret i1 %r
70}
71
72define i1 @t5_commutative(i8 %x) {
73; CHECK-LABEL: @t5_commutative(
74; CHECK-NEXT:    [[Y:%.*]] = call i8 @gen8()
75; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y]], -1
76; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[TMP1]], [[X:%.*]]
77; CHECK-NEXT:    ret i1 [[R]]
78;
79  %y = call i8 @gen8()
80  %t0 = add i8 %y, %x ; swapped
81  %r = icmp ugt i8 %y, %t0 ; swapped
82  ret i1 %r
83}
84
85; Extra-use tests
86
87declare void @use8(i8)
88
89define i1 @t6_extrause(i8 %x, i8 %y) {
90; CHECK-LABEL: @t6_extrause(
91; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
92; CHECK-NEXT:    call void @use8(i8 [[T0]])
93; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T0]], [[Y]]
94; CHECK-NEXT:    ret i1 [[R]]
95;
96  %t0 = add i8 %x, %y
97  call void @use8(i8 %t0)
98  %r = icmp ult i8 %t0, %y
99  ret i1 %r
100}
101
102; Negative tests
103
104define i1 @n7_different_y(i8 %x, i8 %y0, i8 %y1) {
105; CHECK-LABEL: @n7_different_y(
106; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y0:%.*]]
107; CHECK-NEXT:    [[R:%.*]] = icmp ult i8 [[T0]], [[Y1:%.*]]
108; CHECK-NEXT:    ret i1 [[R]]
109;
110  %t0 = add i8 %x, %y0
111  %r = icmp ult i8 %t0, %y1
112  ret i1 %r
113}
114
115define i1 @n8_wrong_pred0(i8 %x, i8 %y) {
116; CHECK-LABEL: @n8_wrong_pred0(
117; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
118; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[T0]], [[Y]]
119; CHECK-NEXT:    ret i1 [[R]]
120;
121  %t0 = add i8 %x, %y
122  %r = icmp ule i8 %t0, %y
123  ret i1 %r
124}
125
126define i1 @n9_wrong_pred1(i8 %x, i8 %y) {
127; CHECK-LABEL: @n9_wrong_pred1(
128; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
129; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[T0]], [[Y]]
130; CHECK-NEXT:    ret i1 [[R]]
131;
132  %t0 = add i8 %x, %y
133  %r = icmp ugt i8 %t0, %y
134  ret i1 %r
135}
136
137define i1 @n10_wrong_pred2(i8 %x, i8 %y) {
138; CHECK-LABEL: @n10_wrong_pred2(
139; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[X:%.*]], 0
140; CHECK-NEXT:    ret i1 [[R]]
141;
142  %t0 = add i8 %x, %y
143  %r = icmp eq i8 %t0, %y
144  ret i1 %r
145}
146
147define i1 @n11_wrong_pred3(i8 %x, i8 %y) {
148; CHECK-LABEL: @n11_wrong_pred3(
149; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[X:%.*]], 0
150; CHECK-NEXT:    ret i1 [[R]]
151;
152  %t0 = add i8 %x, %y
153  %r = icmp ne i8 %t0, %y
154  ret i1 %r
155}
156
157define i1 @n12_wrong_pred4(i8 %x, i8 %y) {
158; CHECK-LABEL: @n12_wrong_pred4(
159; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
160; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[T0]], [[Y]]
161; CHECK-NEXT:    ret i1 [[R]]
162;
163  %t0 = add i8 %x, %y
164  %r = icmp slt i8 %t0, %y
165  ret i1 %r
166}
167
168define i1 @n13_wrong_pred5(i8 %x, i8 %y) {
169; CHECK-LABEL: @n13_wrong_pred5(
170; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
171; CHECK-NEXT:    [[R:%.*]] = icmp sle i8 [[T0]], [[Y]]
172; CHECK-NEXT:    ret i1 [[R]]
173;
174  %t0 = add i8 %x, %y
175  %r = icmp sle i8 %t0, %y
176  ret i1 %r
177}
178
179define i1 @n14_wrong_pred6(i8 %x, i8 %y) {
180; CHECK-LABEL: @n14_wrong_pred6(
181; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
182; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[T0]], [[Y]]
183; CHECK-NEXT:    ret i1 [[R]]
184;
185  %t0 = add i8 %x, %y
186  %r = icmp sgt i8 %t0, %y
187  ret i1 %r
188}
189
190define i1 @n15_wrong_pred7(i8 %x, i8 %y) {
191; CHECK-LABEL: @n15_wrong_pred7(
192; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
193; CHECK-NEXT:    [[R:%.*]] = icmp sge i8 [[T0]], [[Y]]
194; CHECK-NEXT:    ret i1 [[R]]
195;
196  %t0 = add i8 %x, %y
197  %r = icmp sge i8 %t0, %y
198  ret i1 %r
199}
200