[llvm] [VPlan] Introduce replaceSymbolicStrides (NFC) (PR #155842)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 28 07:25:15 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Ramkumar Ramachandra (artagnon)
<details>
<summary>Changes</summary>
Introduce VPlanTransforms::replaceSymbolicStrides factoring some code from LoopVectorize.
---
Full diff: https://github.com/llvm/llvm-project/pull/155842.diff
3 Files Affected:
- (modified) llvm/lib/Transforms/Vectorize/LoopVectorize.cpp (+3-35)
- (modified) llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp (+41)
- (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 6317bc3c20e25..23ec073a8f4ff 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -8777,41 +8777,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 d32d2a9ad11f7..9a87be5fe7803 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"
@@ -2535,6 +2536,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..5afff8edbc511 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 the symbolic strides in \p Plan, with data from \p StridesMap,
+ /// 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:
``````````
</details>
https://github.com/llvm/llvm-project/pull/155842
More information about the llvm-commits
mailing list