xref: /llvm-project/llvm/test/Transforms/InstCombine/icmp-div-constant.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4target datalayout = "n32"
5
6define i1 @is_rem2_neg_i8(i8 %x) {
7; CHECK-LABEL: @is_rem2_neg_i8(
8; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], -127
9; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[TMP1]], -127
10; CHECK-NEXT:    ret i1 [[R]]
11;
12  %s = srem i8 %x, 2
13  %r = icmp slt i8 %s, 0
14  ret i1 %r
15}
16
17define <2 x i1> @is_rem2_pos_v2i8(<2 x i8> %x) {
18; CHECK-LABEL: @is_rem2_pos_v2i8(
19; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], splat (i8 -127)
20; CHECK-NEXT:    [[R:%.*]] = icmp eq <2 x i8> [[TMP1]], splat (i8 1)
21; CHECK-NEXT:    ret <2 x i1> [[R]]
22;
23  %s = srem <2 x i8> %x, <i8 2, i8 2>
24  %r = icmp sgt <2 x i8> %s, zeroinitializer
25  ret <2 x i1> %r
26}
27
28; i8 -97 == 159 == 0b10011111
29
30define i1 @is_rem32_pos_i8(i8 %x) {
31; CHECK-LABEL: @is_rem32_pos_i8(
32; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[X:%.*]], -97
33; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[TMP1]], 0
34; CHECK-NEXT:    ret i1 [[R]]
35;
36  %s = srem i8 %x, 32
37  %r = icmp sgt i8 %s, 0
38  ret i1 %r
39}
40
41; i16 -32765 == 32771 == 0b1000000000000011
42
43define i1 @is_rem4_neg_i16(i16 %x) {
44; CHECK-LABEL: @is_rem4_neg_i16(
45; CHECK-NEXT:    [[TMP1:%.*]] = and i16 [[X:%.*]], -32765
46; CHECK-NEXT:    [[R:%.*]] = icmp ugt i16 [[TMP1]], -32768
47; CHECK-NEXT:    ret i1 [[R]]
48;
49  %s = srem i16 %x, 4
50  %r = icmp slt i16 %s, 0
51  ret i1 %r
52}
53
54declare void @use(i32)
55
56; TODO: This is still worth folding because srem is difficult?
57
58define i1 @is_rem32_neg_i32_extra_use(i32 %x) {
59; CHECK-LABEL: @is_rem32_neg_i32_extra_use(
60; CHECK-NEXT:    [[S:%.*]] = srem i32 [[X:%.*]], 32
61; CHECK-NEXT:    call void @use(i32 [[S]])
62; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[S]], 0
63; CHECK-NEXT:    ret i1 [[R]]
64;
65  %s = srem i32 %x, 32
66  call void @use(i32 %s)
67  %r = icmp slt i32 %s, 0
68  ret i1 %r
69}
70
71; Negative test - wrong compare constant
72
73define i1 @is_rem8_nonneg_i16(i16 %x) {
74; CHECK-LABEL: @is_rem8_nonneg_i16(
75; CHECK-NEXT:    [[S:%.*]] = srem i16 [[X:%.*]], 8
76; CHECK-NEXT:    [[R:%.*]] = icmp sgt i16 [[S]], -1
77; CHECK-NEXT:    ret i1 [[R]]
78;
79  %s = srem i16 %x, 8
80  %r = icmp sgt i16 %s, -1
81  ret i1 %r
82}
83
84; Negative test - wrong remainder constant
85
86define i1 @is_rem3_neg_i8(i8 %x) {
87; CHECK-LABEL: @is_rem3_neg_i8(
88; CHECK-NEXT:    [[S:%.*]] = srem i8 [[X:%.*]], 3
89; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[S]], 0
90; CHECK-NEXT:    ret i1 [[R]]
91;
92  %s = srem i8 %x, 3
93  %r = icmp slt i8 %s, 0
94  ret i1 %r
95}
96
97; Negative test - wrong compare constant
98
99define i1 @is_rem16_something_i8(i8 %x) {
100; CHECK-LABEL: @is_rem16_something_i8(
101; CHECK-NEXT:    [[S:%.*]] = srem i8 [[X:%.*]], 16
102; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[S]], 7
103; CHECK-NEXT:    ret i1 [[R]]
104;
105  %s = srem i8 %x, 16
106  %r = icmp slt i8 %s, 7
107  ret i1 %r
108}
109
110; PR30281 - https://llvm.org/bugs/show_bug.cgi?id=30281
111
112; All of these tests contain foldable division-by-constant instructions, but we
113; can't assert that those folds have occurred before we process the later icmp.
114
115define i32 @icmp_div(i16 %a, i16 %c) {
116; CHECK-LABEL: @icmp_div(
117; CHECK-NEXT:  entry:
118; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0
119; CHECK-NEXT:    br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]]
120; CHECK:       then:
121; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i16 [[C:%.*]], 0
122; CHECK-NEXT:    [[TMP0:%.*]] = sext i1 [[CMP_NOT]] to i32
123; CHECK-NEXT:    br label [[EXIT]]
124; CHECK:       exit:
125; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[TMP0]], [[THEN]] ]
126; CHECK-NEXT:    ret i32 [[PHI]]
127;
128entry:
129  %tobool = icmp eq i16 %a, 0
130  br i1 %tobool, label %then, label %exit
131
132then:
133  %div = sdiv i16 %c, -1
134  %cmp = icmp ne i16 %div, 0
135  br label %exit
136
137exit:
138  %phi = phi i1 [ false, %entry ], [ %cmp, %then ]
139  %zext = zext i1 %phi to i32
140  %add = add nsw i32 %zext, -1
141  ret i32 %add
142}
143
144define i32 @icmp_div2(i16 %a, i16 %c) {
145; CHECK-LABEL: @icmp_div2(
146; CHECK-NEXT:  entry:
147; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0
148; CHECK-NEXT:    br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]]
149; CHECK:       then:
150; CHECK-NEXT:    br label [[EXIT]]
151; CHECK:       exit:
152; CHECK-NEXT:    ret i32 -1
153;
154entry:
155  %tobool = icmp eq i16 %a, 0
156  br i1 %tobool, label %then, label %exit
157
158then:
159  %div = sdiv i16 %c, 0
160  %cmp = icmp ne i16 %div, 0
161  br label %exit
162
163exit:
164  %phi = phi i1 [ false, %entry ], [ %cmp, %then ]
165  %zext = zext i1 %phi to i32
166  %add = add nsw i32 %zext, -1
167  ret i32 %add
168}
169
170define i32 @icmp_div3(i16 %a, i16 %c) {
171; CHECK-LABEL: @icmp_div3(
172; CHECK-NEXT:  entry:
173; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i16 [[A:%.*]], 0
174; CHECK-NEXT:    br i1 [[TOBOOL]], label [[THEN:%.*]], label [[EXIT:%.*]]
175; CHECK:       then:
176; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp eq i16 [[C:%.*]], 0
177; CHECK-NEXT:    [[TMP0:%.*]] = sext i1 [[CMP_NOT]] to i32
178; CHECK-NEXT:    br label [[EXIT]]
179; CHECK:       exit:
180; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[TMP0]], [[THEN]] ]
181; CHECK-NEXT:    ret i32 [[PHI]]
182;
183entry:
184  %tobool = icmp eq i16 %a, 0
185  br i1 %tobool, label %then, label %exit
186
187then:
188  %div = sdiv i16 %c, 1
189  %cmp = icmp ne i16 %div, 0
190  br label %exit
191
192exit:
193  %phi = phi i1 [ false, %entry ], [ %cmp, %then ]
194  %zext = zext i1 %phi to i32
195  %add = add nsw i32 %zext, -1
196  ret i32 %add
197}
198
199define i1 @udiv_eq_umax(i8 %x, i8 %y) {
200; CHECK-LABEL: @udiv_eq_umax(
201; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], -1
202; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[Y:%.*]], 1
203; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP1]], [[TMP2]]
204; CHECK-NEXT:    ret i1 [[R]]
205;
206  %d = udiv i8 %x, %y
207  %r = icmp eq i8 %d, 255
208  ret i1 %r
209}
210
211define <2 x i1> @udiv_ne_umax(<2 x i5> %x, <2 x i5> %y) {
212; CHECK-LABEL: @udiv_ne_umax(
213; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <2 x i5> [[X:%.*]], splat (i5 -1)
214; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <2 x i5> [[Y:%.*]], splat (i5 1)
215; CHECK-NEXT:    [[R:%.*]] = or <2 x i1> [[TMP1]], [[TMP2]]
216; CHECK-NEXT:    ret <2 x i1> [[R]]
217;
218  %d = udiv <2 x i5> %x, %y
219  %r = icmp ne <2 x i5> %d, <i5 -1, i5 -1>
220  ret <2 x i1> %r
221}
222
223define i1 @udiv_eq_big(i8 %x, i8 %y) {
224; CHECK-LABEL: @udiv_eq_big(
225; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], -128
226; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[Y:%.*]], 1
227; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP1]], [[TMP2]]
228; CHECK-NEXT:    ret i1 [[R]]
229;
230  %d = udiv i8 %x, %y
231  %r = icmp eq i8 %d, 128
232  ret i1 %r
233}
234
235define i1 @udiv_ne_big(i8 %x, i8 %y) {
236; CHECK-LABEL: @udiv_ne_big(
237; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[X:%.*]], -128
238; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i8 [[Y:%.*]], 1
239; CHECK-NEXT:    [[R:%.*]] = or i1 [[TMP1]], [[TMP2]]
240; CHECK-NEXT:    ret i1 [[R]]
241;
242  %d = udiv i8 %x, %y
243  %r = icmp ne i8 %d, 128
244  ret i1 %r
245}
246
247; negative test - must have negative compare constant
248
249define i1 @udiv_eq_not_big(i8 %x, i8 %y) {
250; CHECK-LABEL: @udiv_eq_not_big(
251; CHECK-NEXT:    [[D:%.*]] = udiv i8 [[X:%.*]], [[Y:%.*]]
252; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[D]], 127
253; CHECK-NEXT:    ret i1 [[R]]
254;
255  %d = udiv i8 %x, %y
256  %r = icmp eq i8 %d, 127
257  ret i1 %r
258}
259
260; negative test - must be equality predicate
261
262define i1 @udiv_slt_umax(i8 %x, i8 %y) {
263; CHECK-LABEL: @udiv_slt_umax(
264; CHECK-NEXT:    [[D:%.*]] = udiv i8 [[X:%.*]], [[Y:%.*]]
265; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[D]], -1
266; CHECK-NEXT:    ret i1 [[R]]
267;
268  %d = udiv i8 %x, %y
269  %r = icmp slt i8 %d, 255
270  ret i1 %r
271}
272
273; negative test - extra use
274
275define i1 @udiv_eq_umax_use(i32 %x, i32 %y) {
276; CHECK-LABEL: @udiv_eq_umax_use(
277; CHECK-NEXT:    [[D:%.*]] = udiv i32 [[X:%.*]], [[Y:%.*]]
278; CHECK-NEXT:    call void @use(i32 [[D]])
279; CHECK-NEXT:    [[R:%.*]] = icmp eq i32 [[D]], -1
280; CHECK-NEXT:    ret i1 [[R]]
281;
282  %d = udiv i32 %x, %y
283  call void @use(i32 %d)
284  %r = icmp eq i32 %d, -1
285  ret i1 %r
286}
287
288define i1 @sdiv_eq_smin(i8 %x, i8 %y) {
289; CHECK-LABEL: @sdiv_eq_smin(
290; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i8 [[X:%.*]], -128
291; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i8 [[Y:%.*]], 1
292; CHECK-NEXT:    [[R:%.*]] = and i1 [[TMP1]], [[TMP2]]
293; CHECK-NEXT:    ret i1 [[R]]
294;
295  %d = sdiv i8 %x, %y
296  %r = icmp eq i8 %d, -128
297  ret i1 %r
298}
299
300define <2 x i1> @sdiv_ne_smin(<2 x i5> %x, <2 x i5> %y) {
301; CHECK-LABEL: @sdiv_ne_smin(
302; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne <2 x i5> [[X:%.*]], splat (i5 -16)
303; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne <2 x i5> [[Y:%.*]], splat (i5 1)
304; CHECK-NEXT:    [[R:%.*]] = or <2 x i1> [[TMP1]], [[TMP2]]
305; CHECK-NEXT:    ret <2 x i1> [[R]]
306;
307  %d = sdiv <2 x i5> %x, %y
308  %r = icmp ne <2 x i5> %d, <i5 -16, i5 -16>
309  ret <2 x i1> %r
310}
311
312; negative test - must be SMIN
313
314define i1 @sdiv_eq_small(i8 %x, i8 %y) {
315; CHECK-LABEL: @sdiv_eq_small(
316; CHECK-NEXT:    [[D:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]]
317; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[D]], -127
318; CHECK-NEXT:    ret i1 [[R]]
319;
320  %d = sdiv i8 %x, %y
321  %r = icmp eq i8 %d, -127
322  ret i1 %r
323}
324
325; negative test - must be SMIN
326
327define i1 @sdiv_ne_big(i8 %x, i8 %y) {
328; CHECK-LABEL: @sdiv_ne_big(
329; CHECK-NEXT:    [[D:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]]
330; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[D]], 127
331; CHECK-NEXT:    ret i1 [[R]]
332;
333  %d = sdiv i8 %x, %y
334  %r = icmp ne i8 %d, 127
335  ret i1 %r
336}
337
338; negative test - must be SMIN
339
340define i1 @sdiv_eq_not_big(i8 %x, i8 %y) {
341; CHECK-LABEL: @sdiv_eq_not_big(
342; CHECK-NEXT:    [[D:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]]
343; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[D]], 100
344; CHECK-NEXT:    ret i1 [[R]]
345;
346  %d = sdiv i8 %x, %y
347  %r = icmp eq i8 %d, 100
348  ret i1 %r
349}
350
351; negative test - must be equality predicate
352
353define i1 @sdiv_ult_smin(i8 %x, i8 %y) {
354; CHECK-LABEL: @sdiv_ult_smin(
355; CHECK-NEXT:    [[D:%.*]] = sdiv i8 [[X:%.*]], [[Y:%.*]]
356; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[D]], -1
357; CHECK-NEXT:    ret i1 [[R]]
358;
359  %d = sdiv i8 %x, %y
360  %r = icmp ult i8 %d, 128
361  ret i1 %r
362}
363
364; negative test - extra use
365
366define i1 @sdiv_eq_smin_use(i32 %x, i32 %y) {
367; CHECK-LABEL: @sdiv_eq_smin_use(
368; CHECK-NEXT:    [[D:%.*]] = sdiv i32 [[X:%.*]], [[Y:%.*]]
369; CHECK-NEXT:    call void @use(i32 [[D]])
370; CHECK-NEXT:    [[R:%.*]] = icmp eq i32 [[D]], -2147483648
371; CHECK-NEXT:    ret i1 [[R]]
372;
373  %d = sdiv i32 %x, %y
374  call void @use(i32 %d)
375  %r = icmp eq i32 %d, -2147483648
376  ret i1 %r
377}
378
379; Fold (X / C) cmp X into X ~cmp 0 (~cmp is the inverse predicate of cmp), for some C != 1
380; Alternative form of this fold is when division is replaced with logic right shift
381
382define i1 @sdiv_x_by_const_cmp_x(i32 %x) {
383; CHECK-LABEL: @sdiv_x_by_const_cmp_x(
384; CHECK-NEXT:    [[R:%.*]] = icmp eq i32 [[X:%.*]], 0
385; CHECK-NEXT:    ret i1 [[R]]
386;
387  %v = sdiv i32 %x, 13
388  %r = icmp eq i32 %v, %x
389  ret i1 %r
390}
391
392define i1 @udiv_x_by_const_cmp_x(i32 %x) {
393; CHECK-LABEL: @udiv_x_by_const_cmp_x(
394; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[X:%.*]], 0
395; CHECK-NEXT:    ret i1 [[TMP1]]
396;
397  %1 = udiv i32 %x, 123
398  %2 = icmp slt i32 %1, %x
399  ret i1 %2
400}
401
402define <2 x i1> @udiv_x_by_const_cmp_x_non_splat(<2 x i32> %x) {
403; CHECK-LABEL: @udiv_x_by_const_cmp_x_non_splat(
404; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <2 x i32> [[X:%.*]], zeroinitializer
405; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
406;
407  %1 = udiv <2 x i32> %x, <i32 123, i32 -123>
408  %2 = icmp slt <2 x i32> %1, %x
409  ret <2 x i1> %2
410}
411
412
413define <2 x i1> @sdiv_x_by_const_cmp_x_non_splat(<2 x i32> %x) {
414; CHECK-LABEL: @sdiv_x_by_const_cmp_x_non_splat(
415; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq <2 x i32> [[X:%.*]], zeroinitializer
416; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
417;
418  %1 = sdiv <2 x i32> %x, <i32 2, i32 3>
419  %2 = icmp eq <2 x i32> %1, %x
420  ret <2 x i1> %2
421}
422
423; Same as above but with right shift instead of division (C != 0)
424
425define i1 @lshr_x_by_const_cmp_x(i32 %x) {
426; CHECK-LABEL: @lshr_x_by_const_cmp_x(
427; CHECK-NEXT:    [[R:%.*]] = icmp eq i32 [[X:%.*]], 0
428; CHECK-NEXT:    ret i1 [[R]]
429;
430  %v = lshr i32 %x, 1
431  %r = icmp eq i32 %v, %x
432  ret i1 %r
433}
434
435define <4 x i1> @lshr_by_const_cmp_sle_value(<4 x i32> %x) {
436; CHECK-LABEL: @lshr_by_const_cmp_sle_value(
437; CHECK-NEXT:    [[R:%.*]] = icmp sgt <4 x i32> [[X:%.*]], splat (i32 -1)
438; CHECK-NEXT:    ret <4 x i1> [[R]]
439;
440  %v = lshr <4 x i32> %x, <i32 3, i32 3, i32 3, i32 3>
441  %r = icmp sle <4 x i32> %v, %x
442  ret <4 x i1> %r
443}
444
445define <4 x i1> @lshr_by_const_cmp_sle_value_non_splat(<4 x i32> %x) {
446; CHECK-LABEL: @lshr_by_const_cmp_sle_value_non_splat(
447; CHECK-NEXT:    [[R:%.*]] = icmp sgt <4 x i32> [[X:%.*]], splat (i32 -1)
448; CHECK-NEXT:    ret <4 x i1> [[R]]
449;
450  %v = lshr <4 x i32> %x, <i32 3, i32 3, i32 3, i32 5>
451  %r = icmp sle <4 x i32> %v, %x
452  ret <4 x i1> %r
453}
454
455
456define <4 x i1> @ashr_by_const_cmp_sge_value_non_splat(<4 x i32> %x) {
457; CHECK-LABEL: @ashr_by_const_cmp_sge_value_non_splat(
458; CHECK-NEXT:    [[R:%.*]] = icmp slt <4 x i32> [[X:%.*]], splat (i32 1)
459; CHECK-NEXT:    ret <4 x i1> [[R]]
460;
461  %v = ashr <4 x i32> %x, <i32 1, i32 2, i32 3, i32 4>
462  %r = icmp sge <4 x i32> %v, %x
463  ret <4 x i1> %r
464}
465
466
467define i1 @lshr_by_const_cmp_sge_value(i32 %x) {
468; CHECK-LABEL: @lshr_by_const_cmp_sge_value(
469; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[X:%.*]], 1
470; CHECK-NEXT:    ret i1 [[R]]
471;
472  %v = lshr i32 %x, 3
473  %r = icmp sge i32 %v, %x
474  ret i1 %r
475}
476
477define i1 @ashr_x_by_const_cmp_sge_x(i32 %x) {
478; CHECK-LABEL: @ashr_x_by_const_cmp_sge_x(
479; CHECK-NEXT:    [[R:%.*]] = icmp slt i32 [[X:%.*]], 1
480; CHECK-NEXT:    ret i1 [[R]]
481;
482  %v = ashr i32 %x, 5
483  %r = icmp sge i32 %v, %x
484  ret i1 %r
485}
486
487; Negative test - constant is 1
488
489define <2 x i1> @udiv_x_by_const_cmp_eq_value_neg(<2 x i32> %x) {
490; CHECK-LABEL: @udiv_x_by_const_cmp_eq_value_neg(
491; CHECK-NEXT:    [[V:%.*]] = udiv <2 x i32> [[X:%.*]], <i32 1, i32 3>
492; CHECK-NEXT:    [[R:%.*]] = icmp eq <2 x i32> [[V]], [[X]]
493; CHECK-NEXT:    ret <2 x i1> [[R]]
494;
495  %v = udiv <2 x i32> %x, <i32 1, i32 3>
496  %r = icmp eq <2 x i32> %v, %x
497  ret <2 x i1> %r
498}
499
500define <2 x i1> @sdiv_x_by_const_cmp_eq_value_neg(<2 x i32> %x) {
501; CHECK-LABEL: @sdiv_x_by_const_cmp_eq_value_neg(
502; CHECK-NEXT:    [[V:%.*]] = sdiv <2 x i32> [[X:%.*]], <i32 1, i32 3>
503; CHECK-NEXT:    [[R:%.*]] = icmp eq <2 x i32> [[V]], [[X]]
504; CHECK-NEXT:    ret <2 x i1> [[R]]
505;
506  %v = sdiv <2 x i32> %x, <i32 1, i32 3>
507  %r = icmp eq <2 x i32> %v, %x
508  ret <2 x i1> %r
509}
510
511; Negative test - constant is 0
512
513define <2 x i1> @lshr_x_by_const_cmp_slt_value_neg(<2 x i32> %x) {
514; CHECK-LABEL: @lshr_x_by_const_cmp_slt_value_neg(
515; CHECK-NEXT:    [[V:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 0, i32 2>
516; CHECK-NEXT:    [[R:%.*]] = icmp slt <2 x i32> [[V]], [[X]]
517; CHECK-NEXT:    ret <2 x i1> [[R]]
518;
519  %v = lshr <2 x i32> %x, <i32 0, i32 2>
520  %r = icmp slt <2 x i32> %v, %x
521  ret <2 x i1> %r
522}
523
524; Negative test - unsigned predicate with sdiv
525
526define i1 @sdiv_x_by_const_cmp_ult_value_neg(i32 %x) {
527; CHECK-LABEL: @sdiv_x_by_const_cmp_ult_value_neg(
528; CHECK-NEXT:    [[V:%.*]] = sdiv i32 [[X:%.*]], 3
529; CHECK-NEXT:    [[R:%.*]] = icmp ult i32 [[V]], [[X]]
530; CHECK-NEXT:    ret i1 [[R]]
531;
532  %v = sdiv i32 %x, 3
533  %r = icmp ult i32 %v, %x
534  ret i1 %r
535}
536
537; Negative case - one of the components of a vector is 1
538
539define <4 x i1> @sdiv_x_by_const_cmp_sgt_value_neg(<4 x i32> %x) {
540; CHECK-LABEL: @sdiv_x_by_const_cmp_sgt_value_neg(
541; CHECK-NEXT:    [[V:%.*]] = sdiv <4 x i32> [[X:%.*]], <i32 1, i32 2, i32 3, i32 4>
542; CHECK-NEXT:    [[R:%.*]] = icmp sgt <4 x i32> [[V]], [[X]]
543; CHECK-NEXT:    ret <4 x i1> [[R]]
544;
545  %v = sdiv <4 x i32> %x, <i32 1, i32 2, i32 3, i32 4>
546  %r = icmp sgt <4 x i32> %v, %x
547  ret <4 x i1> %r
548}
549
550; Negative case - ashr only allows sge/slt predicates
551
552define i1 @ashr_x_by_const_cmp_sle_value_neg(i32 %x) {
553; CHECK-LABEL: @ashr_x_by_const_cmp_sle_value_neg(
554; CHECK-NEXT:    [[V:%.*]] = ashr i32 [[X:%.*]], 3
555; CHECK-NEXT:    [[R:%.*]] = icmp sle i32 [[V]], [[X]]
556; CHECK-NEXT:    ret i1 [[R]]
557;
558  %v = ashr i32 %x, 3
559  %r = icmp sle i32 %v, %x
560  ret i1 %r
561}
562