Skip to content

Commit 339dc95

Browse files
authored
[VPlan] Retain exit conditions and edges in initial VPlan (NFC). (#137709)
Update initial VPlan construction to include exit conditions and edges. The loop region is now first constructed without entry/exiting. Those are set after inserting the region in the CFG, to preserve the original predecessor/successor order of blocks. For now, all early exits are disconnected before forming the regions, but a follow-up will update uncountable exit handling to also happen here. This is required to enable VPlan predication and remove the dependence any IR BBs (#128420). PR: #137709
1 parent 81786b9 commit 339dc95

File tree

3 files changed

+58
-44
lines changed

3 files changed

+58
-44
lines changed

llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp

+48-41
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,6 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
182182
"Instruction shouldn't have been visited.");
183183

184184
if (auto *Br = dyn_cast<BranchInst>(Inst)) {
185-
if (TheLoop->getLoopLatch() == BB ||
186-
any_of(successors(BB),
187-
[this](BasicBlock *Succ) { return !TheLoop->contains(Succ); }))
188-
continue;
189-
190185
// Conditional branch instruction are represented using BranchOnCond
191186
// recipes.
192187
if (Br->isConditional()) {
@@ -251,6 +246,8 @@ std::unique_ptr<VPlan> PlainCFGBuilder::buildPlainCFG(
251246
DenseMap<VPBlockBase *, BasicBlock *> &VPB2IRBB) {
252247
VPIRBasicBlock *Entry = cast<VPIRBasicBlock>(Plan->getEntry());
253248
BB2VPBB[Entry->getIRBasicBlock()] = Entry;
249+
for (VPIRBasicBlock *ExitVPBB : Plan->getExitBlocks())
250+
BB2VPBB[ExitVPBB->getIRBasicBlock()] = ExitVPBB;
254251

255252
// 1. Scan the body of the loop in a topological order to visit each basic
256253
// block after having visited its predecessor basic blocks. Create a VPBB for
@@ -276,7 +273,6 @@ std::unique_ptr<VPlan> PlainCFGBuilder::buildPlainCFG(
276273
for (BasicBlock *BB : RPO) {
277274
// Create or retrieve the VPBasicBlock for this BB.
278275
VPBasicBlock *VPBB = getOrCreateVPBB(BB);
279-
Loop *LoopForBB = LI->getLoopFor(BB);
280276
// Set VPBB predecessors in the same order as they are in the incoming BB.
281277
setVPBBPredsFromBB(VPBB, BB);
282278

@@ -307,24 +303,12 @@ std::unique_ptr<VPlan> PlainCFGBuilder::buildPlainCFG(
307303
BasicBlock *IRSucc1 = BI->getSuccessor(1);
308304
VPBasicBlock *Successor0 = getOrCreateVPBB(IRSucc0);
309305
VPBasicBlock *Successor1 = getOrCreateVPBB(IRSucc1);
310-
311-
// Don't connect any blocks outside the current loop except the latches for
312-
// inner loops.
313-
// TODO: Also connect exit blocks during initial VPlan construction.
314-
if (LoopForBB == TheLoop || BB != LoopForBB->getLoopLatch()) {
315-
if (!LoopForBB->contains(IRSucc0)) {
316-
VPBB->setOneSuccessor(Successor1);
317-
continue;
318-
}
319-
if (!LoopForBB->contains(IRSucc1)) {
320-
VPBB->setOneSuccessor(Successor0);
321-
continue;
322-
}
323-
}
324-
325306
VPBB->setTwoSuccessors(Successor0, Successor1);
326307
}
327308

309+
for (auto *EB : Plan->getExitBlocks())
310+
setVPBBPredsFromBB(EB, EB->getIRBasicBlock());
311+
328312
// 2. The whole CFG has been built at this point so all the input Values must
329313
// have a VPlan counterpart. Fix VPlan header phi by adding their
330314
// corresponding VPlan operands.
@@ -424,22 +408,23 @@ static void createLoopRegion(VPlan &Plan, VPBlockBase *HeaderVPB) {
424408

425409
VPBlockUtils::disconnectBlocks(PreheaderVPBB, HeaderVPB);
426410
VPBlockUtils::disconnectBlocks(LatchVPBB, HeaderVPB);
427-
VPBlockBase *Succ = LatchVPBB->getSingleSuccessor();
428-
assert(LatchVPBB->getNumSuccessors() <= 1 &&
429-
"Latch has more than one successor");
430-
if (Succ)
431-
VPBlockUtils::disconnectBlocks(LatchVPBB, Succ);
432-
433-
auto *R = Plan.createVPRegionBlock(HeaderVPB, LatchVPBB, "",
434-
false /*isReplicator*/);
435-
// All VPBB's reachable shallowly from HeaderVPB belong to top level loop,
436-
// because VPlan is expected to end at top level latch disconnected above.
411+
VPBlockBase *LatchExitVPB = LatchVPBB->getSingleSuccessor();
412+
assert(LatchExitVPB && "Latch expected to be left with a single successor");
413+
414+
// Create an empty region first and insert it between PreheaderVPBB and
415+
// LatchExitVPB, taking care to preserve the original predecessor & successor
416+
// order of blocks. Set region entry and exiting after both HeaderVPB and
417+
// LatchVPBB have been disconnected from their predecessors/successors.
418+
auto *R = Plan.createVPRegionBlock("", false /*isReplicator*/);
419+
VPBlockUtils::insertOnEdge(LatchVPBB, LatchExitVPB, R);
420+
VPBlockUtils::disconnectBlocks(LatchVPBB, R);
421+
VPBlockUtils::connectBlocks(PreheaderVPBB, R);
422+
R->setEntry(HeaderVPB);
423+
R->setExiting(LatchVPBB);
424+
425+
// All VPBB's reachable shallowly from HeaderVPB belong to the current region.
437426
for (VPBlockBase *VPBB : vp_depth_first_shallow(HeaderVPB))
438427
VPBB->setParent(R);
439-
440-
VPBlockUtils::insertBlockAfter(R, PreheaderVPBB);
441-
if (Succ)
442-
VPBlockUtils::connectBlocks(R, Succ);
443428
}
444429

445430
// Add the necessary canonical IV and branch recipes required to control the
@@ -491,12 +476,34 @@ void VPlanTransforms::prepareForVectorization(VPlan &Plan, Type *InductionTy,
491476
VPBlockUtils::insertBlockAfter(VecPreheader, Plan.getEntry());
492477

493478
VPBasicBlock *MiddleVPBB = Plan.createVPBasicBlock("middle.block");
494-
VPBlockUtils::connectBlocks(LatchVPB, MiddleVPBB);
495-
LatchVPB->swapSuccessors();
479+
// The canonical LatchVPB has the header block as last successor. If it has
480+
// another successor, this successor is an exit block - insert middle block on
481+
// its edge. Otherwise, add middle block as another successor retaining header
482+
// as last.
483+
if (LatchVPB->getNumSuccessors() == 2) {
484+
VPBlockBase *LatchExitVPB = LatchVPB->getSuccessors()[0];
485+
VPBlockUtils::insertOnEdge(LatchVPB, LatchExitVPB, MiddleVPBB);
486+
} else {
487+
VPBlockUtils::connectBlocks(LatchVPB, MiddleVPBB);
488+
LatchVPB->swapSuccessors();
489+
}
496490

497491
addCanonicalIVRecipes(Plan, cast<VPBasicBlock>(HeaderVPB),
498492
cast<VPBasicBlock>(LatchVPB), InductionTy, IVDL);
499493

494+
// Disconnect all edges to exit blocks other than from the middle block.
495+
// TODO: VPlans with early exits should be explicitly converted to a form
496+
// exiting only via the latch here, including adjusting the exit condition,
497+
// instead of simply disconnecting the edges and adjusting the VPlan later.
498+
for (VPBlockBase *EB : Plan.getExitBlocks()) {
499+
for (VPBlockBase *Pred : to_vector(EB->getPredecessors())) {
500+
if (Pred == MiddleVPBB)
501+
continue;
502+
cast<VPBasicBlock>(Pred)->getTerminator()->eraseFromParent();
503+
VPBlockUtils::disconnectBlocks(Pred, EB);
504+
}
505+
}
506+
500507
// Create SCEV and VPValue for the trip count.
501508
// We use the symbolic max backedge-taken-count, which works also when
502509
// vectorizing loops with uncountable early exits.
@@ -523,6 +530,8 @@ void VPlanTransforms::prepareForVectorization(VPlan &Plan, Type *InductionTy,
523530
// 3) Otherwise, construct a runtime check.
524531

525532
if (!RequiresScalarEpilogueCheck) {
533+
if (auto *LatchExitVPB = MiddleVPBB->getSingleSuccessor())
534+
VPBlockUtils::disconnectBlocks(MiddleVPBB, LatchExitVPB);
526535
VPBlockUtils::connectBlocks(MiddleVPBB, ScalarPH);
527536
// The exit blocks are unreachable, remove their recipes to make sure no
528537
// users remain that may pessimize transforms.
@@ -533,10 +542,8 @@ void VPlanTransforms::prepareForVectorization(VPlan &Plan, Type *InductionTy,
533542
return;
534543
}
535544

536-
// The connection order corresponds to the operands of the conditional branch.
537-
BasicBlock *IRExitBlock = TheLoop->getUniqueLatchExitBlock();
538-
auto *VPExitBlock = Plan.getExitBlock(IRExitBlock);
539-
VPBlockUtils::connectBlocks(MiddleVPBB, VPExitBlock);
545+
// The connection order corresponds to the operands of the conditional branch,
546+
// with the middle block already connected to the exit block.
540547
VPBlockUtils::connectBlocks(MiddleVPBB, ScalarPH);
541548

542549
auto *ScalarLatchTerm = TheLoop->getLoopLatch()->getTerminator();

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ 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): outer.header
34+
; CHECK-NEXT: EMIT branch-on-cond ir<%outer.ec>
35+
; CHECK-NEXT: Successor(s): ir-bb<exit>, outer.header
36+
; CHECK-EMPTY:
37+
; CHECK-NEXT: ir-bb<exit>:
38+
; CHECK-NEXT: No successors
3539
; CHECK-NEXT: }
3640
entry:
3741
br label %outer.header

llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ TEST_F(VPlanHCFGTest, testBuildHCFGInnerLoop) {
5151
// Check that the region following the preheader consists of a block for the
5252
// original header and a separate latch.
5353
VPBasicBlock *VecBB = Plan->getVectorLoopRegion()->getEntryBasicBlock();
54-
EXPECT_EQ(10u, VecBB->size());
54+
EXPECT_EQ(11u, VecBB->size());
5555
EXPECT_EQ(0u, VecBB->getNumPredecessors());
5656
EXPECT_EQ(0u, VecBB->getNumSuccessors());
5757
EXPECT_EQ(VecBB->getParent()->getEntryBasicBlock(), VecBB);
@@ -129,6 +129,7 @@ compound=true
129129
" EMIT store ir\<%res\>, ir\<%arr.idx\>\l" +
130130
" EMIT ir\<%indvars.iv.next\> = add ir\<%indvars.iv\>, ir\<1\>\l" +
131131
" EMIT ir\<%exitcond\> = icmp ir\<%indvars.iv.next\>, ir\<%N\>\l" +
132+
" EMIT vp\<%3\> = not ir\<%exitcond\>\l" +
132133
" EMIT vp\<%index.next\> = add nuw vp\<%2\>, vp\<%0\>\l" +
133134
" EMIT branch-on-count vp\<%index.next\>, vp\<%1\>\l" +
134135
"No successors\l"
@@ -212,7 +213,7 @@ TEST_F(VPlanHCFGTest, testVPInstructionToVPRecipesInner) {
212213
// Check that the region following the preheader consists of a block for the
213214
// original header and a separate latch.
214215
VPBasicBlock *VecBB = Plan->getVectorLoopRegion()->getEntryBasicBlock();
215-
EXPECT_EQ(11u, VecBB->size());
216+
EXPECT_EQ(12u, VecBB->size());
216217
EXPECT_EQ(0u, VecBB->getNumPredecessors());
217218
EXPECT_EQ(0u, VecBB->getNumSuccessors());
218219
EXPECT_EQ(VecBB->getParent()->getEntryBasicBlock(), VecBB);
@@ -229,6 +230,7 @@ TEST_F(VPlanHCFGTest, testVPInstructionToVPRecipesInner) {
229230
EXPECT_NE(nullptr, dyn_cast<VPInstruction>(&*Iter++));
230231
EXPECT_NE(nullptr, dyn_cast<VPInstruction>(&*Iter++));
231232
EXPECT_NE(nullptr, dyn_cast<VPInstruction>(&*Iter++));
233+
EXPECT_NE(nullptr, dyn_cast<VPInstruction>(&*Iter++));
232234
EXPECT_EQ(VecBB->end(), Iter);
233235
}
234236

@@ -302,6 +304,7 @@ compound=true
302304
" EMIT store ir\<%res\>, ir\<%arr.idx\>\l" +
303305
" EMIT ir\<%iv.next\> = add ir\<%iv\>, ir\<1\>\l" +
304306
" EMIT ir\<%exitcond\> = icmp ir\<%iv.next\>, ir\<%N\>\l" +
307+
" EMIT vp\<%3\> = not ir\<%exitcond\>\l" +
305308
" EMIT vp\<%index.next\> = add nuw vp\<%2\>, vp\<%0\>\l" +
306309
" EMIT branch-on-count vp\<%index.next\>, vp\<%1\>\l" +
307310
"No successors\l"

0 commit comments

Comments
 (0)