[llvm] [InstCombine] Reduce multiplicands of even numbers when a shift is involved (PR #92475)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 24 07:47:28 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;
+      }
+    }
+
----------------
AtariDreams wrote:

> Helper function then?

Given how many things need to be passed like the pointer to value x, the type, etc, this is one of those cases where just because some code looks like it can be shared doesn't mean it is a good idea if it is, mostly because values like X are bound way earlier in the code in the lshr case, and to avoid unnecessary overhead, I ensure that I group the transforms that are known to only apply when similar conditions are met. 

This suggestion also doesn't work unless X is passed because ashr requires nsw for the transform to work, and lshr requires nuw for the transform to work. 

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


More information about the llvm-commits mailing list