xref: /llvm-project/llvm/test/Transforms/InstCombine/icmp-mul.ll (revision 59720dc703f7f207d013b065d0ed7d3af7168bcc)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4declare void @llvm.assume(i1)
5declare void @use(i8)
6declare void @usev2xi8(<2 x i8>)
7
8
9define i1 @squared_nsw_eq0(i5 %x) {
10; CHECK-LABEL: @squared_nsw_eq0(
11; CHECK-NEXT:    [[R:%.*]] = icmp eq i5 [[X:%.*]], 0
12; CHECK-NEXT:    ret i1 [[R]]
13;
14  %m = mul nsw i5 %x, %x
15  %r = icmp eq i5 %m, 0
16  ret i1 %r
17}
18
19define <2 x i1> @squared_nuw_eq0(<2 x i8> %x) {
20; CHECK-LABEL: @squared_nuw_eq0(
21; CHECK-NEXT:    [[R:%.*]] = icmp eq <2 x i8> [[X:%.*]], zeroinitializer
22; CHECK-NEXT:    ret <2 x i1> [[R]]
23;
24  %m = mul nuw <2 x i8> %x, %x
25  %r = icmp eq <2 x i8> %m, zeroinitializer
26  ret <2 x i1> %r
27}
28
29; extra use is ok
30
31define i1 @squared_nsw_nuw_ne0(i8 %x) {
32; CHECK-LABEL: @squared_nsw_nuw_ne0(
33; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw i8 [[X:%.*]], [[X]]
34; CHECK-NEXT:    call void @use(i8 [[M]])
35; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[X]], 0
36; CHECK-NEXT:    ret i1 [[R]]
37;
38  %m = mul nsw nuw i8 %x, %x
39  call void @use(i8 %m)
40  %r = icmp ne i8 %m, 0
41  ret i1 %r
42}
43
44; negative test - must have no-overflow
45
46define i1 @squared_eq0(i8 %x) {
47; CHECK-LABEL: @squared_eq0(
48; CHECK-NEXT:    [[M:%.*]] = mul i8 [[X:%.*]], [[X]]
49; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[M]], 0
50; CHECK-NEXT:    ret i1 [[R]]
51;
52  %m = mul i8 %x, %x
53  %r = icmp eq i8 %m, 0
54  ret i1 %r
55}
56
57; negative test - not squared
58; TODO: This could be or-of-icmps.
59
60define i1 @mul_nsw_eq0(i5 %x, i5 %y) {
61; CHECK-LABEL: @mul_nsw_eq0(
62; CHECK-NEXT:    [[M:%.*]] = mul nsw i5 [[X:%.*]], [[Y:%.*]]
63; CHECK-NEXT:    [[R:%.*]] = icmp eq i5 [[M]], 0
64; CHECK-NEXT:    ret i1 [[R]]
65;
66  %m = mul nsw i5 %x, %y
67  %r = icmp eq i5 %m, 0
68  ret i1 %r
69}
70
71; negative test - non-zero cmp
72
73define i1 @squared_nsw_eq1(i5 %x) {
74; CHECK-LABEL: @squared_nsw_eq1(
75; CHECK-NEXT:    [[M:%.*]] = mul nsw i5 [[X:%.*]], [[X]]
76; CHECK-NEXT:    [[R:%.*]] = icmp eq i5 [[M]], 1
77; CHECK-NEXT:    ret i1 [[R]]
78;
79  %m = mul nsw i5 %x, %x
80  %r = icmp eq i5 %m, 1
81  ret i1 %r
82}
83
84define i1 @squared_nsw_sgt0(i5 %x) {
85; CHECK-LABEL: @squared_nsw_sgt0(
86; CHECK-NEXT:    [[R:%.*]] = icmp ne i5 [[X:%.*]], 0
87; CHECK-NEXT:    ret i1 [[R]]
88;
89  %m = mul nsw i5 %x, %x
90  %r = icmp sgt i5 %m, 0
91  ret i1 %r
92}
93
94; Tests for slt/ult
95
96define i1 @slt_positive_multip_rem_zero(i8 %x) {
97; CHECK-LABEL: @slt_positive_multip_rem_zero(
98; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 [[X:%.*]], 3
99; CHECK-NEXT:    ret i1 [[B]]
100;
101  %a = mul nsw i8 %x, 7
102  %b = icmp slt i8 %a, 21
103  ret i1 %b
104}
105
106define i1 @slt_negative_multip_rem_zero(i8 %x) {
107; CHECK-LABEL: @slt_negative_multip_rem_zero(
108; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 [[X:%.*]], -3
109; CHECK-NEXT:    ret i1 [[B]]
110;
111  %a = mul nsw i8 %x, -7
112  %b = icmp slt i8 %a, 21
113  ret i1 %b
114}
115
116define i1 @slt_positive_multip_rem_nz(i8 %x) {
117; CHECK-LABEL: @slt_positive_multip_rem_nz(
118; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 [[X:%.*]], 5
119; CHECK-NEXT:    ret i1 [[B]]
120;
121  %a = mul nsw i8 %x, 5
122  %b = icmp slt i8 %a, 21
123  ret i1 %b
124}
125
126define i1 @ult_rem_zero(i8 %x) {
127; CHECK-LABEL: @ult_rem_zero(
128; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 [[X:%.*]], 3
129; CHECK-NEXT:    ret i1 [[B]]
130;
131  %a = mul nuw i8 %x, 7
132  %b = icmp ult i8 %a, 21
133  ret i1 %b
134}
135
136; Same as above, but with nsw flag too.
137; This used to not optimize due to nsw being prioritized too much.
138define i1 @ult_rem_zero_nsw(i8 %x) {
139; CHECK-LABEL: @ult_rem_zero_nsw(
140; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 [[X:%.*]], 3
141; CHECK-NEXT:    ret i1 [[B]]
142;
143  %a = mul nuw nsw i8 %x, 7
144  %b = icmp ult i8 %a, 21
145  ret i1 %b
146}
147
148define i1 @ult_rem_nz(i8 %x) {
149; CHECK-LABEL: @ult_rem_nz(
150; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 [[X:%.*]], 5
151; CHECK-NEXT:    ret i1 [[B]]
152;
153  %a = mul nuw i8 %x, 5
154  %b = icmp ult i8 %a, 21
155  ret i1 %b
156}
157
158; Same as above, but with nsw flag too.
159; This used to not optimize due to nsw being prioritized too much.
160define i1 @ult_rem_nz_nsw(i8 %x) {
161; CHECK-LABEL: @ult_rem_nz_nsw(
162; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 [[X:%.*]], 5
163; CHECK-NEXT:    ret i1 [[B]]
164;
165  %a = mul nuw nsw i8 %x, 5
166  %b = icmp ult i8 %a, 21
167  ret i1 %b
168}
169
170; Tests for sgt/ugt
171
172define i1 @sgt_positive_multip_rem_zero(i8 %x) {
173; CHECK-LABEL: @sgt_positive_multip_rem_zero(
174; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 [[X:%.*]], 3
175; CHECK-NEXT:    ret i1 [[B]]
176;
177  %a = mul nsw i8 %x, 7
178  %b = icmp sgt i8 %a, 21
179  ret i1 %b
180}
181
182define i1 @sgt_negative_multip_rem_zero(i8 %x) {
183; CHECK-LABEL: @sgt_negative_multip_rem_zero(
184; CHECK-NEXT:    [[B:%.*]] = icmp slt i8 [[X:%.*]], -3
185; CHECK-NEXT:    ret i1 [[B]]
186;
187  %a = mul nsw i8 %x, -7
188  %b = icmp sgt i8 %a, 21
189  ret i1 %b
190}
191
192define i1 @sgt_positive_multip_rem_nz(i8 %x) {
193; CHECK-LABEL: @sgt_positive_multip_rem_nz(
194; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 [[X:%.*]], 4
195; CHECK-NEXT:    ret i1 [[B]]
196;
197  %a = mul nsw i8 %x, 5
198  %b = icmp sgt i8 %a, 21
199  ret i1 %b
200}
201
202define i1 @ugt_rem_zero(i8 %x) {
203; CHECK-LABEL: @ugt_rem_zero(
204; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 [[X:%.*]], 3
205; CHECK-NEXT:    ret i1 [[B]]
206;
207  %a = mul nuw i8 %x, 7
208  %b = icmp ugt i8 %a, 21
209  ret i1 %b
210}
211
212; Same as above, but with nsw flag too.
213; This used to not optimize due to nsw being prioritized too much.
214define i1 @ugt_rem_zero_nsw(i8 %x) {
215; CHECK-LABEL: @ugt_rem_zero_nsw(
216; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 [[X:%.*]], 3
217; CHECK-NEXT:    ret i1 [[B]]
218;
219  %a = mul nuw nsw i8 %x, 7
220  %b = icmp ugt i8 %a, 21
221  ret i1 %b
222}
223
224define i1 @ugt_rem_nz(i8 %x) {
225; CHECK-LABEL: @ugt_rem_nz(
226; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 [[X:%.*]], 4
227; CHECK-NEXT:    ret i1 [[B]]
228;
229  %a = mul nuw i8 %x, 5
230  %b = icmp ugt i8 %a, 21
231  ret i1 %b
232}
233
234; Same as above, but with nsw flag too.
235; This used to not optimize due to nsw being prioritized too much.
236define i1 @ugt_rem_nz_nsw(i8 %x) {
237; CHECK-LABEL: @ugt_rem_nz_nsw(
238; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 [[X:%.*]], 4
239; CHECK-NEXT:    ret i1 [[B]]
240;
241  %a = mul nuw nsw i8 %x, 5
242  %b = icmp ugt i8 %a, 21
243  ret i1 %b
244}
245
246; Tests for eq/ne
247
248define i1 @eq_nsw_rem_zero(i8 %x) {
249; CHECK-LABEL: @eq_nsw_rem_zero(
250; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 [[X:%.*]], -4
251; CHECK-NEXT:    ret i1 [[B]]
252;
253  %a = mul nsw i8 %x, -5
254  %b = icmp eq i8 %a, 20
255  ret i1 %b
256}
257
258define <2 x i1> @ne_nsw_rem_zero(<2 x i8> %x) {
259; CHECK-LABEL: @ne_nsw_rem_zero(
260; CHECK-NEXT:    [[B:%.*]] = icmp ne <2 x i8> [[X:%.*]], splat (i8 -6)
261; CHECK-NEXT:    ret <2 x i1> [[B]]
262;
263  %a = mul nsw <2 x i8> %x, <i8 5, i8 5>
264  %b = icmp ne <2 x i8> %a, <i8 -30, i8 -30>
265  ret <2 x i1> %b
266}
267
268; TODO: Missed fold with undef.
269
270define <2 x i1> @ne_nsw_rem_zero_undef1(<2 x i8> %x) {
271; CHECK-LABEL: @ne_nsw_rem_zero_undef1(
272; CHECK-NEXT:    [[A:%.*]] = mul nsw <2 x i8> [[X:%.*]], <i8 5, i8 undef>
273; CHECK-NEXT:    [[B:%.*]] = icmp ne <2 x i8> [[A]], splat (i8 -30)
274; CHECK-NEXT:    ret <2 x i1> [[B]]
275;
276  %a = mul nsw <2 x i8> %x, <i8 5, i8 undef>
277  %b = icmp ne <2 x i8> %a, <i8 -30, i8 -30>
278  ret <2 x i1> %b
279}
280
281; TODO: Missed fold with undef.
282
283define <2 x i1> @ne_nsw_rem_zero_undef2(<2 x i8> %x) {
284; CHECK-LABEL: @ne_nsw_rem_zero_undef2(
285; CHECK-NEXT:    [[A:%.*]] = mul nsw <2 x i8> [[X:%.*]], splat (i8 5)
286; CHECK-NEXT:    [[B:%.*]] = icmp ne <2 x i8> [[A]], <i8 -30, i8 undef>
287; CHECK-NEXT:    ret <2 x i1> [[B]]
288;
289  %a = mul nsw <2 x i8> %x, <i8 5, i8 5>
290  %b = icmp ne <2 x i8> %a, <i8 -30, i8 undef>
291  ret <2 x i1> %b
292}
293
294define i1 @eq_nsw_rem_zero_uses(i8 %x) {
295; CHECK-LABEL: @eq_nsw_rem_zero_uses(
296; CHECK-NEXT:    [[A:%.*]] = mul nsw i8 [[X:%.*]], -5
297; CHECK-NEXT:    call void @use(i8 [[A]])
298; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 [[X]], -4
299; CHECK-NEXT:    ret i1 [[B]]
300;
301  %a = mul nsw i8 %x, -5
302  call void @use(i8 %a)
303  %b = icmp eq i8 %a, 20
304  ret i1 %b
305}
306
307; Impossible multiple should be handled by instsimplify.
308
309define i1 @eq_nsw_rem_nz(i8 %x) {
310; CHECK-LABEL: @eq_nsw_rem_nz(
311; CHECK-NEXT:    ret i1 false
312;
313  %a = mul nsw i8 %x, 5
314  %b = icmp eq i8 %a, 245
315  ret i1 %b
316}
317
318; Impossible multiple should be handled by instsimplify.
319
320define i1 @ne_nsw_rem_nz(i8 %x) {
321; CHECK-LABEL: @ne_nsw_rem_nz(
322; CHECK-NEXT:    ret i1 true
323;
324  %a = mul nsw i8 %x, 5
325  %b = icmp ne i8 %a, 130
326  ret i1 %b
327}
328
329define <2 x i1> @eq_nuw_rem_zero(<2 x i8> %x) {
330; CHECK-LABEL: @eq_nuw_rem_zero(
331; CHECK-NEXT:    [[B:%.*]] = icmp eq <2 x i8> [[X:%.*]], splat (i8 4)
332; CHECK-NEXT:    ret <2 x i1> [[B]]
333;
334  %a = mul nuw <2 x i8> %x, <i8 5, i8 5>
335  %b = icmp eq <2 x i8> %a, <i8 20, i8 20>
336  ret <2 x i1> %b
337}
338
339; TODO: Missed fold with undef.
340
341define <2 x i1> @eq_nuw_rem_zero_undef1(<2 x i8> %x) {
342; CHECK-LABEL: @eq_nuw_rem_zero_undef1(
343; CHECK-NEXT:    [[A:%.*]] = mul nuw <2 x i8> [[X:%.*]], <i8 undef, i8 5>
344; CHECK-NEXT:    [[B:%.*]] = icmp eq <2 x i8> [[A]], splat (i8 20)
345; CHECK-NEXT:    ret <2 x i1> [[B]]
346;
347  %a = mul nuw <2 x i8> %x, <i8 undef, i8 5>
348  %b = icmp eq <2 x i8> %a, <i8 20, i8 20>
349  ret <2 x i1> %b
350}
351
352; TODO: Missed fold with undef.
353
354define <2 x i1> @eq_nuw_rem_zero_undef2(<2 x i8> %x) {
355; CHECK-LABEL: @eq_nuw_rem_zero_undef2(
356; CHECK-NEXT:    [[A:%.*]] = mul nuw <2 x i8> [[X:%.*]], splat (i8 5)
357; CHECK-NEXT:    [[B:%.*]] = icmp eq <2 x i8> [[A]], <i8 undef, i8 20>
358; CHECK-NEXT:    ret <2 x i1> [[B]]
359;
360  %a = mul nuw <2 x i8> %x, <i8 5, i8 5>
361  %b = icmp eq <2 x i8> %a, <i8 undef, i8 20>
362  ret <2 x i1> %b
363}
364
365define i1 @ne_nuw_rem_zero(i8 %x) {
366; CHECK-LABEL: @ne_nuw_rem_zero(
367; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 [[X:%.*]], 26
368; CHECK-NEXT:    ret i1 [[B]]
369;
370  %a = mul nuw i8 %x, 5
371  %b = icmp ne i8 %a, 130
372  ret i1 %b
373}
374
375define i1 @ne_nuw_rem_zero_uses(i8 %x) {
376; CHECK-LABEL: @ne_nuw_rem_zero_uses(
377; CHECK-NEXT:    [[A:%.*]] = mul nuw i8 [[X:%.*]], 5
378; CHECK-NEXT:    call void @use(i8 [[A]])
379; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 [[X]], 26
380; CHECK-NEXT:    ret i1 [[B]]
381;
382  %a = mul nuw i8 %x, 5
383  call void @use(i8 %a)
384  %b = icmp ne i8 %a, 130
385  ret i1 %b
386}
387
388; Impossible multiple should be handled by instsimplify.
389
390define i1 @eq_nuw_rem_nz(i8 %x) {
391; CHECK-LABEL: @eq_nuw_rem_nz(
392; CHECK-NEXT:    ret i1 false
393;
394  %a = mul nuw i8 %x, -5
395  %b = icmp eq i8 %a, 20
396  ret i1 %b
397}
398
399; Impossible multiple should be handled by instsimplify.
400
401define i1 @ne_nuw_rem_nz(i8 %x) {
402; CHECK-LABEL: @ne_nuw_rem_nz(
403; CHECK-NEXT:    ret i1 true
404;
405  %a = mul nuw i8 %x, 5
406  %b = icmp ne i8 %a, -30
407  ret i1 %b
408}
409
410; Negative tests for the icmp mul folds
411
412define i1 @sgt_positive_multip_rem_zero_nonsw(i8 %x) {
413; CHECK-LABEL: @sgt_positive_multip_rem_zero_nonsw(
414; CHECK-NEXT:    [[A:%.*]] = mul i8 [[X:%.*]], 7
415; CHECK-NEXT:    [[B:%.*]] = icmp sgt i8 [[A]], 21
416; CHECK-NEXT:    ret i1 [[B]]
417;
418  %a = mul i8 %x, 7
419  %b = icmp sgt i8 %a, 21
420  ret i1 %b
421}
422
423define i1 @ult_multip_rem_zero_nonsw(i8 %x) {
424; CHECK-LABEL: @ult_multip_rem_zero_nonsw(
425; CHECK-NEXT:    [[A:%.*]] = mul i8 [[X:%.*]], 7
426; CHECK-NEXT:    [[B:%.*]] = icmp ult i8 [[A]], 21
427; CHECK-NEXT:    ret i1 [[B]]
428;
429  %a = mul i8 %x, 7
430  %b = icmp ult i8 %a, 21
431  ret i1 %b
432}
433
434define i1 @ugt_rem_zero_nonuw(i8 %x) {
435; CHECK-LABEL: @ugt_rem_zero_nonuw(
436; CHECK-NEXT:    [[A:%.*]] = mul i8 [[X:%.*]], 7
437; CHECK-NEXT:    [[B:%.*]] = icmp ugt i8 [[A]], 21
438; CHECK-NEXT:    ret i1 [[B]]
439;
440  %a = mul i8 %x, 7
441  %b = icmp ugt i8 %a, 21
442  ret i1 %b
443}
444
445define i1 @sgt_minnum(i8 %x) {
446; CHECK-LABEL: @sgt_minnum(
447; CHECK-NEXT:    ret i1 true
448;
449  %a = mul nsw i8 %x, 7
450  %b = icmp sgt i8 %a, -128
451  ret i1 %b
452}
453
454define i1 @ule_bignum(i8 %x) {
455; CHECK-LABEL: @ule_bignum(
456; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 [[X:%.*]], 0
457; CHECK-NEXT:    ret i1 [[B]]
458;
459  %a = mul i8 %x, 2147483647
460  %b = icmp ule i8 %a, 0
461  ret i1 %b
462}
463
464define i1 @sgt_mulzero(i8 %x) {
465; CHECK-LABEL: @sgt_mulzero(
466; CHECK-NEXT:    ret i1 false
467;
468  %a = mul nsw i8 %x, 0
469  %b = icmp sgt i8 %a, 21
470  ret i1 %b
471}
472
473define i1 @eq_rem_zero_nonuw(i8 %x) {
474; CHECK-LABEL: @eq_rem_zero_nonuw(
475; CHECK-NEXT:    [[B:%.*]] = icmp eq i8 [[X:%.*]], 4
476; CHECK-NEXT:    ret i1 [[B]]
477;
478  %a = mul i8 %x, 5
479  %b = icmp eq i8 %a, 20
480  ret i1 %b
481}
482
483define i1 @ne_rem_zero_nonuw(i8 %x) {
484; CHECK-LABEL: @ne_rem_zero_nonuw(
485; CHECK-NEXT:    [[B:%.*]] = icmp ne i8 [[X:%.*]], 6
486; CHECK-NEXT:    ret i1 [[B]]
487;
488  %a = mul i8 %x, 5
489  %b = icmp ne i8 %a, 30
490  ret i1 %b
491}
492
493define i1 @mul_constant_eq(i32 %x, i32 %y) {
494; CHECK-LABEL: @mul_constant_eq(
495; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
496; CHECK-NEXT:    ret i1 [[C]]
497;
498  %A = mul i32 %x, 5
499  %B = mul i32 %y, 5
500  %C = icmp eq i32 %A, %B
501  ret i1 %C
502}
503
504define <2 x i1> @mul_constant_ne_splat(<2 x i32> %x, <2 x i32> %y) {
505; CHECK-LABEL: @mul_constant_ne_splat(
506; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
507; CHECK-NEXT:    ret <2 x i1> [[C]]
508;
509  %A = mul <2 x i32> %x, <i32 5, i32 5>
510  %B = mul <2 x i32> %y, <i32 5, i32 5>
511  %C = icmp ne <2 x i32> %A, %B
512  ret <2 x i1> %C
513}
514
515define i1 @mul_constant_ne_extra_use1(i8 %x, i8 %y) {
516; CHECK-LABEL: @mul_constant_ne_extra_use1(
517; CHECK-NEXT:    [[A:%.*]] = mul i8 [[X:%.*]], 5
518; CHECK-NEXT:    call void @use(i8 [[A]])
519; CHECK-NEXT:    [[C:%.*]] = icmp ne i8 [[X]], [[Y:%.*]]
520; CHECK-NEXT:    ret i1 [[C]]
521;
522  %A = mul i8 %x, 5
523  call void @use(i8 %A)
524  %B = mul i8 %y, 5
525  %C = icmp ne i8 %A, %B
526  ret i1 %C
527}
528
529define i1 @mul_constant_eq_extra_use2(i8 %x, i8 %y) {
530; CHECK-LABEL: @mul_constant_eq_extra_use2(
531; CHECK-NEXT:    [[B:%.*]] = mul i8 [[Y:%.*]], 5
532; CHECK-NEXT:    call void @use(i8 [[B]])
533; CHECK-NEXT:    [[C:%.*]] = icmp eq i8 [[X:%.*]], [[Y]]
534; CHECK-NEXT:    ret i1 [[C]]
535;
536  %A = mul i8 %x, 5
537  %B = mul i8 %y, 5
538  call void @use(i8 %B)
539  %C = icmp eq i8 %A, %B
540  ret i1 %C
541}
542
543define i1 @mul_constant_ne_extra_use3(i8 %x, i8 %y) {
544; CHECK-LABEL: @mul_constant_ne_extra_use3(
545; CHECK-NEXT:    [[A:%.*]] = mul i8 [[X:%.*]], 5
546; CHECK-NEXT:    call void @use(i8 [[A]])
547; CHECK-NEXT:    [[B:%.*]] = mul i8 [[Y:%.*]], 5
548; CHECK-NEXT:    call void @use(i8 [[B]])
549; CHECK-NEXT:    [[C:%.*]] = icmp ne i8 [[X]], [[Y]]
550; CHECK-NEXT:    ret i1 [[C]]
551;
552  %A = mul i8 %x, 5
553  call void @use(i8 %A)
554  %B = mul i8 %y, 5
555  call void @use(i8 %B)
556  %C = icmp ne i8 %A, %B
557  ret i1 %C
558}
559
560define i1 @mul_constant_eq_nsw(i32 %x, i32 %y) {
561; CHECK-LABEL: @mul_constant_eq_nsw(
562; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
563; CHECK-NEXT:    ret i1 [[C]]
564;
565  %A = mul nsw i32 %x, 6
566  %B = mul nsw i32 %y, 6
567  %C = icmp eq i32 %A, %B
568  ret i1 %C
569}
570
571define <2 x i1> @mul_constant_ne_nsw_splat(<2 x i32> %x, <2 x i32> %y) {
572; CHECK-LABEL: @mul_constant_ne_nsw_splat(
573; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
574; CHECK-NEXT:    ret <2 x i1> [[C]]
575;
576  %A = mul nsw <2 x i32> %x, <i32 12, i32 12>
577  %B = mul nsw <2 x i32> %y, <i32 12, i32 12>
578  %C = icmp ne <2 x i32> %A, %B
579  ret <2 x i1> %C
580}
581
582define i1 @mul_constant_ne_nsw_extra_use1(i8 %x, i8 %y) {
583; CHECK-LABEL: @mul_constant_ne_nsw_extra_use1(
584; CHECK-NEXT:    [[A:%.*]] = mul nsw i8 [[X:%.*]], 74
585; CHECK-NEXT:    call void @use(i8 [[A]])
586; CHECK-NEXT:    [[C:%.*]] = icmp ne i8 [[X]], [[Y:%.*]]
587; CHECK-NEXT:    ret i1 [[C]]
588;
589  %A = mul nsw i8 %x, 74
590  call void @use(i8 %A)
591  %B = mul nsw i8 %y, 74
592  %C = icmp ne i8 %A, %B
593  ret i1 %C
594}
595
596define i1 @mul_constant_eq_nsw_extra_use2(i8 %x, i8 %y) {
597; CHECK-LABEL: @mul_constant_eq_nsw_extra_use2(
598; CHECK-NEXT:    [[B:%.*]] = mul nsw i8 [[Y:%.*]], 20
599; CHECK-NEXT:    call void @use(i8 [[B]])
600; CHECK-NEXT:    [[C:%.*]] = icmp eq i8 [[X:%.*]], [[Y]]
601; CHECK-NEXT:    ret i1 [[C]]
602;
603  %A = mul nsw i8 %x, 20
604  %B = mul nsw i8 %y, 20
605  call void @use(i8 %B)
606  %C = icmp eq i8 %A, %B
607  ret i1 %C
608}
609
610define i1 @mul_constant_ne_nsw_extra_use3(i8 %x, i8 %y) {
611; CHECK-LABEL: @mul_constant_ne_nsw_extra_use3(
612; CHECK-NEXT:    [[A:%.*]] = mul nsw i8 [[X:%.*]], 24
613; CHECK-NEXT:    call void @use(i8 [[A]])
614; CHECK-NEXT:    [[B:%.*]] = mul nsw i8 [[Y:%.*]], 24
615; CHECK-NEXT:    call void @use(i8 [[B]])
616; CHECK-NEXT:    [[C:%.*]] = icmp ne i8 [[X]], [[Y]]
617; CHECK-NEXT:    ret i1 [[C]]
618;
619  %A = mul nsw i8 %x, 24
620  call void @use(i8 %A)
621  %B = mul nsw i8 %y, 24
622  call void @use(i8 %B)
623  %C = icmp ne i8 %A, %B
624  ret i1 %C
625}
626
627define i1 @mul_constant_nuw_eq(i32 %x, i32 %y) {
628; CHECK-LABEL: @mul_constant_nuw_eq(
629; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
630; CHECK-NEXT:    ret i1 [[C]]
631;
632  %A = mul nuw i32 %x, 22
633  %B = mul nuw i32 %y, 22
634  %C = icmp eq i32 %A, %B
635  ret i1 %C
636}
637
638define <2 x i1> @mul_constant_ne_nuw_splat(<2 x i32> %x, <2 x i32> %y) {
639; CHECK-LABEL: @mul_constant_ne_nuw_splat(
640; CHECK-NEXT:    [[C:%.*]] = icmp ne <2 x i32> [[X:%.*]], [[Y:%.*]]
641; CHECK-NEXT:    ret <2 x i1> [[C]]
642;
643  %A = mul nuw <2 x i32> %x, <i32 10, i32 10>
644  %B = mul nuw <2 x i32> %y, <i32 10, i32 10>
645  %C = icmp ne <2 x i32> %A, %B
646  ret <2 x i1> %C
647}
648
649define i1 @mul_constant_ne_nuw_extra_use1(i8 %x, i8 %y) {
650; CHECK-LABEL: @mul_constant_ne_nuw_extra_use1(
651; CHECK-NEXT:    [[A:%.*]] = mul nuw i8 [[X:%.*]], 6
652; CHECK-NEXT:    call void @use(i8 [[A]])
653; CHECK-NEXT:    [[C:%.*]] = icmp ne i8 [[X]], [[Y:%.*]]
654; CHECK-NEXT:    ret i1 [[C]]
655;
656  %A = mul nuw i8 %x, 6
657  call void @use(i8 %A)
658  %B = mul nuw i8 %y, 6
659  %C = icmp ne i8 %A, %B
660  ret i1 %C
661}
662
663define i1 @mul_constant_eq_nuw_extra_use2(i8 %x, i8 %y) {
664; CHECK-LABEL: @mul_constant_eq_nuw_extra_use2(
665; CHECK-NEXT:    [[B:%.*]] = mul nuw i8 [[Y:%.*]], 36
666; CHECK-NEXT:    call void @use(i8 [[B]])
667; CHECK-NEXT:    [[C:%.*]] = icmp eq i8 [[X:%.*]], [[Y]]
668; CHECK-NEXT:    ret i1 [[C]]
669;
670  %A = mul nuw i8 %x, 36
671  %B = mul nuw i8 %y, 36
672  call void @use(i8 %B)
673  %C = icmp eq i8 %A, %B
674  ret i1 %C
675}
676
677define i1 @mul_constant_ne_nuw_extra_use3(i8 %x, i8 %y) {
678; CHECK-LABEL: @mul_constant_ne_nuw_extra_use3(
679; CHECK-NEXT:    [[A:%.*]] = mul nuw i8 [[X:%.*]], 38
680; CHECK-NEXT:    call void @use(i8 [[A]])
681; CHECK-NEXT:    [[B:%.*]] = mul nuw i8 [[Y:%.*]], 38
682; CHECK-NEXT:    call void @use(i8 [[B]])
683; CHECK-NEXT:    [[C:%.*]] = icmp ne i8 [[X]], [[Y]]
684; CHECK-NEXT:    ret i1 [[C]]
685;
686  %A = mul nuw i8 %x, 38
687  call void @use(i8 %A)
688  %B = mul nuw i8 %y, 38
689  call void @use(i8 %B)
690  %C = icmp ne i8 %A, %B
691  ret i1 %C
692}
693
694; Negative test - wrong pred
695
696define i1 @mul_constant_ult(i32 %x, i32 %y) {
697; CHECK-LABEL: @mul_constant_ult(
698; CHECK-NEXT:    [[A:%.*]] = mul i32 [[X:%.*]], 47
699; CHECK-NEXT:    [[B:%.*]] = mul i32 [[Y:%.*]], 47
700; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[A]], [[B]]
701; CHECK-NEXT:    ret i1 [[C]]
702;
703  %A = mul i32 %x, 47
704  %B = mul i32 %y, 47
705  %C = icmp ult i32 %A, %B
706  ret i1 %C
707}
708
709; Negative test - wrong pred
710
711define i1 @mul_constant_nuw_sgt(i32 %x, i32 %y) {
712; CHECK-LABEL: @mul_constant_nuw_sgt(
713; CHECK-NEXT:    [[A:%.*]] = mul nuw i32 [[X:%.*]], 46
714; CHECK-NEXT:    [[B:%.*]] = mul nuw i32 [[Y:%.*]], 46
715; CHECK-NEXT:    [[C:%.*]] = icmp sgt i32 [[A]], [[B]]
716; CHECK-NEXT:    ret i1 [[C]]
717;
718  %A = mul nuw i32 %x, 46
719  %B = mul nuw i32 %y, 46
720  %C = icmp sgt i32 %A, %B
721  ret i1 %C
722}
723
724; Negative test - wrong constants
725
726define i1 @mul_mismatch_constant_nuw_eq(i32 %x, i32 %y) {
727; CHECK-LABEL: @mul_mismatch_constant_nuw_eq(
728; CHECK-NEXT:    [[A:%.*]] = mul nuw i32 [[X:%.*]], 46
729; CHECK-NEXT:    [[B:%.*]] = mul nuw i32 [[Y:%.*]], 44
730; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[A]], [[B]]
731; CHECK-NEXT:    ret i1 [[C]]
732;
733  %A = mul nuw i32 %x, 46
734  %B = mul nuw i32 %y, 44
735  %C = icmp eq i32 %A, %B
736  ret i1 %C
737}
738
739; If the multiply constant has any trailing zero bits but could overflow,
740; we get something completely different.
741; We mask off the high bits of each input and then convert:
742; (X&Z) == (Y&Z) -> (X^Y) & Z == 0
743
744define i1 @mul_constant_partial_nuw_eq(i32 %x, i32 %y) {
745; CHECK-LABEL: @mul_constant_partial_nuw_eq(
746; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
747; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 1073741823
748; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[TMP2]], 0
749; CHECK-NEXT:    ret i1 [[C]]
750;
751  %A = mul i32 %x, 44
752  %B = mul nuw i32 %y, 44
753  %C = icmp eq i32 %A, %B
754  ret i1 %C
755}
756
757define i1 @mul_constant_mismatch_wrap_eq(i32 %x, i32 %y) {
758; CHECK-LABEL: @mul_constant_mismatch_wrap_eq(
759; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
760; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 2147483647
761; CHECK-NEXT:    [[C:%.*]] = icmp eq i32 [[TMP2]], 0
762; CHECK-NEXT:    ret i1 [[C]]
763;
764  %A = mul nsw i32 %x, 54
765  %B = mul nuw i32 %y, 54
766  %C = icmp eq i32 %A, %B
767  ret i1 %C
768}
769
770define i1 @eq_mul_constants_with_tz(i32 %x, i32 %y) {
771; CHECK-LABEL: @eq_mul_constants_with_tz(
772; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
773; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 1073741823
774; CHECK-NEXT:    [[C:%.*]] = icmp ne i32 [[TMP2]], 0
775; CHECK-NEXT:    ret i1 [[C]]
776;
777  %A = mul i32 %x, 12
778  %B = mul i32 %y, 12
779  %C = icmp ne i32 %A, %B
780  ret i1 %C
781}
782
783define <2 x i1> @eq_mul_constants_with_tz_splat(<2 x i32> %x, <2 x i32> %y) {
784; CHECK-LABEL: @eq_mul_constants_with_tz_splat(
785; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i32> [[X:%.*]], [[Y:%.*]]
786; CHECK-NEXT:    [[TMP2:%.*]] = and <2 x i32> [[TMP1]], splat (i32 1073741823)
787; CHECK-NEXT:    [[C:%.*]] = icmp eq <2 x i32> [[TMP2]], zeroinitializer
788; CHECK-NEXT:    ret <2 x i1> [[C]]
789;
790  %A = mul <2 x i32> %x, <i32 12, i32 12>
791  %B = mul <2 x i32> %y, <i32 12, i32 12>
792  %C = icmp eq <2 x i32> %A, %B
793  ret <2 x i1> %C
794}
795
796@g = extern_weak global i32
797
798define i1 @oss_fuzz_39934(i32 %arg) {
799; CHECK-LABEL: @oss_fuzz_39934(
800; CHECK-NEXT:    [[C10:%.*]] = icmp ne i32 [[ARG:%.*]], 1
801; CHECK-NEXT:    ret i1 [[C10]]
802;
803  %B13 = mul nsw i32 %arg, -65536
804  %cmp = icmp eq ptr @g, null
805  %ext = zext i1 %cmp to i32
806  %or = or i32 %ext, 65537
807  %mul = mul i32 %or, -65536
808  %C10 = icmp ne i32 %mul, %B13
809  ret i1 %C10
810}
811
812define i1 @mul_of_bool(i32 %x, i8 %y) {
813; CHECK-LABEL: @mul_of_bool(
814; CHECK-NEXT:    ret i1 false
815;
816  %b = and i32 %x, 1
817  %z = zext i8 %y to i32
818  %m = mul i32 %b, %z
819  %r = icmp ugt i32 %m, 255
820  ret i1 %r
821}
822
823define i1 @mul_of_bool_commute(i32 %x, i32 %y) {
824; CHECK-LABEL: @mul_of_bool_commute(
825; CHECK-NEXT:    ret i1 false
826;
827  %x1 = and i32 %x, 1
828  %y8 = and i32 %y, 255
829  %m = mul i32 %y8, %x1
830  %r = icmp ugt i32 %m, 255
831  ret i1 %r
832}
833
834define i1 @mul_of_bools(i32 %x, i32 %y) {
835; CHECK-LABEL: @mul_of_bools(
836; CHECK-NEXT:    ret i1 true
837;
838  %x1 = and i32 %x, 1
839  %y1 = and i32 %y, 1
840  %m = mul i32 %x1, %y1
841  %r = icmp ult i32 %m, 2
842  ret i1 %r
843}
844
845; negative test - not a mask of low bit
846
847define i1 @not_mul_of_bool(i32 %x, i8 %y) {
848; CHECK-LABEL: @not_mul_of_bool(
849; CHECK-NEXT:    [[Q:%.*]] = and i32 [[X:%.*]], 3
850; CHECK-NEXT:    [[Z:%.*]] = zext i8 [[Y:%.*]] to i32
851; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw i32 [[Q]], [[Z]]
852; CHECK-NEXT:    [[R:%.*]] = icmp samesign ugt i32 [[M]], 255
853; CHECK-NEXT:    ret i1 [[R]]
854;
855  %q = and i32 %x, 3
856  %z = zext i8 %y to i32
857  %m = mul i32 %q, %z
858  %r = icmp ugt i32 %m, 255
859  ret i1 %r
860}
861
862; negative test - not a single low bit
863
864define i1 @not_mul_of_bool_commute(i32 %x, i32 %y) {
865; CHECK-LABEL: @not_mul_of_bool_commute(
866; CHECK-NEXT:    [[X30:%.*]] = lshr i32 [[X:%.*]], 30
867; CHECK-NEXT:    [[Y8:%.*]] = and i32 [[Y:%.*]], 255
868; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw i32 [[Y8]], [[X30]]
869; CHECK-NEXT:    [[R:%.*]] = icmp samesign ugt i32 [[M]], 255
870; CHECK-NEXT:    ret i1 [[R]]
871;
872  %x30 = lshr i32 %x, 30
873  %y8 = and i32 %y, 255
874  %m = mul i32 %y8, %x30
875  %r = icmp ugt i32 %m, 255
876  ret i1 %r
877}
878
879; no leading zeros for 's', but we reduce this with other transforms
880
881define i1 @mul_of_bool_no_lz_other_op(i32 %x, i8 %y) {
882; CHECK-LABEL: @mul_of_bool_no_lz_other_op(
883; CHECK-NEXT:    ret i1 false
884;
885  %b = and i32 %x, 1
886  %s = sext i8 %y to i32
887  %m = mul nuw nsw i32 %b, %s
888  %r = icmp sgt i32 %m, 127
889  ret i1 %r
890}
891
892; high and low bits are known 0
893
894define i1 @mul_of_pow2(i32 %x, i8 %y) {
895; CHECK-LABEL: @mul_of_pow2(
896; CHECK-NEXT:    ret i1 false
897;
898  %b = and i32 %x, 2
899  %z = zext i8 %y to i32
900  %m = mul i32 %b, %z
901  %r = icmp ugt i32 %m, 510
902  ret i1 %r
903}
904
905; high and low bits are known 0
906
907define i1 @mul_of_pow2_commute(i32 %x, i32 %y) {
908; CHECK-LABEL: @mul_of_pow2_commute(
909; CHECK-NEXT:    ret i1 false
910;
911  %x4 = and i32 %x, 4
912  %y8 = and i32 %y, 255
913  %m = mul i32 %y8, %x4
914  %r = icmp ugt i32 %m, 1020
915  ret i1 %r
916}
917
918; only bit 7 can be set by the multiply
919
920define i32 @mul_of_pow2s(i32 %x, i32 %y) {
921; CHECK-LABEL: @mul_of_pow2s(
922; CHECK-NEXT:    ret i32 128
923;
924  %x8 = and i32 %x, 8
925  %y16 = and i32 %y, 16
926  %m = mul i32 %x8, %y16
927  %bit7 = or i32 %m, 128
928  ret i32 %bit7
929}
930
931; negative test - 6 * 255 = 1530 (but constant range analysis can get this)
932
933define i1 @not_mul_of_pow2(i32 %x, i8 %y) {
934; CHECK-LABEL: @not_mul_of_pow2(
935; CHECK-NEXT:    [[Q:%.*]] = and i32 [[X:%.*]], 6
936; CHECK-NEXT:    [[Z:%.*]] = zext i8 [[Y:%.*]] to i32
937; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw i32 [[Q]], [[Z]]
938; CHECK-NEXT:    [[R:%.*]] = icmp samesign ugt i32 [[M]], 1530
939; CHECK-NEXT:    ret i1 [[R]]
940;
941  %q = and i32 %x, 6
942  %z = zext i8 %y to i32
943  %m = mul i32 %q, %z
944  %r = icmp ugt i32 %m, 1530
945  ret i1 %r
946}
947
948; negative test - 12 * 255 = 3060 (but constant range analysis can get this)
949
950define i1 @not_mul_of_pow2_commute(i32 %x, i32 %y) {
951; CHECK-LABEL: @not_mul_of_pow2_commute(
952; CHECK-NEXT:    [[X30:%.*]] = and i32 [[X:%.*]], 12
953; CHECK-NEXT:    [[Y8:%.*]] = and i32 [[Y:%.*]], 255
954; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw i32 [[Y8]], [[X30]]
955; CHECK-NEXT:    [[R:%.*]] = icmp samesign ugt i32 [[M]], 3060
956; CHECK-NEXT:    ret i1 [[R]]
957;
958  %x30 = and i32 %x, 12
959  %y8 = and i32 %y, 255
960  %m = mul i32 %y8, %x30
961  %r = icmp ugt i32 %m, 3060
962  ret i1 %r
963}
964
965; negative test - no leading zeros for 's'
966; TODO: If analysis was generalized for sign bits, we could reduce this to false.
967
968define i1 @mul_of_pow2_no_lz_other_op(i32 %x, i8 %y) {
969; CHECK-LABEL: @mul_of_pow2_no_lz_other_op(
970; CHECK-NEXT:    [[B:%.*]] = and i32 [[X:%.*]], 2
971; CHECK-NEXT:    [[S:%.*]] = sext i8 [[Y:%.*]] to i32
972; CHECK-NEXT:    [[M:%.*]] = mul nuw nsw i32 [[B]], [[S]]
973; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[M]], 254
974; CHECK-NEXT:    ret i1 [[R]]
975;
976  %b = and i32 %x, 2
977  %s = sext i8 %y to i32
978  %m = mul nuw nsw i32 %b, %s
979  %r = icmp sgt i32 %m, 254
980  ret i1 %r
981}
982
983; The top 32-bits must be zero.
984
985define i1 @splat_mul_known_lz(i32 %x) {
986; CHECK-LABEL: @splat_mul_known_lz(
987; CHECK-NEXT:    ret i1 true
988;
989  %z = zext i32 %x to i128
990  %m = mul i128 %z, 18446744078004518913 ; 0x00000000_00000001_00000001_00000001
991  %s = lshr i128 %m, 96
992  %r = icmp eq i128 %s, 0
993  ret i1 %r
994}
995
996; The 33rd bit can only be set when MSB of x is set.
997
998define i1 @splat_mul_unknown_lz(i32 %x) {
999; CHECK-LABEL: @splat_mul_unknown_lz(
1000; CHECK-NEXT:    [[R:%.*]] = icmp sgt i32 [[X:%.*]], -1
1001; CHECK-NEXT:    ret i1 [[R]]
1002;
1003  %z = zext i32 %x to i128
1004  %m = mul i128 %z, 18446744078004518913 ; 0x00000000_00000001_00000001_00000001
1005  %s = lshr i128 %m, 95
1006  %r = icmp eq i128 %s, 0
1007  ret i1 %r
1008}
1009
1010define i1 @mul_oddC_overflow_eq(i8 %v) {
1011; CHECK-LABEL: @mul_oddC_overflow_eq(
1012; CHECK-NEXT:    [[MUL:%.*]] = mul i8 [[V:%.*]], 5
1013; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[MUL]], 101
1014; CHECK-NEXT:    ret i1 [[CMP]]
1015;
1016  %mul = mul i8 %v, 5
1017  %cmp = icmp eq i8 %mul, 101
1018  ret i1 %cmp
1019}
1020
1021define i1 @mul_oddC_eq_nomod(i8 %v) {
1022; CHECK-LABEL: @mul_oddC_eq_nomod(
1023; CHECK-NEXT:    [[MUL:%.*]] = mul i8 [[V:%.*]], 3
1024; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[MUL]], 34
1025; CHECK-NEXT:    ret i1 [[CMP]]
1026;
1027  %mul = mul i8 %v, 3
1028  %cmp = icmp eq i8 %mul, 34
1029  ret i1 %cmp
1030}
1031
1032define i1 @mul_evenC_ne(i8 %v) {
1033; CHECK-LABEL: @mul_evenC_ne(
1034; CHECK-NEXT:    [[MUL:%.*]] = mul i8 [[V:%.*]], 6
1035; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[MUL]], 36
1036; CHECK-NEXT:    ret i1 [[CMP]]
1037;
1038  %mul = mul i8 %v, 6
1039  %cmp = icmp ne i8 %mul, 36
1040  ret i1 %cmp
1041}
1042
1043define <2 x i1> @mul_oddC_ne_vec(<2 x i8> %v) {
1044; CHECK-LABEL: @mul_oddC_ne_vec(
1045; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i8> [[V:%.*]], splat (i8 4)
1046; CHECK-NEXT:    ret <2 x i1> [[CMP]]
1047;
1048  %mul = mul <2 x i8> %v, <i8 3, i8 3>
1049  %cmp = icmp ne <2 x i8> %mul, <i8 12, i8 12>
1050  ret <2 x i1> %cmp
1051}
1052
1053define <2 x i1> @mul_oddC_ne_nosplat_vec(<2 x i8> %v) {
1054; CHECK-LABEL: @mul_oddC_ne_nosplat_vec(
1055; CHECK-NEXT:    [[MUL:%.*]] = mul <2 x i8> [[V:%.*]], <i8 3, i8 5>
1056; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i8> [[MUL]], <i8 12, i8 15>
1057; CHECK-NEXT:    ret <2 x i1> [[CMP]]
1058;
1059  %mul = mul <2 x i8> %v, <i8 3, i8 5>
1060  %cmp = icmp ne <2 x i8> %mul, <i8 12, i8 15>
1061  ret <2 x i1> %cmp
1062}
1063
1064define i1 @mul_nsuw_xy_z_maybe_zero_eq(i8 %x, i8 %y, i8 %z) {
1065; CHECK-LABEL: @mul_nsuw_xy_z_maybe_zero_eq(
1066; CHECK-NEXT:    [[MULX:%.*]] = mul nuw nsw i8 [[X:%.*]], [[Z:%.*]]
1067; CHECK-NEXT:    [[MULY:%.*]] = mul nuw nsw i8 [[Y:%.*]], [[Z]]
1068; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[MULX]], [[MULY]]
1069; CHECK-NEXT:    ret i1 [[CMP]]
1070;
1071  %mulx = mul nsw nuw i8 %x, %z
1072  %muly = mul nsw nuw i8 %y, %z
1073  %cmp = icmp eq i8 %mulx, %muly
1074  ret i1 %cmp
1075}
1076
1077define i1 @mul_xy_z_assumenozero_ne(i8 %x, i8 %y, i8 %z) {
1078; CHECK-LABEL: @mul_xy_z_assumenozero_ne(
1079; CHECK-NEXT:    [[NZ:%.*]] = icmp ne i8 [[Z:%.*]], 0
1080; CHECK-NEXT:    call void @llvm.assume(i1 [[NZ]])
1081; CHECK-NEXT:    [[MULX:%.*]] = mul i8 [[X:%.*]], [[Z]]
1082; CHECK-NEXT:    [[MULY:%.*]] = mul i8 [[Y:%.*]], [[Z]]
1083; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[MULY]], [[MULX]]
1084; CHECK-NEXT:    ret i1 [[CMP]]
1085;
1086  %nz = icmp ne i8 %z, 0
1087  call void @llvm.assume(i1 %nz)
1088  %mulx = mul i8 %x, %z
1089  %muly = mul i8 %y, %z
1090  %cmp = icmp ne i8 %muly, %mulx
1091  ret i1 %cmp
1092}
1093
1094define i1 @mul_xy_z_assumeodd_eq(i8 %x, i8 %y, i8 %z) {
1095; CHECK-LABEL: @mul_xy_z_assumeodd_eq(
1096; CHECK-NEXT:    [[LB:%.*]] = and i8 [[Z:%.*]], 1
1097; CHECK-NEXT:    [[NZ:%.*]] = icmp ne i8 [[LB]], 0
1098; CHECK-NEXT:    call void @llvm.assume(i1 [[NZ]])
1099; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
1100; CHECK-NEXT:    ret i1 [[CMP]]
1101;
1102  %lb = and i8 %z, 1
1103  %nz = icmp ne i8 %lb, 0
1104  call void @llvm.assume(i1 %nz)
1105  %mulx = mul i8 %x, %z
1106  %muly = mul i8 %z, %y
1107  %cmp = icmp eq i8 %mulx, %muly
1108  ret i1 %cmp
1109}
1110
1111define <2 x i1> @reused_mul_nsw_xy_z_setnonzero_vec_ne(<2 x i8> %x, <2 x i8> %y, <2 x i8> %zi) {
1112; CHECK-LABEL: @reused_mul_nsw_xy_z_setnonzero_vec_ne(
1113; CHECK-NEXT:    [[Z:%.*]] = or <2 x i8> [[ZI:%.*]], splat (i8 4)
1114; CHECK-NEXT:    [[MULY:%.*]] = mul nsw <2 x i8> [[Y:%.*]], [[Z]]
1115; CHECK-NEXT:    [[CMP:%.*]] = icmp ne <2 x i8> [[Y]], [[X:%.*]]
1116; CHECK-NEXT:    call void @usev2xi8(<2 x i8> [[MULY]])
1117; CHECK-NEXT:    ret <2 x i1> [[CMP]]
1118;
1119  %z = or <2 x i8> %zi, <i8 4, i8 4>
1120  %mulx = mul nsw <2 x i8> %z, %x
1121  %muly = mul nsw <2 x i8> %y, %z
1122  %cmp = icmp ne <2 x i8> %muly, %mulx
1123  call void @usev2xi8(<2 x i8> %muly)
1124  ret <2 x i1> %cmp
1125}
1126
1127define i1 @mul_mixed_nuw_nsw_xy_z_setodd_ult(i8 %x, i8 %y, i8 %zi) {
1128; CHECK-LABEL: @mul_mixed_nuw_nsw_xy_z_setodd_ult(
1129; CHECK-NEXT:    [[Z:%.*]] = or i8 [[ZI:%.*]], 1
1130; CHECK-NEXT:    [[MULX:%.*]] = mul nsw i8 [[X:%.*]], [[Z]]
1131; CHECK-NEXT:    [[MULY:%.*]] = mul nuw nsw i8 [[Y:%.*]], [[Z]]
1132; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[MULX]], [[MULY]]
1133; CHECK-NEXT:    ret i1 [[CMP]]
1134;
1135  %z = or i8 %zi, 1
1136  %mulx = mul nsw i8 %x, %z
1137  %muly = mul nuw nsw i8 %y, %z
1138  %cmp = icmp ult i8 %mulx, %muly
1139  ret i1 %cmp
1140}
1141
1142define i1 @mul_nuw_xy_z_assumenonzero_uge(i8 %x, i8 %y, i8 %z) {
1143; CHECK-LABEL: @mul_nuw_xy_z_assumenonzero_uge(
1144; CHECK-NEXT:    [[NZ:%.*]] = icmp ne i8 [[Z:%.*]], 0
1145; CHECK-NEXT:    call void @llvm.assume(i1 [[NZ]])
1146; CHECK-NEXT:    [[MULX:%.*]] = mul nuw i8 [[X:%.*]], [[Z]]
1147; CHECK-NEXT:    [[CMP:%.*]] = icmp uge i8 [[Y:%.*]], [[X]]
1148; CHECK-NEXT:    call void @use(i8 [[MULX]])
1149; CHECK-NEXT:    ret i1 [[CMP]]
1150;
1151  %nz = icmp ne i8 %z, 0
1152  call void @llvm.assume(i1 %nz)
1153  %mulx = mul nuw i8 %x, %z
1154  %muly = mul nuw i8 %y, %z
1155  %cmp = icmp uge i8 %muly, %mulx
1156  call void @use(i8 %mulx)
1157  ret i1 %cmp
1158}
1159
1160define <2 x i1> @mul_nuw_xy_z_setnonzero_vec_eq(<2 x i8> %x, <2 x i8> %y, <2 x i8> %zi) {
1161; CHECK-LABEL: @mul_nuw_xy_z_setnonzero_vec_eq(
1162; CHECK-NEXT:    [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], [[Y:%.*]]
1163; CHECK-NEXT:    ret <2 x i1> [[CMP]]
1164;
1165  %z = or <2 x i8> %zi, <i8 41, i8 12>
1166  %mulx = mul nuw <2 x i8> %z, %x
1167  %muly = mul nuw <2 x i8> %z, %y
1168  %cmp = icmp eq <2 x i8> %mulx, %muly
1169  ret <2 x i1> %cmp
1170}
1171
1172define i1 @mul_nuw_xy_z_brnonzero_ult(i8 %x, i8 %y, i8 %z) {
1173; CHECK-LABEL: @mul_nuw_xy_z_brnonzero_ult(
1174; CHECK-NEXT:    [[NZ_NOT:%.*]] = icmp eq i8 [[Z:%.*]], 0
1175; CHECK-NEXT:    br i1 [[NZ_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
1176; CHECK:       true:
1177; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[Y:%.*]], [[X:%.*]]
1178; CHECK-NEXT:    ret i1 [[CMP]]
1179; CHECK:       false:
1180; CHECK-NEXT:    call void @use(i8 [[Z]])
1181; CHECK-NEXT:    ret i1 true
1182;
1183  %nz = icmp ne i8 %z, 0
1184  br i1 %nz, label %true, label %false
1185true:
1186  %mulx = mul nuw i8 %x, %z
1187  %muly = mul nuw i8 %y, %z
1188  %cmp = icmp ult i8 %muly, %mulx
1189  ret i1 %cmp
1190false:
1191  call void @use(i8 %z)
1192  ret i1 true
1193}
1194
1195define i1 @reused_mul_nuw_xy_z_selectnonzero_ugt(i8 %x, i8 %y, i8 %z) {
1196; CHECK-LABEL: @reused_mul_nuw_xy_z_selectnonzero_ugt(
1197; CHECK-NEXT:    [[NZ_NOT:%.*]] = icmp eq i8 [[Z:%.*]], 0
1198; CHECK-NEXT:    [[MULX:%.*]] = mul nuw i8 [[X:%.*]], [[Z]]
1199; CHECK-NEXT:    [[MULY:%.*]] = mul nuw i8 [[Y:%.*]], [[Z]]
1200; CHECK-NEXT:    [[CMP:%.*]] = icmp ugt i8 [[MULY]], [[MULX]]
1201; CHECK-NEXT:    [[R:%.*]] = select i1 [[NZ_NOT]], i1 true, i1 [[CMP]]
1202; CHECK-NEXT:    ret i1 [[R]]
1203;
1204  %nz = icmp ne i8 %z, 0
1205  %mulx = mul nuw i8 %x, %z
1206  %muly = mul nuw i8 %y, %z
1207  %cmp = icmp ugt i8 %muly, %mulx
1208  %r = select i1 %nz, i1 %cmp, i1 true
1209  ret i1 %r
1210}
1211
1212define <2 x i1> @mul_mixed_nsw_nuw_xy_z_setnonzero_vec_ule(<2 x i8> %x, <2 x i8> %y, <2 x i8> %zi) {
1213; CHECK-LABEL: @mul_mixed_nsw_nuw_xy_z_setnonzero_vec_ule(
1214; CHECK-NEXT:    [[Z:%.*]] = or <2 x i8> [[ZI:%.*]], <i8 1, i8 3>
1215; CHECK-NEXT:    [[MULX:%.*]] = mul nuw <2 x i8> [[X:%.*]], [[Z]]
1216; CHECK-NEXT:    [[MULY:%.*]] = mul nsw <2 x i8> [[Z]], [[Y:%.*]]
1217; CHECK-NEXT:    [[CMP:%.*]] = icmp ule <2 x i8> [[MULY]], [[MULX]]
1218; CHECK-NEXT:    ret <2 x i1> [[CMP]]
1219;
1220  %z = or <2 x i8> %zi, <i8 1, i8 3>
1221  %mulx = mul nuw <2 x i8> %x, %z
1222  %muly = mul nsw <2 x i8> %z, %y
1223  %cmp = icmp ule <2 x i8> %muly, %mulx
1224  ret <2 x i1> %cmp
1225}
1226
1227define i1 @icmp_eq_mul_nsw_nonequal(i8 %a, i8 %c) {
1228; CHECK-LABEL: @icmp_eq_mul_nsw_nonequal(
1229; CHECK-NEXT:  entry:
1230; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C:%.*]], 0
1231; CHECK-NEXT:    ret i1 [[CMP]]
1232;
1233entry:
1234  %b = add i8 %a, 1
1235  %mul1 = mul nsw i8 %a, %c
1236  %mul2 = mul nsw i8 %b, %c
1237  %cmp = icmp eq i8 %mul1, %mul2
1238  ret i1 %cmp
1239}
1240
1241define i1 @icmp_eq_mul_nuw_nonequal(i8 %a, i8 %c) {
1242; CHECK-LABEL: @icmp_eq_mul_nuw_nonequal(
1243; CHECK-NEXT:  entry:
1244; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C:%.*]], 0
1245; CHECK-NEXT:    ret i1 [[CMP]]
1246;
1247entry:
1248  %b = add i8 %a, 1
1249  %mul1 = mul nuw i8 %a, %c
1250  %mul2 = mul nuw i8 %b, %c
1251  %cmp = icmp eq i8 %mul1, %mul2
1252  ret i1 %cmp
1253}
1254
1255define i1 @icmp_eq_mul_nsw_nonequal_commuted(i8 %a, i8 %c) {
1256; CHECK-LABEL: @icmp_eq_mul_nsw_nonequal_commuted(
1257; CHECK-NEXT:  entry:
1258; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C:%.*]], 0
1259; CHECK-NEXT:    ret i1 [[CMP]]
1260;
1261entry:
1262  %b = add i8 %a, 1
1263  %mul1 = mul nsw i8 %a, %c
1264  %mul2 = mul nsw i8 %c, %b
1265  %cmp = icmp eq i8 %mul1, %mul2
1266  ret i1 %cmp
1267}
1268
1269define i1 @icmp_ne_mul_nsw_nonequal(i8 %a, i8 %c) {
1270; CHECK-LABEL: @icmp_ne_mul_nsw_nonequal(
1271; CHECK-NEXT:  entry:
1272; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8 [[C:%.*]], 0
1273; CHECK-NEXT:    ret i1 [[CMP]]
1274;
1275entry:
1276  %b = add i8 %a, 1
1277  %mul1 = mul nsw i8 %a, %c
1278  %mul2 = mul nsw i8 %b, %c
1279  %cmp = icmp ne i8 %mul1, %mul2
1280  ret i1 %cmp
1281}
1282
1283; Negative tests
1284
1285define i1 @icmp_eq_mul_nsw_mayequal(i8 %a, i8 %b, i8 %c) {
1286; CHECK-LABEL: @icmp_eq_mul_nsw_mayequal(
1287; CHECK-NEXT:  entry:
1288; CHECK-NEXT:    [[MUL1:%.*]] = mul nsw i8 [[A:%.*]], [[C:%.*]]
1289; CHECK-NEXT:    [[MUL2:%.*]] = mul nsw i8 [[B:%.*]], [[C]]
1290; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]]
1291; CHECK-NEXT:    ret i1 [[CMP]]
1292;
1293entry:
1294  %mul1 = mul nsw i8 %a, %c
1295  %mul2 = mul nsw i8 %b, %c
1296  %cmp = icmp eq i8 %mul1, %mul2
1297  ret i1 %cmp
1298}
1299
1300define i1 @icmp_eq_mul_nsw_nuw_nonequal(i8 %a, i8 %c) {
1301; CHECK-LABEL: @icmp_eq_mul_nsw_nuw_nonequal(
1302; CHECK-NEXT:  entry:
1303; CHECK-NEXT:    [[B:%.*]] = add i8 [[A:%.*]], 1
1304; CHECK-NEXT:    [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]]
1305; CHECK-NEXT:    [[MUL2:%.*]] = mul nuw i8 [[B]], [[C]]
1306; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[MUL1]], [[MUL2]]
1307; CHECK-NEXT:    ret i1 [[CMP]]
1308;
1309entry:
1310  %b = add i8 %a, 1
1311  %mul1 = mul nsw i8 %a, %c
1312  %mul2 = mul nuw i8 %b, %c
1313  %cmp = icmp eq i8 %mul1, %mul2
1314  ret i1 %cmp
1315}
1316
1317define i1 @icmp_ult_mul_nsw_nonequal(i8 %a, i8 %c) {
1318; CHECK-LABEL: @icmp_ult_mul_nsw_nonequal(
1319; CHECK-NEXT:  entry:
1320; CHECK-NEXT:    [[B:%.*]] = add i8 [[A:%.*]], 1
1321; CHECK-NEXT:    [[MUL1:%.*]] = mul nsw i8 [[A]], [[C:%.*]]
1322; CHECK-NEXT:    [[MUL2:%.*]] = mul nsw i8 [[B]], [[C]]
1323; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i8 [[MUL1]], [[MUL2]]
1324; CHECK-NEXT:    ret i1 [[CMP]]
1325;
1326entry:
1327  %b = add i8 %a, 1
1328  %mul1 = mul nsw i8 %a, %c
1329  %mul2 = mul nsw i8 %b, %c
1330  %cmp = icmp ult i8 %mul1, %mul2
1331  ret i1 %cmp
1332}
1333
1334define i1 @icmp_mul_nsw_slt(i8 %x, i8 %y) {
1335; CHECK-LABEL: @icmp_mul_nsw_slt(
1336; CHECK-NEXT:  entry:
1337; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]]
1338; CHECK-NEXT:    ret i1 [[CMP]]
1339;
1340entry:
1341  %mul1 = mul nsw i8 %x, 7
1342  %mul2 = mul nsw i8 %y, 7
1343  %cmp = icmp slt i8 %mul1, %mul2
1344  ret i1 %cmp
1345}
1346
1347define i1 @icmp_mul_nsw_sle(i8 %x, i8 %y) {
1348; CHECK-LABEL: @icmp_mul_nsw_sle(
1349; CHECK-NEXT:  entry:
1350; CHECK-NEXT:    [[CMP:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]]
1351; CHECK-NEXT:    ret i1 [[CMP]]
1352;
1353entry:
1354  %mul1 = mul nsw i8 %x, 7
1355  %mul2 = mul nsw i8 %y, 7
1356  %cmp = icmp sle i8 %mul1, %mul2
1357  ret i1 %cmp
1358}
1359
1360define i1 @icmp_mul_nsw_sgt(i8 %x, i8 %y) {
1361; CHECK-LABEL: @icmp_mul_nsw_sgt(
1362; CHECK-NEXT:  entry:
1363; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]]
1364; CHECK-NEXT:    ret i1 [[CMP]]
1365;
1366entry:
1367  %mul1 = mul nsw i8 %x, 7
1368  %mul2 = mul nsw i8 %y, 7
1369  %cmp = icmp sgt i8 %mul1, %mul2
1370  ret i1 %cmp
1371}
1372
1373define i1 @icmp_mul_nsw_sge(i8 %x, i8 %y) {
1374; CHECK-LABEL: @icmp_mul_nsw_sge(
1375; CHECK-NEXT:  entry:
1376; CHECK-NEXT:    [[CMP:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]]
1377; CHECK-NEXT:    ret i1 [[CMP]]
1378;
1379entry:
1380  %mul1 = mul nsw i8 %x, 7
1381  %mul2 = mul nsw i8 %y, 7
1382  %cmp = icmp sge i8 %mul1, %mul2
1383  ret i1 %cmp
1384}
1385
1386define i1 @icmp_mul_nsw_slt_neg(i8 %x, i8 %y) {
1387; CHECK-LABEL: @icmp_mul_nsw_slt_neg(
1388; CHECK-NEXT:  entry:
1389; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]]
1390; CHECK-NEXT:    ret i1 [[CMP]]
1391;
1392entry:
1393  %mul1 = mul nsw i8 %x, -7
1394  %mul2 = mul nsw i8 %y, -7
1395  %cmp = icmp slt i8 %mul1, %mul2
1396  ret i1 %cmp
1397}
1398
1399define i1 @icmp_mul_nsw_slt_neg_var(i8 %x, i8 %y, i8 %z) {
1400; CHECK-LABEL: @icmp_mul_nsw_slt_neg_var(
1401; CHECK-NEXT:  entry:
1402; CHECK-NEXT:    [[COND:%.*]] = icmp slt i8 [[Z:%.*]], 0
1403; CHECK-NEXT:    call void @llvm.assume(i1 [[COND]])
1404; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]]
1405; CHECK-NEXT:    ret i1 [[CMP]]
1406;
1407entry:
1408  %cond = icmp slt i8 %z, 0
1409  call void @llvm.assume(i1 %cond)
1410  %mul1 = mul nsw i8 %x, %z
1411  %mul2 = mul nsw i8 %y, %z
1412  %cmp = icmp slt i8 %mul1, %mul2
1413  ret i1 %cmp
1414}
1415
1416; Negative tests
1417
1418define i1 @icmp_mul_nonsw_slt(i8 %x, i8 %y) {
1419; CHECK-LABEL: @icmp_mul_nonsw_slt(
1420; CHECK-NEXT:  entry:
1421; CHECK-NEXT:    [[MUL1:%.*]] = mul i8 [[X:%.*]], 7
1422; CHECK-NEXT:    [[MUL2:%.*]] = mul nsw i8 [[Y:%.*]], 7
1423; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[MUL1]], [[MUL2]]
1424; CHECK-NEXT:    ret i1 [[CMP]]
1425;
1426entry:
1427  %mul1 = mul i8 %x, 7
1428  %mul2 = mul nsw i8 %y, 7
1429  %cmp = icmp slt i8 %mul1, %mul2
1430  ret i1 %cmp
1431}
1432
1433define i1 @icmp_mul_nsw_slt_unknown_sign(i8 %x, i8 %y, i8 %z) {
1434; CHECK-LABEL: @icmp_mul_nsw_slt_unknown_sign(
1435; CHECK-NEXT:  entry:
1436; CHECK-NEXT:    [[MUL1:%.*]] = mul nsw i8 [[X:%.*]], [[Z:%.*]]
1437; CHECK-NEXT:    [[MUL2:%.*]] = mul nsw i8 [[Y:%.*]], [[Z]]
1438; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[MUL1]], [[MUL2]]
1439; CHECK-NEXT:    ret i1 [[CMP]]
1440;
1441entry:
1442  %mul1 = mul nsw i8 %x, %z
1443  %mul2 = mul nsw i8 %y, %z
1444  %cmp = icmp slt i8 %mul1, %mul2
1445  ret i1 %cmp
1446}
1447
1448define i1 @icmp_mul_nsw_slt_may_be_zero(i8 %x, i8 %y, i8 %z) {
1449; CHECK-LABEL: @icmp_mul_nsw_slt_may_be_zero(
1450; CHECK-NEXT:  entry:
1451; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i8 [[Z:%.*]], -1
1452; CHECK-NEXT:    call void @llvm.assume(i1 [[COND]])
1453; CHECK-NEXT:    [[MUL1:%.*]] = mul nsw i8 [[X:%.*]], [[Z]]
1454; CHECK-NEXT:    [[MUL2:%.*]] = mul nsw i8 [[Y:%.*]], [[Z]]
1455; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i8 [[MUL1]], [[MUL2]]
1456; CHECK-NEXT:    ret i1 [[CMP]]
1457;
1458entry:
1459  %cond = icmp sgt i8 %z, -1
1460  call void @llvm.assume(i1 %cond)
1461
1462  %mul1 = mul nsw i8 %x, %z
1463  %mul2 = mul nsw i8 %y, %z
1464  %cmp = icmp slt i8 %mul1, %mul2
1465  ret i1 %cmp
1466}
1467
1468define i1 @test_icmp_slt_mul_known_sgt(i64 %x, i64 %z) {
1469; CHECK-LABEL: @test_icmp_slt_mul_known_sgt(
1470; CHECK-NEXT:  entry:
1471; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], 0
1472; CHECK-NEXT:    ret i1 [[CMP]]
1473;
1474entry:
1475  %y = add nsw i64 %x, 1
1476  %mul1 = mul nsw i64 %x, %z
1477  %mul2 = mul nsw i64 %y, %z
1478  %cmp = icmp slt i64 %mul1, %mul2
1479  ret i1 %cmp
1480}
1481
1482define i1 @test_icmp_sle_mul_known_sgt(i64 %x, i64 %z) {
1483; CHECK-LABEL: @test_icmp_sle_mul_known_sgt(
1484; CHECK-NEXT:  entry:
1485; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], -1
1486; CHECK-NEXT:    ret i1 [[CMP]]
1487;
1488entry:
1489  %y = add nsw i64 %x, 1
1490  %mul1 = mul nsw i64 %x, %z
1491  %mul2 = mul nsw i64 %y, %z
1492  %cmp = icmp sle i64 %mul1, %mul2
1493  ret i1 %cmp
1494}
1495
1496define i1 @test_icmp_mul_known_slt(i64 %x, i64 %z) {
1497; CHECK-LABEL: @test_icmp_mul_known_slt(
1498; CHECK-NEXT:  entry:
1499; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[Z:%.*]], 0
1500; CHECK-NEXT:    ret i1 [[CMP]]
1501;
1502entry:
1503  %y = add nsw i64 %x, 1
1504  %mul1 = mul nsw i64 %x, %z
1505  %mul2 = mul nsw i64 %y, %z
1506  %cmp = icmp slt i64 %mul2, %mul1
1507  ret i1 %cmp
1508}
1509
1510define i1 @test_icmp_slt_mul_known_sgt_commuted1(i64 %x, i64 %z) {
1511; CHECK-LABEL: @test_icmp_slt_mul_known_sgt_commuted1(
1512; CHECK-NEXT:  entry:
1513; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], 0
1514; CHECK-NEXT:    ret i1 [[CMP]]
1515;
1516entry:
1517  %y = add nsw i64 %x, 1
1518  %mul1 = mul nsw i64 %z, %x
1519  %mul2 = mul nsw i64 %y, %z
1520  %cmp = icmp slt i64 %mul1, %mul2
1521  ret i1 %cmp
1522}
1523
1524define i1 @test_icmp_slt_mul_known_sgt_commuted2(i64 %x, i64 %z) {
1525; CHECK-LABEL: @test_icmp_slt_mul_known_sgt_commuted2(
1526; CHECK-NEXT:  entry:
1527; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i64 [[Z:%.*]], 0
1528; CHECK-NEXT:    ret i1 [[CMP]]
1529;
1530entry:
1531  %y = add nsw i64 %x, 1
1532  %mul1 = mul nsw i64 %x, %z
1533  %mul2 = mul nsw i64 %z, %y
1534  %cmp = icmp slt i64 %mul1, %mul2
1535  ret i1 %cmp
1536}
1537
1538define i1 @test_icmp_slt_mul_unknown(i64 %x, i64 %z) {
1539; CHECK-LABEL: @test_icmp_slt_mul_unknown(
1540; CHECK-NEXT:  entry:
1541; CHECK-NEXT:    [[Y:%.*]] = add i64 [[X:%.*]], 1
1542; CHECK-NEXT:    [[MUL1:%.*]] = mul nsw i64 [[X]], [[Z:%.*]]
1543; CHECK-NEXT:    [[MUL2:%.*]] = mul nsw i64 [[Z]], [[Y]]
1544; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[MUL1]], [[MUL2]]
1545; CHECK-NEXT:    ret i1 [[CMP]]
1546;
1547entry:
1548  %y = add i64 %x, 1
1549  %mul1 = mul nsw i64 %x, %z
1550  %mul2 = mul nsw i64 %z, %y
1551  %cmp = icmp slt i64 %mul1, %mul2
1552  ret i1 %cmp
1553}
1554
1555define i1 @test_icmp_slt_mul_no_nsw(i64 %x, i64 %z) {
1556; CHECK-LABEL: @test_icmp_slt_mul_no_nsw(
1557; CHECK-NEXT:  entry:
1558; CHECK-NEXT:    [[Y:%.*]] = add nsw i64 [[X:%.*]], 1
1559; CHECK-NEXT:    [[MUL1:%.*]] = mul i64 [[X]], [[Z:%.*]]
1560; CHECK-NEXT:    [[MUL2:%.*]] = mul nsw i64 [[Z]], [[Y]]
1561; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[MUL1]], [[MUL2]]
1562; CHECK-NEXT:    ret i1 [[CMP]]
1563;
1564entry:
1565  %y = add nsw i64 %x, 1
1566  %mul1 = mul i64 %x, %z
1567  %mul2 = mul nsw i64 %z, %y
1568  %cmp = icmp slt i64 %mul1, %mul2
1569  ret i1 %cmp
1570}
1571