Skip to content

Commit 3bec84c

Browse files
committed
move ControlFlowHub::createCallBrTarget to BasicBlockUtils::SplitCallBrEdge
1 parent 11fcaae commit 3bec84c

File tree

6 files changed

+106
-95
lines changed

6 files changed

+106
-95
lines changed

llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/ADT/ArrayRef.h"
2020
#include "llvm/ADT/SetVector.h"
2121
#include "llvm/IR/BasicBlock.h"
22+
#include "llvm/IR/CycleInfo.h"
2223
#include "llvm/IR/Dominators.h"
2324
#include "llvm/Support/Compiler.h"
2425
#include "llvm/Support/Printable.h"
@@ -262,6 +263,34 @@ LLVM_ABI BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To,
262263
MemorySSAUpdater *MSSAU = nullptr,
263264
const Twine &BBName = "");
264265

266+
/// \brief Create a new intermediate target block for a callbr edge.
267+
///
268+
/// Create a new basic block between a callbr instruction and one of its
269+
/// successors. The new block replaces the original successor in the callbr
270+
/// instruction and unconditionally branches to the original successor. This
271+
/// is useful for normalizing control flow, e.g., when transforming
272+
/// irreducible loops.
273+
///
274+
/// \param CallBrBlock block containing the callbr instruction
275+
/// \param Succ original successor block
276+
/// \param SuccIdx index of the original successor in the callbr
277+
/// instruction
278+
/// \param DTU optional \p DomTreeUpdater for updating the
279+
/// dominator tree
280+
/// \param CI optional \p CycleInfo for updating cycle membership
281+
/// \param LI optional \p LoopInfo for updating loop membership
282+
/// \param UpdatedLI optional output flag indicating if \p LoopInfo has
283+
/// been updated
284+
///
285+
/// \returns newly created intermediate target block
286+
///
287+
/// \note This function updates PHI nodes, dominator tree, loop info, and
288+
/// cycle info as needed.
289+
LLVM_ABI BasicBlock *
290+
SplitCallBrEdge(BasicBlock *CallBrBlock, BasicBlock *Succ, unsigned SuccIdx,
291+
DomTreeUpdater *DTU = nullptr, CycleInfo *CI = nullptr,
292+
LoopInfo *LI = nullptr, bool *UpdatedLI = nullptr);
293+
265294
/// Sets the unwind edge of an instruction to a particular successor.
266295
LLVM_ABI void setUnwindEdgeTo(Instruction *TI, BasicBlock *Succ);
267296

llvm/include/llvm/Transforms/Utils/ControlFlowUtils.h

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -122,34 +122,6 @@ struct ControlFlowHub {
122122
std::optional<unsigned> MaxControlFlowBooleans = std::nullopt);
123123

124124
SmallVector<BranchDescriptor> Branches;
125-
126-
/// \brief Create a new intermediate target block for a callbr edge.
127-
///
128-
/// This function creates a new basic block (the "target block") that sits
129-
/// between a callbr instruction and one of its successors. The callbr's
130-
/// successor is rewired to this new block, and the new block unconditionally
131-
/// branches to the original successor. This is useful for normalizing control
132-
/// flow, e.g., when transforming irreducible loops.
133-
///
134-
/// \param CallBr The callbr instruction whose edge is to be split.
135-
/// \param Succ The original successor basic block to be reached.
136-
/// \param SuccIdx The index of the successor in the callbr
137-
/// instruction.
138-
/// \param CI Optional CycleInfo for updating cycle membership.
139-
/// \param DTU Optional DomTreeUpdater for updating the dominator
140-
/// tree.
141-
/// \param LI Optional LoopInfo for updating loop membership.
142-
/// \param UpdatedLI Optional output flag indicating if LoopInfo has been
143-
/// updated.
144-
///
145-
/// \returns The newly created intermediate target block.
146-
///
147-
/// \note This function updates PHI nodes, dominator tree, loop info, and
148-
/// cycle info as needed.
149-
static BasicBlock *
150-
createCallBrTarget(CallBrInst *CallBr, BasicBlock *Succ, unsigned SuccIdx,
151-
CycleInfo *CI = nullptr, DomTreeUpdater *DTU = nullptr,
152-
LoopInfo *LI = nullptr, bool *UpdatedLI = nullptr);
153125
};
154126

155127
} // end namespace llvm

llvm/lib/Transforms/Utils/BasicBlockUtils.cpp

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,79 @@ BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, DominatorTree *DT,
674674
return SplitBlock(BB, BB->getTerminator(), DT, LI, MSSAU, BBName);
675675
}
676676

