[llvm] [VPlan] Convert EVL loops to variable-length stepping after dissolution (PR #147222)
Shih-Po Hung via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 17 06:11:54 PDT 2025
================
@@ -2357,6 +2357,58 @@ bool VPlanTransforms::tryAddExplicitVectorLength(
return true;
}
+void VPlanTransforms::simplifyEVLIVs(VPlan &Plan) {
+ auto ConvertEVLPhi = [](VPlan &Plan, VPBasicBlock *Entry,
+ VPEVLBasedIVPHIRecipe *EVLPhi) {
+ using namespace llvm::VPlanPatternMatch;
+ VPValue *EVLIncrement = EVLPhi->getBackedgeValue();
+
+ // Convert EVLPhi to concrete recipe.
+ auto *ScalarR = VPBuilder(EVLPhi).createScalarPhi(
+ {EVLPhi->getStartValue(), EVLIncrement}, EVLPhi->getDebugLoc(),
+ "evl.based.iv");
+ EVLPhi->replaceAllUsesWith(ScalarR);
+ EVLPhi->eraseFromParent();
+
+ // Find the latch-exiting block and convert to variable-length stepping.
+ // Before: (branch-on-count CanonicalIVInc, VectorTripCount)
+ // After: (branch-on-count EVLIVInc, TripCount)
+ auto FindLatchExiting = [](VPBasicBlock *Entry) {
+ auto Range =
+ VPBlockUtils::blocksOnly<VPBasicBlock>(vp_depth_first_shallow(Entry));
+ auto It = find_if(Range, [&](VPBasicBlock *VPBB) {
+ return any_of(VPBB->successors(),
+ [&](VPBlockBase *Succ) { return Succ == Entry; });
+ });
+ return It != Range.end() ? *It : nullptr;
+ };
+ VPBasicBlock *LatchExiting = FindLatchExiting(Entry);
+ assert(LatchExiting && "LatchExiting is not found");
+ auto *LatchExitingBr = cast<VPInstruction>(LatchExiting->getTerminator());
+ VPValue *ScalarIVInc;
+ if (!LatchExitingBr ||
+ !match(LatchExitingBr,
+ m_BranchOnCount(m_VPValue(ScalarIVInc),
+ m_Specific(&Plan.getVectorTripCount()))))
+ return;
+ LatchExitingBr->setOperand(1, Plan.getTripCount());
+ ScalarIVInc->replaceAllUsesWith(EVLIncrement);
+ VPRecipeBase *IVIncR = ScalarIVInc->getDefiningRecipe();
+ VPRecipeBase *ScalarIV = IVIncR->getOperand(0)->getDefiningRecipe();
+ IVIncR->eraseFromParent();
+ ScalarIV->eraseFromParent();
+ };
+
+ // Find EVL loop entries by locating VPEVLBasedIVPHIRecipe
+ for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
+ vp_depth_first_shallow(Plan.getEntry())))
+ for (VPRecipeBase &R : VPBB->phis())
----------------
arcbbb wrote:
> I think VPEVLBasedIVPHIRecipe only appear in the header. You just need to visit the header block.
Before loop region dissolution, we can get the region directly from the plan and get the loop header via VPRegionBlock.getEntry().
However, at this stage (after dissolution), we need to traverse all blocks to find which block contains the EVL phi, since the region structure is no longer available.
> there should only be one EVL based PHI? So can we replace the loop with something like
yeah, there should only be one EVL-phi for now. I see two ways to handle this:
1. Assert when there are multiple EVL PHIs
2. Silently skip when there are multiple EVL PHIs
Which approach do you suggest?
https://github.com/llvm/llvm-project/pull/147222
More information about the llvm-commits
mailing list