@@ -2390,6 +2390,58 @@ bool VPlanTransforms::tryAddExplicitVectorLength(
2390
2390
return true ;
2391
2391
}
2392
2392
2393
+ void VPlanTransforms::simplifyEVLIVs (VPlan &Plan) {
2394
+ auto ConvertEVLPhi = [](VPlan &Plan, VPBasicBlock *Entry,
2395
+ VPEVLBasedIVPHIRecipe *EVLPhi) {
2396
+ using namespace llvm ::VPlanPatternMatch;
2397
+ VPValue *EVLIncrement = EVLPhi->getBackedgeValue ();
2398
+
2399
+ // Convert EVLPhi to concrete recipe.
2400
+ auto *ScalarR = VPBuilder (EVLPhi).createScalarPhi (
2401
+ {EVLPhi->getStartValue (), EVLIncrement}, EVLPhi->getDebugLoc (),
2402
+ " evl.based.iv" );
2403
+ EVLPhi->replaceAllUsesWith (ScalarR);
2404
+ EVLPhi->eraseFromParent ();
2405
+
2406
+ // Find the latch-exiting block and convert to variable-length stepping.
2407
+ // Before: (branch-on-cond CanonicalIVInc, VectorTripCount)
2408
+ // After: (branch-on-cond EVLIVInc, TripCount)
2409
+ auto FindLatchExiting = [](VPBasicBlock *Entry) {
2410
+ auto Range =
2411
+ VPBlockUtils::blocksOnly<VPBasicBlock>(vp_depth_first_shallow (Entry));
2412
+ auto It = find_if (Range, [&](VPBasicBlock *VPBB) {
2413
+ return any_of (VPBB->successors (),
2414
+ [&](VPBlockBase *Succ) { return Succ == Entry; });
2415
+ });
2416
+ return It != Range.end () ? *It : nullptr ;
2417
+ };
2418
+ VPBasicBlock *LatchExiting = FindLatchExiting (Entry);
2419
+ assert (LatchExiting && " LatchExiting is not found" );
2420
+ auto *LatchExitingBr = cast<VPInstruction>(LatchExiting->getTerminator ());
2421
+ VPValue *ScalarIVInc;
2422
+ if (!LatchExitingBr ||
2423
+ !match (LatchExitingBr,
2424
+ m_BranchOnCount (m_VPValue (ScalarIVInc),
2425
+ m_Specific (&Plan.getVectorTripCount ()))))
2426
+ return ;
2427
+ LatchExitingBr->setOperand (1 , Plan.getTripCount ());
2428
+ ScalarIVInc->replaceAllUsesWith (EVLIncrement);
2429
+ VPRecipeBase *IVIncR = ScalarIVInc->getDefiningRecipe ();
2430
+ VPRecipeBase *ScalarIV = IVIncR->getOperand (0 )->getDefiningRecipe ();
2431
+ IVIncR->eraseFromParent ();
2432
+ ScalarIV->eraseFromParent ();
2433
+ };
2434
+
2435
+ // Find EVL loop entries by locating VPEVLBasedIVPHIRecipe
2436
+ for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
2437
+ vp_depth_first_shallow (Plan.getEntry ())))
2438
+ for (VPRecipeBase &R : VPBB->phis ())
2439
+ if (auto *PhiR = dyn_cast<VPEVLBasedIVPHIRecipe>(&R)) {
2440
+ ConvertEVLPhi (Plan, VPBB, PhiR);
2441
+ break ;
2442
+ }
2443
+ }
2444
+
2393
2445
void VPlanTransforms::dropPoisonGeneratingRecipes (
2394
2446
VPlan &Plan,
2395
2447
const std::function<bool (BasicBlock *)> &BlockNeedsPredication) {
@@ -2721,15 +2773,6 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan,
2721
2773
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(
2722
2774
vp_depth_first_deep (Plan.getEntry ()))) {
2723
2775
for (VPRecipeBase &R : make_early_inc_range (*VPBB)) {
2724
- if (auto *PhiR = dyn_cast<VPEVLBasedIVPHIRecipe>(&R)) {
2725
- auto *ScalarR = VPBuilder (PhiR).createScalarPhi (
2726
- {PhiR->getStartValue (), PhiR->getBackedgeValue ()},
2727
- PhiR->getDebugLoc (), " evl.based.iv" );
2728
- PhiR->replaceAllUsesWith (ScalarR);
2729
- ToRemove.push_back (PhiR);
2730
- continue ;
2731
- }
2732
-
2733
2776
if (auto *WidenIVR = dyn_cast<VPWidenIntOrFpInductionRecipe>(&R)) {
2734
2777
expandVPWidenIntOrFpInduction (WidenIVR, TypeInfo);
2735
2778
ToRemove.push_back (WidenIVR);
0 commit comments