677+
/// Helper function to update the cycle or loop information after inserting a
678+
/// new block between a callbr instruction and one of its target blocks. Adds
679+
/// the new block to the innermost cycle or loop that the callbr instruction and
680+
/// the original target block share.
681+
/// \p LCI cycle or loop information to update
682+
/// \p CallBrBlock block containing the callbr instruction
683+
/// \p CallBrTarget new target block of the callbr instruction
684+
/// \p Succ original target block of the callbr instruction
685+
template <typename TI, typename T>
686+
static bool updateCycleLoopInfo(TI *LCI, BasicBlock *CallBrBlock,
687+
BasicBlock *CallBrTarget, BasicBlock *Succ) {
688+
static_assert(std::is_same_v<TI, CycleInfo> || std::is_same_v<TI, LoopInfo>,
689+
"type must be CycleInfo or LoopInfo");
690+
if (!LCI)
691+
return false;
692+
693+
T *LC;
694+
if constexpr (std::is_same_v<TI, CycleInfo>)
695+
LC = LCI->getSmallestCommonCycle(CallBrBlock, Succ);
696+
else
697+
LC = LCI->getSmallestCommonLoop(CallBrBlock, Succ);
698+
if (!LC)
699+
return false;
700+
701+
if constexpr (std::is_same_v<TI, CycleInfo>)
702+
LCI->addBlockToCycle(CallBrTarget, LC);
703+
else
704+
LC->addBasicBlockToLoop(CallBrTarget, *LCI);
705+
706+
return true;
707+
}
708+
709+
BasicBlock *llvm::SplitCallBrEdge(BasicBlock *CallBrBlock, BasicBlock *Succ,
710+
unsigned SuccIdx, DomTreeUpdater *DTU,
711+
CycleInfo *CI, LoopInfo *LI,
712+
bool *UpdatedLI) {
713+
CallBrInst *CallBr = dyn_cast<CallBrInst>(CallBrBlock->getTerminator());
714+
assert(CallBr && "expected callbr terminator");
715+
assert(SuccIdx < CallBr->getNumSuccessors() &&
716+
Succ == CallBr->getSuccessor(SuccIdx) && "invalid successor index");
717+
718+
// Create a new block between callbr and the specified successor.
719+
// splitBlockBefore cannot be re-used here since it cannot split if the split
720+
// point is a PHI node (because BasicBlock::splitBasicBlockBefore cannot
721+
// handle that). But we don't need to rewire every part of a potential PHI
722+
// node. We only care about the edge between CallBrBlock and the original
723+
// successor.
724+
BasicBlock *CallBrTarget =
725+
BasicBlock::Create(CallBrBlock->getContext(),
726+
CallBrBlock->getName() + ".target." + Succ->getName(),
727+
CallBrBlock->getParent());
728+
// Rewire control flow from the new target block to the original successor.
729+
Succ->replacePhiUsesWith(CallBrBlock, CallBrTarget);
730+
// Rewire control flow from callbr to the new target block.
731+
CallBr->setSuccessor(SuccIdx, CallBrTarget);
732+
// Jump from the new target block to the original successor.
733+
BranchInst::Create(Succ, CallBrTarget);
734+
735+
bool Updated =
736+
updateCycleLoopInfo<LoopInfo, Loop>(LI, CallBrBlock, CallBrTarget, Succ);
737+
if (UpdatedLI)
738+
*UpdatedLI = Updated;
739+
updateCycleLoopInfo<CycleInfo, Cycle>(CI, CallBrBlock, CallBrTarget, Succ);
740+
if (DTU) {
741+
DTU->applyUpdates({{DominatorTree::Insert, CallBrBlock, CallBrTarget}});
742+
if (DTU->getDomTree().dominates(CallBrBlock, Succ))
743+
DTU->applyUpdates({{DominatorTree::Delete, CallBrBlock, Succ},
744+
{DominatorTree::Insert, CallBrTarget, Succ}});
745+
}
746+
747+
return CallBrTarget;
748+
}
749+
677750
void llvm::setUnwindEdgeTo(Instruction *TI, BasicBlock *Succ) {
678751
if (auto *II = dyn_cast<InvokeInst>(TI))
679752
II->setUnwindDest(Succ);

llvm/lib/Transforms/Utils/ControlFlowUtils.cpp

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -344,64 +344,3 @@ std::pair<BasicBlock *, bool> ControlFlowHub::finalize(
344344

345345
return {FirstGuardBlock, true};
346346
}
347-
348-
/// Helper function to update the cycle or loop information after inserting a
349-
/// new block between a callbr instruction and one of its target blocks. Adds
350-
/// the new block to the innermost cycle or loop that the callbr instruction and
351-
/// the original target block share.
352-
/// \p LCI cycle or loop information to update
353-
/// \p CallBrBlock block containing the callbr instruction
354-
/// \p CallBrTarget new target block of the callbr instruction
355-
/// \p Succ original target block of the callbr instruction
356-
template <typename TI, typename T>
357-
static bool updateCycleLoopInfo(TI *LCI, BasicBlock *CallBrBlock,
358-
BasicBlock *CallBrTarget, BasicBlock *Succ) {
359-
static_assert(std::is_same_v<TI, CycleInfo> || std::is_same_v<TI, LoopInfo>,
360-
"type must be CycleInfo or LoopInfo");
361-
if (!LCI)
362-
return false;
363-
364-
T *LC;
365-
if constexpr (std::is_same_v<TI, CycleInfo>)
366-
LC = LCI->getSmallestCommonCycle(CallBrBlock, Succ);
367-
else
368-
LC = LCI->getSmallestCommonLoop(CallBrBlock, Succ);
369-
if (!LC)
370-
return false;
371-
372-
if constexpr (std::is_same_v<TI, CycleInfo>)
373-
LCI->addBlockToCycle(CallBrTarget, LC);
374-
else
375-
LC->addBasicBlockToLoop(CallBrTarget, *LCI);
376-
377-
return true;
378-
}
379-
380-
BasicBlock *ControlFlowHub::createCallBrTarget(CallBrInst *CallBr,
381-
BasicBlock *Succ,
382-
unsigned SuccIdx, CycleInfo *CI,
383-
DomTreeUpdater *DTU,
384-
LoopInfo *LI, bool *UpdatedLI) {
385-
BasicBlock *CallBrBlock = CallBr->getParent();
386-
BasicBlock *CallBrTarget =
387-
BasicBlock::Create(CallBrBlock->getContext(),
388-
CallBrBlock->getName() + ".target." + Succ->getName(),
389-
CallBrBlock->getParent());
390-
// Rewire control flow from callbr to the new target block.
391-
Succ->replacePhiUsesWith(CallBrBlock, CallBrTarget);
392-
CallBr->setSuccessor(SuccIdx, CallBrTarget);
393-
// Jump from the new target block to the original successor.
394-
BranchInst::Create(Succ, CallBrTarget);
395-
bool Updated =
396-
updateCycleLoopInfo<LoopInfo, Loop>(LI, CallBrBlock, CallBrTarget, Succ);
397-
if (UpdatedLI)
398-
*UpdatedLI = Updated;
399-
updateCycleLoopInfo<CycleInfo, Cycle>(CI, CallBrBlock, CallBrTarget, Succ);
400-
if (DTU) {
401-
DTU->applyUpdates({{DominatorTree::Insert, CallBrBlock, CallBrTarget}});
402-
if (DTU->getDomTree().dominates(CallBrBlock, Succ))
403-
DTU->applyUpdates({{DominatorTree::Delete, CallBrBlock, Succ},
404-
{DominatorTree::Insert, CallBrTarget, Succ}});
405-
}
406-
return CallBrTarget;
407-
}

llvm/lib/Transforms/Utils/FixIrreducible.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,7 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
307307
BasicBlock *Succ = CallBr->getSuccessor(I);
308308
if (Succ != Header)
309309
continue;
310-
BasicBlock *NewSucc =
311-
ControlFlowHub::createCallBrTarget(CallBr, Succ, I, &CI, &DTU, LI);
310+
BasicBlock *NewSucc = SplitCallBrEdge(P, Succ, I, &DTU, &CI, LI);
312311
CHub.addBranch(NewSucc, Succ);
313312
LLVM_DEBUG(dbgs() << "Added internal branch: "
314313
<< printBasicBlock(NewSucc) << " -> "
@@ -346,8 +345,7 @@ static bool fixIrreducible(Cycle &C, CycleInfo &CI, DominatorTree &DT,
346345
BasicBlock *Succ = CallBr->getSuccessor(I);
347346
if (!C.contains(Succ))
348347
continue;
349-
BasicBlock *NewSucc =
350-
ControlFlowHub::createCallBrTarget(CallBr, Succ, I, &CI, &DTU, LI);
348+
BasicBlock *NewSucc = SplitCallBrEdge(P, Succ, I, &DTU, &CI, LI);
351349
CHub.addBranch(NewSucc, Succ);
352350
LLVM_DEBUG(dbgs() << "Added external branch: "
353351
<< printBasicBlock(NewSucc) << " -> "

llvm/lib/Transforms/Utils/UnifyLoopExits.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,8 @@ static bool unifyLoopExits(DominatorTree &DT, LoopInfo &LI, Loop *L) {
180180
if (L->contains(Succ))
181181
continue;
182182
bool UpdatedLI = false;
183-
BasicBlock *NewSucc = ControlFlowHub::createCallBrTarget(
184-
CallBr, Succ, J, nullptr, &DTU, &LI, &UpdatedLI);
183+
BasicBlock *NewSucc =
184+
SplitCallBrEdge(BB, Succ, J, &DTU, nullptr, &LI, &UpdatedLI);
185185
// Even if CallBr and Succ do not have a common parent loop, we need to
186186
// add the new target block to the parent loop of the current loop.
187187
if (!UpdatedLI)

0 commit comments

Comments
 (0)