[llvm] [Reassociate] Distribute multiply over add to enable factorization (PR #178201)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sat May 2 03:47:52 PDT 2026


================
@@ -963,6 +963,69 @@ static BinaryOperator *convertOrWithNoCommonBitsToAdd(Instruction *Or) {
   return New;
 }
 
+/// Return true if Mul is of the form (X+Y)*C or (X-Y)*C where C is a
+/// constant, and there exists a sibling instruction of the form X*C' or Y*C'
+/// in the same expression — indicating that distribution followed by
+/// factoring will reduce the instruction count.
+static bool ShouldBreakUpDistribution(Instruction *Mul) {
+  Value *A, *B;
+  if (!match(Mul, m_c_Mul(m_OneUse(m_CombineOr(m_Add(m_Value(A), m_Value(B)),
+                                               m_Sub(m_Value(A), m_Value(B)))),
+                          m_ImmConstant())))
+    return false;
+
+  if (!Mul->hasOneUse())
+    return false;
+
+  auto *MulUser = dyn_cast<Instruction>(Mul->user_back());
+  // The parent MUST be an Add or Sub to ensure the tree is flattened
+  if (!MulUser || (MulUser->getOpcode() != Instruction::Add &&
+                   MulUser->getOpcode() != Instruction::Sub))
+    return false;
+
+  for (Value *Sibling : MulUser->operands()) {
+    if (Sibling == Mul || !Sibling->hasOneUse())
+      continue;
+
+    // Sibling must be NonConst * C'.
+    Value *SibNC;
+    if (match(Sibling, m_Mul(m_Value(SibNC), m_Constant()))) {
+      if ((SibNC == A || SibNC == B) && !isa<Constant>(SibNC))
+        return true;
+    }
+  }
+  return false;
+}
+
+/// Distribute Mul of the form (X+Y)*C into X*C + Y*C.
+/// For the sub case (X-Y)*C, the second term uses -C to avoid
+/// introducing a negation instruction.
+static BinaryOperator *BreakUpDistribute(Instruction *Mul,
+                                         ReassociatePass::OrderedSet &ToRedo) {
+
+  Instruction *AddSub = cast<Instruction>(Mul->getOperand(0));
+  Constant *C = cast<Constant>(Mul->getOperand(1));
+  Constant *C2 = (AddSub->getOpcode() == Instruction::Sub)
+                     ? cast<Constant>(ConstantExpr::getNeg(C))
+                     : C;
+
+  BinaryOperator *M1 =
+      CreateMul(AddSub->getOperand(0), C, "Mul1", Mul->getIterator(), nullptr);
----------------
dtcxzyw wrote:

Just use `BinaryOperator::CreateMul`.


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


More information about the llvm-commits mailing list