The existing logic in foldICmpMulConstant can only optimize the
constant if we have (X * Y) * C. However, reassociate pass currently
produces this form with the constant on the inner multiply, so let's
reassociate it in foldICmpMulConstant to enable further optimizations.
Related issue: https://github.com/llvm/llvm-project/issues/61538
Signed-off-by: Jun Zhang <jun@junz.org>
I'm not sure what are you going to do now. If you just want to reassociate C to outer mul, there is no extra condition. https://alive2.llvm.org/ce/z/v-f92Q
The code should be simple:
BinaryOperator *InnerMul; Value *Y; Constant *InnerC; if (match(Mul, m_OneUse(m_c_Mul(m_BinOp(InnerMul), m_Value(Y)))) && match(InnerMul, m_Mul(m_Value(X), m_Constant(InnerC)))) { Value *NewInner = Builder.CreateMul(X, Y); Value *NewMul = Builder.CreateMul(NewInner, InnerC); return new ICmpInst(Pred, NewMul, Mul->getOperand(1)); }If you want to keep nsw/nuw flags, you can set the flag after create NewMul like:
if (!InnerC->isZeroValue() && Mul->hasNoUnsignedWrap() && InnerMul->hasNoUnsignedWrap()) { cast<BinaryOperator>(NewInner)->setHasNoUnsignedWrap(); cast<BinaryOperator>(NewMul)->setHasNoUnsignedWrap(); } else { Constant *Zero = Constant::getNullValue(InnerC->getType()); Constant *InnerCSleZero = ConstantExpr::getCompare(ICmpInst::ICMP_SLE, InnerC, Zero); if (InnerCSleZero->isZeroValue() && Mul->hasNoSignedWrap() && InnerMul->hasNoSignedWrap()) { cast<BinaryOperator>(NewInner)->setHasNoSignedWrap(); cast<BinaryOperator>(NewMul)->setHasNoSignedWrap(); } }