Skip to content

Commit c368b5d

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 d2ce88a commit c368b5d

File tree

4 files changed

+55
-44
lines changed

4 files changed

+55
-44
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9167,6 +9167,7 @@ void LoopVectorizationPlanner::buildVPlansWithVPRecipes(ElementCount MinVF,
91679167
// loop.
91689168
static void addCanonicalIVRecipes(VPlan &Plan, Type *IdxTy, bool HasNUW,
91699169
DebugLoc DL) {
9170+
using namespace VPlanPatternMatch;
91709171
Value *StartIdx = ConstantInt::get(IdxTy, 0);
91719172
auto *StartV = Plan.getOrAddLiveIn(StartIdx);
91729173

@@ -9176,7 +9177,16 @@ static void addCanonicalIVRecipes(VPlan &Plan, Type *IdxTy, bool HasNUW,
91769177
VPBasicBlock *Header = TopRegion->getEntryBasicBlock();
91779178
Header->insert(CanonicalIVPHI, Header->begin());
91789179

9179-
VPBuilder Builder(TopRegion->getExitingBasicBlock());
9180+
VPBasicBlock *LatchVPBB = TopRegion->getExitingBasicBlock();
9181+
// We are about to replace the branch to exit the region. Remove the original
9182+
// BranchOnCond, if there is any.
9183+
// TODO: Move canonical IV and BranchOnCount introduction to initial skeleton
9184+
// creation.
9185+
if (!LatchVPBB->empty() &&
9186+
match(&LatchVPBB->back(), m_BranchOnCond(m_VPValue())))
9187+
LatchVPBB->getTerminator()->eraseFromParent();
9188+
9189+
VPBuilder Builder(LatchVPBB);
91809190
// Add a VPInstruction to increment the scalar canonical IV by VF * UF.
91819191
auto *CanonicalIVIncrement = Builder.createOverflowingOp(
91829192
Instruction::Add, {CanonicalIVPHI, &Plan.getVFxUF()}, {HasNUW, false}, DL,

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 1 addition & 2 deletions
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

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ VPBasicBlock *PlainCFGBuilder::getOrCreateVPBB(BasicBlock *BB) {
112112
return VPBB;
113113
}
114114

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

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

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

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

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

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

459438
VPBlockUtils::insertBlockAfter(R, PreheaderVPBB);
460-
if (Succ)
461-
VPBlockUtils::connectBlocks(R, Succ);
439+
R->setOneSuccessor(Succ);
440+
Succ->replacePredecessor(LatchVPBB, R);
462441
}
463442

464443
void VPlanTransforms::prepareForVectorization(VPlan &Plan, Type *InductionTy,
@@ -476,8 +455,29 @@ void VPlanTransforms::prepareForVectorization(VPlan &Plan, Type *InductionTy,
476455
VPBlockUtils::insertBlockAfter(VecPreheader, Plan.getEntry());
477456

478457
VPBasicBlock *MiddleVPBB = Plan.createVPBasicBlock("middle.block");
479-
VPBlockUtils::connectBlocks(LatchVPB, MiddleVPBB);
480-
LatchVPB->swapSuccessors();
458+
VPBlockBase *LatchExitVPB = LatchVPB->getNumSuccessors() == 2
459+
? LatchVPB->getSuccessors()[0]
460+
: nullptr;
461+
if (LatchExitVPB) {
462+
LatchVPB->getSuccessors()[0] = MiddleVPBB;
463+
MiddleVPBB->setPredecessors({LatchVPB});
464+
MiddleVPBB->setSuccessors({LatchExitVPB});
465+
LatchExitVPB->replacePredecessor(LatchVPB, MiddleVPBB);
466+
} else {
467+
VPBlockUtils::connectBlocks(LatchVPB, MiddleVPBB);
468+
LatchVPB->swapSuccessors();
469+
}
470+
471+
// Disconnect all edges between exit blocks other than from the latch.
472+
// TODO: Uncountable exit blocks should be handled here.
473+
for (VPBlockBase *EB : to_vector(Plan.getExitBlocks())) {
474+
for (VPBlockBase *Pred : to_vector(EB->getPredecessors())) {
475+
if (Pred == MiddleVPBB)
476+
continue;
477+
cast<VPBasicBlock>(Pred)->getTerminator()->eraseFromParent();
478+
VPBlockUtils::disconnectBlocks(Pred, EB);
479+
}
480+
}
481481

482482
// Create SCEV and VPValue for the trip count.
483483
// We use the symbolic max backedge-taken-count, which works also when
@@ -503,8 +503,9 @@ void VPlanTransforms::prepareForVectorization(VPlan &Plan, Type *InductionTy,
503503
// Thus if tail is to be folded, we know we don't need to run the
504504
// remainder and we can set the condition to true.
505505
// 3) Otherwise, construct a runtime check.
506-
507506
if (!RequiresScalarEpilogueCheck) {
507+
if (LatchExitVPB)
508+
VPBlockUtils::disconnectBlocks(MiddleVPBB, LatchExitVPB);
508509
VPBlockUtils::connectBlocks(MiddleVPBB, ScalarPH);
509510
// The exit blocks are unreachable, remove their recipes to make sure no
510511
// users remain that may pessimize transforms.
@@ -516,9 +517,6 @@ void VPlanTransforms::prepareForVectorization(VPlan &Plan, Type *InductionTy,
516517
}
517518

518519
// The connection order corresponds to the operands of the conditional branch.
519-
BasicBlock *IRExitBlock = TheLoop->getUniqueLatchExitBlock();
520-
auto *VPExitBlock = Plan.getExitBlock(IRExitBlock);
521-
VPBlockUtils::connectBlocks(MiddleVPBB, VPExitBlock);
522520
VPBlockUtils::connectBlocks(MiddleVPBB, ScalarPH);
523521

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

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

Lines changed: 5 additions & 1 deletion
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)