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 @@ -5231,6 +5231,21 @@ return new ICmpInst(Pred, OtherVal, Constant::getNullValue(A->getType())); } + // ((A / -B) == (A / B)) -> ((A / B) == 0) + // if known A != INT_MIN or B != INT_MIN + // ToDo: Add case where B is constant and Op1 uses -B + { + if (match(Op0, m_OneUse(m_SDiv(m_Value(A), m_OneUse(m_Neg(m_Value(B)))))) && + match(Op1, m_SDiv(m_Specific(A), m_Specific(B)))) { + // Check if A is known to be != INT_MIN + if (!computeKnownBits(A, 0, &I).getSignedMinValue().isMinSignedValue()) + return new ICmpInst(Pred, Op1, Constant::getNullValue(A->getType())); + // Check if B is known to be != INT_MIN + if (!computeKnownBits(B, 0, &I).getSignedMinValue().isMinSignedValue()) + return new ICmpInst(Pred, Op1, Constant::getNullValue(A->getType())); + } + } + // (X&Z) == (Y&Z) -> (X^Y) & Z == 0 if (match(Op0, m_OneUse(m_And(m_Value(A), m_Value(B)))) && match(Op1, m_OneUse(m_And(m_Value(C), m_Value(D))))) { diff --git a/llvm/test/Transforms/InstCombine/icmp-sdiv-sdiv.ll b/llvm/test/Transforms/InstCombine/icmp-sdiv-sdiv.ll --- a/llvm/test/Transforms/InstCombine/icmp-sdiv-sdiv.ll +++ b/llvm/test/Transforms/InstCombine/icmp-sdiv-sdiv.ll @@ -9,10 +9,8 @@ ; CHECK-LABEL: @icmp_sdiv_sdiv_normal_i8( ; CHECK-NEXT: [[PRECOND:%.*]] = icmp eq i8 [[C:%.*]], 12 ; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]]) -; CHECK-NEXT: [[NEGC:%.*]] = sub nsw i8 0, [[C]] -; CHECK-NEXT: [[D1:%.*]] = sdiv i8 [[X:%.*]], [[NEGC]] -; CHECK-NEXT: [[D2:%.*]] = sdiv i8 [[X]], [[C]] -; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[D1]], [[D2]] +; CHECK-NEXT: [[D2:%.*]] = sdiv i8 [[X:%.*]], [[C]] +; CHECK-NEXT: [[C:%.*]] = icmp eq i8 [[D2]], 0 ; CHECK-NEXT: ret i1 [[C]] ; %precond = icmp eq i8 %C, 12 @@ -28,10 +26,8 @@ ; CHECK-LABEL: @icmp_sdiv_sdiv_normal_i64( ; CHECK-NEXT: [[PRECOND:%.*]] = icmp eq i64 [[C:%.*]], -9223372036854775807 ; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]]) -; CHECK-NEXT: [[NEGC:%.*]] = sub nsw i64 0, [[C]] -; CHECK-NEXT: [[D1:%.*]] = sdiv i64 [[X:%.*]], [[NEGC]] -; CHECK-NEXT: [[D2:%.*]] = sdiv i64 [[X]], [[C]] -; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[D1]], [[D2]] +; CHECK-NEXT: [[D2:%.*]] = sdiv i64 [[X:%.*]], [[C]] +; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[D2]], 0 ; CHECK-NEXT: ret i1 [[C]] ; %precond = icmp eq i64 %C, -9223372036854775807 ; off by one @@ -47,10 +43,8 @@ ; CHECK-LABEL: @icmp_sdiv_sdiv_normal_ne( ; CHECK-NEXT: [[PRECOND:%.*]] = icmp eq i6 [[C:%.*]], 4 ; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]]) -; CHECK-NEXT: [[NEGC:%.*]] = sub nsw i6 0, [[C]] -; CHECK-NEXT: [[D1:%.*]] = sdiv i6 [[X:%.*]], [[NEGC]] -; CHECK-NEXT: [[D2:%.*]] = sdiv i6 [[X]], [[C]] -; CHECK-NEXT: [[C:%.*]] = icmp ne i6 [[D1]], [[D2]] +; CHECK-NEXT: [[D2:%.*]] = sdiv i6 [[X:%.*]], [[C]] +; CHECK-NEXT: [[C:%.*]] = icmp ne i6 [[D2]], 0 ; CHECK-NEXT: ret i1 [[C]] ; %precond = icmp eq i6 %C, 4