1 //===- UnifyLoopExits.cpp - Redirect exiting edges to one block -*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // For each natural loop with multiple exit blocks, this pass creates a new
10 // block N such that all exiting blocks now branch to N, and then control flow
11 // is redistributed to all the original exit blocks.
13 // Limitation: This assumes that all terminators in the CFG are direct branches
14 // (the "br" instruction). The presence of any other control flow
15 // such as indirectbr, switch or callbr will cause an assert.
17 //===----------------------------------------------------------------------===//
19 #include "llvm/Transforms/Utils/UnifyLoopExits.h"
20 #include "llvm/ADT/MapVector.h"
21 #include "llvm/Analysis/DomTreeUpdater.h"
22 #include "llvm/Analysis/LoopInfo.h"
23 #include "llvm/IR/Constants.h"
24 #include "llvm/IR/Dominators.h"
25 #include "llvm/InitializePasses.h"
26 #include "llvm/Support/CommandLine.h"
27 #include "llvm/Transforms/Utils.h"
28 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
29 #include "llvm/Transforms/Utils/ControlFlowUtils.h"
31 #define DEBUG_TYPE "unify-loop-exits"
35 static cl::opt
<unsigned> MaxBooleansInControlFlowHub(
36 "max-booleans-in-control-flow-hub", cl::init(32), cl::Hidden
,
37 cl::desc("Set the maximum number of outgoing blocks for using a boolean "
38 "value to record the exiting block in the ControlFlowHub."));
41 struct UnifyLoopExitsLegacyPass
: public FunctionPass
{
43 UnifyLoopExitsLegacyPass() : FunctionPass(ID
) {
44 initializeUnifyLoopExitsLegacyPassPass(*PassRegistry::getPassRegistry());
47 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
48 AU
.addRequired
<LoopInfoWrapperPass
>();
49 AU
.addRequired
<DominatorTreeWrapperPass
>();
50 AU
.addPreserved
<LoopInfoWrapperPass
>();
51 AU
.addPreserved
<DominatorTreeWrapperPass
>();
54 bool runOnFunction(Function
&F
) override
;
58 char UnifyLoopExitsLegacyPass::ID
= 0;
60 FunctionPass
*llvm::createUnifyLoopExitsPass() {
61 return new UnifyLoopExitsLegacyPass();
64 INITIALIZE_PASS_BEGIN(UnifyLoopExitsLegacyPass
, "unify-loop-exits",
65 "Fixup each natural loop to have a single exit block",
66 false /* Only looks at CFG */, false /* Analysis Pass */)
67 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass
)
68 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass
)
69 INITIALIZE_PASS_END(UnifyLoopExitsLegacyPass
, "unify-loop-exits",
70 "Fixup each natural loop to have a single exit block",
71 false /* Only looks at CFG */, false /* Analysis Pass */)
73 // The current transform introduces new control flow paths which may break the
74 // SSA requirement that every def must dominate all its uses. For example,
75 // consider a value D defined inside the loop that is used by some instruction
76 // U outside the loop. It follows that D dominates U, since the original
77 // program has valid SSA form. After merging the exits, all paths from D to U
78 // now flow through the unified exit block. In addition, there may be other
79 // paths that do not pass through D, but now reach the unified exit
80 // block. Thus, D no longer dominates U.
82 // Restore the dominance by creating a phi for each such D at the new unified
83 // loop exit. But when doing this, ignore any uses U that are in the new unified
84 // loop exit, since those were introduced specially when the block was created.
86 // The use of SSAUpdater seems like overkill for this operation. The location
87 // for creating the new PHI is well-known, and also the set of incoming blocks
89 static void restoreSSA(const DominatorTree
&DT
, const Loop
*L
,
90 SmallVectorImpl
<BasicBlock
*> &Incoming
,
91 BasicBlock
*LoopExitBlock
) {
92 using InstVector
= SmallVector
<Instruction
*, 8>;
93 using IIMap
= MapVector
<Instruction
*, InstVector
>;
95 for (auto *BB
: L
->blocks()) {
97 for (auto &U
: I
.uses()) {
98 auto UserInst
= cast
<Instruction
>(U
.getUser());
99 auto UserBlock
= UserInst
->getParent();
100 if (UserBlock
== LoopExitBlock
)
102 if (L
->contains(UserBlock
))
104 LLVM_DEBUG(dbgs() << "added ext use for " << I
.getName() << "("
105 << BB
->getName() << ")"
106 << ": " << UserInst
->getName() << "("
107 << UserBlock
->getName() << ")"
109 ExternalUsers
[&I
].push_back(UserInst
);
114 for (const auto &II
: ExternalUsers
) {
115 // For each Def used outside the loop, create NewPhi in
116 // LoopExitBlock. NewPhi receives Def only along exiting blocks that
117 // dominate it, while the remaining values are undefined since those paths
118 // didn't exist in the original CFG.
120 LLVM_DEBUG(dbgs() << "externally used: " << Def
->getName() << "\n");
122 PHINode::Create(Def
->getType(), Incoming
.size(),
123 Def
->getName() + ".moved", LoopExitBlock
->begin());
124 for (auto *In
: Incoming
) {
125 LLVM_DEBUG(dbgs() << "predecessor " << In
->getName() << ": ");
126 if (Def
->getParent() == In
|| DT
.dominates(Def
, In
)) {
127 LLVM_DEBUG(dbgs() << "dominated\n");
128 NewPhi
->addIncoming(Def
, In
);
130 LLVM_DEBUG(dbgs() << "not dominated\n");
131 NewPhi
->addIncoming(PoisonValue::get(Def
->getType()), In
);
135 LLVM_DEBUG(dbgs() << "external users:");
136 for (auto *U
: II
.second
) {
137 LLVM_DEBUG(dbgs() << " " << U
->getName());
138 U
->replaceUsesOfWith(Def
, NewPhi
);
140 LLVM_DEBUG(dbgs() << "\n");
144 static bool unifyLoopExits(DominatorTree
&DT
, LoopInfo
&LI
, Loop
*L
) {
145 // To unify the loop exits, we need a list of the exiting blocks as
146 // well as exit blocks. The functions for locating these lists both
147 // traverse the entire loop body. It is more efficient to first
148 // locate the exiting blocks and then examine their successors to
149 // locate the exit blocks.
150 SmallVector
<BasicBlock
*, 8> ExitingBlocks
;
151 L
->getExitingBlocks(ExitingBlocks
);
153 // Redirect exiting edges through a control flow hub.
155 for (auto *BB
: ExitingBlocks
) {
156 auto *Branch
= cast
<BranchInst
>(BB
->getTerminator());
157 BasicBlock
*Succ0
= Branch
->getSuccessor(0);
158 Succ0
= L
->contains(Succ0
) ? nullptr : Succ0
;
161 Branch
->isUnconditional() ? nullptr : Branch
->getSuccessor(1);
162 Succ1
= L
->contains(Succ1
) ? nullptr : Succ1
;
163 CHub
.addBranch(BB
, Succ0
, Succ1
);
165 LLVM_DEBUG(dbgs() << "Added exiting branch: " << BB
->getName() << " -> {"
166 << (Succ0
? Succ0
->getName() : "<none>") << ", "
167 << (Succ1
? Succ1
->getName() : "<none>") << "}\n");
170 SmallVector
<BasicBlock
*, 8> GuardBlocks
;
171 DomTreeUpdater
DTU(DT
, DomTreeUpdater::UpdateStrategy::Eager
);
172 BasicBlock
*LoopExitBlock
= CHub
.finalize(
173 &DTU
, GuardBlocks
, "loop.exit", MaxBooleansInControlFlowHub
.getValue());
175 restoreSSA(DT
, L
, ExitingBlocks
, LoopExitBlock
);
177 #if defined(EXPENSIVE_CHECKS)
178 assert(DT
.verify(DominatorTree::VerificationLevel::Full
));
180 assert(DT
.verify(DominatorTree::VerificationLevel::Fast
));
181 #endif // EXPENSIVE_CHECKS
184 // The guard blocks were created outside the loop, so they need to become
185 // members of the parent loop.
186 if (auto ParentLoop
= L
->getParentLoop()) {
187 for (auto *G
: GuardBlocks
) {
188 ParentLoop
->addBasicBlockToLoop(G
, LI
);
190 ParentLoop
->verifyLoop();
193 #if defined(EXPENSIVE_CHECKS)
195 #endif // EXPENSIVE_CHECKS
200 static bool runImpl(LoopInfo
&LI
, DominatorTree
&DT
) {
202 bool Changed
= false;
203 auto Loops
= LI
.getLoopsInPreorder();
204 for (auto *L
: Loops
) {
205 LLVM_DEBUG(dbgs() << "Processing loop:\n"; L
->print(dbgs()));
206 Changed
|= unifyLoopExits(DT
, LI
, L
);
211 bool UnifyLoopExitsLegacyPass::runOnFunction(Function
&F
) {
212 LLVM_DEBUG(dbgs() << "===== Unifying loop exits in function " << F
.getName()
214 auto &LI
= getAnalysis
<LoopInfoWrapperPass
>().getLoopInfo();
215 auto &DT
= getAnalysis
<DominatorTreeWrapperPass
>().getDomTree();
217 assert(hasOnlySimpleTerminator(F
) && "Unsupported block terminator.");
219 return runImpl(LI
, DT
);
224 PreservedAnalyses
UnifyLoopExitsPass::run(Function
&F
,
225 FunctionAnalysisManager
&AM
) {
226 LLVM_DEBUG(dbgs() << "===== Unifying loop exits in function " << F
.getName()
228 auto &LI
= AM
.getResult
<LoopAnalysis
>(F
);
229 auto &DT
= AM
.getResult
<DominatorTreeAnalysis
>(F
);
231 if (!runImpl(LI
, DT
))
232 return PreservedAnalyses::all();
233 PreservedAnalyses PA
;
234 PA
.preserve
<LoopAnalysis
>();
235 PA
.preserve
<DominatorTreeAnalysis
>();