[llvm] [InstCombine] Fold `(mul (div exact X, C0), C1)` -> `(div exact X, C0/C1)` (PR #96915)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 27 21:01:04 PDT 2024


================
@@ -365,6 +365,28 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
       return BinaryOperator::CreateMul(NegOp0, X);
   }
 
+  if (Op0->hasOneUse()) {
+    // (mul (div exact X, C0), C1)
+    //    -> (div exact C0 / C1)
+    // iff C0 % C1 == 0 and C0 / C1 doesn't create UB.
+    const APInt *C1;
+    auto UDivCheck = [&C1](const APInt &C) { return C.urem(*C1).isZero(); };
+    auto SDivCheck = [&C1](const APInt &C) {
+      APInt Quot, Rem;
+      APInt::sdivrem(C, *C1, Quot, Rem);
+      return Rem.isZero() && !Quot.isMinSignedValue();
+    };
+    if (match(Op1, m_APInt(C1)) &&
+        (match(Op0, m_Exact(m_UDiv(m_Value(X), m_CheckedInt(UDivCheck)))) ||
+         match(Op0, m_Exact(m_SDiv(m_Value(X), m_CheckedInt(SDivCheck)))))) {
+      auto BOpc = cast<BinaryOperator>(Op0)->getOpcode();
+      return BinaryOperator::CreateExact(
+          BOpc, X,
+          Builder.CreateBinOp(BOpc, cast<BinaryOperator>(Op0)->getOperand(1),
----------------
goldsteinn wrote:

B.c `CreateBinOp` needs non-constant `Value *` but `m_CheckedInt` sets a `const Constant *`. Im a but reluctant to use `const_cast`. Although maybe in a follow up could had non-const pointer support in `cstval_pred_ty`.

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


More information about the llvm-commits mailing list