7979// Limitation: The pass cannot handle switch statements and indirect
8080// branches. Both must be lowered to plain branches first.
8181//
82+ // CallBr support: CallBr is handled as a more general branch instruction which
83+ // can have multiple successors. The pass redirects the edges to intermediate
84+ // target blocks that unconditionally branch to the original callbr target
85+ // blocks. This allows the control flow hub to know to which of the original
86+ // target blocks to jump to.
87+ // Example input CFG:
88+ // Entry (callbr)
89+ // / \
90+ // v v
91+ // H ----> B
92+ // ^ /|
93+ // `----' |
94+ // v
95+ // Exit
96+ //
97+ // becomes:
98+ // Entry (callbr)
99+ // / \
100+ // v v
101+ // target.H target.B
102+ // | |
103+ // v v
104+ // H ----> B
105+ // ^ /|
106+ // `----' |
107+ // v
108+ // Exit
109+ //
110+ // Note
111+ // OUTPUT CFG: Converted to a natural loop with a new header N.
112+ //
113+ // Entry (callbr)
114+ // / \
115+ // v v
116+ // target.H target.B
117+ // \ /
118+ // \ /
119+ // v v
120+ // N <---.
121+ // / \ \
122+ // / \ |
123+ // v v /
124+ // H --> B --'
125+ // |
126+ // v
127+ // Exit
128+ //
82129// ===----------------------------------------------------------------------===//
83130
84131#include " llvm/Transforms/Utils/FixIrreducible.h"
@@ -231,6 +278,7 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
231278 return false ;
232279 LLVM_DEBUG (dbgs () << " Processing cycle:\n " << CI.print (&C) << " \n " ;);
233280
281+ DomTreeUpdater DTU (DT, DomTreeUpdater::UpdateStrategy::Eager);
234282 ControlFlowHub CHub;
235283 SetVector<BasicBlock *> Predecessors;
236284
@@ -242,18 +290,33 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
242290 }
243291
244292 for (BasicBlock *P : Predecessors) {
245- auto *Branch = cast<BranchInst>(P->getTerminator ());
246- // Exactly one of the two successors is the header.
247- BasicBlock *Succ0 = Branch->getSuccessor (0 ) == Header ? Header : nullptr ;
248- BasicBlock *Succ1 = Succ0 ? nullptr : Header;
249- if (!Succ0)
250- assert (Branch->getSuccessor (1 ) == Header);
251- assert (Succ0 || Succ1);
252- CHub.addBranch (P, Succ0, Succ1);
253-
254- LLVM_DEBUG (dbgs () << " Added internal branch: " << P->getName () << " -> "
255- << (Succ0 ? Succ0->getName () : " " ) << " "
256- << (Succ1 ? Succ1->getName () : " " ) << " \n " );
293+ if (BranchInst *Branch = dyn_cast<BranchInst>(P->getTerminator ()); Branch) {
294+ // Exactly one of the two successors is the header.
295+ BasicBlock *Succ0 = Branch->getSuccessor (0 ) == Header ? Header : nullptr ;
296+ BasicBlock *Succ1 = Succ0 ? nullptr : Header;
297+ if (!Succ0)
298+ assert (Branch->getSuccessor (1 ) == Header);
299+ assert (Succ0 || Succ1);
300+ CHub.addBranch (P, Succ0, Succ1);
301+
302+ LLVM_DEBUG (dbgs () << " Added internal branch: " << P->getName () << " -> "
303+ << (Succ0 ? Succ0->getName () : " " ) << " "
304+ << (Succ1 ? Succ1->getName () : " " ) << " \n " );
305+ } else if (CallBrInst *CallBr = dyn_cast<CallBrInst>(P->getTerminator ());
306+ CallBr) {
307+ for (unsigned I = 0 ; I < CallBr->getNumSuccessors (); ++I) {
308+ BasicBlock *Succ = CallBr->getSuccessor (I);
309+ if (Succ != Header)
310+ continue ;
311+ BasicBlock *NewSucc = llvm::ControlFlowHub::createCallBrTarget (
312+ CallBr, Succ, I, false , &CI, &DTU, LI);
313+ CHub.addBranch (NewSucc, Succ);
314+ LLVM_DEBUG (dbgs () << " Added internal branch: " << NewSucc->getName ()
315+ << " -> " << Succ->getName () << " \n " );
316+ }
317+ } else {
318+ llvm_unreachable (" Unsupported block terminator." );
319+ }
257320 }
258321
259322 // Redirect external incoming edges. This includes the edges on the header.
@@ -266,17 +329,32 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
266329 }
267330
268331 for (BasicBlock *P : Predecessors) {
269- auto *Branch = cast<BranchInst>(P->getTerminator ());
270- BasicBlock *Succ0 = Branch->getSuccessor (0 );
271- Succ0 = C.contains (Succ0) ? Succ0 : nullptr ;
272- BasicBlock *Succ1 =
273- Branch->isUnconditional () ? nullptr : Branch->getSuccessor (1 );
274- Succ1 = Succ1 && C.contains (Succ1) ? Succ1 : nullptr ;
275- CHub.addBranch (P, Succ0, Succ1);
276-
277- LLVM_DEBUG (dbgs () << " Added external branch: " << P->getName () << " -> "
278- << (Succ0 ? Succ0->getName () : " " ) << " "
279- << (Succ1 ? Succ1->getName () : " " ) << " \n " );
332+ if (BranchInst *Branch = dyn_cast<BranchInst>(P->getTerminator ()); Branch) {
333+ BasicBlock *Succ0 = Branch->getSuccessor (0 );
334+ Succ0 = C.contains (Succ0) ? Succ0 : nullptr ;
335+ BasicBlock *Succ1 =
336+ Branch->isUnconditional () ? nullptr : Branch->getSuccessor (1 );
337+ Succ1 = Succ1 && C.contains (Succ1) ? Succ1 : nullptr ;
338+ CHub.addBranch (P, Succ0, Succ1);
339+
340+ LLVM_DEBUG (dbgs () << " Added external branch: " << P->getName () << " -> "
341+ << (Succ0 ? Succ0->getName () : " " ) << " "
342+ << (Succ1 ? Succ1->getName () : " " ) << " \n " );
343+ } else if (CallBrInst *CallBr = dyn_cast<CallBrInst>(P->getTerminator ());
344+ CallBr) {
345+ for (unsigned I = 0 ; I < CallBr->getNumSuccessors (); ++I) {
346+ BasicBlock *Succ = CallBr->getSuccessor (I);
347+ if (!C.contains (Succ))
348+ continue ;
349+ BasicBlock *NewSucc = llvm::ControlFlowHub::createCallBrTarget (
350+ CallBr, Succ, I, true , &CI, &DTU, LI);
351+ CHub.addBranch (NewSucc, Succ);
352+ LLVM_DEBUG (dbgs () << " Added external branch: " << NewSucc->getName ()
353+ << " -> " << Succ->getName () << " \n " );
354+ }
355+ } else {
356+ llvm_unreachable (" Unsupported block terminator." );
357+ }
280358 }
281359
282360 // Redirect all the backedges through a "hub" consisting of a series
@@ -292,7 +370,6 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
292370 SetVector<BasicBlock *> Entries;
293371 Entries.insert (C.entry_rbegin (), C.entry_rend ());
294372
295- DomTreeUpdater DTU (DT, DomTreeUpdater::UpdateStrategy::Eager);
296373 CHub.finalize (&DTU, GuardBlocks, " irr" );
297374#if defined(EXPENSIVE_CHECKS)
298375 assert (DT.verify (DominatorTree::VerificationLevel::Full));
@@ -325,7 +402,7 @@ static bool FixIrreducibleImpl(Function &F, CycleInfo &CI, DominatorTree &DT,
325402 LLVM_DEBUG (dbgs () << " ===== Fix irreducible control-flow in function: "
326403 << F.getName () << " \n " );
327404
328- assert (hasOnlySimpleTerminator (F) && " Unsupported block terminator." );
405+ assert (hasOnlySimpleTerminatorOrCallBr (F) && " Unsupported block terminator." );
329406
330407 bool Changed = false ;
331408 for (Cycle *TopCycle : CI.toplevel_cycles ()) {
0 commit comments