1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
9 ; @llvm.uadd.with.overflow(%x, %y) + extractvalue
11 ; All tests here have extra uses, to ensure that the pattern isn't perturbed.
13 declare void @use8(i8)
14 declare void @use2x8(<2 x i8>)
16 define 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 ult i8 [[T0]], [[Y]]
21 ; CHECK-NEXT: ret i1 [[R]]
24 call void @use8(i8 %t0)
25 %r = icmp ult i8 %t0, %y
29 define <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 ult <2 x i8> [[T0]], [[Y]]
34 ; CHECK-NEXT: ret <2 x i1> [[R]]
36 %t0 = add <2 x i8> %x, %y
37 call void @use2x8(<2 x i8> %t0)
38 %r = icmp ult <2 x i8> %t0, %y
44 define 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 ult i8 [[T0]], [[X]]
49 ; CHECK-NEXT: ret i1 [[R]]
52 call void @use8(i8 %t0)
53 %r = icmp ult i8 %t0, %x ; can check against either of `add` arguments
59 define 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 ult i8 [[T0]], [[Y]]
65 ; CHECK-NEXT: ret i1 [[R]]
68 %t0 = add i8 %y, %x ; swapped
69 call void @use8(i8 %t0)
70 %r = icmp ult i8 %t0, %y
74 define i1 @t4_commutative(i8 %x, i8 %y) {
75 ; CHECK-LABEL: @t4_commutative(
76 ; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
77 ; CHECK-NEXT: call void @use8(i8 [[T0]])
78 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T0]], [[Y]]
79 ; CHECK-NEXT: ret i1 [[R]]
82 call void @use8(i8 %t0)
83 %r = icmp ugt i8 %y, %t0 ; swapped
87 define i1 @t5_commutative(i8 %x) {
88 ; CHECK-LABEL: @t5_commutative(
89 ; CHECK-NEXT: [[Y:%.*]] = call i8 @gen8()
90 ; CHECK-NEXT: [[T0:%.*]] = add i8 [[Y]], [[X:%.*]]
91 ; CHECK-NEXT: call void @use8(i8 [[T0]])
92 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[Y]], [[T0]]
93 ; CHECK-NEXT: ret i1 [[R]]
96 %t0 = add i8 %y, %x ; swapped
97 call void @use8(i8 %t0)
98 %r = icmp ugt i8 %y, %t0 ; swapped
104 define i1 @t6_no_extrause(i8 %x, i8 %y) {
105 ; CHECK-LABEL: @t6_no_extrause(
106 ; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
107 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[TMP1]], [[X:%.*]]
108 ; CHECK-NEXT: ret i1 [[R]]
111 %r = icmp ult i8 %t0, %y
117 define i1 @n7_different_y(i8 %x, i8 %y0, i8 %y1) {
118 ; CHECK-LABEL: @n7_different_y(
119 ; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y0:%.*]]
120 ; CHECK-NEXT: call void @use8(i8 [[T0]])
121 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[T0]], [[Y1:%.*]]
122 ; CHECK-NEXT: ret i1 [[R]]
125 call void @use8(i8 %t0)
126 %r = icmp ult i8 %t0, %y1
130 define i1 @n8_wrong_pred0(i8 %x, i8 %y) {
131 ; CHECK-LABEL: @n8_wrong_pred0(
132 ; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
133 ; CHECK-NEXT: call void @use8(i8 [[T0]])
134 ; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[T0]], [[Y]]
135 ; CHECK-NEXT: ret i1 [[R]]
138 call void @use8(i8 %t0)
139 %r = icmp ule i8 %t0, %y
143 define i1 @n9_wrong_pred1(i8 %x, i8 %y) {
144 ; CHECK-LABEL: @n9_wrong_pred1(
145 ; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
146 ; CHECK-NEXT: call void @use8(i8 [[T0]])
147 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[T0]], [[Y]]
148 ; CHECK-NEXT: ret i1 [[R]]
151 call void @use8(i8 %t0)
152 %r = icmp ugt i8 %t0, %y
156 define i1 @n10_wrong_pred2(i8 %x, i8 %y) {
157 ; CHECK-LABEL: @n10_wrong_pred2(
158 ; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
159 ; CHECK-NEXT: call void @use8(i8 [[T0]])
160 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X]], 0
161 ; CHECK-NEXT: ret i1 [[R]]
164 call void @use8(i8 %t0)
165 %r = icmp eq i8 %t0, %y
169 define i1 @n11_wrong_pred3(i8 %x, i8 %y) {
170 ; CHECK-LABEL: @n11_wrong_pred3(
171 ; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
172 ; CHECK-NEXT: call void @use8(i8 [[T0]])
173 ; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X]], 0
174 ; CHECK-NEXT: ret i1 [[R]]
177 call void @use8(i8 %t0)
178 %r = icmp ne i8 %t0, %y
182 define i1 @n12_wrong_pred4(i8 %x, i8 %y) {
183 ; CHECK-LABEL: @n12_wrong_pred4(
184 ; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
185 ; CHECK-NEXT: call void @use8(i8 [[T0]])
186 ; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[T0]], [[Y]]
187 ; CHECK-NEXT: ret i1 [[R]]
190 call void @use8(i8 %t0)
191 %r = icmp slt i8 %t0, %y
195 define i1 @n13_wrong_pred5(i8 %x, i8 %y) {
196 ; CHECK-LABEL: @n13_wrong_pred5(
197 ; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
198 ; CHECK-NEXT: call void @use8(i8 [[T0]])
199 ; CHECK-NEXT: [[R:%.*]] = icmp sle i8 [[T0]], [[Y]]
200 ; CHECK-NEXT: ret i1 [[R]]
203 call void @use8(i8 %t0)
204 %r = icmp sle i8 %t0, %y
208 define i1 @n14_wrong_pred6(i8 %x, i8 %y) {
209 ; CHECK-LABEL: @n14_wrong_pred6(
210 ; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
211 ; CHECK-NEXT: call void @use8(i8 [[T0]])
212 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[T0]], [[Y]]
213 ; CHECK-NEXT: ret i1 [[R]]
216 call void @use8(i8 %t0)
217 %r = icmp sgt i8 %t0, %y
221 define i1 @n15_wrong_pred7(i8 %x, i8 %y) {
222 ; CHECK-LABEL: @n15_wrong_pred7(
223 ; CHECK-NEXT: [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
224 ; CHECK-NEXT: call void @use8(i8 [[T0]])
225 ; CHECK-NEXT: [[R:%.*]] = icmp sge i8 [[T0]], [[Y]]
226 ; CHECK-NEXT: ret i1 [[R]]
229 call void @use8(i8 %t0)
230 %r = icmp sge i8 %t0, %y