Skip to content

Commit 2d19adb

Browse files
committed
[InstCombine] Add test cases for folds (X / C) cmp X and (X >> C) cmp X
1 parent e77378c commit 2d19adb

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed

llvm/test/Transforms/InstCombine/icmp-div-constant.ll

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,3 +375,150 @@ define i1 @sdiv_eq_smin_use(i32 %x, i32 %y) {
375375
%r = icmp eq i32 %d, -2147483648
376376
ret i1 %r
377377
}
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+
382+
define i1 @sdiv_x_by_const_cmp_x(i32 %x) {
383+
; CHECK-LABEL: @sdiv_x_by_const_cmp_x(
384+
; CHECK-NEXT: [[V:%.*]] = sdiv i32 [[X:%.*]], 13
385+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[V]], [[X]]
386+
; CHECK-NEXT: ret i1 [[TMP1]]
387+
;
388+
%v = sdiv i32 %x, 13
389+
%r = icmp eq i32 %v, %x
390+
ret i1 %r
391+
}
392+
393+
define i1 @udiv_x_by_const_cmp_x(i32 %x) {
394+
; CHECK-LABEL: @udiv_x_by_const_cmp_x(
395+
; CHECK-NEXT: [[TMP2:%.*]] = udiv i32 [[X:%.*]], 123
396+
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[TMP2]], [[X]]
397+
; CHECK-NEXT: ret i1 [[TMP1]]
398+
;
399+
%1 = udiv i32 %x, 123
400+
%2 = icmp slt i32 %1, %x
401+
ret i1 %2
402+
}
403+
404+
; Same as above but with right shift instead of division (C != 0)
405+
406+
define i1 @lshr_x_by_const_cmp_x(i32 %x) {
407+
; CHECK-LABEL: @lshr_x_by_const_cmp_x(
408+
; CHECK-NEXT: [[V:%.*]] = lshr i32 [[X:%.*]], 1
409+
; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[V]], [[X]]
410+
; CHECK-NEXT: ret i1 [[TMP1]]
411+
;
412+
%v = lshr i32 %x, 1
413+
%r = icmp eq i32 %v, %x
414+
ret i1 %r
415+
}
416+
417+
define <4 x i1> @lshr_by_const_cmp_sle_value(<4 x i32> %x) {
418+
; CHECK-LABEL: @lshr_by_const_cmp_sle_value(
419+
; CHECK-NEXT: [[V:%.*]] = lshr <4 x i32> [[X:%.*]], <i32 3, i32 3, i32 3, i32 3>
420+
; CHECK-NEXT: [[R:%.*]] = icmp sle <4 x i32> [[V]], [[X]]
421+
; CHECK-NEXT: ret <4 x i1> [[R]]
422+
;
423+
%v = lshr <4 x i32> %x, <i32 3, i32 3, i32 3, i32 3>
424+
%r = icmp sle <4 x i32> %v, %x
425+
ret <4 x i1> %r
426+
}
427+
428+
define i1 @lshr_by_const_cmp_uge_value(i32 %x) {
429+
; CHECK-LABEL: @lshr_by_const_cmp_uge_value(
430+
; CHECK-NEXT: [[V:%.*]] = lshr i32 [[X:%.*]], 3
431+
; CHECK-NEXT: [[R:%.*]] = icmp sle i32 [[V]], [[X]]
432+
; CHECK-NEXT: ret i1 [[R]]
433+
;
434+
%v = lshr i32 %x, 3
435+
%r = icmp sle i32 %v, %x
436+
ret i1 %r
437+
}
438+
439+
define i1 @ashr_x_by_const_cmp_sge_x(i32 %x) {
440+
; CHECK-LABEL: @ashr_x_by_const_cmp_sge_x(
441+
; CHECK-NEXT: [[V:%.*]] = ashr i32 [[X:%.*]], 5
442+
; CHECK-NEXT: [[R:%.*]] = icmp sge i32 [[V]], [[X]]
443+
; CHECK-NEXT: ret i1 [[R]]
444+
;
445+
%v = ashr i32 %x, 5
446+
%r = icmp sge i32 %v, %x
447+
ret i1 %r
448+
}
449+
450+
; Negative test - constant is 1
451+
452+
define <2 x i1> @udiv_x_by_const_cmp_eq_value_neg(<2 x i32> %x) {
453+
; CHECK-LABEL: @udiv_x_by_const_cmp_eq_value_neg(
454+
; CHECK-NEXT: [[V:%.*]] = udiv <2 x i32> [[X:%.*]], <i32 1, i32 3>
455+
; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i32> [[V]], [[X]]
456+
; CHECK-NEXT: ret <2 x i1> [[R]]
457+
;
458+
%v = udiv <2 x i32> %x, <i32 1, i32 3>
459+
%r = icmp eq <2 x i32> %v, %x
460+
ret <2 x i1> %r
461+
}
462+
463+
define <2 x i1> @sdiv_x_by_const_cmp_eq_value_neg(<2 x i32> %x) {
464+
; CHECK-LABEL: @sdiv_x_by_const_cmp_eq_value_neg(
465+
; CHECK-NEXT: [[V:%.*]] = sdiv <2 x i32> [[X:%.*]], <i32 1, i32 3>
466+
; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i32> [[V]], [[X]]
467+
; CHECK-NEXT: ret <2 x i1> [[R]]
468+
;
469+
%v = sdiv <2 x i32> %x, <i32 1, i32 3>
470+
%r = icmp eq <2 x i32> %v, %x
471+
ret <2 x i1> %r
472+
}
473+
474+
; Negative test - constant is 0
475+
476+
define <2 x i1> @lshr_x_by_const_cmp_slt_value_neg(<2 x i32> %x) {
477+
; CHECK-LABEL: @lshr_x_by_const_cmp_slt_value_neg(
478+
; CHECK-NEXT: [[V:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 0, i32 2>
479+
; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i32> [[V]], [[X]]
480+
; CHECK-NEXT: ret <2 x i1> [[R]]
481+
;
482+
%v = lshr <2 x i32> %x, <i32 0, i32 2>
483+
%r = icmp slt <2 x i32> %v, %x
484+
ret <2 x i1> %r
485+
}
486+
487+
; Negative test - unsigned predicate with sdiv
488+
489+
define i1 @sdiv_x_by_const_cmp_ult_value_neg(i32 %x) {
490+
; CHECK-LABEL: @sdiv_x_by_const_cmp_ult_value_neg(
491+
; CHECK-NEXT: [[V:%.*]] = sdiv i32 [[X:%.*]], 3
492+
; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[V]], [[X]]
493+
; CHECK-NEXT: ret i1 [[R]]
494+
;
495+
%v = sdiv i32 %x, 3
496+
%r = icmp ult i32 %v, %x
497+
ret i1 %r
498+
}
499+
500+
; Negative case - one of the components of a vector is 1
501+
502+
define <4 x i1> @sdiv_x_by_const_cmp_sgt_value_neg(<4 x i32> %x) {
503+
; CHECK-LABEL: @sdiv_x_by_const_cmp_sgt_value_neg(
504+
; CHECK-NEXT: [[V:%.*]] = sdiv <4 x i32> [[X:%.*]], <i32 1, i32 2, i32 3, i32 4>
505+
; CHECK-NEXT: [[R:%.*]] = icmp sgt <4 x i32> [[V]], [[X]]
506+
; CHECK-NEXT: ret <4 x i1> [[R]]
507+
;
508+
%v = sdiv <4 x i32> %x, <i32 1, i32 2, i32 3, i32 4>
509+
%r = icmp sgt <4 x i32> %v, %x
510+
ret <4 x i1> %r
511+
}
512+
513+
; Negative case - ashr only allows sge/slt predicates
514+
515+
define i1 @ashr_x_by_const_cmp_sle_value_neg(i32 %x) {
516+
; CHECK-LABEL: @ashr_x_by_const_cmp_sle_value_neg(
517+
; CHECK-NEXT: [[V:%.*]] = ashr i32 [[X:%.*]], 3
518+
; CHECK-NEXT: [[R:%.*]] = icmp sle i32 [[V]], [[X]]
519+
; CHECK-NEXT: ret i1 [[R]]
520+
;
521+
%v = ashr i32 %x, 3
522+
%r = icmp sle i32 %v, %x
523+
ret i1 %r
524+
}

0 commit comments

Comments
 (0)