Skip to content

[VPlan] Remove CanonicalIV when dissolving loop regions (NFC). #142372

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 3, 2025

Conversation

fhahn
Copy link
Contributor

@fhahn fhahn commented Jun 2, 2025

Directly replace the canonical IV when we dissolve the containing region. That ensures that it won't get removed before the region gets removed, which would result in an invalid region.

This removes the current ordering constraint between convertToConcreteRecipes and dissolving regions.

Directly replace the canonical IV when we dissolve the containing
region. That ensures that it won't get removed before the region gets
removed, which would result in an invalid region.

This removes the current ordering constraint between convertToConcreteRecipes
and dissolving regions.
@llvmbot
Copy link
Member

llvmbot commented Jun 2, 2025

@llvm/pr-subscribers-vectorizers

@llvm/pr-subscribers-llvm-transforms

Author: Florian Hahn (fhahn)

Changes

Directly replace the canonical IV when we dissolve the containing region. That ensures that it won't get removed before the region gets removed, which would result in an invalid region.

This removes the current ordering constraint between convertToConcreteRecipes and dissolving regions.


Full diff: https://github.com/llvm/llvm-project/pull/142372.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/Vectorize/VPlan.cpp (+10)
  • (modified) llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp (+3-7)
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp
index 165b57c87beb1..2580031c9186b 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp
@@ -883,6 +883,16 @@ void VPRegionBlock::print(raw_ostream &O, const Twine &Indent,
 
 void VPRegionBlock::dissolveToCFGLoop() {
   auto *Header = cast<VPBasicBlock>(getEntry());
+  if (auto *CanIV = dyn_cast<VPCanonicalIVPHIRecipe>(&Header->front())) {
+    assert(this == getPlan()->getVectorLoopRegion() &&
+           "Canonical IV must be in the entry of the top-level loop region");
+    auto *ScalarR = Builder(CanIV).createScalarPhi(
+        {CanIV->getStartValue(), CanIV->getBackedgeValue()},
+        CanIV->getDebugLoc(), "index");
+    CanIV->replaceAllUsesWith(ScalarR);
+    CanIV->eraseFromParent();
+  }
+
   VPBlockBase *Preheader = getSinglePredecessor();
   auto *ExitingLatch = cast<VPBasicBlock>(getExiting());
   VPBlockBase *Middle = getSingleSuccessor();
diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
index 5b42a9056b69e..5c6d7b0c5b529 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
@@ -2601,14 +2601,10 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan,
   for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
            vp_depth_first_deep(Plan.getEntry()))) {
     for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
-      if (isa<VPCanonicalIVPHIRecipe, VPEVLBasedIVPHIRecipe>(&R)) {
-        auto *PhiR = cast<VPHeaderPHIRecipe>(&R);
-        StringRef Name =
-            isa<VPCanonicalIVPHIRecipe>(PhiR) ? "index" : "evl.based.iv";
-        VPBuilder Builder(PhiR);
-        auto *ScalarR = Builder.createScalarPhi(
+      if (auto *PhiR = dyn_cast<VPEVLBasedIVPHIRecipe>(&R)) {
+        auto *ScalarR = Builder(PhiR).createScalarPhi(
             {PhiR->getStartValue(), PhiR->getBackedgeValue()},
-            PhiR->getDebugLoc(), Name);
+            PhiR->getDebugLoc(), "evl.based.iv");
         PhiR->replaceAllUsesWith(ScalarR);
         ToRemove.push_back(PhiR);
         continue;

Copy link
Contributor

@lukel97 lukel97 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, LGTM

@@ -883,6 +883,16 @@ void VPRegionBlock::print(raw_ostream &O, const Twine &Indent,

void VPRegionBlock::dissolveToCFGLoop() {
auto *Header = cast<VPBasicBlock>(getEntry());
if (auto *CanIV = dyn_cast<VPCanonicalIVPHIRecipe>(&Header->front())) {
assert(this == getPlan()->getVectorLoopRegion() &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an idea, alternatively it could also be replaced in VPlanTransforms::dissolveLoopRegions where you could get it directly from getCanonicalIV()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep that would also do the trick, but doing it here has the advantage it cannot be missed by potential other users

@david-arm
Copy link
Contributor

Looks like there are build failures:

C:\ws\src\llvm\lib\Transforms\Vectorize\VPlan.cpp(889): error C3861: 'Builder': identifier not found
C:\ws\src\llvm\lib\Transforms\Vectorize\VPlan.cpp(892): error C3536: 'ScalarR': cannot be used before it is initialized
C:\ws\src\llvm\lib\Transforms\Vectorize\VPlan.cpp(892): error C2664: 'void llvm::VPValue::replaceAllUsesWith(llvm::VPValue *)': cannot convert argument 1 from 'int' to 'llvm::VPValue *'
C:\ws\src\llvm\lib\Transforms\Vectorize\VPlan.cpp(892): note: Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
C:\ws\src\llvm\lib\Transforms\Vectorize\VPlanValue.h(156): note: see declaration of 'llvm::VPValue::replaceAllUsesWith'

Copy link
Contributor Author

@fhahn fhahn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there are build failures:

C:\ws\src\llvm\lib\Transforms\Vectorize\VPlan.cpp(889): error C3861: 'Builder': identifier not found
C:\ws\src\llvm\lib\Transforms\Vectorize\VPlan.cpp(892): error C3536: 'ScalarR': cannot be used before it is initialized
C:\ws\src\llvm\lib\Transforms\Vectorize\VPlan.cpp(892): error C2664: 'void llvm::VPValue::replaceAllUsesWith(llvm::VPValue *)': cannot convert argument 1 from 'int' to 'llvm::VPValue *'
C:\ws\src\llvm\lib\Transforms\Vectorize\VPlan.cpp(892): note: Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
C:\ws\src\llvm\lib\Transforms\Vectorize\VPlanValue.h(156): note: see declaration of 'llvm::VPValue::replaceAllUsesWith'

Thanks, windows build failure should be fixed

@@ -883,6 +883,16 @@ void VPRegionBlock::print(raw_ostream &O, const Twine &Indent,

void VPRegionBlock::dissolveToCFGLoop() {
auto *Header = cast<VPBasicBlock>(getEntry());
if (auto *CanIV = dyn_cast<VPCanonicalIVPHIRecipe>(&Header->front())) {
assert(this == getPlan()->getVectorLoopRegion() &&
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep that would also do the trick, but doing it here has the advantage it cannot be missed by potential other users

@fhahn fhahn merged commit 2eab83f into llvm:main Jun 3, 2025
11 checks passed
@fhahn fhahn deleted the vplan-replace-caniv-when-dissolving-region branch June 3, 2025 09:05
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Jun 3, 2025
…FC). (#142372)

Directly replace the canonical IV when we dissolve the containing
region. That ensures that it won't get removed before the region gets
removed, which would result in an invalid region.

This removes the current ordering constraint between
convertToConcreteRecipes and dissolving regions.

PR: llvm/llvm-project#142372
sallto pushed a commit to sallto/llvm-project that referenced this pull request Jun 3, 2025
…142372)

Directly replace the canonical IV when we dissolve the containing
region. That ensures that it won't get removed before the region gets
removed, which would result in an invalid region.

This removes the current ordering constraint between
convertToConcreteRecipes and dissolving regions.

PR: llvm#142372
@ayalz
Copy link
Collaborator

ayalz commented Jun 3, 2025

Post-commit follow-up comment: this raises the thought of coupling CanonicalIVPHI with its loop Region - also to be created together, i.e., within a createFromCFGLoop() complementing dissolveToCFGLoop(). A loop region could hold its CanonicalIVPHI rather than place it inside its header block, abstracting away CanonicalIVIncrement along with its cyclic dependence w/o risk of dce, guaranteeing CanonicalIVPHI's uniqueness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants