[llvm] [VPlan] Add transform to replace VPWidenCanonicalIV with wide IV. (PR #194267)
Ramkumar Ramachandra via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 27 02:53:19 PDT 2026
================
@@ -691,6 +691,73 @@ static void removeRedundantCanonicalIVs(VPlan &Plan) {
}
}
+void VPlanTransforms::replaceWidenCanonicalIVWithWidenIV(
+ VPlan &Plan, ScalarEvolution &SE, const TargetTransformInfo &TTI,
+ TargetTransformInfo::TargetCostKind CostKind, ElementCount VF,
+ unsigned UF) {
+ VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
+ if (!LoopRegion || Plan.hasScalarVFOnly())
+ return;
+
+ VPValue *CanonicalIV = LoopRegion->getCanonicalIV();
+ auto *WideCanIV = vputils::findUserOf<VPWidenCanonicalIVRecipe>(CanonicalIV);
+ if (!WideCanIV)
+ return;
+
+ // If a canonical VPWidenIntOrFpInductionRecipe already exists, reuse it.
+ VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
+ for (VPRecipeBase &Phi : Header->phis()) {
+ auto *WideIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(&Phi);
+ if (!WideIV || !WideIV->isCanonical())
+ continue;
+ // The canonical wide IV is used to compute the header mask, hence all
+ // lanes will be used. Drop poison-generating flags.
+ WideIV->dropPoisonGeneratingFlags();
+ WideCanIV->replaceAllUsesWith(WideIV);
+ WideCanIV->eraseFromParent();
+ return;
+ }
----------------
artagnon wrote:
I just tried it out and the following patch:
```diff
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 5e6d1bbcd5a7..b956683c5b2c 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -658,36 +658,28 @@ static void removeRedundantInductionCasts(VPlan &Plan) {
/// Try to replace VPWidenCanonicalIVRecipes with a widened canonical IV
/// recipe, if it exists.
static void removeRedundantCanonicalIVs(VPlan &Plan) {
+ if (Plan.hasScalarVFOnly())
+ return;
VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
VPValue *CanonicalIV = LoopRegion->getCanonicalIV();
- auto *WidenNewIV = vputils::findUserOf<VPWidenCanonicalIVRecipe>(CanonicalIV);
-
- if (!WidenNewIV)
+ auto *WideCanIV = vputils::findUserOf<VPWidenCanonicalIVRecipe>(CanonicalIV);
+ if (!WideCanIV)
return;
VPBasicBlock *HeaderVPBB = LoopRegion->getEntryBasicBlock();
for (VPRecipeBase &Phi : HeaderVPBB->phis()) {
- auto *WidenOriginalIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(&Phi);
-
- if (!WidenOriginalIV || !WidenOriginalIV->isCanonical())
+ auto *WideInd = dyn_cast<VPWidenIntOrFpInductionRecipe>(&Phi);
+ if (!WideInd || !WideInd->isCanonical())
continue;
- // Replace WidenNewIV with WidenOriginalIV if WidenOriginalIV provides
- // everything WidenNewIV's users need. That is, WidenOriginalIV will
- // generate a vector phi or all users of WidenNewIV demand the first lane
- // only.
- if (Plan.hasScalarVFOnly() ||
- !vputils::onlyScalarValuesUsed(WidenOriginalIV) ||
- vputils::onlyFirstLaneUsed(WidenNewIV)) {
- // We are replacing a wide canonical iv with a suitable wide induction.
- // This is used to compute header mask, hence all lanes will be used and
- // we need to drop wrap flags only applying to lanes guranteed to execute
- // in the original scalar loop.
- WidenOriginalIV->dropPoisonGeneratingFlags();
- WidenNewIV->replaceAllUsesWith(WidenOriginalIV);
- WidenNewIV->eraseFromParent();
- return;
- }
+ // We are replacing a wide canonical iv with a suitable wide induction.
+ // This is used to compute header mask, hence all lanes will be used and
+ // we need to drop wrap flags only applying to lanes guranteed to execute
+ // in the original scalar loop.
+ WideInd->dropPoisonGeneratingFlags();
+ WideCanIV->replaceAllUsesWith(WideInd);
+ WideCanIV->eraseFromParent();
+ return;
}
}
```
leads to minor regressions from adds not being CSE'd. I think the right thing to do is my preparatory patch to lower first-lane wide IVs to SIVSteps, expand the WideCanIV, finally making the proposed diff possible without regressions.
https://github.com/llvm/llvm-project/pull/194267
More information about the llvm-commits
mailing list