Skip to content

Commit 6383a12

Browse files
committed
[VPlan] Refactor HCFG builder to preserve original vector latch (NFC).
Update HCFG builder to preserve the original latch block of the initial VPlan, ensuring there is always a latch. It also skips creating the BranchOnCond for the latch of the top-level loop, instead of removing it later. Exiting via the latch is controlled by later recipes. This further unifies HCFG construction and prepares for use to also build an initial VPlan (VPlan0) for inner loops.
1 parent de5ff8a commit 6383a12

File tree

5 files changed

+49
-34
lines changed

5 files changed

+49
-34
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9509,12 +9509,6 @@ VPlanPtr LoopVectorizationPlanner::buildVPlan(VFRange &Range) {
95099509
[this](PHINode *P) { return Legal->getIntOrFpInductionDescriptor(P); },
95109510
*PSE.getSE(), *TLI);
95119511

9512-
// Remove the existing terminator of the exiting block of the top-most region.
9513-
// A BranchOnCount will be added instead when adding the canonical IV recipes.
9514-
auto *Term =
9515-
Plan->getVectorLoopRegion()->getExitingBasicBlock()->getTerminator();
9516-
Term->eraseFromParent();
9517-
95189512
// Tail folding is not supported for outer loops, so the induction increment
95199513
// is guaranteed to not wrap.
95209514
bool HasNUW = true;

llvm/lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,6 +1628,9 @@ void LoopVectorizationPlanner::buildVPlans(ElementCount MinVF,
16281628
VFRange SubRange = {VF, MaxVFTimes2};
16291629
auto Plan = buildVPlan(SubRange);
16301630
VPlanTransforms::optimize(*Plan);
1631+
// Update the name of the latch of the top-level vector loop region region
1632+
// after optimizations which includes block folding.
1633+
Plan->getVectorLoopRegion()->getExiting()->setName("vector.latch");
16311634
VPlans.push_back(std::move(Plan));
16321635
VF = SubRange.End;
16331636
}

llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,11 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
292292
"Instruction shouldn't have been visited.");
293293

