[llvm] [AMDGPU] Add islands to StructurizeCFG (PR #201675)
Robert Imschweiler via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 00:16:25 PDT 2026
================
@@ -1188,17 +1309,231 @@ void StructurizeCFG::wireFlow(bool ExitUseAllowed,
addPhiValues(Flow, Entry);
DT->changeImmediateDominator(Entry, Flow);
- PrevNode = Node;
+ Tail = Node;
while (!Order.empty() && !Visited.count(LoopEnd) &&
dominatesPredicates(Entry, Order.back())) {
handleLoops(false, LoopEnd);
}
- changeExit(PrevNode, Next, false);
+ if (Tail.isRewritable())
+ changeExit(Tail, Next, false);
setPrevNode(Next);
}
}
+/// Handle an "island", i.e. a block whose terminator is not rewritable (e.g., a
+/// callbr) in this context and considered immutable from this pass's
+/// perspective.
+///
+/// The island is left untouched; its edges are split into forwarders that
+/// converge at a new Flow block (ExitFlow). The callbr's runtime target choice
+/// is recovered as a per-target i1 "sel" phi and re-dispatched by a structured
+/// ladder of 2-way branches:
+///
+/// callbr
+/// / | \
+/// fwd_0 fwd_1 fwd_2 forwarders (intermediate target blocks)
+/// \ | /
+/// ExitFlow (Flow_0) -- sel_0? --> real_0
+/// | else
+/// Flow_1 --------- sel_1? --> real_1
+/// | else
+/// real_2
+/// or Flow_2 (if real_1 == real_2) ------> real_2 (shared last
+/// target)
+///
+void StructurizeCFG::handleIsland(BasicBlock *IslandBB) {
+ DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
+
+ // 1. Split the island's edges into forwarders, so the island's targets are no
+ // longer direct successors of the (immutable) callbr terminator. This also
+ // turns a self-loop back-edge into a *mutable* forwarder, so later steps
+ // never rewrite the island edge itself.
+ //
+ // Reuse a target as-is only if it is already a trivial forwarder *inside this
+ // region*. A trivial target that is the region's exit block is still split:
+ // the ladder consumes its forwarders, and consuming the exit block would move
+ // the region's SESE boundary, which the precomputed RegionInfo cannot
+ // represent.
+ SmallVector<BasicBlock *, 4> Targets;
+ // Several island edges to the same block are indistinguishable, so each
+ // distinct target is given a single forwarder (one ladder arm, one sel
+ // value).
+ SmallDenseMap<BasicBlock *, BasicBlock *> ForwarderFor;
+
+ if (CallBrInst *CallBr = dyn_cast<CallBrInst>(IslandBB->getTerminator())) {
+ for (unsigned I = 0; I < CallBr->getNumSuccessors(); ++I) {
+ BasicBlock *Target = CallBr->getSuccessor(I);
+ // Leave an unreachable target's callbr edge direct and keep the dead lane
+ // out of the dispatch sel phi, which SILowerI1Copies cannot lower. It
+ // stays a direct predecessor of its successor and is not part of the
+ // ladder.
+ // However, that gives the region exit a predecessor createFlow's
+ // single-pred exit wiring does not account for. Flag that the exit's
+ // immediate dominator needs to be fixed.
+ if (isUnreachableTarget(*Target)) {
+ NeedFixRegionExitDom = true;
+ continue;
+ }
+ // Already handled this target: route this edge to the same forwarder.
+ if (BasicBlock *Fwd = ForwarderFor.lookup(Target)) {
+ CallBr->setSuccessor(I, Fwd);
----------------
ro-i wrote:
rightfully so, there was a bug. But this is covered by SplitMultiBrEdge now, anyway
https://github.com/llvm/llvm-project/pull/201675
More information about the llvm-commits
mailing list