Skip to content

Commit a6a8906

Browse files
committed
[VPlan] Retain exit conditions early
1 parent 2477756 commit a6a8906

File tree

6 files changed

+89
-53
lines changed

6 files changed

+89
-53
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

+29-6
Original file line numberDiff line numberDiff line change
@@ -9324,6 +9324,24 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
93249324
bool HasNUW = !IVUpdateMayOverflow || Style == TailFoldingStyle::None;
93259325
addCanonicalIVRecipes(*Plan, Legal->getWidestInductionType(), HasNUW, DL);
93269326

9327+
if (auto *UncountableExitingBlock =
9328+
Legal->getUncountableEarlyExitingBlock()) {
9329+
VPlanTransforms::runPass(VPlanTransforms::handleUncountableEarlyExit, *Plan,
9330+
*PSE.getSE(), OrigLoop, UncountableExitingBlock);
9331+
} else {
9332+
SmallPtrSet<VPBlockBase *, 2> ExitBlocks(Plan->getExitBlocks().begin(),
9333+
Plan->getExitBlocks().end());
9334+
for (VPBlockBase *VPBB : to_vector(
9335+
vp_depth_first_shallow(Plan->getVectorLoopRegion()->getEntry()))) {
9336+
for (VPBlockBase *EB : ExitBlocks) {
9337+
if (is_contained(VPBB->getSuccessors(), EB)) {
9338+
cast<VPBasicBlock>(VPBB)->getTerminator()->eraseFromParent();
9339+
VPBlockUtils::disconnectBlocks(VPBB, EB);
9340+
}
9341+
}
9342+
}
9343+
}
9344+
93279345
VPRecipeBuilder RecipeBuilder(*Plan, OrigLoop, TLI, &TTI, Legal, CM, PSE,
93289346
Builder);
93299347

@@ -9502,12 +9520,6 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
95029520
R->setOperand(1, WideIV->getStepValue());
95039521
}
95049522

9505-
if (auto *UncountableExitingBlock =
9506-
Legal->getUncountableEarlyExitingBlock()) {
9507-
VPlanTransforms::runPass(VPlanTransforms::handleUncountableEarlyExit, *Plan,
9508-
*PSE.getSE(), OrigLoop, UncountableExitingBlock,
9509-
RecipeBuilder);
9510-
}
95119523
DenseMap<VPValue *, VPValue *> IVEndValues;
95129524
addScalarResumePhis(RecipeBuilder, *Plan, IVEndValues);
95139525
SetVector<VPIRInstruction *> ExitUsersToFix =
@@ -9604,6 +9616,17 @@ VPlanPtr LoopVectorizationPlanner::tryToBuildVPlan(VFRange &Range) {
96049616
auto Plan = VPlanTransforms::buildPlainCFG(OrigLoop, *LI, VPB2IRBB);
96059617
VPlanTransforms::introduceTopLevelVectorLoopRegion(
96069618
*Plan, Legal->getWidestInductionType(), PSE, true, false, OrigLoop);
9619+
SmallPtrSet<VPBlockBase *, 2> ExitBlocks(Plan->getExitBlocks().begin(),
9620+
Plan->getExitBlocks().end());
9621+
for (VPBlockBase *VPBB : to_vector(
9622+
vp_depth_first_shallow(Plan->getVectorLoopRegion()->getEntry()))) {
9623+
for (VPBlockBase *EB : ExitBlocks) {
9624+
if (is_contained(VPBB->getSuccessors(), EB)) {
9625+
cast<VPBasicBlock>(VPBB)->getTerminator()->eraseFromParent();
9626+
VPBlockUtils::disconnectBlocks(VPBB, EB);
9627+
}
9628+
}
9629+
}
96079630

96089631
for (ElementCount VF : Range)
96099632
Plan->addVF(VF);

llvm/lib/Transforms/Vectorize/VPlan.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ VPlan::VPlan(Loop *L) {
855855
ScalarHeader = createVPIRBasicBlock(L->getHeader());
856856

857857
SmallVector<BasicBlock *> IRExitBlocks;
858-
L->getExitBlocks(IRExitBlocks);
858+
L->getUniqueExitBlocks(IRExitBlocks);
859859
for (BasicBlock *EB : IRExitBlocks)
860860
ExitBlocks.push_back(createVPIRBasicBlock(EB));
861861
}

llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp

+30-31
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ VPBasicBlock *PlainCFGBuilder::getOrCreateVPBB(BasicBlock *BB) {
123123
return VPBB;
124124
}
125125

126+
if (!TheLoop->contains(BB))
127+
return Plan.getExitBlock(BB);
128+
126129
// Create new VPBB.
127130
StringRef Name = isHeaderBB(BB, TheLoop) ? "vector.body" : BB->getName();
128131
LLVM_DEBUG(dbgs() << "Creating VPBasicBlock for " << Name << "\n");
@@ -156,14 +159,6 @@ bool PlainCFGBuilder::isExternalDef(Value *Val) {
156159
// Instruction definition is in outermost loop PH.
157160
return false;
158161

159-
// Check whether Instruction definition is in a loop exit.
160-
SmallVector<BasicBlock *> ExitBlocks;
161-
TheLoop->getExitBlocks(ExitBlocks);
162-
if (is_contained(ExitBlocks, InstParent)) {
163-
// Instruction definition is in outermost loop exit.
164-
return false;
165-
}
166-
167162
// Check whether Instruction definition is in loop body.
168163
return !TheLoop->contains(Inst);
169164
}
@@ -212,11 +207,8 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
212207
"Instruction shouldn't have been visited.");
213208

