[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 23 20:32:58 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:

Helper function then?

https://github.com/llvm/llvm-project/pull/92475


More information about the llvm-commits mailing list