Skip to content

Commit 05afa55

Browse files
committed
[VPlan] Add getPlan() to VPBlockBase.
This patch adds a getPlan accessor to VPBlockBase, which finds the entry block of the plan containing the block and returns the plan set for this block. VPBlockBase contains a VPlan pointer, but it should only be set for the entry block of a plan. This allows moving blocks without updating the pointer for each moved block and in the future we might introduce a parent relationship between plans and blocks, similar to the one in LLVM IR. Reviewers: rengolin, hsaito, fhahn, Ayal, dorit, gilr Reviewed By: gilr Differential Revision: https://reviews.llvm.org/D74445
1 parent 1d6fa41 commit 05afa55

File tree

6 files changed

+149
-2
lines changed

6 files changed

+149
-2
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7193,8 +7193,9 @@ VPlanPtr LoopVectorizationPlanner::buildVPlanWithVPRecipes(
71937193
// ---------------------------------------------------------------------------
71947194

71957195
// Create a dummy pre-entry VPBasicBlock to start building the VPlan.
7196+
auto Plan = std::make_unique<VPlan>();
71967197
VPBasicBlock *VPBB = new VPBasicBlock("Pre-Entry");
7197-
auto Plan = std::make_unique<VPlan>(VPBB);
7198+
Plan->setEntry(VPBB);
71987199

71997200
// Represent values that will have defs inside VPlan.
72007201
for (Value *V : NeedDef)

llvm/lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,32 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const VPValue &V) {
5656
return OS;
5757
}
5858

