-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[VPlan] Retain exit conditions and edges in initial VPlan (NFC). #137709
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
de0fc2d
19bec82
55b4d5e
ca45f88
ddfdeef
1284bc6
79317a5
3cc4b31
bbb902e
c1902ed
0cadcf9
5fa6b7d
5d6729d
1211faf
50d7ee1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -113,6 +113,9 @@ VPBasicBlock *PlainCFGBuilder::getOrCreateVPBB(BasicBlock *BB) { | |||||||||||||||||||||||||||||
| return VPBB; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if (!TheLoop->contains(BB)) | ||||||||||||||||||||||||||||||
| return Plan->getExitBlock(BB); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
| // Create new VPBB. | ||||||||||||||||||||||||||||||
| StringRef Name = BB->getName(); | ||||||||||||||||||||||||||||||
| LLVM_DEBUG(dbgs() << "Creating VPBasicBlock for " << Name << "\n"); | ||||||||||||||||||||||||||||||
|
|
@@ -146,14 +149,6 @@ bool PlainCFGBuilder::isExternalDef(Value *Val) { | |||||||||||||||||||||||||||||
| // Instruction definition is in outermost loop PH. | ||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Check whether Instruction definition is in a loop exit. | ||||||||||||||||||||||||||||||
| SmallVector<BasicBlock *> ExitBlocks; | ||||||||||||||||||||||||||||||
| TheLoop->getExitBlocks(ExitBlocks); | ||||||||||||||||||||||||||||||
| if (is_contained(ExitBlocks, InstParent)) { | ||||||||||||||||||||||||||||||
| // Instruction definition is in outermost loop exit. | ||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
| // Check whether Instruction definition is in loop body. | ||||||||||||||||||||||||||||||
| return !TheLoop->contains(Inst); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
@@ -202,11 +197,6 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB, | |||||||||||||||||||||||||||||
| "Instruction shouldn't have been visited."); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if (auto *Br = dyn_cast<BranchInst>(Inst)) { | ||||||||||||||||||||||||||||||
| if (TheLoop->getLoopLatch() == BB || | ||||||||||||||||||||||||||||||
| any_of(successors(BB), | ||||||||||||||||||||||||||||||
| [this](BasicBlock *Succ) { return !TheLoop->contains(Succ); })) | ||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Conditional branch instruction are represented using BranchOnCond | ||||||||||||||||||||||||||||||
| // recipes. | ||||||||||||||||||||||||||||||
| if (Br->isConditional()) { | ||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: seems a bit clearer to early continue?
Suggested change
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, ignore, we continue also after handling a conditional branch. |
||||||||||||||||||||||||||||||
|
|
@@ -296,7 +286,6 @@ std::unique_ptr<VPlan> PlainCFGBuilder::buildPlainCFG( | |||||||||||||||||||||||||||||
| for (BasicBlock *BB : RPO) { | ||||||||||||||||||||||||||||||
| // Create or retrieve the VPBasicBlock for this BB. | ||||||||||||||||||||||||||||||
| VPBasicBlock *VPBB = getOrCreateVPBB(BB); | ||||||||||||||||||||||||||||||
| Loop *LoopForBB = LI->getLoopFor(BB); | ||||||||||||||||||||||||||||||
| // Set VPBB predecessors in the same order as they are in the incoming BB. | ||||||||||||||||||||||||||||||
| setVPBBPredsFromBB(VPBB, BB); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
@@ -327,24 +316,12 @@ std::unique_ptr<VPlan> PlainCFGBuilder::buildPlainCFG( | |||||||||||||||||||||||||||||
| BasicBlock *IRSucc1 = BI->getSuccessor(1); | ||||||||||||||||||||||||||||||
| VPBasicBlock *Successor0 = getOrCreateVPBB(IRSucc0); | ||||||||||||||||||||||||||||||
| VPBasicBlock *Successor1 = getOrCreateVPBB(IRSucc1); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Don't connect any blocks outside the current loop except the latches for | ||||||||||||||||||||||||||||||
| // inner loops. | ||||||||||||||||||||||||||||||
| // TODO: Also connect exit blocks during initial VPlan construction. | ||||||||||||||||||||||||||||||
| if (LoopForBB == TheLoop || BB != LoopForBB->getLoopLatch()) { | ||||||||||||||||||||||||||||||
| if (!LoopForBB->contains(IRSucc0)) { | ||||||||||||||||||||||||||||||
| VPBB->setOneSuccessor(Successor1); | ||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| if (!LoopForBB->contains(IRSucc1)) { | ||||||||||||||||||||||||||||||
| VPBB->setOneSuccessor(Successor0); | ||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| VPBB->setTwoSuccessors(Successor0, Successor1); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| for (auto *EB : Plan->getExitBlocks()) | ||||||||||||||||||||||||||||||
| setVPBBPredsFromBB(EB, EB->getIRBasicBlock()); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // 2. The whole CFG has been built at this point so all the input Values must | ||||||||||||||||||||||||||||||
| // have a VPlan counterpart. Fix VPlan header phi by adding their | ||||||||||||||||||||||||||||||
| // corresponding VPlan operands. | ||||||||||||||||||||||||||||||
|
|
@@ -447,19 +424,21 @@ static void createLoopRegion(VPlan &Plan, VPBlockBase *HeaderVPB) { | |||||||||||||||||||||||||||||
| VPBlockBase *Succ = LatchVPBB->getSingleSuccessor(); | ||||||||||||||||||||||||||||||
| assert(LatchVPBB->getNumSuccessors() <= 1 && | ||||||||||||||||||||||||||||||
| "Latch has more than one successor"); | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
| assert(LatchVPBB->getNumSuccessors() <= 1 && | |
| "Latch has more than one successor"); | |
| assert(Succ && "Latch expected to be left with a single successor"); |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done thanks!
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The constructor of VPRegionBlock will assert that LatchVPBB is free of successors (and HeaderVPB free of predecessors), yet we want to retain LatchVPBB's place in Succ's predecessors - to be replaced by R, the region itself. One possible way to achieve this using current public API may by using an auxiliary temporary place holder VPBB:
| LatchVPBB->removeSuccessor(Succ); | |
| auto *PlaceHolder = Plan.createVPBasicBlock ("Region place holder"); | |
| VPBlockUtils::insertOnEdge(LatchVPBB, Succ, PlaceHolder); | |
| VPBlockUtils::disconnectBlocks(LatchVPBB, PlaceHolder); | |
| VPBlockUtils::connectBlocks(PreheaderVPBB, PlaceHolder); |
Note that disconnecting LatchVPBB from PlaceHolder and connecting PreheaderVPBB to PlaceHolder instead retains the position in PlaceHolder's predecessors, as PlaceHolder has but one predecessor (unlike Succ). Plus PreheaderVPBB has but one successor. More on this later.
It is also conceivable to have a(nother) constructor of VPRegionBlock which accepts a Header and Latch that are connected to a Preheader and Exit/Succ, respectively, and takes care of hooking them up with the newly created region block instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, introducing a temporary block nicely solves the issue, thank you very much!
This also required changing the region construction order to innermost first, to ensure the parents for VPBBs are set correctly at all times 32928a0
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Above explanation needs update - can now also reach exit blocks from HeaderVPB - via early exits?
Latch isn't fully disconnected yet its successors are, which should still prevent reaching an exit block from it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, updated the comment to refer to non-latch exiting blocks.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| SmallPtrSet<VPBlockBase *, 2> ExitBlocks(Plan.getExitBlocks().begin(), | |
| Plan.getExitBlocks().end()); |
?
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can now reach exit blocks, contrary to above comment, via early exits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, comment updated, thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm2, createLoopRegion() is called after prepareForVectorization(), which according to the changes below should have removed all early-exit edges, so is this check (if VPBB is an exit block) needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not reachable in the latest version, removed thanks!
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PlaceHolder introduced earlier may now be used instead as follows
| VPBlockUtils::insertBlockAfter(R, PreheaderVPBB); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done thanks
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| R->setOneSuccessor(Succ); | |
| Succ->replacePredecessor(LatchVPBB, R); | |
| VPBlockUtils::insertOnEdge(PlaceHolder, Succ, R); |
followed by either letting mergeBlocksIntoPredecessors() eliminate the empty PlaceHolder by merging it into PreheaderVPBB, or doing so explicitly here by adding:
VPBlockUtils::disconnectBlocks(PreheaderVPBB, PlaceHolder);
VPBlockUtils::disconnectBlocks(PlaceHolder, R);
VPBlockUtils::connectBlocks(PreheaderVPBB, R);
Note that doing
VPBlockUtils::insertOnEdge(PreheaderVPBB, RegionPlaceHolder, R);
instead will lose LatchVPBB's position in Succ's predecessors, suggesting that mergeBlocksIntoPredecessors() needs to be improved to retain this position (TODO). Should we have a removeOnEdge() which takes care of removing a Block on an edge from From to To, making sure From will appear as the predecessor of To in place of Block, and To will appear as the successor of From in place of Block? Analogous to insertOnEdge(), which utilizes connectBlocks(From, To, PredIx, SuccIdx), to ensure such positions are retained.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, I went with removing the temporary block
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| VPBlockBase *LatchExitVPB = LatchVPB->getNumSuccessors() == 2 | |
| ? LatchVPB->getSuccessors()[0] | |
| : nullptr; | |
| if (LatchExitVPB) { | |
| LatchVPB->getSuccessors()[0] = MiddleVPBB; | |
| MiddleVPBB->setPredecessors({LatchVPB}); | |
| MiddleVPBB->setSuccessors({LatchExitVPB}); | |
| LatchExitVPB->replacePredecessor(LatchVPB, MiddleVPBB); | |
| // Canonical LatchVPB has header block as last successor. If it has another | |
| // successor, the latter is an exit block - insert middle block on its edge. | |
| // Otherwise, add middle block as another successor retaining header as last. | |
| if (LatchVPB->getNumSuccessors() == 2) { | |
| VPBlockBase *LatchExitVPB = LatchVPB->getSuccessors()[0]; | |
| VPBlockUtils::insertOnEdge(LatchVPB, LatchExitVPB, MiddleVPBB); |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done thanks!
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // Disconnect all edges between exit blocks other than from the latch. | |
| // Disconnect all edges to exit blocks other than from the middle block. |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done thanks!
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are "handled", being listed in getExitBlocks; but should be handled differently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated, here for now we just simply drop the edges, i.e. leaving the plan in an incorrect/incomplete state, relying on the later transform to adjust the exit condition and introduce an extra middle block, looking up the early exit condition using original IR references.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks a bit odd at first as it seems to be undoing what you did above with VPBlockUtils::insertOnEdge(LatchVPB, LatchExitVPB, MiddleVPBB);. I presume that's because the vector.early.exit VPBB sits between the latch block and the original IR early exit block?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The edge from MiddleVPBB to LatchExitVPB is retained here explicitly via the early-continue exclusion. The edges removed here are early-exits from non-latch Pred block to early.exit block. Block vector.early.exit is introduced by handleUncountableEarlyExit() which currently takes place later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Above with insertOnEdge we only handle the edge exiting from the latch. The exit block via the latch will now be connected to the middle block.
The loop here disconnects all early exits and they will be handled later: either by requiring at least one scalar iteration, nothing more needs to be done, or introducing the early exit control flow to go to the early exit via the additional middle block. For the latter case, the VPlan is now incomplete/incorrect.
To avoid this, we should directly handle the uncountable early exits here, which is done in #138393. This way, we do not need to rely on IR references in handleUncountableEarlyExit and the VPlan remains complete/correct throughout.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (LatchExitVPB) | |
| if (auto *LatchExitVPB = MiddleVPBB->getSingleSuccessor()) |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done thanks!
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"// with middle block already connected to exit block."?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hopefully this low-level API can remain private, possibly with an addition to the high-level public API, see below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done thanks!