Skip to content

Commit ddd18d0

Browse files
committed
[InstCombine] Transform icmp eq/ne ({su}div exact X,Y),C -> icmp eq/ne X, Y*C
We can do this if `Y*C` doesn't overflow. This is trivial if `C` is 0/1. Otherwise we actually generate a `mul` instruction iff the `div` has one use. Alive2 Links: udiv: https://alive2.llvm.org/ce/z/GWPW67 sdiv: https://alive2.llvm.org/ce/z/bUoX9h Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D150091
1 parent fd691fc commit ddd18d0

File tree

2 files changed

+31
-12
lines changed

2 files changed

+31
-12
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3323,7 +3323,29 @@ Instruction *InstCombinerImpl::foldICmpBinOpEqualityWithConstant(
33233323
break;
33243324
}
33253325
case Instruction::UDiv:
3326-
if (C.isZero()) {
3326+
case Instruction::SDiv:
3327+
if (BO->isExact()) {
3328+
// div exact X, Y eq/ne 0 -> X eq/ne 0
3329+
// div exact X, Y eq/ne 1 -> X eq/ne Y
3330+
// div exact X, Y eq/ne C ->
3331+
// if Y * C never-overflow && OneUse:
3332+
// -> Y * C eq/ne X
3333+
if (C.isZero())
3334+
return new ICmpInst(Pred, BOp0, Constant::getNullValue(BO->getType()));
3335+
else if (C.isOne())
3336+
return new ICmpInst(Pred, BOp0, BOp1);
3337+
else if (BO->hasOneUse()) {
3338+
OverflowResult OR = computeOverflow(
3339+
Instruction::Mul, BO->getOpcode() == Instruction::SDiv, BOp1,
3340+
Cmp.getOperand(1), BO);
3341+
if (OR == OverflowResult::NeverOverflows) {
3342+
Value *YC =
3343+
Builder.CreateMul(BOp1, ConstantInt::get(BO->getType(), C));
3344+
return new ICmpInst(Pred, YC, BOp0);
3345+
}
3346+
}
3347+
}
3348+
if (BO->getOpcode() == Instruction::UDiv && C.isZero()) {
33273349
// (icmp eq/ne (udiv A, B), 0) -> (icmp ugt/ule i32 B, A)
33283350
auto NewPred = isICMP_NE ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_UGT;
33293351
return new ICmpInst(NewPred, BOp1, BOp0);

llvm/test/Transforms/InstCombine/sdiv-icmp.ll

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
declare void @use.i8(i8)
55
define i1 @sdiv_exact_eq_0(i8 %x, i8 %y) {
66
; CHECK-LABEL: @sdiv_exact_eq_0(
7-
; CHECK-NEXT: [[D:%.*]] = sdiv exact i8 [[X:%.*]], [[Y:%.*]]
8-
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[D]], 0
7+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], 0
98
; CHECK-NEXT: ret i1 [[R]]
109
;
1110
%d = sdiv exact i8 %x, %y
@@ -15,7 +14,7 @@ define i1 @sdiv_exact_eq_0(i8 %x, i8 %y) {
1514

1615
define i1 @udiv_exact_ne_0(i8 %x, i8 %y) {
1716
; CHECK-LABEL: @udiv_exact_ne_0(
18-
; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[Y:%.*]], [[X:%.*]]
17+
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], 0
1918
; CHECK-NEXT: ret i1 [[R]]
2019
;
2120
%d = udiv exact i8 %x, %y
@@ -25,8 +24,7 @@ define i1 @udiv_exact_ne_0(i8 %x, i8 %y) {
2524

2625
define i1 @sdiv_exact_ne_1(i8 %x, i8 %y) {
2726
; CHECK-LABEL: @sdiv_exact_ne_1(
28-
; CHECK-NEXT: [[D:%.*]] = sdiv exact i8 [[X:%.*]], [[Y:%.*]]
29-
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[D]], 0
27+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], 0
3028
; CHECK-NEXT: ret i1 [[R]]
3129
;
3230
%d = sdiv exact i8 %x, %y
@@ -36,8 +34,7 @@ define i1 @sdiv_exact_ne_1(i8 %x, i8 %y) {
3634

3735
define i1 @udiv_exact_eq_1(i8 %x, i8 %y) {
3836
; CHECK-LABEL: @udiv_exact_eq_1(
39-
; CHECK-NEXT: [[D:%.*]] = udiv exact i8 [[X:%.*]], [[Y:%.*]]
40-
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[D]], 1
37+
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], [[Y:%.*]]
4138
; CHECK-NEXT: ret i1 [[R]]
4239
;
4340
%d = udiv exact i8 %x, %y
@@ -48,8 +45,8 @@ define i1 @udiv_exact_eq_1(i8 %x, i8 %y) {
4845
define i1 @sdiv_exact_eq_9_no_of(i8 %x, i8 %y) {
4946
; CHECK-LABEL: @sdiv_exact_eq_9_no_of(
5047
; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y:%.*]], 7
51-
; CHECK-NEXT: [[D:%.*]] = sdiv exact i8 [[X:%.*]], [[YY]]
52-
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[D]], 9
48+
; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i8 [[YY]], 9
49+
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP1]], [[X:%.*]]
5350
; CHECK-NEXT: ret i1 [[R]]
5451
;
5552
%yy = and i8 %y, 7
@@ -100,8 +97,8 @@ define i1 @sdiv_exact_eq_9_must_of_todo_is_false(i8 %x, i8 %y) {
10097
define i1 @udiv_exact_ne_30_no_of(i8 %x, i8 %y) {
10198
; CHECK-LABEL: @udiv_exact_ne_30_no_of(
10299
; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y:%.*]], 7
103-
; CHECK-NEXT: [[D:%.*]] = udiv exact i8 [[X:%.*]], [[YY]]
104-
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[D]], 30
100+
; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i8 [[YY]], 30
101+
; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP1]], [[X:%.*]]
105102
; CHECK-NEXT: ret i1 [[R]]
106103
;
107104
%yy = and i8 %y, 7

0 commit comments

Comments
 (0)