From c6a0f7ecd4c6f80d28a83904d4dd9968fbbcfe45 Mon Sep 17 00:00:00 2001 From: Rose Date: Wed, 17 Jul 2024 14:47:11 -0400 Subject: [PATCH] [InstCombine] Fold mul (lshr exact (X, N)), 2^N + 1 -> add (X , lshr exact (X, N)) Alive2 Proofs: https://alive2.llvm.org/ce/z/aJnxyp https://alive2.llvm.org/ce/z/dyeGEv --- .../InstCombine/InstCombineMulDivRem.cpp | 31 +++++++++++++++++ llvm/test/Transforms/InstCombine/ashr-lshr.ll | 34 +++++++++++-------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index f4f3644acfe5ea0..5fb8097471a398a 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -261,6 +261,37 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) { } } + // mul (shr exact X, N), (2^N + 1) -> add (X, shr exact (X, N)) + { + Value *NewOp; + const APInt *ShiftC; + const APInt *MulAP; + if (match(&I, m_Mul(m_Exact(m_Shr(m_Value(NewOp), m_APInt(ShiftC))), + m_APInt(MulAP)))) { + if (BitWidth > 2 && (*MulAP - 1).isPowerOf2() && + *ShiftC == MulAP->logBase2()) { + Value *BinOp = Op0; + BinaryOperator *OpBO = cast(Op0); + if (!isGuaranteedNotToBeUndef(NewOp, &AC, &I, &DT)) + NewOp = Builder.CreateFreeze(NewOp, NewOp->getName() + ".fr"); + + // mul (ashr nuw exact X, N) -> add (X, lshr nuw exact (X, N)) + if (HasNUW && OpBO->getOpcode() == Instruction::AShr && + OpBO->hasOneUse()) + BinOp = Builder.CreateLShr(NewOp, ConstantInt::get(Ty, *ShiftC), "", + /*isExact=*/true); + + auto *NewAdd = BinaryOperator::CreateAdd(NewOp, BinOp); + if (HasNSW && (HasNUW || OpBO->getOpcode() == Instruction::LShr || + ShiftC->getZExtValue() < BitWidth - 1)) + NewAdd->setHasNoSignedWrap(true); + + NewAdd->setHasNoUnsignedWrap(HasNUW); + return NewAdd; + } + } + } + if (Op0->hasOneUse() && match(Op1, m_NegatedPower2())) { // Interpret X * (-1<