[llvm] [LV] Handle partial sub-reductions with sub in middle block. (PR #178919)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 5 07:13:40 PST 2026
================
@@ -5828,7 +5833,46 @@ void VPlanTransforms::createPartialReductions(VPlan &Plan,
}
}
- for (const auto &[_, Chains] : ChainsByPhi)
+ for (auto &[Phi, Chains] : ChainsByPhi) {
+ RecurKind RK = cast<VPReductionPHIRecipe>(Phi)->getRecurrenceKind();
+ bool IsTransformed = false;
for (const VPPartialReductionChain &Chain : Chains)
- transformToPartialReduction(Chain, Range, CostCtx, Plan);
+ IsTransformed |=
+ transformToPartialReduction(Chain, Range, CostCtx, Plan, RK);
+
+ // Sub-reductions can be implemented in two ways:
+ // (1) negate the operand in the vector loop (the default way).
+ // (2) subtract the reduced value from the init value in the middle block.
+ // Both ways keep the reduction itself as an 'add' reduction.
+ //
+ // The ISD nodes for partial reductions don't support folding the
+ // sub/negation into its operands because the following is not a valid
+ // transformation:
+ // sub(0, mul(ext(a), ext(b)))
+ // -> mul(ext(a), ext(sub(0, b)))
+ //
+ // It's therefore better to choose option (2) such that the partial
+ // reduction is always positive (starting at '0') and to do a final
+ // subtract in the middle block.
+ if (IsTransformed && !Range.isEmpty() && RK == RecurKind::Sub) {
+ // Update start value of PHI node.
+ auto *StartInst = cast<VPInstruction>(Phi->getStartValue());
+ assert(StartInst->getOpcode() == VPInstruction::ReductionStartVector);
+ VPValue *OldStartValue = StartInst->getOperand(0);
+ StartInst->setOperand(0, StartInst->getOperand(1));
+
+ // Replace reduction_result by 'sub (startval, reductionresult)'.
+ VPInstruction *RdxResult = vputils::findComputeReductionResult(Phi);
+ assert(RdxResult && "Could not find reduction result");
----------------
fhahn wrote:
Is there a reason we cannot do this directly in `transformToPartialReduction`? I think we already check if it is a last link, could we do it directly there (where we find `ExitValue`?). There's also now VPlan-based sinking, which should take care of sinking outside the loop I think.
https://github.com/llvm/llvm-project/pull/178919
More information about the llvm-commits
mailing list