Skip to content

Commit 29b7487

Browse files
committed
!fixup address latest comments, thanks
1 parent decf567 commit 29b7487

File tree

4 files changed

+39
-32
lines changed

4 files changed

+39
-32
lines changed

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,13 @@ class VPBlockBase {
304304
/// Remove all the successors of this block.
305305
void clearSuccessors() { Successors.clear(); }
306306

307+
/// Swap predecessors of the block. The block must have exactly 2
308+
/// predecessors.
309+
void swapPredecessors() {
310+
assert(Predecessors.size() == 2 && "must have 2 predecessors to swap");
311+
std::swap(Predecessors[0], Predecessors[1]);
312+
}
313+
307314
/// Swap successors of the block. The block must have exactly 2 successors.
308315
// TODO: This should be part of introducing conditional branch recipes rather
309316
// than being independent.

llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,48 +24,40 @@ using namespace llvm;
2424
/// Checks if \p HeaderVPB is a loop header block in the plain CFG; that is, it
2525
/// has exactly 2 predecessors (preheader and latch), where the block
2626
/// dominates the latch and the preheader dominates the block. If it is a
27-
/// header block, returns a pair with the corresponding preheader and latch
28-
/// blocks. Otherwise return std::nullopt.
29-
static std::optional<std::pair<VPBasicBlock *, VPBasicBlock *>>
30-
getPreheaderAndLatch(VPBlockBase *HeaderVPB, const VPDominatorTree &VPDT) {
27+
/// header block return true, making sure the preheader appears first and
28+
/// the latch second. Otherwise return false.
29+
static bool canonicalHeader(VPBlockBase *HeaderVPB,
30+
const VPDominatorTree &VPDT) {
3131
ArrayRef<VPBlockBase *> Preds = HeaderVPB->getPredecessors();
3232
if (Preds.size() != 2)
33-
return std::nullopt;
33+
return false;
3434

35-
auto *PreheaderVPBB = cast<VPBasicBlock>(Preds[0]);
36-
auto *LatchVPBB = cast<VPBasicBlock>(Preds[1]);
35+
auto *PreheaderVPBB = Preds[0];
36+
auto *LatchVPBB = Preds[1];
3737
if (VPDT.dominates(PreheaderVPBB, HeaderVPB) &&
3838
VPDT.dominates(HeaderVPB, LatchVPBB))
39-
return {std::make_pair(PreheaderVPBB, LatchVPBB)};
39+
return true;
4040

4141
std::swap(PreheaderVPBB, LatchVPBB);
42+
4243
if (VPDT.dominates(PreheaderVPBB, HeaderVPB) &&
43-
VPDT.dominates(HeaderVPB, LatchVPBB))
44-
return {std::make_pair(PreheaderVPBB, LatchVPBB)};
44+
VPDT.dominates(HeaderVPB, LatchVPBB)) {
45+
// Canonicalize predecessors of header so that preheader is first and latch
46+
// second.
47+
HeaderVPB->swapPredecessors();
48+
for (VPRecipeBase &R : cast<VPBasicBlock>(HeaderVPB)->phis())
49+
R.swapOperands();
50+
return true;
51+
}
4552

46-
return std::nullopt;
53+
return false;
4754
}
4855

49-
/// Try to create a new VPRegionBlock if there is a loop starting at \p
50-
/// HeaderVPB.
51-
static void tryToCreateLoopRegion(VPlan &Plan, VPBlockBase *HeaderVPB,
52-
VPDominatorTree &VPDT) {
53-
auto Res = getPreheaderAndLatch(HeaderVPB, VPDT);
54-
if (!Res)
55-
return;
56+
/// Create a new VPRegionBlock for the loop starting at \p HeaderVPB.
57+
static void createLoopRegion(VPlan &Plan, VPBlockBase *HeaderVPB) {
58+
auto *PreheaderVPBB = HeaderVPB->getPredecessors()[0];
59+
auto *LatchVPBB = HeaderVPB->getPredecessors()[1];
5660

57-
const auto &[PreheaderVPBB, LatchVPBB] = *Res;
58-
59-
// Swap the operands of header phis if needed. After creating the region, the
60-
// incoming value from the preheader must be the first operand and the one
61-
// from the latch must be the second operand.
62-
if (HeaderVPB->getPredecessors()[0] != PreheaderVPBB) {
63-
for (VPRecipeBase &R : cast<VPBasicBlock>(HeaderVPB)->phis()) {
64-
VPValue *Inc0 = R.getOperand(0);
65-
R.setOperand(0, R.getOperand(1));
66-
R.setOperand(1, Inc0);
67-
}
68-
}
6961
VPBlockUtils::disconnectBlocks(PreheaderVPBB, HeaderVPB);
7062
VPBlockUtils::disconnectBlocks(LatchVPBB, HeaderVPB);
7163
VPBlockBase *Succ = LatchVPBB->getSingleSuccessor();
@@ -94,7 +86,8 @@ void VPlanTransforms::createLoopRegions(VPlan &Plan, Type *InductionTy,
9486
VPDominatorTree VPDT;
9587
VPDT.recalculate(Plan);
9688
for (VPBlockBase *HeaderVPB : vp_depth_first_shallow(Plan.getEntry()))
97-
tryToCreateLoopRegion(Plan, HeaderVPB, VPDT);
89+
if (canonicalHeader(HeaderVPB, VPDT))
90+
createLoopRegion(Plan, HeaderVPB);
9891

9992
VPRegionBlock *TopRegion = Plan.getVectorLoopRegion();
10093
auto *OrigExiting = TopRegion->getExiting();

llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ void PlainCFGBuilder::fixHeaderPhis() {
9898
auto *VPPhi = cast<VPWidenPHIRecipe>(VPVal);
9999
assert(VPPhi->getNumOperands() == 0 &&
100100
"Expected VPInstruction with no operands.");
101-
assert(isHeaderBB(Phi->getParent(), LI->getLoopFor(Phi->getParent())));
101+
assert(isHeaderBB(Phi->getParent(), LI->getLoopFor(Phi->getParent())) &&
102+
"Expected Phi in header block.");
102103
assert(Phi->getNumOperands() == 2 &&
103104
"header phi must have exactly 2 operands");
104105
for (BasicBlock *Pred : predecessors(Phi->getParent()))

llvm/lib/Transforms/Vectorize/VPlanValue.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,12 @@ class VPUser {
246246
New->addUser(*this);
247247
}
248248

249+
/// Swap operands of the VPUser. It must have exactly 2 operands.
250+
void swapOperands() {
251+
assert(Operands.size() == 2 && "must have 2 operands to swap");
252+
std::swap(Operands[0], Operands[1]);
253+
}
254+
249255
/// Replaces all uses of \p From in the VPUser with \p To.
250256
void replaceUsesOfWith(VPValue *From, VPValue *To);
251257

0 commit comments

Comments
 (0)