Skip to content

Commit e347f11

Browse files
committed
[VPlan] Retain exit conditions and edges in initial VPlan (NFC).
Update initial VPlan construction to include exit conditions and edges. 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). This includes updates in a few places to use replaceSuccessor/replacePredecessor to preserve the order of predecessors and successors, to reduce the need of fixing up phi operand orderings. This unfortunately required making them public, not sure if there's a
1 parent edb690d commit e347f11

File tree

3 files changed

+44
-43
lines changed

3 files changed

+44
-43
lines changed

llvm/lib/Transforms/Vectorize/VPlan.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class VPBlockBase {
117117
Predecessors.erase(Pos);
118118
}
119119

120+
public:
120121
/// Remove \p Successor from the successors of this block.
121122
void removeSuccessor(VPBlockBase *Successor) {
122123
auto Pos = find(Successors, Successor);
@@ -129,8 +130,6 @@ class VPBlockBase {
129130
void replacePredecessor(VPBlockBase *Old, VPBlockBase *New) {
130131
auto I = find(Predecessors, Old);
131132
assert(I != Predecessors.end());
132-
assert(Old->getParent() == New->getParent() &&
133-
"replaced predecessor must have the same parent");
134133
*I = New;
135134
}
136135

llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp

+38-40
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ VPBasicBlock *PlainCFGBuilder::getOrCreateVPBB(BasicBlock *BB) {
113113
return VPBB;
114114
}
115115

116+
if (!TheLoop->contains(BB))
117+
return Plan->getExitBlock(BB);
118+
116119
// Create new VPBB.
117120
StringRef Name = BB->getName();
118121
LLVM_DEBUG(dbgs() << "Creating VPBasicBlock for " << Name << "\n");
@@ -146,14 +149,6 @@ bool PlainCFGBuilder::isExternalDef(Value *Val) {
146149
// Instruction definition is in outermost loop PH.
147150
return false;
148151

149-
// Check whether Instruction definition is in a loop exit.
150-
SmallVector<BasicBlock *> ExitBlocks;
151-
TheLoop->getExitBlocks(ExitBlocks);
152-
if (is_contained(ExitBlocks, InstParent)) {
153-
// Instruction definition is in outermost loop exit.
154-
return false;
155-
}
156-
157152
// Check whether Instruction definition is in loop body.
158153
return !TheLoop->contains(Inst);
159154
}
@@ -202,11 +197,6 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
202197
"Instruction shouldn't have been visited.");
203198

204199
if (auto *Br = dyn_cast<BranchInst>(Inst)) {
205-
if (TheLoop->getLoopLatch() == BB ||
206-
any_of(successors(BB),
207-
[this](BasicBlock *Succ) { return !TheLoop->contains(Succ); }))
208-
continue;
209-
210200
// Conditional branch instruction are represented using BranchOnCond
211201
// recipes.
212202
if (Br->isConditional()) {
@@ -296,7 +286,6 @@ std::unique_ptr<VPlan> PlainCFGBuilder::buildPlainCFG(
296286
for (BasicBlock *BB : RPO) {
297287
// Create or retrieve the VPBasicBlock for this BB.
298288
VPBasicBlock *VPBB = getOrCreateVPBB(BB);
299-
Loop *LoopForBB = LI->getLoopFor(BB);
300289
// Set VPBB predecessors in the same order as they are in the incoming BB.
301290
setVPBBPredsFromBB(VPBB, BB);
302291

@@ -327,24 +316,12 @@ std::unique_ptr<VPlan> PlainCFGBuilder::buildPlainCFG(
327316
BasicBlock *IRSucc1 = BI->getSuccessor(1);
328317
VPBasicBlock *Successor0 = getOrCreateVPBB(IRSucc0);
329318
VPBasicBlock *Successor1 = getOrCreateVPBB(IRSucc1);
330-
331-
// Don't connect any blocks outside the current loop except the latches for
332-
// inner loops.
333-
// TODO: Also connect exit blocks during initial VPlan construction.
334-
if (LoopForBB == TheLoop || BB != LoopForBB->getLoopLatch()) {
335-
if (!LoopForBB->contains(IRSucc0)) {
336-
VPBB->setOneSuccessor(Successor1);
337-
continue;
338-
}
339-
if (!LoopForBB->contains(IRSucc1)) {
340-
VPBB->setOneSuccessor(Successor0);
341-
continue;
342-
}
343-
}
344-
345319
VPBB->setTwoSuccessors(Successor0, Successor1);
346320
}
347321

322+
for (auto *EB : Plan->getExitBlocks())
323+
setVPBBPredsFromBB(EB, EB->getIRBasicBlock());
324+
348325
// 2. The whole CFG has been built at this point so all the input Values must
349326
// have a VPlan counterpart. Fix VPlan header phi by adding their
350327
// corresponding VPlan operands.
@@ -447,19 +424,21 @@ static void createLoopRegion(VPlan &Plan, VPBlockBase *HeaderVPB) {
447424
VPBlockBase *Succ = LatchVPBB->getSingleSuccessor();
448425
assert(LatchVPBB->getNumSuccessors() <= 1 &&
449426
"Latch has more than one successor");
450-
if (Succ)
451-
VPBlockUtils::disconnectBlocks(LatchVPBB, Succ);
427+
LatchVPBB->removeSuccessor(Succ);
452428

453429
auto *R = Plan.createVPRegionBlock(HeaderVPB, LatchVPBB, "",
454430
false /*isReplicator*/);
455431
// All VPBB's reachable shallowly from HeaderVPB belong to top level loop,
456432
// because VPlan is expected to end at top level latch disconnected above.
433+
SmallPtrSet<VPBlockBase *, 2> ExitBlocks(Plan.getExitBlocks().begin(),
434+
Plan.getExitBlocks().end());
457435
for (VPBlockBase *VPBB : vp_depth_first_shallow(HeaderVPB))
458-
VPBB->setParent(R);
436+
if (!ExitBlocks.contains(VPBB))
437+
VPBB->setParent(R);
459438

460439
VPBlockUtils::insertBlockAfter(R, PreheaderVPBB);
461-
if (Succ)
462-
VPBlockUtils::connectBlocks(R, Succ);
440+
R->setOneSuccessor(Succ);
441+
Succ->replacePredecessor(LatchVPBB, R);
463442
}
464443

465444
// Add the necessary canonical IV and branch recipes required to control the
@@ -511,12 +490,33 @@ void VPlanTransforms::prepareForVectorization(VPlan &Plan, Type *InductionTy,
511490
VPBlockUtils::insertBlockAfter(VecPreheader, Plan.getEntry());
512491

513492
VPBasicBlock *MiddleVPBB = Plan.createVPBasicBlock("middle.block");
514-
VPBlockUtils::connectBlocks(LatchVPB, MiddleVPBB);
515-
LatchVPB->swapSuccessors();
493+
VPBlockBase *LatchExitVPB = LatchVPB->getNumSuccessors() == 2
494+
? LatchVPB->getSuccessors()[0]
495+
: nullptr;
496+
if (LatchExitVPB) {
497+
LatchVPB->getSuccessors()[0] = MiddleVPBB;
498+
MiddleVPBB->setPredecessors({LatchVPB});
499+
MiddleVPBB->setSuccessors({LatchExitVPB});
500+
LatchExitVPB->replacePredecessor(LatchVPB, MiddleVPBB);
501+
} else {
502+
VPBlockUtils::connectBlocks(LatchVPB, MiddleVPBB);
503+
LatchVPB->swapSuccessors();
504+
}
516505

517506
addCanonicalIVRecipes(Plan, cast<VPBasicBlock>(HeaderVPB),
518507
cast<VPBasicBlock>(LatchVPB), InductionTy, IVDL);
519508

509+
// Disconnect all edges between exit blocks other than from the latch.
510+
// TODO: Uncountable exit blocks should be handled here.
511+
for (VPBlockBase *EB : to_vector(Plan.getExitBlocks())) {
512+
for (VPBlockBase *Pred : to_vector(EB->getPredecessors())) {
513+
if (Pred == MiddleVPBB)
514+
continue;
515+
cast<VPBasicBlock>(Pred)->getTerminator()->eraseFromParent();
516+
VPBlockUtils::disconnectBlocks(Pred, EB);
517+
}
518+
}
519+
520520
// Create SCEV and VPValue for the trip count.
521521
// We use the symbolic max backedge-taken-count, which works also when
522522
// vectorizing loops with uncountable early exits.
@@ -541,8 +541,9 @@ void VPlanTransforms::prepareForVectorization(VPlan &Plan, Type *InductionTy,
541541
// Thus if tail is to be folded, we know we don't need to run the
542542
// remainder and we can set the condition to true.
543543
// 3) Otherwise, construct a runtime check.
544-
545544
if (!RequiresScalarEpilogueCheck) {
545+
if (LatchExitVPB)
546+
VPBlockUtils::disconnectBlocks(MiddleVPBB, LatchExitVPB);
546547
VPBlockUtils::connectBlocks(MiddleVPBB, ScalarPH);
547548
// The exit blocks are unreachable, remove their recipes to make sure no
548549
// users remain that may pessimize transforms.
@@ -554,9 +555,6 @@ void VPlanTransforms::prepareForVectorization(VPlan &Plan, Type *InductionTy,
554555
}
555556

556557
// The connection order corresponds to the operands of the conditional branch.
557-
BasicBlock *IRExitBlock = TheLoop->getUniqueLatchExitBlock();
558-
auto *VPExitBlock = Plan.getExitBlock(IRExitBlock);
559-
VPBlockUtils::connectBlocks(MiddleVPBB, VPExitBlock);
560558
VPBlockUtils::connectBlocks(MiddleVPBB, ScalarPH);
561559

562560
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

0 commit comments

Comments
 (0)