[llvm] [InstCombine] Combine interleaved PHI reduction chains. (PR #143878)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 16 04:15:03 PDT 2025
================
@@ -996,6 +997,154 @@ Instruction *InstCombinerImpl::foldPHIArgOpIntoPHI(PHINode &PN) {
return NewCI;
}
+/// Try to fold reduction ops interleaved through two PHIs to a single PHI.
+///
+/// For example, combine:
+/// %phi1 = phi [init1, %BB1], [%op1, %BB2]
+/// %phi2 = phi [init2, %BB1], [%op2, %BB2]
+/// %op1 = binop %phi1, constant1
+/// %op2 = binop %phi2, constant2
+/// %rdx = binop %op1, %op2
+/// =>
+/// %phi_combined = phi [init_combined, %BB1], [%op_combined, %BB2]
+/// %rdx_combined = binop %phi_combined, constant_combined
+///
+/// For now, we require init1, init2, constant1 and constant2 to be constants.
+Instruction *InstCombinerImpl::foldPHIReduction(PHINode &PN) {
+ BinaryOperator *BO1;
+ Value *Start1;
+ Value *Step1;
+
+ // Find the first recurrence.
+ if (!PN.hasOneUse() || !matchSimpleRecurrence(&PN, BO1, Start1, Step1))
+ return nullptr;
+
+ // Ensure BO1 has two uses (PN and the reduction op) and can be reassociated.
+ if (!BO1->hasNUses(2) || !BO1->isAssociative())
+ return nullptr;
+
+ // Convert Start1 and Step1 to constants.
+ auto *Init1 = dyn_cast<Constant>(Start1);
+ auto *C1 = dyn_cast<Constant>(Step1);
+ if (!Init1 || !C1)
+ return nullptr;
+
+ // Find the reduction operation.
+ auto Opc = BO1->getOpcode();
+ BinaryOperator *Rdx = nullptr;
+ for (User *U : BO1->users())
+ if (U != &PN) {
+ Rdx = dyn_cast<BinaryOperator>(U);
+ break;
+ }
----------------
antoniofrighetto wrote:
```suggestion
auto It = find_if(BO1->users(), [&](auto *U) { return U != &PN; });
if (It != BO1->users().end())
Rdx = dyn_cast<BinaryOperator>(*It);
```
https://github.com/llvm/llvm-project/pull/143878
More information about the llvm-commits
mailing list