[llvm] 4cf7702 - [VPlan] Introduce replaceSymbolicStrides (NFC) (#155842)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 1 02:03:51 PDT 2025
Author: Ramkumar Ramachandra
Date: 2025-09-01T09:03:46Z
New Revision: 4cf770275fb54270fe7d4e22fbe9c08f70933d5c
URL: https://github.com/llvm/llvm-project/commit/4cf770275fb54270fe7d4e22fbe9c08f70933d5c
DIFF: https://github.com/llvm/llvm-project/commit/4cf770275fb54270fe7d4e22fbe9c08f70933d5c.diff
LOG: [VPlan] Introduce replaceSymbolicStrides (NFC) (#155842)
Introduce VPlanTransforms::replaceSymbolicStrides factoring some code
from LoopVectorize.
Added:
Modified:
llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
llvm/lib/Transforms/Vectorize/VPlanTransforms.h
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 2a0fef3625b0f..97bf49357ebe6 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8778,41 +8778,9 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(
InterleaveGroups, RecipeBuilder,
CM.isScalarEpilogueAllowed());
- // Replace VPValues for known constant strides guaranteed by predicate scalar
- // evolution.
- auto CanUseVersionedStride = [&Plan](VPUser &U, unsigned) {
- auto *R = cast<VPRecipeBase>(&U);
- return R->getParent()->getParent() ||
- R->getParent() ==
- Plan->getVectorLoopRegion()->getSinglePredecessor();
- };
- for (auto [_, Stride] : Legal->getLAI()->getSymbolicStrides()) {
- auto *StrideV = cast<SCEVUnknown>(Stride)->getValue();
- auto *ScevStride = dyn_cast<SCEVConstant>(PSE.getSCEV(StrideV));
- // Only handle constant strides for now.
- if (!ScevStride)
- continue;
-
- auto *CI = Plan->getOrAddLiveIn(
- ConstantInt::get(Stride->getType(), ScevStride->getAPInt()));
- if (VPValue *StrideVPV = Plan->getLiveIn(StrideV))
- StrideVPV->replaceUsesWithIf(CI, CanUseVersionedStride);
-
- // The versioned value may not be used in the loop directly but through a
- // sext/zext. Add new live-ins in those cases.
- for (Value *U : StrideV->users()) {
- if (!isa<SExtInst, ZExtInst>(U))
- continue;
- VPValue *StrideVPV = Plan->getLiveIn(U);
- if (!StrideVPV)
- continue;
- unsigned BW = U->getType()->getScalarSizeInBits();
- APInt C = isa<SExtInst>(U) ? ScevStride->getAPInt().sext(BW)
- : ScevStride->getAPInt().zext(BW);
- VPValue *CI = Plan->getOrAddLiveIn(ConstantInt::get(U->getType(), C));
- StrideVPV->replaceUsesWithIf(CI, CanUseVersionedStride);
- }
- }
+ // Replace VPValues for known constant strides.
+ VPlanTransforms::runPass(VPlanTransforms::replaceSymbolicStrides, *Plan, PSE,
+ Legal->getLAI()->getSymbolicStrides());
auto BlockNeedsPredication = [this](BasicBlock *BB) {
return Legal->blockNeedsPredication(BB);
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index ded9e46b407b1..17b54f2ef9c05 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -29,6 +29,7 @@
#include "llvm/Analysis/IVDescriptors.h"
#include "llvm/Analysis/InstSimplifyFolder.h"
#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/ScalarEvolutionPatternMatch.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
@@ -2539,6 +2540,46 @@ void VPlanTransforms::canonicalizeEVLLoops(VPlan &Plan) {
LatchExitingBr->eraseFromParent();
}
+void VPlanTransforms::replaceSymbolicStrides(
+ VPlan &Plan, PredicatedScalarEvolution &PSE,
+ const DenseMap<Value *, const SCEV *> &StridesMap) {
+ // Replace VPValues for known constant strides guaranteed by predicate scalar
+ // evolution.
+ auto CanUseVersionedStride = [&Plan](VPUser &U, unsigned) {
+ auto *R = cast<VPRecipeBase>(&U);
+ return R->getParent()->getParent() ||
+ R->getParent() == Plan.getVectorLoopRegion()->getSinglePredecessor();
+ };
+ for (const SCEV *Stride : StridesMap.values()) {
+ using namespace SCEVPatternMatch;
+ auto *StrideV = cast<SCEVUnknown>(Stride)->getValue();
+ const APInt *StrideConst;
+ if (!match(PSE.getSCEV(StrideV), m_scev_APInt(StrideConst)))
+ // Only handle constant strides for now.
+ continue;
+
+ auto *CI =
+ Plan.getOrAddLiveIn(ConstantInt::get(Stride->getType(), *StrideConst));
+ if (VPValue *StrideVPV = Plan.getLiveIn(StrideV))
+ StrideVPV->replaceUsesWithIf(CI, CanUseVersionedStride);
+
+ // The versioned value may not be used in the loop directly but through a
+ // sext/zext. Add new live-ins in those cases.
+ for (Value *U : StrideV->users()) {
+ if (!isa<SExtInst, ZExtInst>(U))
+ continue;
+ VPValue *StrideVPV = Plan.getLiveIn(U);
+ if (!StrideVPV)
+ continue;
+ unsigned BW = U->getType()->getScalarSizeInBits();
+ APInt C =
+ isa<SExtInst>(U) ? StrideConst->sext(BW) : StrideConst->zext(BW);
+ VPValue *CI = Plan.getOrAddLiveIn(ConstantInt::get(U->getType(), C));
+ StrideVPV->replaceUsesWithIf(CI, CanUseVersionedStride);
+ }
+ }
+}
+
void VPlanTransforms::dropPoisonGeneratingRecipes(
VPlan &Plan,
const std::function<bool(BasicBlock *)> &BlockNeedsPredication) {
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
index 9cf62a35ae36b..a2c1f2e000f63 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.h
@@ -199,6 +199,12 @@ struct VPlanTransforms {
truncateToMinimalBitwidths(VPlan &Plan,
const MapVector<Instruction *, uint64_t> &MinBWs);
+ /// Replace symbolic strides from \p StridesMap in \p Plan with constants when
+ /// possible.
+ static void
+ replaceSymbolicStrides(VPlan &Plan, PredicatedScalarEvolution &PSE,
+ const DenseMap<Value *, const SCEV *> &StridesMap);
+
/// Drop poison flags from recipes that may generate a poison value that is
/// used after vectorization, even when their operands are not poison. Those
/// recipes meet the following conditions:
More information about the llvm-commits
mailing list