59+
// Get the top-most entry block of \p Start. This is the entry block of the
60+
// containing VPlan. This function is templated to support both const and non-const blocks
61+
template <typename T> static T *getPlanEntry(T *Start) {
62+
T *Next = Start;
63+
T *Current = Start;
64+
while ((Next = Next->getParent()))
65+
Current = Next;
66+
67+
SmallSetVector<T *, 8> WorkList;
68+
WorkList.insert(Current);
69+
70+
for (unsigned i = 0; i < WorkList.size(); i++) {
71+
T *Current = WorkList[i];
72+
if (Current->getNumPredecessors() == 0)
73+
return Current;
74+
auto &Predecessors = Current->getPredecessors();
75+
WorkList.insert(Predecessors.begin(), Predecessors.end());
76+
}
77+
78+
llvm_unreachable("VPlan without any entry node without predecessors");
79+
}
80+
81+
VPlan *VPBlockBase::getPlan() { return getPlanEntry(this)->Plan; }
82+
83+
const VPlan *VPBlockBase::getPlan() const { return getPlanEntry(this)->Plan; }
84+
5985
/// \return the VPBasicBlock that is the entry of Block, possibly indirectly.
6086
const VPBasicBlock *VPBlockBase::getEntryBasicBlock() const {
6187
const VPBlockBase *Block = this;
@@ -71,6 +97,12 @@ VPBasicBlock *VPBlockBase::getEntryBasicBlock() {
7197
return cast<VPBasicBlock>(Block);
7298
}
7399

100+
void VPBlockBase::setPlan(VPlan *ParentPlan) {
101+
assert(ParentPlan->getEntry() == this &&
102+
"Can only set plan on its entry block.");
103+
Plan = ParentPlan;
104+
}
105+
74106
/// \return the VPBasicBlock that is the exit of Block, possibly indirectly.
75107
const VPBasicBlock *VPBlockBase::getExitBasicBlock() const {
76108
const VPBlockBase *Block = this;

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,10 @@ class VPBlockBase {
365365
/// Current block predicate - null if the block does not need a predicate.
366366
VPValue *Predicate = nullptr;
367367

368+
/// VPlan containing the block. Can only be set on the entry block of the
369+
/// plan.
370+
VPlan *Plan = nullptr;
371+
368372
/// Add \p Successor as the last successor to this block.
369373
void appendSuccessor(VPBlockBase *Successor) {
370374
assert(Successor && "Cannot add nullptr successor!");
@@ -418,6 +422,14 @@ class VPBlockBase {
418422
VPRegionBlock *getParent() { return Parent; }
419423
const VPRegionBlock *getParent() const { return Parent; }
420424

425+
/// \return A pointer to the plan containing the current block.
426+
VPlan *getPlan();
427+
const VPlan *getPlan() const;
428+
429+
/// Sets the pointer of the plan containing the block. The block must be the
430+
/// entry block into the VPlan.
431+
void setPlan(VPlan *ParentPlan);
432+
421433
void setParent(VPRegionBlock *P) { Parent = P; }
422434

423435
/// \return the VPBasicBlock that is the entry of this VPBlockBase,
@@ -1402,7 +1414,11 @@ class VPlan {
14021414
VPBlockBase *getEntry() { return Entry; }
14031415
const VPBlockBase *getEntry() const { return Entry; }
14041416

1405-
VPBlockBase *setEntry(VPBlockBase *Block) { return Entry = Block; }
1417+
VPBlockBase *setEntry(VPBlockBase *Block) {
1418+
Entry = Block;
1419+
Block->setPlan(this);
1420+
return Entry;
1421+
}
14061422

14071423
/// The backedge taken count of the original loop.
14081424
VPValue *getOrCreateBackedgeTakenCount() {

llvm/unittests/Transforms/Vectorize/VPlanHCFGTest.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ TEST_F(VPlanHCFGTest, testBuildHCFGInnerLoop) {
5050
EXPECT_EQ(7u, VecBB->size());
5151
EXPECT_EQ(2u, VecBB->getNumPredecessors());
5252
EXPECT_EQ(2u, VecBB->getNumSuccessors());
53+
EXPECT_EQ(&*Plan, VecBB->getPlan());
5354

5455
auto Iter = VecBB->begin();
5556
VPInstruction *Phi = dyn_cast<VPInstruction>(&*Iter++);

llvm/unittests/Transforms/Vectorize/VPlanPredicatorTest.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,13 @@ TEST_F(VPlanPredicatorTest, BasicPredicatorTest) {
102102
EXPECT_EQ(InnerLoopLinSucc, OuterIf);
103103
EXPECT_EQ(OuterIfLinSucc, InnerIf);
104104
EXPECT_EQ(InnerIfLinSucc, InnerLoopLatch);
105+
106+
// Check that the containing VPlan is set correctly.
107+
EXPECT_EQ(&*Plan, InnerLoopLinSucc->getPlan());
108+
EXPECT_EQ(&*Plan, OuterIfLinSucc->getPlan());
109+
EXPECT_EQ(&*Plan, InnerIfLinSucc->getPlan());
110+
EXPECT_EQ(&*Plan, InnerIf->getPlan());
111+
EXPECT_EQ(&*Plan, InnerLoopLatch->getPlan());
105112
}
106113

107114
// Test generation of Not and Or during predication.

llvm/unittests/Transforms/Vectorize/VPlanTest.cpp

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,95 @@ TEST(VPInstructionTest, moveAfter) {
8686
EXPECT_EQ(I3->getParent(), I4->getParent());
8787
}
8888

89+
TEST(VPBasicBlockTest, getPlan) {
90+
{
91+
VPBasicBlock *VPBB1 = new VPBasicBlock();
92+
VPBasicBlock *VPBB2 = new VPBasicBlock();
93+
VPBasicBlock *VPBB3 = new VPBasicBlock();
94+
VPBasicBlock *VPBB4 = new VPBasicBlock();
95+
96+
// VPBB1
97+
// / \
98+
// VPBB2 VPBB3
99+
// \ /
100+
// VPBB4
101+
VPBlockUtils::connectBlocks(VPBB1, VPBB2);
102+
VPBlockUtils::connectBlocks(VPBB1, VPBB3);
103+
VPBlockUtils::connectBlocks(VPBB2, VPBB4);
104+
VPBlockUtils::connectBlocks(VPBB3, VPBB4);
105+
106+
VPlan Plan;
107+
Plan.setEntry(VPBB1);
108+
109+
EXPECT_EQ(&Plan, VPBB1->getPlan());
110+
EXPECT_EQ(&Plan, VPBB2->getPlan());
111+
EXPECT_EQ(&Plan, VPBB3->getPlan());
112+
EXPECT_EQ(&Plan, VPBB4->getPlan());
113+
}
114+
115+
{
116+
// Region block is entry into VPlan.
117+
VPBasicBlock *R1BB1 = new VPBasicBlock();
118+
VPBasicBlock *R1BB2 = new VPBasicBlock();
119+
VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB2, "R1");
120+
VPBlockUtils::connectBlocks(R1BB1, R1BB2);
121+
122+
VPlan Plan;
123+
Plan.setEntry(R1);
124+
EXPECT_EQ(&Plan, R1->getPlan());
125+
EXPECT_EQ(&Plan, R1BB1->getPlan());
126+
EXPECT_EQ(&Plan, R1BB2->getPlan());
127+
}
128+
129+
{
130+
// VPBasicBlock is the entry into the VPlan, followed by a region.
131+
VPBasicBlock *R1BB1 = new VPBasicBlock();
132+
VPBasicBlock *R1BB2 = new VPBasicBlock();
133+
VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB2, "R1");
134+
VPBlockUtils::connectBlocks(R1BB1, R1BB2);
135+
136+
VPBasicBlock *VPBB1 = new VPBasicBlock();
137+
VPBlockUtils::connectBlocks(VPBB1, R1);
138+
139+
VPlan Plan;
140+
Plan.setEntry(VPBB1);
141+
EXPECT_EQ(&Plan, VPBB1->getPlan());
142+
EXPECT_EQ(&Plan, R1->getPlan());
143+
EXPECT_EQ(&Plan, R1BB1->getPlan());
144+
EXPECT_EQ(&Plan, R1BB2->getPlan());
145+
}
146+
147+
{
148+
VPBasicBlock *R1BB1 = new VPBasicBlock();
149+
VPBasicBlock *R1BB2 = new VPBasicBlock();
150+
VPRegionBlock *R1 = new VPRegionBlock(R1BB1, R1BB2, "R1");
151+
VPBlockUtils::connectBlocks(R1BB1, R1BB2);
152+
153+
VPBasicBlock *R2BB1 = new VPBasicBlock();
154+
VPBasicBlock *R2BB2 = new VPBasicBlock();
155+
VPRegionBlock *R2 = new VPRegionBlock(R2BB1, R2BB2, "R2");
156+
VPBlockUtils::connectBlocks(R2BB1, R2BB2);
157+
158+
VPBasicBlock *VPBB1 = new VPBasicBlock();
159+
VPBlockUtils::connectBlocks(VPBB1, R1);
160+
VPBlockUtils::connectBlocks(VPBB1, R2);
161+
162+
VPBasicBlock *VPBB2 = new VPBasicBlock();
163+
VPBlockUtils::connectBlocks(R1, VPBB2);
164+
VPBlockUtils::connectBlocks(R2, VPBB2);
165+
166+
VPlan Plan;
167+
Plan.setEntry(VPBB1);
168+
EXPECT_EQ(&Plan, VPBB1->getPlan());
169+
EXPECT_EQ(&Plan, R1->getPlan());
170+
EXPECT_EQ(&Plan, R1BB1->getPlan());
171+
EXPECT_EQ(&Plan, R1BB2->getPlan());
172+
EXPECT_EQ(&Plan, R2->getPlan());
173+
EXPECT_EQ(&Plan, R2BB1->getPlan());
174+
EXPECT_EQ(&Plan, R2BB2->getPlan());
175+
EXPECT_EQ(&Plan, VPBB2->getPlan());
176+
}
177+
}
178+
89179
} // namespace
90180
} // namespace llvm

0 commit comments

Comments
 (0)