[llvm] [InstCombine] Reduce multiplicands of even numbers when a shift is involved (PR #92475)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 9 15:39:14 PDT 2024
================
@@ -1712,6 +1727,36 @@ Instruction *InstCombinerImpl::visitAShr(BinaryOperator &I) {
return BinaryOperator::CreateAShr(X, ConstantInt::get(Ty, AmtSum));
}
+ if (match(Op0, m_OneUse(m_NSWMul(m_Value(X), m_APInt(ShOp1))))) {
+ unsigned CommonZeros = std::min(ShOp1->countr_zero(), ShAmt);
+ if (CommonZeros != 0) {
+ APInt NewMulC = ShOp1->ashr(CommonZeros);
+ unsigned NewShAmtC = ShAmt - CommonZeros;
+ // if c is divisible by (1 << ShAmtC):
+ // ashr (mul nsw x, MulC), ShAmtC -> mul nsw x, (MulC >> ShAmtC)
+ if (NewShAmtC == 0) {
+ auto *NewMul =
+ BinaryOperator::CreateNSWMul(X, ConstantInt::get(Ty, NewMulC));
+ NewMul->setHasNoUnsignedWrap(
+ cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap());
+ return NewMul;
+ }
+
+ // We can reduce expressions such as ashr (mul nsw x, 6), 2 -> ashr (mul
+ // nsw x, 3), 1
+ // TODO: What about if ALL uses can be simplified in this way? Is that
+ // likely enough to happen to justify even caring?
+ auto *NewMul = Builder.CreateMul(
+ X, ConstantInt::get(Ty, NewMulC), "",
+ /*NUW*/ cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap(),
+ /*NSW*/ true);
+ auto *NewAshr =
+ BinaryOperator::CreateAShr(NewMul, ConstantInt::get(Ty, NewShAmtC));
+ NewAshr->copyIRFlags(&I); // We can preserve 'exact'-ness.
+ return NewAshr;
+ }
+ }
+
----------------
goldsteinn wrote:
For my money, this should all be in a lambda. AFAICT the only difference between is whether you create `lshr`/`ashr` and `APInt NewMulC = ShOp1->ashr(CommonZeros);` The rest can use this exact same code.
https://github.com/llvm/llvm-project/pull/92475
More information about the llvm-commits
mailing list