diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3323,7 +3323,29 @@ break; } case Instruction::UDiv: - if (C.isZero()) { + case Instruction::SDiv: + if (BO->isExact()) { + // div exact X, Y eq/ne 0 -> X eq/ne 0 + // div exact X, Y eq/ne 1 -> X eq/ne Y + // div exact X, Y eq/ne C -> + // if Y * C never-overflow && OneUse: + // -> Y * C eq/ne X + if (C.isZero()) + return new ICmpInst(Pred, BOp0, Constant::getNullValue(BO->getType())); + else if (C.isOne()) + return new ICmpInst(Pred, BOp0, BOp1); + else if (BO->hasOneUse()) { + OverflowResult OR = computeOverflow( + Instruction::Mul, BO->getOpcode() == Instruction::SDiv, BOp1, + Cmp.getOperand(1), BO); + if (OR == OverflowResult::NeverOverflows) { + Value *YC = + Builder.CreateMul(BOp1, ConstantInt::get(BO->getType(), C)); + return new ICmpInst(Pred, YC, BOp0); + } + } + } + if (BO->getOpcode() == Instruction::UDiv && C.isZero()) { // (icmp eq/ne (udiv A, B), 0) -> (icmp ugt/ule i32 B, A) auto NewPred = isICMP_NE ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_UGT; return new ICmpInst(NewPred, BOp1, BOp0); diff --git a/llvm/test/Transforms/InstCombine/sdiv-icmp.ll b/llvm/test/Transforms/InstCombine/sdiv-icmp.ll --- a/llvm/test/Transforms/InstCombine/sdiv-icmp.ll +++ b/llvm/test/Transforms/InstCombine/sdiv-icmp.ll @@ -4,8 +4,7 @@ declare void @use.i8(i8) define i1 @sdiv_exact_eq_0(i8 %x, i8 %y) { ; CHECK-LABEL: @sdiv_exact_eq_0( -; CHECK-NEXT: [[D:%.*]] = sdiv exact i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[D]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %d = sdiv exact i8 %x, %y @@ -15,7 +14,7 @@ define i1 @udiv_exact_ne_0(i8 %x, i8 %y) { ; CHECK-LABEL: @udiv_exact_ne_0( -; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %d = udiv exact i8 %x, %y @@ -25,8 +24,7 @@ define i1 @sdiv_exact_ne_1(i8 %x, i8 %y) { ; CHECK-LABEL: @sdiv_exact_ne_1( -; CHECK-NEXT: [[D:%.*]] = sdiv exact i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[D]], 0 +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %d = sdiv exact i8 %x, %y @@ -36,8 +34,7 @@ define i1 @udiv_exact_eq_1(i8 %x, i8 %y) { ; CHECK-LABEL: @udiv_exact_eq_1( -; CHECK-NEXT: [[D:%.*]] = udiv exact i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[D]], 1 +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %d = udiv exact i8 %x, %y @@ -48,8 +45,8 @@ define i1 @sdiv_exact_eq_9_no_of(i8 %x, i8 %y) { ; CHECK-LABEL: @sdiv_exact_eq_9_no_of( ; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y:%.*]], 7 -; CHECK-NEXT: [[D:%.*]] = sdiv exact i8 [[X:%.*]], [[YY]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[D]], 9 +; CHECK-NEXT: [[TMP1:%.*]] = mul nuw nsw i8 [[YY]], 9 +; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %yy = and i8 %y, 7 @@ -100,8 +97,8 @@ define i1 @udiv_exact_ne_30_no_of(i8 %x, i8 %y) { ; CHECK-LABEL: @udiv_exact_ne_30_no_of( ; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y:%.*]], 7 -; CHECK-NEXT: [[D:%.*]] = udiv exact i8 [[X:%.*]], [[YY]] -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[D]], 30 +; CHECK-NEXT: [[TMP1:%.*]] = mul nuw i8 [[YY]], 30 +; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP1]], [[X:%.*]] ; CHECK-NEXT: ret i1 [[R]] ; %yy = and i8 %y, 7