@@ -2461,63 +2461,56 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan,
2461
2461
}
2462
2462
2463
2463
void VPlanTransforms::handleUncountableEarlyExit (
2464
- VPlan &Plan, Loop *OrigLoop, BasicBlock *UncountableExitingBlock,
2465
- VPRecipeBuilder &RecipeBuilder, VFRange &Range) {
2466
- VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion ();
2467
- auto *LatchVPBB = cast<VPBasicBlock>(LoopRegion->getExiting ());
2468
- VPBuilder Builder (LatchVPBB->getTerminator ());
2469
- auto *MiddleVPBB = Plan.getMiddleBlock ();
2470
- VPValue *IsEarlyExitTaken = nullptr ;
2471
-
2472
- // Process the uncountable exiting block. Update IsEarlyExitTaken, which
2473
- // tracks if the uncountable early exit has been taken. Also split the middle
2474
- // block and have it conditionally branch to the early exit block if
2475
- // EarlyExitTaken.
2476
- auto *EarlyExitingBranch =
2477
- cast<BranchInst>(UncountableExitingBlock->getTerminator ());
2478
- BasicBlock *TrueSucc = EarlyExitingBranch->getSuccessor (0 );
2479
- BasicBlock *FalseSucc = EarlyExitingBranch->getSuccessor (1 );
2480
- BasicBlock *EarlyExitIRBB =
2481
- !OrigLoop->contains (TrueSucc) ? TrueSucc : FalseSucc;
2482
- VPIRBasicBlock *VPEarlyExitBlock = Plan.getExitBlock (EarlyExitIRBB);
2483
-
2484
- VPValue *EarlyExitNotTakenCond = RecipeBuilder.getBlockInMask (
2485
- OrigLoop->contains (TrueSucc) ? TrueSucc : FalseSucc);
2486
- auto *EarlyExitTakenCond = Builder.createNot (EarlyExitNotTakenCond);
2487
- IsEarlyExitTaken =
2488
- Builder.createNaryOp (VPInstruction::AnyOf, {EarlyExitTakenCond});
2464
+ VPBasicBlock *EarlyExitingVPBB, VPBasicBlock *EarlyExitVPBB, VPlan &Plan,
2465
+ VPBasicBlock *HeaderVPBB, VPBasicBlock *LatchVPBB, VFRange &Range) {
2466
+ using namespace llvm ::VPlanPatternMatch;
2489
2467
2468
+ VPBlockBase *MiddleVPBB = LatchVPBB->getSuccessors ()[0 ];
2469
+ if (!EarlyExitVPBB->getSinglePredecessor () &&
2470
+ EarlyExitVPBB->getPredecessors ()[1 ] == MiddleVPBB) {
2471
+ assert (EarlyExitVPBB->getNumPredecessors () == 2 &&
2472
+ EarlyExitVPBB->getPredecessors ()[0 ] == EarlyExitingVPBB &&
2473
+ " unsupported early exit VPBB" );
2474
+ // Early exit operand should always be last phi operand. If EarlyExitVPBB
2475
+ // has two predecessors and EarlyExitingVPBB is the first, swap the operands
2476
+ // of the phis.
2477
+ for (VPRecipeBase &R : EarlyExitVPBB->phis ())
2478
+ cast<VPIRPhi>(&R)->swapOperands ();
2479
+ }
2480
+
2481
+ VPBuilder Builder (LatchVPBB->getTerminator ());
2482
+ VPBlockBase *TrueSucc = EarlyExitingVPBB->getSuccessors ()[0 ];
2483
+ assert (
2484
+ match (EarlyExitingVPBB->getTerminator (), m_BranchOnCond (m_VPValue ())) &&
2485
+ " Terminator must be be BranchOnCond" );
2486
+ VPValue *CondOfEarlyExitingVPBB =
2487
+ EarlyExitingVPBB->getTerminator ()->getOperand (0 );
2488
+ auto *CondToEarlyExit = TrueSucc == EarlyExitVPBB
2489
+ ? CondOfEarlyExitingVPBB
2490
+ : Builder.createNot (CondOfEarlyExitingVPBB);
2491
+
2492
+ // Split the middle block and have it conditionally branch to the early exit
2493
+ // block if CondToEarlyExit.
2494
+ VPValue *IsEarlyExitTaken =
2495
+ Builder.createNaryOp (VPInstruction::AnyOf, {CondToEarlyExit});
2490
2496
VPBasicBlock *NewMiddle = Plan.createVPBasicBlock (" middle.split" );
2491
2497
VPBasicBlock *VectorEarlyExitVPBB =
2492
2498
Plan.createVPBasicBlock (" vector.early.exit" );
2493
- VPBlockUtils::insertOnEdge (LoopRegion , MiddleVPBB, NewMiddle);
2499
+ VPBlockUtils::insertOnEdge (LatchVPBB , MiddleVPBB, NewMiddle);
2494
2500
VPBlockUtils::connectBlocks (NewMiddle, VectorEarlyExitVPBB);
2495
2501
NewMiddle->swapSuccessors ();
2496
2502
2497
- VPBlockUtils::connectBlocks (VectorEarlyExitVPBB, VPEarlyExitBlock );
2503
+ VPBlockUtils::connectBlocks (VectorEarlyExitVPBB, EarlyExitVPBB );
2498
2504
2499
2505
// Update the exit phis in the early exit block.
2500
2506
VPBuilder MiddleBuilder (NewMiddle);
2501
2507
VPBuilder EarlyExitB (VectorEarlyExitVPBB);
2502
- for (VPRecipeBase &R : VPEarlyExitBlock ->phis ()) {
2508
+ for (VPRecipeBase &R : EarlyExitVPBB ->phis ()) {
2503
2509
auto *ExitIRI = cast<VPIRPhi>(&R);
2504
- // Early exit operand should always be last, i.e., 0 if VPEarlyExitBlock has
2510
+ // Early exit operand should always be last, i.e., 0 if EarlyExitVPBB has
2505
2511
// a single predecessor and 1 if it has two.
2506
2512
unsigned EarlyExitIdx = ExitIRI->getNumOperands () - 1 ;
2507
- if (!VPEarlyExitBlock->getSinglePredecessor ()) {
2508
- // If VPEarlyExitBlock has two predecessors, they are already ordered such
2509
- // that early exit is second (and latch exit is first), by construction.
2510
- // But its underlying IRBB (EarlyExitIRBB) may have its predecessors
2511
- // ordered the other way around, and it is the order of the latter which
2512
- // corresponds to the order of operands of VPEarlyExitBlock's phi recipes.
2513
- // Therefore, if early exit (UncountableExitingBlock) is the first
2514
- // predecessor of EarlyExitIRBB, we swap the operands of phi recipes,
2515
- // thereby bringing them to match VPEarlyExitBlock's predecessor order,
2516
- // with early exit being last (second). Otherwise they already match.
2517
- if (*pred_begin (VPEarlyExitBlock->getIRBasicBlock ()) ==
2518
- UncountableExitingBlock)
2519
- ExitIRI->swapOperands ();
2520
-
2513
+ if (ExitIRI->getNumOperands () != 1 ) {
2521
2514
// The first of two operands corresponds to the latch exit, via MiddleVPBB
2522
2515
// predecessor. Extract its last lane.
2523
2516
ExitIRI->extractLastLaneOfFirstOperand (MiddleBuilder);
@@ -2533,7 +2526,7 @@ void VPlanTransforms::handleUncountableEarlyExit(
2533
2526
LoopVectorizationPlanner::getDecisionAndClampRange (IsVector, Range)) {
2534
2527
// Update the incoming value from the early exit.
2535
2528
VPValue *FirstActiveLane = EarlyExitB.createNaryOp (
2536
- VPInstruction::FirstActiveLane, {EarlyExitTakenCond }, nullptr ,
2529
+ VPInstruction::FirstActiveLane, {CondToEarlyExit }, nullptr ,
2537
2530
" first.active.lane" );
2538
2531
IncomingFromEarlyExit = EarlyExitB.createNaryOp (
2539
2532
Instruction::ExtractElement, {IncomingFromEarlyExit, FirstActiveLane},
0 commit comments