214209
if (auto *Br = dyn_cast<BranchInst>(Inst)) {
215-
if (TheLoop->getLoopLatch() == BB ||
216-
any_of(successors(BB),
217-
[this](BasicBlock *Succ) { return !TheLoop->contains(Succ); }))
210+
if (TheLoop->getLoopLatch() == BB)
218211
continue;
219-
220212
// Conditional branch instruction are represented using BranchOnCond
221213
// recipes.
222214
if (Br->isConditional()) {
@@ -319,6 +311,13 @@ void PlainCFGBuilder::buildPlainCFG(
319311
if (BB == TheLoop->getLoopLatch()) {
320312
VPBasicBlock *HeaderVPBB = getOrCreateVPBB(LoopForBB->getHeader());
321313
VPBlockUtils::connectBlocks(VPBB, HeaderVPBB);
314+
assert(isa<BranchInst>(BB->getTerminator()) && "latch must be terminated by branch"
315+
);
316+
for (BasicBlock *IRSucc : successors(BB)) {
317+
VPBasicBlock *VPSucc = getOrCreateVPBB(IRSucc);
318+
if (VPSucc != HeaderVPBB)
319+
VPBB->getSuccessors().push_back(VPSucc);
320+
}
322321
continue;
323322
}
324323

@@ -349,24 +348,12 @@ void PlainCFGBuilder::buildPlainCFG(
349348
BasicBlock *IRSucc1 = BI->getSuccessor(1);
350349
VPBasicBlock *Successor0 = getOrCreateVPBB(IRSucc0);
351350
VPBasicBlock *Successor1 = getOrCreateVPBB(IRSucc1);
352-
353-
// Don't connect any blocks outside the current loop except the latch, which
354-
// is handled below.
355-
if (LoopForBB &&
356-
(LoopForBB == TheLoop || BB != LoopForBB->getLoopLatch())) {
357-
if (!LoopForBB->contains(IRSucc0)) {
358-
VPBB->setOneSuccessor(Successor1);
359-
continue;
360-
}
361-
if (!LoopForBB->contains(IRSucc1)) {
362-
VPBB->setOneSuccessor(Successor0);
363-
continue;
364-
}
365-
}
366-
367351
VPBB->setTwoSuccessors(Successor0, Successor1);
368352
}
369353

354+
for (auto *EB : Plan.getExitBlocks()) {
355+
setVPBBPredsFromBB(EB, EB->getIRBasicBlock());
356+
}
370357
// 2. The whole CFG has been built at this point so all the input Values must
371358
// have a VPlan counterpart. Fix VPlan header phi by adding their
372359
// corresponding VPlan operands.
@@ -448,6 +435,11 @@ void VPlanTransforms::introduceTopLevelVectorLoopRegion(
448435
VPBasicBlock *OriginalLatch =
449436
cast<VPBasicBlock>(HeaderVPBB->getSinglePredecessor());
450437
VPBlockUtils::disconnectBlocks(OriginalLatch, HeaderVPBB);
438+
if (auto *RemainingSucc = OriginalLatch->getSingleSuccessor())
439+
VPBlockUtils::disconnectBlocks(OriginalLatch,
440+
RemainingSucc);
441+
else
442+
assert(OriginalLatch->getSuccessors().empty() && "Unsupported number of successors");
451443
VPBasicBlock *VecPreheader = Plan.createVPBasicBlock("vector.ph");
452444
VPBlockUtils::connectBlocks(Plan.getEntry(), VecPreheader);
453445
assert(OriginalLatch->getNumSuccessors() == 0 &&
@@ -473,8 +465,12 @@ void VPlanTransforms::introduceTopLevelVectorLoopRegion(
473465
HeaderVPBB, LatchVPBB, "vector loop", false /*isReplicator*/);
474466
// All VPBB's reachable shallowly from HeaderVPBB belong to top level loop,
475467
// because VPlan is expected to end at top level latch.
476-
for (VPBlockBase *VPBB : vp_depth_first_shallow(HeaderVPBB))
477-
VPBB->setParent(TopRegion);
468+
SmallPtrSet<VPBlockBase *, 2> ExitBlocks(Plan.getExitBlocks().begin(),
469+
Plan.getExitBlocks().end());
470+
for (VPBlockBase *VPBB : vp_depth_first_shallow(HeaderVPBB)) {
471+
if (!ExitBlocks.contains(VPBB))
472+
VPBB->setParent(TopRegion);
473+
}
478474

479475
VPBlockUtils::insertBlockAfter(TopRegion, VecPreheader);
480476
VPBasicBlock *MiddleVPBB = Plan.createVPBasicBlock("middle.block");
@@ -503,7 +499,7 @@ void VPlanTransforms::introduceTopLevelVectorLoopRegion(
503499
BasicBlock *IRExitBlock = TheLoop->getUniqueLatchExitBlock();
504500
auto *VPExitBlock = Plan.getExitBlock(IRExitBlock);
505501
// The connection order corresponds to the operands of the conditional branch.
506-
VPBlockUtils::insertBlockAfter(VPExitBlock, MiddleVPBB);
502+
VPBlockUtils::connectBlocks(MiddleVPBB, VPExitBlock);
507503
VPBlockUtils::connectBlocks(MiddleVPBB, ScalarPH);
508504

509505
auto *ScalarLatchTerm = TheLoop->getLoopLatch()->getTerminator();
@@ -522,5 +518,8 @@ void VPlanTransforms::introduceTopLevelVectorLoopRegion(
522518
Builder.createNaryOp(VPInstruction::BranchOnCond, {Cmp},
523519
ScalarLatchTerm->getDebugLoc());
524520

525-
introduceInnerLoopRegions(Plan);
521+
if (all_of(Plan.getExitBlocks(), [MiddleVPBB](VPBlockBase *EB) {
522+
return EB->getSinglePredecessor() == MiddleVPBB;
523+
}))
524+
introduceInnerLoopRegions(Plan);
526525
}

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

+24-12
Original file line numberDiff line numberDiff line change
@@ -2275,7 +2275,7 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan) {
22752275

22762276
void VPlanTransforms::handleUncountableEarlyExit(
22772277
VPlan &Plan, ScalarEvolution &SE, Loop *OrigLoop,
2278-
BasicBlock *UncountableExitingBlock, VPRecipeBuilder &RecipeBuilder) {
2278+
BasicBlock *UncountableExitingBlock) {
22792279
VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
22802280
auto *LatchVPBB = cast<VPBasicBlock>(LoopRegion->getExiting());
22812281
VPBuilder Builder(LatchVPBB->getTerminator());
@@ -2286,17 +2286,29 @@ void VPlanTransforms::handleUncountableEarlyExit(
22862286
// tracks if the uncountable early exit has been taken. Also split the middle
22872287
// block and have it conditionally branch to the early exit block if
22882288
// EarlyExitTaken.
2289-
auto *EarlyExitingBranch =
2290-
cast<BranchInst>(UncountableExitingBlock->getTerminator());
2291-
BasicBlock *TrueSucc = EarlyExitingBranch->getSuccessor(0);
2292-
BasicBlock *FalseSucc = EarlyExitingBranch->getSuccessor(1);
2293-
BasicBlock *EarlyExitIRBB =
2294-
!OrigLoop->contains(TrueSucc) ? TrueSucc : FalseSucc;
2295-
VPIRBasicBlock *VPEarlyExitBlock = Plan.getExitBlock(EarlyExitIRBB);
2296-
2297-
VPValue *EarlyExitNotTakenCond = RecipeBuilder.getBlockInMask(
2298-
OrigLoop->contains(TrueSucc) ? TrueSucc : FalseSucc);
2299-
auto *EarlyExitTakenCond = Builder.createNot(EarlyExitNotTakenCond);
2289+
VPBasicBlock *EEB = nullptr;
2290+
for (auto *EB : Plan.getExitBlocks()) {
2291+
for (VPBlockBase *Pred : EB->getPredecessors()) {
2292+
if (Pred != MiddleVPBB) {
2293+
EEB = cast<VPBasicBlock>(Pred);
2294+
break;
2295+
}
2296+
}
2297+
}
2298+
2299+
VPBlockBase *TrueSucc = EEB->getSuccessors()[0];
2300+
VPBlockBase *FalseSucc = EEB->getSuccessors()[1];
2301+
auto *VPEarlyExitBlock =
2302+
cast<VPIRBasicBlock>(TrueSucc->getParent() ? FalseSucc : TrueSucc);
2303+
2304+
VPValue *EarlyExitCond = EEB->getTerminator()->getOperand(0);
2305+
auto *EarlyExitTakenCond = TrueSucc == VPEarlyExitBlock
2306+
? EarlyExitCond
2307+
: Builder.createNot(EarlyExitCond);
2308+
2309+
EEB->getTerminator()->eraseFromParent();
2310+
VPBlockUtils::disconnectBlocks(EEB, VPEarlyExitBlock);
2311+
23002312
IsEarlyExitTaken =
23012313
Builder.createNaryOp(VPInstruction::AnyOf, {EarlyExitTakenCond});
23022314

llvm/lib/Transforms/Vectorize/VPlanTransforms.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,7 @@ struct VPlanTransforms {
177177
/// if taken.
178178
static void handleUncountableEarlyExit(VPlan &Plan, ScalarEvolution &SE,
179179
Loop *OrigLoop,
180-
BasicBlock *UncountableExitingBlock,
181-
VPRecipeBuilder &RecipeBuilder);
180+
BasicBlock *UncountableExitingBlock);
182181

183182
/// Lower abstract recipes to concrete ones, that can be codegen'd.
184183
static void convertToConcreteRecipes(VPlan &Plan);

llvm/test/Transforms/LoopVectorize/vplan-printing-outer-loop.ll

+4-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ define void @foo(i64 %n) {
3131
; CHECK-NEXT: outer.latch:
3232
; CHECK-NEXT: EMIT ir<%outer.iv.next> = add ir<%outer.iv>, ir<1>
3333
; CHECK-NEXT: EMIT ir<%outer.ec> = icmp ir<%outer.iv.next>, ir<8>
34-
; CHECK-NEXT: Successor(s): vector.body
34+
; CHECK-NEXT: Successor(s): vector.body, ir-bb<exit>
35+
; CHECK-EMPTY:
36+
; CHECK-NEXT: ir-bb<exit>:
37+
; CHECK-NEXT: No successors
3538
; CHECK-NEXT: }
3639
entry:
3740
br label %outer.header

0 commit comments

Comments
 (0)