1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
5 declare void @use_vec(<2 x i8>)
7 define i1 @test_nuw_and_unsigned_pred(i64 %x) {
8 ; CHECK-LABEL: @test_nuw_and_unsigned_pred(
9 ; CHECK-NEXT: [[Z:%.*]] = icmp ugt i64 [[X:%.*]], 7
10 ; CHECK-NEXT: ret i1 [[Z]]
12 %y = sub nuw i64 10, %x
13 %z = icmp ult i64 %y, 3
17 define i1 @test_nsw_and_signed_pred(i64 %x) {
18 ; CHECK-LABEL: @test_nsw_and_signed_pred(
19 ; CHECK-NEXT: [[Z:%.*]] = icmp slt i64 [[X:%.*]], -7
20 ; CHECK-NEXT: ret i1 [[Z]]
22 %y = sub nsw i64 3, %x
23 %z = icmp sgt i64 %y, 10
27 define i1 @test_nuw_nsw_and_unsigned_pred(i64 %x) {
28 ; CHECK-LABEL: @test_nuw_nsw_and_unsigned_pred(
29 ; CHECK-NEXT: [[Z:%.*]] = icmp ugt i64 [[X:%.*]], 6
30 ; CHECK-NEXT: ret i1 [[Z]]
32 %y = sub nuw nsw i64 10, %x
33 %z = icmp ule i64 %y, 3
37 define i1 @test_nuw_nsw_and_signed_pred(i64 %x) {
38 ; CHECK-LABEL: @test_nuw_nsw_and_signed_pred(
39 ; CHECK-NEXT: [[Z:%.*]] = icmp sgt i64 [[X:%.*]], 7
40 ; CHECK-NEXT: ret i1 [[Z]]
42 %y = sub nuw nsw i64 10, %x
43 %z = icmp slt i64 %y, 3
47 define i1 @test_negative_nuw_and_signed_pred(i64 %x) {
48 ; CHECK-LABEL: @test_negative_nuw_and_signed_pred(
49 ; CHECK-NEXT: [[NOTSUB:%.*]] = add nuw i64 [[X:%.*]], -11
50 ; CHECK-NEXT: [[Z:%.*]] = icmp sgt i64 [[NOTSUB]], -4
51 ; CHECK-NEXT: ret i1 [[Z]]
53 %y = sub nuw i64 10, %x
54 %z = icmp slt i64 %y, 3
58 define i1 @test_negative_nsw_and_unsigned_pred(i64 %x) {
59 ; CHECK-LABEL: @test_negative_nsw_and_unsigned_pred(
60 ; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[X:%.*]], -8
61 ; CHECK-NEXT: [[Z:%.*]] = icmp ult i64 [[TMP1]], 3
62 ; CHECK-NEXT: ret i1 [[Z]]
64 %y = sub nsw i64 10, %x
65 %z = icmp ult i64 %y, 3
69 define i1 @test_negative_combined_sub_unsigned_overflow(i64 %x) {
70 ; CHECK-LABEL: @test_negative_combined_sub_unsigned_overflow(
71 ; CHECK-NEXT: ret i1 true
73 %y = sub nuw i64 10, %x
74 %z = icmp ult i64 %y, 11
78 define i1 @test_negative_combined_sub_signed_overflow(i8 %x) {
79 ; CHECK-LABEL: @test_negative_combined_sub_signed_overflow(
80 ; CHECK-NEXT: ret i1 false
82 %y = sub nsw i8 127, %x
83 %z = icmp slt i8 %y, -1
87 define i1 @test_sub_0_Y_eq_0(i8 %y) {
88 ; CHECK-LABEL: @test_sub_0_Y_eq_0(
89 ; CHECK-NEXT: [[Z:%.*]] = icmp eq i8 [[Y:%.*]], 0
90 ; CHECK-NEXT: ret i1 [[Z]]
97 define i1 @test_sub_0_Y_ne_0(i8 %y) {
98 ; CHECK-LABEL: @test_sub_0_Y_ne_0(
99 ; CHECK-NEXT: [[Z:%.*]] = icmp ne i8 [[Y:%.*]], 0
100 ; CHECK-NEXT: ret i1 [[Z]]
103 %z = icmp ne i8 %s, 0
107 define i1 @test_sub_4_Y_ne_4(i8 %y) {
108 ; CHECK-LABEL: @test_sub_4_Y_ne_4(
109 ; CHECK-NEXT: [[Z:%.*]] = icmp ne i8 [[Y:%.*]], 0
110 ; CHECK-NEXT: ret i1 [[Z]]
113 %z = icmp ne i8 %s, 4
117 define i1 @test_sub_127_Y_eq_127(i8 %y) {
118 ; CHECK-LABEL: @test_sub_127_Y_eq_127(
119 ; CHECK-NEXT: [[Z:%.*]] = icmp eq i8 [[Y:%.*]], 0
120 ; CHECK-NEXT: ret i1 [[Z]]
123 %z = icmp eq i8 %s, 127
127 define i1 @test_sub_255_Y_eq_255(i8 %y) {
128 ; CHECK-LABEL: @test_sub_255_Y_eq_255(
129 ; CHECK-NEXT: [[Z:%.*]] = icmp eq i8 [[Y:%.*]], 0
130 ; CHECK-NEXT: ret i1 [[Z]]
133 %z = icmp eq i8 %s, 255
136 define <2 x i1> @test_sub_255_Y_eq_255_vec(<2 x i8> %y) {
137 ; CHECK-LABEL: @test_sub_255_Y_eq_255_vec(
138 ; CHECK-NEXT: [[Z:%.*]] = icmp eq <2 x i8> [[Y:%.*]], zeroinitializer
139 ; CHECK-NEXT: ret <2 x i1> [[Z]]
141 %s = sub <2 x i8> <i8 255, i8 255>, %y
142 %z = icmp eq <2 x i8> %s, <i8 255, i8 255>
146 define <2 x i1> @icmp_eq_sub_undef(<2 x i32> %a) {
147 ; CHECK-LABEL: @icmp_eq_sub_undef(
148 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 5, i32 undef>
149 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
151 %sub = sub <2 x i32> <i32 15, i32 undef>, %a
152 %cmp = icmp eq <2 x i32> %sub, <i32 10, i32 10>
156 define <2 x i1> @icmp_eq_sub_non_splat(<2 x i32> %a) {
157 ; CHECK-LABEL: @icmp_eq_sub_non_splat(
158 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 5, i32 6>
159 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
161 %sub = sub <2 x i32> <i32 15, i32 16>, %a
162 %cmp = icmp eq <2 x i32> %sub, <i32 10, i32 10>
166 define <2 x i1> @icmp_eq_sub_undef2(<2 x i32> %a) {
167 ; CHECK-LABEL: @icmp_eq_sub_undef2(
168 ; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> <i32 15, i32 15>, [[A:%.*]]
169 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[SUB]], <i32 10, i32 undef>
170 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
172 %sub = sub <2 x i32> <i32 15, i32 15>, %a
173 %cmp = icmp eq <2 x i32> %sub, <i32 10, i32 undef>
177 define <2 x i1> @icmp_eq_sub_non_splat2(<2 x i32> %a) {
178 ; CHECK-LABEL: @icmp_eq_sub_non_splat2(
179 ; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i32> <i32 15, i32 15>, [[A:%.*]]
180 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i32> [[SUB]], <i32 10, i32 11>
181 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
183 %sub = sub <2 x i32> <i32 15, i32 15>, %a
184 %cmp = icmp eq <2 x i32> %sub, <i32 10, i32 11>
188 define i1 @neg_sgt_42(i32 %x) {
189 ; CHECK-LABEL: @neg_sgt_42(
190 ; CHECK-NEXT: [[NOTSUB:%.*]] = add i32 [[X:%.*]], -1
191 ; CHECK-NEXT: [[R:%.*]] = icmp slt i32 [[NOTSUB]], -43
192 ; CHECK-NEXT: ret i1 [[R]]
194 %negx = sub i32 0, %x
195 %r = icmp sgt i32 %negx, 42
199 define i1 @neg_eq_43(i32 %x) {
200 ; CHECK-LABEL: @neg_eq_43(
201 ; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X:%.*]]
202 ; CHECK-NEXT: call void @use(i32 [[NEGX]])
203 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], -43
204 ; CHECK-NEXT: ret i1 [[R]]
206 %negx = sub i32 0, %x
207 call void @use(i32 %negx)
208 %r = icmp eq i32 %negx, 43
212 define i1 @neg_ne_44(i32 %x) {
213 ; CHECK-LABEL: @neg_ne_44(
214 ; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X:%.*]]
215 ; CHECK-NEXT: call void @use(i32 [[NEGX]])
216 ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X]], -44
217 ; CHECK-NEXT: ret i1 [[R]]
219 %negx = sub i32 0, %x
220 call void @use(i32 %negx)
221 %r = icmp ne i32 %negx, 44
225 define i1 @neg_nsw_eq_45(i32 %x) {
226 ; CHECK-LABEL: @neg_nsw_eq_45(
227 ; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i32 0, [[X:%.*]]
228 ; CHECK-NEXT: call void @use(i32 [[NEGX]])
229 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], -45
230 ; CHECK-NEXT: ret i1 [[R]]
232 %negx = sub nsw i32 0, %x
233 call void @use(i32 %negx)
234 %r = icmp eq i32 %negx, 45
238 define i1 @neg_nsw_ne_46(i32 %x) {
239 ; CHECK-LABEL: @neg_nsw_ne_46(
240 ; CHECK-NEXT: [[NEGX:%.*]] = sub nsw i32 0, [[X:%.*]]
241 ; CHECK-NEXT: call void @use(i32 [[NEGX]])
242 ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X]], -46
243 ; CHECK-NEXT: ret i1 [[R]]
245 %negx = sub nsw i32 0, %x
246 call void @use(i32 %negx)
247 %r = icmp ne i32 %negx, 46
251 define i1 @subC_eq(i32 %x) {
252 ; CHECK-LABEL: @subC_eq(
253 ; CHECK-NEXT: [[SUBX:%.*]] = sub i32 -2147483648, [[X:%.*]]
254 ; CHECK-NEXT: call void @use(i32 [[SUBX]])
255 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], 2147483605
256 ; CHECK-NEXT: ret i1 [[R]]
258 %subx = sub i32 -2147483648, %x
259 call void @use(i32 %subx)
260 %r = icmp eq i32 %subx, 43
264 define <2 x i1> @subC_ne(<2 x i8> %x) {
265 ; CHECK-LABEL: @subC_ne(
266 ; CHECK-NEXT: [[SUBX:%.*]] = sub <2 x i8> <i8 -6, i8 -128>, [[X:%.*]]
267 ; CHECK-NEXT: call void @use_vec(<2 x i8> [[SUBX]])
268 ; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[X]], <i8 38, i8 -84>
269 ; CHECK-NEXT: ret <2 x i1> [[R]]
271 %subx = sub <2 x i8> <i8 -6, i8 -128>, %x
272 call void @use_vec(<2 x i8> %subx)
273 %r = icmp ne <2 x i8> %subx, <i8 -44, i8 -44>
277 define i1 @subC_nsw_eq(i32 %x) {
278 ; CHECK-LABEL: @subC_nsw_eq(
279 ; CHECK-NEXT: [[SUBX:%.*]] = sub nsw i32 -100, [[X:%.*]]
280 ; CHECK-NEXT: call void @use(i32 [[SUBX]])
281 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[X]], 2147483548
282 ; CHECK-NEXT: ret i1 [[R]]
284 %subx = sub nsw i32 -100, %x
285 call void @use(i32 %subx)
286 %r = icmp eq i32 %subx, -2147483648
290 define i1 @subC_nsw_ne(i32 %x) {
291 ; CHECK-LABEL: @subC_nsw_ne(
292 ; CHECK-NEXT: [[SUBX:%.*]] = sub nsw i32 -2147483647, [[X:%.*]]
293 ; CHECK-NEXT: call void @use(i32 [[SUBX]])
294 ; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[X]], 2147483603
295 ; CHECK-NEXT: ret i1 [[R]]
297 %subx = sub nsw i32 -2147483647, %x
298 call void @use(i32 %subx)
299 %r = icmp ne i32 %subx, 46
303 define i1 @neg_slt_42(i128 %x) {
304 ; CHECK-LABEL: @neg_slt_42(
305 ; CHECK-NEXT: [[NOTSUB:%.*]] = add i128 [[X:%.*]], -1
306 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i128 [[NOTSUB]], -43
307 ; CHECK-NEXT: ret i1 [[R]]
309 %negx = sub i128 0, %x
310 %r = icmp slt i128 %negx, 42
314 define <2 x i1> @neg_ugt_42_splat(<2 x i7> %x) {
315 ; CHECK-LABEL: @neg_ugt_42_splat(
316 ; CHECK-NEXT: [[NOTSUB:%.*]] = add <2 x i7> [[X:%.*]], <i7 -1, i7 -1>
317 ; CHECK-NEXT: [[R:%.*]] = icmp ult <2 x i7> [[NOTSUB]], <i7 -43, i7 -43>
318 ; CHECK-NEXT: ret <2 x i1> [[R]]
320 %negx = sub <2 x i7> zeroinitializer, %x
321 %r = icmp ugt <2 x i7> %negx, <i7 42, i7 42>
325 define i1 @neg_sgt_42_use(i32 %x) {
326 ; CHECK-LABEL: @neg_sgt_42_use(
327 ; CHECK-NEXT: [[NEGX:%.*]] = sub i32 0, [[X:%.*]]
328 ; CHECK-NEXT: call void @use(i32 [[NEGX]])
329 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i32 [[NEGX]], 42
330 ; CHECK-NEXT: ret i1 [[R]]
332 %negx = sub i32 0, %x
333 call void @use(i32 %negx)
334 %r = icmp sgt i32 %negx, 42
338 ; Test common/edge cases with signed pred.
340 define i1 @neg_slt_n1(i8 %x) {
341 ; CHECK-LABEL: @neg_slt_n1(
342 ; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
343 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[NOTSUB]], 0
344 ; CHECK-NEXT: ret i1 [[R]]
347 %r = icmp slt i8 %negx, -1
351 define i1 @neg_slt_0(i8 %x) {
352 ; CHECK-LABEL: @neg_slt_0(
353 ; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
354 ; CHECK-NEXT: [[ISNEGNEG:%.*]] = icmp sgt i8 [[NOTSUB]], -1
355 ; CHECK-NEXT: ret i1 [[ISNEGNEG]]
358 %isnegneg = icmp slt i8 %negx, 0
362 define i1 @neg_slt_1(i8 %x) {
363 ; CHECK-LABEL: @neg_slt_1(
364 ; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[X:%.*]], -127
365 ; CHECK-NEXT: ret i1 [[R]]
368 %r = icmp slt i8 %negx, 1
372 define i1 @neg_sgt_n1(i8 %x) {
373 ; CHECK-LABEL: @neg_sgt_n1(
374 ; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
375 ; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[NOTSUB]], 0
376 ; CHECK-NEXT: ret i1 [[R]]
379 %r = icmp sgt i8 %negx, -1
383 define i1 @neg_sgt_0(i8 %x) {
384 ; CHECK-LABEL: @neg_sgt_0(
385 ; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[X:%.*]], -128
386 ; CHECK-NEXT: ret i1 [[R]]
389 %r = icmp sgt i8 %negx, 0
393 define i1 @neg_sgt_1(i8 %x) {
394 ; CHECK-LABEL: @neg_sgt_1(
395 ; CHECK-NEXT: [[NOTSUB:%.*]] = add i8 [[X:%.*]], -1
396 ; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[NOTSUB]], -2
397 ; CHECK-NEXT: ret i1 [[R]]
400 %r = icmp sgt i8 %negx, 1
404 ; Test common/edge cases with signed pred and nsw.
406 define i1 @neg_nsw_slt_n1(i8 %x) {
407 ; CHECK-LABEL: @neg_nsw_slt_n1(
408 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[X:%.*]], 1
409 ; CHECK-NEXT: ret i1 [[R]]
411 %negx = sub nsw i8 0, %x
412 %r = icmp slt i8 %negx, -1
416 define i1 @neg_nsw_slt_0(i8 %x) {
417 ; CHECK-LABEL: @neg_nsw_slt_0(
418 ; CHECK-NEXT: [[ISNEGNEG:%.*]] = icmp sgt i8 [[X:%.*]], 0
419 ; CHECK-NEXT: ret i1 [[ISNEGNEG]]
421 %negx = sub nsw i8 0, %x
422 %isnegneg = icmp slt i8 %negx, 0
426 define i1 @neg_nsw_slt_1(i8 %x) {
427 ; CHECK-LABEL: @neg_nsw_slt_1(
428 ; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[X:%.*]], -1
429 ; CHECK-NEXT: ret i1 [[R]]
431 %negx = sub nsw i8 0, %x
432 %r = icmp slt i8 %negx, 1
436 define i1 @neg_nsw_sgt_n1(i8 %x) {
437 ; CHECK-LABEL: @neg_nsw_sgt_n1(
438 ; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X:%.*]], 1
439 ; CHECK-NEXT: ret i1 [[R]]
441 %negx = sub nsw i8 0, %x
442 %r = icmp sgt i8 %negx, -1
446 define i1 @neg_nsw_sgt_0(i8 %x) {
447 ; CHECK-LABEL: @neg_nsw_sgt_0(
448 ; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X:%.*]], 0
449 ; CHECK-NEXT: ret i1 [[R]]
451 %negx = sub nsw i8 0, %x
452 %r = icmp sgt i8 %negx, 0
456 define i1 @neg_nsw_sgt_1(i8 %x) {
457 ; CHECK-LABEL: @neg_nsw_sgt_1(
458 ; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X:%.*]], -1
459 ; CHECK-NEXT: ret i1 [[R]]
461 %negx = sub nsw i8 0, %x
462 %r = icmp sgt i8 %negx, 1
466 define i1 @sub_eq_zero_use(i32 %x, i32 %y) {
467 ; CHECK-LABEL: @sub_eq_zero_use(
468 ; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]]
469 ; CHECK-NEXT: call void @use(i32 [[SUB]])
470 ; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[SUB]], 0
471 ; CHECK-NEXT: ret i1 [[R]]
473 %sub = sub i32 %x, %y
474 call void @use(i32 %sub)
475 %r = icmp eq i32 %sub, 0
479 define <2 x i1> @sub_ne_zero_use(<2 x i8> %x, <2 x i8> %y) {
480 ; CHECK-LABEL: @sub_ne_zero_use(
481 ; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i8> [[X:%.*]], [[Y:%.*]]
482 ; CHECK-NEXT: call void @use_vec(<2 x i8> [[SUB]])
483 ; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[SUB]], zeroinitializer
484 ; CHECK-NEXT: ret <2 x i1> [[R]]
486 %sub = sub <2 x i8> %x, %y
487 call void @use_vec(<2 x i8> %sub)
488 %r = icmp eq <2 x i8> %sub, zeroinitializer