From: Noah Goldstein Date: Mon, 6 Feb 2023 18:06:11 +0000 (-0600) Subject: Add transform for `(mul X, OddC) eq/ne N * C` --> `X eq/ne N` X-Git-Tag: upstream/17.0.6~18431 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2a3732f934b1ef46fc8f0fdae77836c6604533cb;p=platform%2Fupstream%2Fllvm.git Add transform for `(mul X, OddC) eq/ne N * C` --> `X eq/ne N` We previously only did this if the `mul` was `nuw`, but it works for any odd value. Alive2 Links: EQ: https://alive2.llvm.org/ce/z/6_HPZ5 NE: https://alive2.llvm.org/ce/z/c34qSU Reviewed By: spatel Differential Revision: https://reviews.llvm.org/D143026 --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 1c7344b..bfe586c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2035,24 +2035,35 @@ Instruction *InstCombinerImpl::foldICmpMulConstant(ICmpInst &Cmp, return new ICmpInst(Pred, X, ConstantInt::getNullValue(MulTy)); } - if (MulC->isZero() || (!Mul->hasNoSignedWrap() && !Mul->hasNoUnsignedWrap())) + if (MulC->isZero()) return nullptr; - // If the multiply does not wrap, try to divide the compare constant by the - // multiplication factor. + // If the multiply does not wrap or the constant is odd, try to divide the + // compare constant by the multiplication factor. if (Cmp.isEquality()) { - // (mul nsw X, MulC) == C --> X == C /s MulC + // (mul nsw X, MulC) eq/ne C --> X eq/ne C /s MulC if (Mul->hasNoSignedWrap() && C.srem(*MulC).isZero()) { Constant *NewC = ConstantInt::get(MulTy, C.sdiv(*MulC)); return new ICmpInst(Pred, X, NewC); } - // (mul nuw X, MulC) == C --> X == C /u MulC - if (Mul->hasNoUnsignedWrap() && C.urem(*MulC).isZero()) { - Constant *NewC = ConstantInt::get(MulTy, C.udiv(*MulC)); - return new ICmpInst(Pred, X, NewC); + + // C % MulC == 0 is weaker than we could use if MulC is odd because it + // correct to transform if MulC * N == C including overflow. I.e with i8 + // (icmp eq (mul X, 5), 101) -> (icmp eq X, 225) but since 101 % 5 != 0, we + // miss that case. + if (C.urem(*MulC).isZero()) { + // (mul nuw X, MulC) eq/ne C --> X eq/ne C /u MulC + // (mul X, OddC) eq/ne N * C --> X eq/ne N + if ((*MulC & 1).isOne() || Mul->hasNoUnsignedWrap()) { + Constant *NewC = ConstantInt::get(MulTy, C.udiv(*MulC)); + return new ICmpInst(Pred, X, NewC); + } } } + if (!Mul->hasNoSignedWrap() && !Mul->hasNoUnsignedWrap()) + return nullptr; + // With a matching no-overflow guarantee, fold the constants: // (X * MulC) < C --> X < (C / MulC) // (X * MulC) > C --> X > (C / MulC) diff --git a/llvm/test/Transforms/InstCombine/icmp-mul.ll b/llvm/test/Transforms/InstCombine/icmp-mul.ll index 04f08f43b..e26ea68 100644 --- a/llvm/test/Transforms/InstCombine/icmp-mul.ll +++ b/llvm/test/Transforms/InstCombine/icmp-mul.ll @@ -424,8 +424,7 @@ define i1 @sgt_mulzero(i8 %x) { define i1 @eq_rem_zero_nonuw(i8 %x) { ; CHECK-LABEL: @eq_rem_zero_nonuw( -; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], 5 -; CHECK-NEXT: [[B:%.*]] = icmp eq i8 [[A]], 20 +; CHECK-NEXT: [[B:%.*]] = icmp eq i8 [[X:%.*]], 4 ; CHECK-NEXT: ret i1 [[B]] ; %a = mul i8 %x, 5 @@ -435,8 +434,7 @@ define i1 @eq_rem_zero_nonuw(i8 %x) { define i1 @ne_rem_zero_nonuw(i8 %x) { ; CHECK-LABEL: @ne_rem_zero_nonuw( -; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], 5 -; CHECK-NEXT: [[B:%.*]] = icmp ne i8 [[A]], 30 +; CHECK-NEXT: [[B:%.*]] = icmp ne i8 [[X:%.*]], 6 ; CHECK-NEXT: ret i1 [[B]] ; %a = mul i8 %x, 5 @@ -995,8 +993,7 @@ define i1 @mul_evenC_ne(i8 %v) { define <2 x i1> @mul_oddC_ne_vec(<2 x i8> %v) { ; CHECK-LABEL: @mul_oddC_ne_vec( -; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i8> [[V:%.*]], -; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[MUL]], +; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[V:%.*]], ; CHECK-NEXT: ret <2 x i1> [[CMP]] ; %mul = mul <2 x i8> %v,