@@ -2461,63 +2461,56 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan,
24612461}
24622462
24632463void 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;
24892467
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});
24902496 VPBasicBlock *NewMiddle = Plan.createVPBasicBlock (" middle.split" );
24912497 VPBasicBlock *VectorEarlyExitVPBB =
24922498 Plan.createVPBasicBlock (" vector.early.exit" );
2493- VPBlockUtils::insertOnEdge (LoopRegion , MiddleVPBB, NewMiddle);
2499+ VPBlockUtils::insertOnEdge (LatchVPBB , MiddleVPBB, NewMiddle);
24942500 VPBlockUtils::connectBlocks (NewMiddle, VectorEarlyExitVPBB);
24952501 NewMiddle->swapSuccessors ();
24962502
2497- VPBlockUtils::connectBlocks (VectorEarlyExitVPBB, VPEarlyExitBlock );
2503+ VPBlockUtils::connectBlocks (VectorEarlyExitVPBB, EarlyExitVPBB );
24982504
24992505 // Update the exit phis in the early exit block.
25002506 VPBuilder MiddleBuilder (NewMiddle);
25012507 VPBuilder EarlyExitB (VectorEarlyExitVPBB);
2502- for (VPRecipeBase &R : VPEarlyExitBlock ->phis ()) {
2508+ for (VPRecipeBase &R : EarlyExitVPBB ->phis ()) {
25032509 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
25052511 // a single predecessor and 1 if it has two.
25062512 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 ) {
25212514 // The first of two operands corresponds to the latch exit, via MiddleVPBB
25222515 // predecessor. Extract its last lane.
25232516 ExitIRI->extractLastLaneOfFirstOperand (MiddleBuilder);
@@ -2533,7 +2526,7 @@ void VPlanTransforms::handleUncountableEarlyExit(
25332526 LoopVectorizationPlanner::getDecisionAndClampRange (IsVector, Range)) {
25342527 // Update the incoming value from the early exit.
25352528 VPValue *FirstActiveLane = EarlyExitB.createNaryOp (
2536- VPInstruction::FirstActiveLane, {EarlyExitTakenCond }, nullptr ,
2529+ VPInstruction::FirstActiveLane, {CondToEarlyExit }, nullptr ,
25372530 " first.active.lane" );
25382531 IncomingFromEarlyExit = EarlyExitB.createNaryOp (
25392532 Instruction::ExtractElement, {IncomingFromEarlyExit, FirstActiveLane},
0 commit comments