[llvm] [VPlan] Introduce removeInvariantStoresOfReduction (NFCI) (PR #158680)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 15 09:39:19 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Ramkumar Ramachandra (artagnon)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/158680.diff
3 Files Affected:
- (modified) llvm/lib/Transforms/Vectorize/LoopVectorize.cpp (+2-19)
- (modified) llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp (+42)
- (modified) llvm/lib/Transforms/Vectorize/VPlanTransforms.h (+6)
``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 640a98c622f80..6e6ac735b1f37 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8474,6 +8474,8 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(
CM.foldTailByMasking());
VPlanTransforms::createLoopRegions(*Plan);
+ VPlanTransforms::removeInvariantStoresOfReduction(
+ *Plan, Legal->getReductionVars(), *LVer);
// Don't use getDecisionAndClampRange here, because we don't know the UF
// so this function is better to be conservative, rather than to split
@@ -8546,8 +8548,6 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(
ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>> RPOT(
HeaderVPBB);
- auto *MiddleVPBB = Plan->getMiddleBlock();
- VPBasicBlock::iterator MBIP = MiddleVPBB->getFirstNonPhi();
// Mapping from VPValues in the initial plan to their widened VPValues. Needed
// temporarily to update created block masks.
DenseMap<VPValue *, VPValue *> Old2New;
@@ -8576,23 +8576,6 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(
Instruction *Instr = cast<Instruction>(UnderlyingValue);
Builder.setInsertPoint(SingleDef);
- // The stores with invariant address inside the loop will be deleted, and
- // in the exit block, a uniform store recipe will be created for the final
- // invariant store of the reduction.
- StoreInst *SI;
- if ((SI = dyn_cast<StoreInst>(Instr)) &&
- Legal->isInvariantAddressOfReduction(SI->getPointerOperand())) {
- // Only create recipe for the final invariant store of the reduction.
- if (Legal->isInvariantStoreOfReduction(SI)) {
- auto *Recipe =
- new VPReplicateRecipe(SI, R.operands(), true /* IsUniform */,
- nullptr /*Mask*/, VPIRMetadata(*SI, LVer));
- Recipe->insertBefore(*MiddleVPBB, MBIP);
- }
- R.eraseFromParent();
- continue;
- }
-
VPRecipeBase *Recipe =
RecipeBuilder.tryToCreateWidenRecipe(SingleDef, Range);
if (!Recipe)
diff --git a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
index cef91c15dd873..849056659edb5 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
@@ -634,6 +634,48 @@ void VPlanTransforms::createLoopRegions(VPlan &Plan) {
TopRegion->getEntryBasicBlock()->setName("vector.body");
}
+void VPlanTransforms::removeInvariantStoresOfReduction(
+ VPlan &Plan, const MapVector<PHINode *, RecurrenceDescriptor> &Rdxs,
+ LoopVersioning &LVer) {
+ auto *MiddleVPBB = Plan.getMiddleBlock();
+ VPBasicBlock::iterator MBIP = MiddleVPBB->getFirstNonPhi();
+
+ auto IsInvariantStore = [Rdxs](StoreInst *SI) {
+ return any_of(Rdxs, [SI](const auto &RdxDesc) {
+ return RdxDesc.second.IntermediateStore == SI;
+ });
+ };
+
+ auto IsInvariantAddr = [Rdxs](Value *V) {
+ return any_of(Rdxs, [V](const auto &RdxDesc) {
+ auto *SI = RdxDesc.second.IntermediateStore;
+ return SI && SI->getPointerOperand() == V;
+ });
+ };
+
+ for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
+ vp_depth_first_shallow(Plan.getVectorLoopRegion()->getEntry()))) {
+ for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
+ auto *Def = cast<VPSingleDefRecipe>(&R);
+
+ // The stores with invariant address inside the loop will be deleted, and
+ // in the exit block, a uniform store recipe will be created for the final
+ // invariant store of the reduction.
+ StoreInst *SI = dyn_cast_if_present<StoreInst>(Def->getUnderlyingValue());
+ if (!SI || !IsInvariantAddr(SI->getPointerOperand()))
+ continue;
+ if (IsInvariantStore(SI)) {
+ // Only create recipe for the final invariant store of the reduction.
+ auto *Recipe =
+ new VPReplicateRecipe(SI, Def->operands(), /*IsSingleScalar=*/true,
+ /*Mask=*/nullptr, VPIRMetadata(*SI, &LVer));
+ Recipe->insertBefore(*MiddleVPBB, MBIP);
+ }
+ Def->eraseFromParent();
+ }
+ }
+}
+
// Likelyhood of bypassing the vectorized loop due to a runtime check block,
// including memory overlap checks block and wrapping/unit-stride checks block.
static constexpr uint32_t CheckBypassWeights[] = {1, 127};
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
index 69452a7e37572..a567ae127cf63 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
@@ -121,6 +121,12 @@ struct VPlanTransforms {
/// flat CFG into a hierarchical CFG.
LLVM_ABI_FOR_TEST static void createLoopRegions(VPlan &Plan);
+ /// Remove invariant stores of reductions, given \p Rdxs, in \p Plan. \p LVer
+ /// is used to create metadata from an existing store.
+ static void removeInvariantStoresOfReduction(
+ VPlan &Plan, const MapVector<PHINode *, RecurrenceDescriptor> &Rdxs,
+ LoopVersioning &LVer);
+
/// Wrap runtime check block \p CheckBlock in a VPIRBB and \p Cond in a
/// VPValue and connect the block to \p Plan, using the VPValue as branch
/// condition.
``````````
</details>
https://github.com/llvm/llvm-project/pull/158680
More information about the llvm-commits
mailing list