294294
if (auto *Br = dyn_cast<BranchInst>(Inst)) {
295+
if (TheLoop->getLoopLatch() == BB ||
296+
any_of(successors(BB),
297+
[this](BasicBlock *Succ) { return !TheLoop->contains(Succ); }))
298+
continue;
299+
295300
// Conditional branch instruction are represented using BranchOnCond
296301
// recipes.
297302
if (Br->isConditional()) {
@@ -356,11 +361,6 @@ void PlainCFGBuilder::buildPlainCFG() {
356361
VPBasicBlock *VectorLatchVPBB = TheRegion->getExitingBasicBlock();
357362
BB2VPBB[TheLoop->getHeader()] = VectorHeaderVPBB;
358363
VectorHeaderVPBB->clearSuccessors();
359-
VectorLatchVPBB->clearPredecessors();
360-
if (TheLoop->getHeader() != TheLoop->getLoopLatch())
361-
BB2VPBB[TheLoop->getLoopLatch()] = VectorLatchVPBB;
362-
else
363-
TheRegion->setExiting(VectorHeaderVPBB);
364364

365365
// 1. Scan the body of the loop in a topological order to visit each basic
366366
// block after having visited its predecessor basic blocks. Create a VPBB for
@@ -398,6 +398,13 @@ void PlainCFGBuilder::buildPlainCFG() {
398398
setRegionPredsFromBB(Region, BB);
399399
}
400400

401+
if (TheLoop->getLoopLatch() == BB) {
402+
VPBB->setOneSuccessor(VectorLatchVPBB);
403+
VectorLatchVPBB->clearPredecessors();
404+
VectorLatchVPBB->setPredecessors({VPBB});
405+
continue;
406+
}
407+
401408
// Set VPBB successors. We create empty VPBBs for successors if they don't
402409
// exist already. Recipes will be created when the successor is visited
403410
// during the RPO traversal.

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ define void @foo(i64 %n) {
3535
; CHECK-NEXT: EMIT branch-on-cond ir<%inner.ec>
3636
; CHECK-NEXT: No successors
3737
; CHECK-NEXT: }
38-
; CHECK-NEXT: Successor(s): vector.latch
38+
; CHECK-NEXT: Successor(s): outer.latch
3939
; CHECK-EMPTY:
40-
; CHECK-NEXT: vector.latch:
40+
; CHECK-NEXT: outer.latch:
4141
; CHECK-NEXT: EMIT ir<%outer.iv.next> = add ir<%outer.iv>, ir<1>
4242
; CHECK-NEXT: EMIT ir<%outer.ec> = icmp ir<%outer.iv.next>, ir<8>
43-
; CHECK-NEXT: EMIT branch-on-cond ir<%outer.ec>
43+
; CHECK-NEXT: Successor(s): vector.latch
44+
; CHECK-EMPTY:
45+
; CHECK-NEXT: vector.latch:
4446
; CHECK-NEXT: No successors
4547
; CHECK-NEXT: }
4648
; CHECK-NEXT: Successor(s): middle.block

llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,19 @@ TEST_F(VPlanHCFGTest, testBuildHCFGInnerLoop) {
4848
EXPECT_EQ(0u, Entry->getNumPredecessors());
4949
EXPECT_EQ(1u, Entry->getNumSuccessors());
5050

51-
// Check that the region following the preheader is a single basic-block
52-
// region (loop).
51+
// Check that the region following the preheader consists of a block for the
52+
// original header and a separate latch.
5353
VPBasicBlock *VecBB = Plan->getVectorLoopRegion()->getEntryBasicBlock();
54-
EXPECT_EQ(8u, VecBB->size());
54+
EXPECT_EQ(7u, VecBB->size());
5555
EXPECT_EQ(0u, VecBB->getNumPredecessors());
56-
EXPECT_EQ(0u, VecBB->getNumSuccessors());
56+
EXPECT_EQ(1u, VecBB->getNumSuccessors());
5757
EXPECT_EQ(VecBB->getParent()->getEntryBasicBlock(), VecBB);
58-
EXPECT_EQ(VecBB->getParent()->getExitingBasicBlock(), VecBB);
5958
EXPECT_EQ(&*Plan, VecBB->getPlan());
6059

60+
VPBlockBase *VecLatch = VecBB->getSingleSuccessor();
61+
EXPECT_EQ(VecLatch->getParent()->getExitingBasicBlock(), VecLatch);
62+
EXPECT_EQ(0u, VecLatch->getNumSuccessors());
63+
6164
auto Iter = VecBB->begin();
6265
VPWidenPHIRecipe *Phi = dyn_cast<VPWidenPHIRecipe>(&*Iter++);
6366
EXPECT_NE(nullptr, Phi);
@@ -127,29 +130,33 @@ compound=true
127130
" EMIT store ir\<%res\>, ir\<%arr.idx\>\l" +
128131
" EMIT ir\<%indvars.iv.next\> = add ir\<%indvars.iv\>, ir\<1\>\l" +
129132
" EMIT ir\<%exitcond\> = icmp ir\<%indvars.iv.next\>, ir\<%N\>\l" +
130-
" EMIT branch-on-cond ir\<%exitcond\>\l" +
133+
"Successor(s): vector.latch\l"
134+
]
135+
N2 -> N4 [ label=""]
136+
N4 [label =
137+
"vector.latch:\l" +
131138
"No successors\l"
132139
]
133140
}
134-
N2 -> N4 [ label="" ltail=cluster_N3]
135-
N4 [label =
141+
N4 -> N5 [ label="" ltail=cluster_N3]
142+
N5 [label =
136143
"middle.block:\l" +
137144
" EMIT vp\<%cmp.n\> = icmp eq ir\<%N\>, vp\<%0\>\l" +
138145
" EMIT branch-on-cond vp\<%cmp.n\>\l" +
139146
"Successor(s): ir-bb\<for.end\>, scalar.ph\l"
140147
]
141-
N4 -> N5 [ label="T"]
142-
N4 -> N6 [ label="F"]
143-
N5 [label =
148+
N5 -> N6 [ label="T"]
149+
N5 -> N7 [ label="F"]
150+
N6 [label =
144151
"ir-bb\<for.end\>:\l" +
145152
"No successors\l"
146153
]
147-
N6 [label =
154+
N7 [label =
148155
"scalar.ph:\l" +
149156
"Successor(s): ir-bb\<for.body\>\l"
150157
]
151-
N6 -> N7 [ label=""]
152-
N7 [label =
158+
N7 -> N8 [ label=""]
159+
N8 [label =
153160
"ir-bb\<for.body\>:\l" +
154161
" IR %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\l" +
155162
" IR %arr.idx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv\l" +
@@ -204,14 +211,17 @@ TEST_F(VPlanHCFGTest, testVPInstructionToVPRecipesInner) {
204211
EXPECT_EQ(0u, Entry->getNumPredecessors());
205212
EXPECT_EQ(1u, Entry->getNumSuccessors());
206213

207-
// Check that the region following the preheader is a single basic-block
208-
// region (loop).
214+
// Check that the region following the preheader consists of a block for the
215+
// original header and a separate latch.
209216
VPBasicBlock *VecBB = Plan->getVectorLoopRegion()->getEntryBasicBlock();
210-
EXPECT_EQ(8u, VecBB->size());
217+
EXPECT_EQ(7u, VecBB->size());
211218
EXPECT_EQ(0u, VecBB->getNumPredecessors());
212-
EXPECT_EQ(0u, VecBB->getNumSuccessors());
219+
EXPECT_EQ(1u, VecBB->getNumSuccessors());
213220
EXPECT_EQ(VecBB->getParent()->getEntryBasicBlock(), VecBB);
214-
EXPECT_EQ(VecBB->getParent()->getExitingBasicBlock(), VecBB);
221+
222+
VPBlockBase *VecLatch = VecBB->getSingleSuccessor();
223+
EXPECT_EQ(VecLatch->getParent()->getExitingBasicBlock(), VecLatch);
224+
EXPECT_EQ(0u, VecLatch->getNumSuccessors());
215225

216226
auto Iter = VecBB->begin();
217227
EXPECT_NE(nullptr, dyn_cast<VPWidenPHIRecipe>(&*Iter++));
@@ -221,7 +231,6 @@ TEST_F(VPlanHCFGTest, testVPInstructionToVPRecipesInner) {
221231
EXPECT_NE(nullptr, dyn_cast<VPWidenMemoryRecipe>(&*Iter++));
222232
EXPECT_NE(nullptr, dyn_cast<VPWidenRecipe>(&*Iter++));
223233
EXPECT_NE(nullptr, dyn_cast<VPWidenRecipe>(&*Iter++));
224-
EXPECT_NE(nullptr, dyn_cast<VPInstruction>(&*Iter++));
225234
EXPECT_EQ(VecBB->end(), Iter);
226235
}
227236

0 commit comments

Comments
 (0)