LLVM 23.0.0git
UnifyLoopExits.cpp
Go to the documentation of this file.
1//===- UnifyLoopExits.cpp - Redirect exiting edges to one block -*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
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.
12//
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 or switch will cause an assert.
16// The callbr terminator is supported by creating intermediate
17// target blocks that unconditionally branch to the original target
18// blocks. These intermediate target blocks can then be redirected
19// through the ControlFlowHub as usual.
20//
21//===----------------------------------------------------------------------===//
22
24#include "llvm/ADT/DenseMap.h"
25#include "llvm/ADT/MapVector.h"
28#include "llvm/IR/Constants.h"
29#include "llvm/IR/Dominators.h"
35
36#define DEBUG_TYPE "unify-loop-exits"
37
38using namespace llvm;
39
41 "max-booleans-in-control-flow-hub", cl::init(32), cl::Hidden,
42 cl::desc("Set the maximum number of outgoing blocks for using a boolean "
43 "value to record the exiting block in the ControlFlowHub."));
44
45namespace {
46struct UnifyLoopExitsLegacyPass : public FunctionPass {
47 static char ID;
48 UnifyLoopExitsLegacyPass() : FunctionPass(ID) {
50 }
51
52 void getAnalysisUsage(AnalysisUsage &AU) const override {
53 AU.addRequired<LoopInfoWrapperPass>();
54 AU.addRequired<DominatorTreeWrapperPass>();
55 AU.addPreserved<LoopInfoWrapperPass>();
56 AU.addPreserved<DominatorTreeWrapperPass>();
57 }
58
59 bool runOnFunction(Function &F) override;
60};
61} // namespace
62
63char UnifyLoopExitsLegacyPass::ID = 0;
64
66 return new UnifyLoopExitsLegacyPass();
67}
68
69INITIALIZE_PASS_BEGIN(UnifyLoopExitsLegacyPass, "unify-loop-exits",
70 "Fixup each natural loop to have a single exit block",
71 false /* Only looks at CFG */, false /* Analysis Pass */)
74INITIALIZE_PASS_END(UnifyLoopExitsLegacyPass, "unify-loop-exits",
75 "Fixup each natural loop to have a single exit block",
76 false /* Only looks at CFG */, false /* Analysis Pass */)
77
78// The current transform introduces new control flow paths which may break the
79// SSA requirement that every def must dominate all its uses. For example,
80// consider a value D defined inside the loop that is used by some instruction
81// U outside the loop. It follows that D dominates U, since the original
82// program has valid SSA form. After merging the exits, all paths from D to U
83// now flow through the unified exit block. In addition, there may be other
84// paths that do not pass through D, but now reach the unified exit
85// block. Thus, D no longer dominates U.
86//
87// Restore the dominance by creating a phi for each such D at the new unified
88// loop exit. But when doing this, ignore any uses U that are in the new unified
89// loop exit, since those were introduced specially when the block was created.
90//
91// The use of SSAUpdater seems like overkill for this operation. The location
92// for creating the new PHI is well-known, and also the set of incoming blocks
93// to the new PHI.
95 SmallVectorImpl<BasicBlock *> &Incoming,
96 BasicBlock *LoopExitBlock) {
97 using InstVector = SmallVector<Instruction *, 8>;
99 IIMap ExternalUsers;
100 for (auto *BB : L->blocks()) {
101 for (auto &I : *BB) {
102 for (auto &U : I.uses()) {
103 auto UserInst = cast<Instruction>(U.getUser());
104 auto UserBlock = UserInst->getParent();
105 if (UserBlock == LoopExitBlock)
106 continue;
107 if (L->contains(UserBlock))
108 continue;
109 LLVM_DEBUG(dbgs() << "added ext use for " << I.getName() << "("
110 << BB->getName() << ")"
111 << ": " << UserInst->getName() << "("
112 << UserBlock->getName() << ")"
113 << "\n");
114 ExternalUsers[&I].push_back(UserInst);
115 }
116 }
117 }
118
119 for (const auto &II : ExternalUsers) {
120 // For each Def used outside the loop, create NewPhi in
121 // LoopExitBlock. NewPhi receives Def only along exiting blocks that
122 // dominate it, while the remaining values are undefined since those paths
123 // didn't exist in the original CFG.
124 auto Def = II.first;
125 LLVM_DEBUG(dbgs() << "externally used: " << Def->getName() << "\n");
126 auto NewPhi =
127 PHINode::Create(Def->getType(), Incoming.size(),
128 Def->getName() + ".moved", LoopExitBlock->begin());
129 for (auto *In : Incoming) {
130 LLVM_DEBUG(dbgs() << "predecessor " << In->getName() << ": ");
131 if (Def->getParent() == In || DT.dominates(Def, In)) {
132 LLVM_DEBUG(dbgs() << "dominated\n");
133 NewPhi->addIncoming(Def, In);
134 } else {
135 LLVM_DEBUG(dbgs() << "not dominated\n");
136 NewPhi->addIncoming(PoisonValue::get(Def->getType()), In);
137 }
138 }
139
140 LLVM_DEBUG(dbgs() << "external users:");
141 for (auto *U : II.second) {
142 LLVM_DEBUG(dbgs() << " " << U->getName());
143 U->replaceUsesOfWith(Def, NewPhi);
144 }
145 LLVM_DEBUG(dbgs() << "\n");
146 }
147}
148
149static bool unifyLoopExits(DominatorTree &DT, LoopInfo &LI, Loop *L) {
150 // To unify the loop exits, we need a list of the exiting blocks as
151 // well as exit blocks. The functions for locating these lists both
152 // traverse the entire loop body. It is more efficient to first
153 // locate the exiting blocks and then examine their successors to
154 // locate the exit blocks.
155 SmallVector<BasicBlock *, 8> ExitingBlocks;
156 L->getExitingBlocks(ExitingBlocks);
157
158 // No exit blocks, so nothing to do. Just return.
159 if (ExitingBlocks.empty())
160 return false;
161
162 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
163 SmallVector<BasicBlock *, 8> CallBrTargetBlocksToFix;
164
165 // Redirect exiting edges through a control flow hub.
166 ControlFlowHub CHub;
167 bool Changed = false;
168
169 unsigned NumExitingBlocks = ExitingBlocks.size();
170 for (unsigned I = 0; I < NumExitingBlocks; ++I) {
171 BasicBlock *BB = ExitingBlocks[I];
173 BasicBlock *Succ0 = Branch->getSuccessor(0);
174 Succ0 = L->contains(Succ0) ? nullptr : Succ0;
175 CHub.addBranch(BB, Succ0);
176
177 LLVM_DEBUG(dbgs() << "Added extiting branch: " << printBasicBlock(BB)
178 << " -> " << printBasicBlock(Succ0) << '\n');
179 } else if (CondBrInst *Branch = dyn_cast<CondBrInst>(BB->getTerminator())) {
180 BasicBlock *Succ0 = Branch->getSuccessor(0);
181 Succ0 = L->contains(Succ0) ? nullptr : Succ0;
182
183 BasicBlock *Succ1 = Branch->getSuccessor(1);
184 Succ1 = L->contains(Succ1) ? nullptr : Succ1;
185 CHub.addBranch(BB, Succ0, Succ1);
186
187 LLVM_DEBUG(dbgs() << "Added extiting branch: " << printBasicBlock(BB)
188 << " -> " << printBasicBlock(Succ0)
189 << (Succ0 && Succ1 ? " " : "") << printBasicBlock(Succ1)
190 << '\n');
191 } else if (CallBrInst *CallBr = dyn_cast<CallBrInst>(BB->getTerminator())) {
193 for (unsigned J = 0; J < CallBr->getNumSuccessors(); ++J) {
194 BasicBlock *Succ = CallBr->getSuccessor(J);
195 if (L->contains(Succ))
196 continue;
197 bool UpdatedLI;
198 auto It = CallBrTargets.find(Succ);
199 BasicBlock *ExistingTarget =
200 (It != CallBrTargets.end()) ? It->second : nullptr;
201 BasicBlock *NewSucc = SplitCallBrEdge(BB, Succ, J, ExistingTarget, &DTU,
202 nullptr, &LI, &UpdatedLI);
203
204 if (!ExistingTarget) {
205 // SplitCallBrEdge modifies the CFG because it creates an intermediate
206 // block. So we need to set the changed flag no matter what the
207 // ControlFlowHub is going to do later.
208 Changed = true;
209 // Even if CallBr and Succ do not have a common parent loop, we need
210 // to add the new target block to the parent loop of the current loop.
211 if (!UpdatedLI)
212 CallBrTargetBlocksToFix.push_back(NewSucc);
213 // ExitingBlocks is later used to restore SSA, so we need to make sure
214 // that the blocks used for phi nodes in the guard blocks match the
215 // predecessors of the guard blocks, which, in the case of callbr, are
216 // the new intermediate target blocks instead of the callbr blocks
217 // themselves. If only one exiting block is generated, the callbr
218 // block itself is overwritten, while further blocks are appended as
219 // additional exiting blocks.
220 if (CallBrTargets.empty())
221 ExitingBlocks[I] = NewSucc;
222 else
223 ExitingBlocks.push_back(NewSucc);
224 CHub.addBranch(NewSucc, Succ);
225 CallBrTargets[Succ] = NewSucc;
226 }
227 LLVM_DEBUG(dbgs() << "Added exiting branch: "
228 << printBasicBlock(NewSucc) << " -> "
229 << printBasicBlock(Succ) << '\n');
230 }
231 } else {
232 llvm_unreachable("unsupported block terminator");
233 }
234 }
235
237 BasicBlock *LoopExitBlock;
238 bool ChangedCFG;
239 std::tie(LoopExitBlock, ChangedCFG) = CHub.finalize(
240 &DTU, GuardBlocks, "loop.exit", MaxBooleansInControlFlowHub.getValue());
241 ChangedCFG |= Changed;
242 if (!ChangedCFG)
243 return false;
244
245 restoreSSA(DT, L, ExitingBlocks, LoopExitBlock);
246
247#if defined(EXPENSIVE_CHECKS)
248 assert(DT.verify(DominatorTree::VerificationLevel::Full));
249#else
250 assert(DT.verify(DominatorTree::VerificationLevel::Fast));
251#endif // EXPENSIVE_CHECKS
252 L->verifyLoop();
253
254 // The guard blocks were created outside the loop, so they need to become
255 // members of the parent loop.
256 // Same goes for the callbr target blocks. Although we try to add them to the
257 // smallest common parent loop of the callbr block and the corresponding
258 // original target block, there might not have been such a loop, in which case
259 // the newly created callbr target blocks are not part of any loop. For nested
260 // loops, this might result in them leading to a loop with multiple entry
261 // points.
262 if (auto *ParentLoop = L->getParentLoop()) {
263 for (auto *G : GuardBlocks) {
264 ParentLoop->addBasicBlockToLoop(G, LI);
265 }
266 for (auto *C : CallBrTargetBlocksToFix) {
267 ParentLoop->addBasicBlockToLoop(C, LI);
268 }
269 ParentLoop->verifyLoop();
270 }
271
272#if defined(EXPENSIVE_CHECKS)
273 LI.verify(DT);
274#endif // EXPENSIVE_CHECKS
275
276 return true;
277}
278
279static bool runImpl(LoopInfo &LI, DominatorTree &DT) {
280
281 bool Changed = false;
282 auto Loops = LI.getLoopsInPreorder();
283 for (auto *L : Loops) {
284 LLVM_DEBUG(dbgs() << "Processing loop:\n"; L->print(dbgs()));
285 Changed |= unifyLoopExits(DT, LI, L);
286 }
287 return Changed;
288}
289
290bool UnifyLoopExitsLegacyPass::runOnFunction(Function &F) {
291 LLVM_DEBUG(dbgs() << "===== Unifying loop exits in function " << F.getName()
292 << "\n");
293 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
294 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
295
296 return runImpl(LI, DT);
297}
298
299namespace llvm {
300
303 LLVM_DEBUG(dbgs() << "===== Unifying loop exits in function " << F.getName()
304 << "\n");
305 auto &LI = AM.getResult<LoopAnalysis>(F);
306 auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
307
308 if (!runImpl(LI, DT))
309 return PreservedAnalyses::all();
313 return PA;
314}
315} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
static bool runImpl(MachineFunction &MF)
Definition CFIFixup.cpp:304
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)
Hexagon Hardware Loops
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
This file implements a map that provides insertion order iteration.
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
#define LLVM_DEBUG(...)
Definition Debug.h:119
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.
Definition BasicBlock.h:62
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
CallBr instruction, tracking function calls that may not return control but instead transfer it to a ...
Conditional Branch instruction.
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
bool empty() const
Definition DenseMap.h:171
iterator end()
Definition DenseMap.h:141
Analysis pass which computes a DominatorTree.
Definition Dominators.h:270
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
Legacy analysis pass which computes a DominatorTree.
Definition Dominators.h:306
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:151
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
Analysis pass that exposes the LoopInfo for a function.
Definition LoopInfo.h:587
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.
Definition LoopInfo.h:612
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
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.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Definition Analysis.h:132
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)
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
initializer< Ty > init(const Ty &Val)
NodeAddr< DefNode * > Def
Definition RDFGraph.h:386
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI void initializeUnifyLoopExitsLegacyPassPass(PassRegistry &)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
LLVM_ABI FunctionPass * createUnifyLoopExitsPass()
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 BasicBlock * SplitCallBrEdge(BasicBlock *CallBrBlock, BasicBlock *Succ, unsigned SuccIdx, BasicBlock *CallBrTarget=nullptr, DomTreeUpdater *DTU=nullptr, CycleInfo *CI=nullptr, LoopInfo *LI=nullptr, bool *UpdatedLI=nullptr)
Create a new intermediate target block for a callbr edge.
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.