37#define DEBUG_TYPE "unify-loop-exits"
43 cl::desc(
"Set the maximum number of outgoing blocks for using a boolean "
44 "value to record the exiting block in the ControlFlowHub."));
53 void getAnalysisUsage(AnalysisUsage &AU)
const override {
64char UnifyLoopExitsLegacyPass::ID = 0;
67 return new UnifyLoopExitsLegacyPass();
71 "Fixup each natural loop to have a single exit block",
76 "Fixup each natural loop to have a single exit block",
101 for (
auto *BB : L->blocks()) {
102 for (auto &I : *BB) {
103 for (auto &U : I.uses()) {
104 auto UserInst = cast<Instruction>(U.getUser());
105 auto UserBlock = UserInst->getParent();
106 if (UserBlock == LoopExitBlock)
108 if (L->contains(UserBlock))
110 LLVM_DEBUG(dbgs() <<
"added ext use for " << I.getName() <<
"("
111 << BB->getName() <<
")"
112 <<
": " << UserInst->getName() <<
"("
113 << UserBlock->getName() <<
")"
115 ExternalUsers[&I].push_back(UserInst);
120 for (
const auto &
II : ExternalUsers) {
129 Def->getName() +
".moved", LoopExitBlock->begin());
130 for (
auto *In : Incoming) {
132 if (
Def->getParent() == In || DT.dominates(Def, In)) {
134 NewPhi->addIncoming(Def, In);
142 for (
auto *U :
II.second) {
144 U->replaceUsesOfWith(Def, NewPhi);
157 L->getExitingBlocks(ExitingBlocks);
160 if (ExitingBlocks.
empty())
170 unsigned NumExitingBlocks = ExitingBlocks.
size();
171 for (
unsigned I = 0;
I < NumExitingBlocks; ++
I) {
176 Succ0 = L->contains(Succ0) ? nullptr : Succ0;
183 Succ0 = L->contains(Succ0) ? nullptr : Succ0;
186 Succ1 = L->contains(Succ1) ? nullptr : Succ1;
195 for (
unsigned J = 0; J < Term->getNumSuccessors(); ++J) {
197 if (L->contains(Succ))
200 auto It = BrTargets.
find(Succ);
202 (It != BrTargets.
end()) ? It->second :
nullptr;
204 &DTU,
nullptr, &LI, &UpdatedLI);
206 if (!ExistingTarget) {
215 MultiBrTargetBlocksToFix.
push_back(NewSucc);
223 if (BrTargets.
empty())
224 ExitingBlocks[
I] = NewSucc;
228 BrTargets[Succ] = NewSucc;
236 "unsupported block terminator: unify-loop-exits "
237 "only supports br, callbr, and switch instructions");
244 std::tie(LoopExitBlock, ChangedCFG) = CHub.
finalize(
250 restoreSSA(DT, L, ExitingBlocks, LoopExitBlock);
252#if defined(EXPENSIVE_CHECKS)
253 assert(DT.
verify(DominatorTree::VerificationLevel::Full));
255 assert(DT.
verify(DominatorTree::VerificationLevel::Fast));
267 if (
auto *ParentLoop = L->getParentLoop()) {
268 for (
auto *
G : GuardBlocks) {
269 ParentLoop->addBasicBlockToLoop(
G, LI);
271 for (
auto *
C : MultiBrTargetBlocksToFix) {
272 ParentLoop->addBasicBlockToLoop(
C, LI);
274 ParentLoop->verifyLoop();
277#if defined(EXPENSIVE_CHECKS)
288 for (
auto *L :
Loops) {
295bool UnifyLoopExitsLegacyPass::runOnFunction(
Function &
F) {
296 LLVM_DEBUG(
dbgs() <<
"===== Unifying loop exits in function " <<
F.getName()
298 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
299 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
308 LLVM_DEBUG(
dbgs() <<
"===== Unifying loop exits in function " <<
F.getName()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool runImpl(MachineFunction &MF)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
This file implements a map that provides insertion order iteration.
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static bool unifyLoopExits(DominatorTree &DT, LoopInfo &LI, Loop *L)
unify loop Fixup each natural loop to have a single exit static false void restoreSSA(const DominatorTree &DT, const Loop *L, SmallVectorImpl< BasicBlock * > &Incoming, BasicBlock *LoopExitBlock)
static cl::opt< unsigned > MaxBooleansInControlFlowHub("max-booleans-in-control-flow-hub", cl::init(32), cl::Hidden, cl::desc("Set the maximum number of outgoing blocks for using a boolean " "value to record the exiting block in the ControlFlowHub."))
static bool runImpl(LoopInfo &LI, DominatorTree &DT)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Conditional Branch instruction.
iterator find(const_arg_type_t< KeyT > Val)
Analysis pass which computes a DominatorTree.
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
FunctionPass class - This class is used to implement most global optimizations.
Analysis pass that exposes the LoopInfo for a function.
void verify(const DominatorTreeBase< BlockT, false > &DomTree) const
SmallVector< LoopT *, 4 > getLoopsInPreorder() const
Return all of the loops in the function in preorder across the loop nests, with siblings in forward p...
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
This class implements a map that also provides access to all stored values in a deterministic order.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Unconditional Branch instruction.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI BasicBlock * SplitMultiBrEdge(BasicBlock *MultiBrBlock, BasicBlock *Succ, unsigned SuccIdx, BasicBlock *BrTarget=nullptr, DomTreeUpdater *DTU=nullptr, CycleInfo *CI=nullptr, LoopInfo *LI=nullptr, bool *UpdatedLI=nullptr)
Create a new intermediate target block for a callbr or switch edge.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void initializeUnifyLoopExitsLegacyPassPass(PassRegistry &)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI FunctionPass * createUnifyLoopExitsPass()
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI Printable printBasicBlock(const BasicBlock *BB)
Print BasicBlock BB as an operand or print "<nullptr>" if BB is a nullptr.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Given a set of branch descriptors [BB, Succ0, Succ1], create a "hub" such that the control flow from ...
void addBranch(BasicBlock *BB, BasicBlock *Succ0, BasicBlock *Succ1=nullptr)
LLVM_ABI std::pair< BasicBlock *, bool > finalize(DomTreeUpdater *DTU, SmallVectorImpl< BasicBlock * > &GuardBlocks, const StringRef Prefix, std::optional< unsigned > MaxControlFlowBooleans=std::nullopt)
Return the unified loop exit block and a flag indicating if the CFG was changed at all.