[llvm] [VPlan] Split off VPReductionRecipe creation for in-loop reductions (NFC) (PR #168784)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 22 08:46:31 PST 2025
================
@@ -699,6 +700,164 @@ void VPlanTransforms::createHeaderPhiRecipes(
}
}
+void VPlanTransforms::createVPReductionRecipesForInLoopReductions(
+ VPlan &Plan, const DenseMap<VPBasicBlock *, VPValue *> &BlockMaskCache,
+ const DenseSet<BasicBlock *> &BlocksNeedingPredication,
+ ElementCount MinVF) {
+ VPTypeAnalysis TypeInfo(Plan);
+ VPBasicBlock *Header = Plan.getVectorLoopRegion()->getEntryBasicBlock();
+ SmallVector<VPRecipeBase *> ToDelete;
+
+ for (VPRecipeBase &R : Header->phis()) {
+ auto *PhiR = dyn_cast<VPReductionPHIRecipe>(&R);
+ if (!PhiR || !PhiR->isInLoop() || (MinVF.isScalar() && !PhiR->isOrdered()))
+ continue;
+
+ RecurKind Kind = PhiR->getRecurrenceKind();
+ assert(
+ !RecurrenceDescriptor::isAnyOfRecurrenceKind(Kind) &&
+ !RecurrenceDescriptor::isFindIVRecurrenceKind(Kind) &&
+ "AnyOf and FindIV reductions are not allowed for in-loop reductions");
+
+ bool IsFPRecurrence =
+ RecurrenceDescriptor::isFloatingPointRecurrenceKind(Kind);
+ FastMathFlags FMFs =
+ IsFPRecurrence ? FastMathFlags::getFast() : FastMathFlags();
+
+ // Collect the chain of "link" recipes for the reduction starting at PhiR.
+ SetVector<VPSingleDefRecipe *> Worklist;
+ Worklist.insert(PhiR);
+ for (unsigned I = 0; I != Worklist.size(); ++I) {
+ VPSingleDefRecipe *Cur = Worklist[I];
+ for (VPUser *U : Cur->users()) {
+ auto *UserRecipe = cast<VPSingleDefRecipe>(U);
+ if (!UserRecipe->getParent()->getEnclosingLoopRegion()) {
+ assert((UserRecipe->getParent() == Plan.getMiddleBlock() ||
+ UserRecipe->getParent() == Plan.getScalarPreheader()) &&
+ "U must be either in the loop region, the middle block or the "
+ "scalar preheader.");
+ continue;
+ }
+
+ // Stores using instructions will be sunk later.
+ if (match(UserRecipe, m_VPInstruction<Instruction::Store>()))
+ continue;
+ Worklist.insert(UserRecipe);
+ }
+ }
+
+ // Visit operation "Links" along the reduction chain top-down starting from
+ // the phi until LoopExitValue. We keep track of the previous item
+ // (PreviousLink) to tell which of the two operands of a Link will remain
+ // scalar and which will be reduced. For minmax by select(cmp), Link will be
+ // the select instructions. Blend recipes of in-loop reduction phi's will
+ // get folded to their non-phi operand, as the reduction recipe handles the
+ // condition directly.
+ VPSingleDefRecipe *PreviousLink = PhiR; // Aka Worklist[0].
+ for (VPSingleDefRecipe *CurrentLink : drop_begin(Worklist)) {
+ if (auto *Blend = dyn_cast<VPBlendRecipe>(CurrentLink)) {
+ assert(Blend->getNumIncomingValues() == 2 &&
+ "Blend must have 2 incoming values");
+ unsigned Idx = Blend->getIncomingValue(0) == PhiR ? 1 : 0;
+ assert(Blend->getIncomingValue(1 - Idx) == PhiR &&
+ "PhiR must be an operand of the blend");
+ Blend->replaceAllUsesWith(Blend->getIncomingValue(Idx));
----------------
fhahn wrote:
renamed, thanks
https://github.com/llvm/llvm-project/pull/168784
More information about the llvm-commits
mailing list