LLVM 20.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, switch or callbr will cause an assert.
16//
17//===----------------------------------------------------------------------===//
18
20#include "llvm/ADT/MapVector.h"
23#include "llvm/IR/Constants.h"
24#include "llvm/IR/Dominators.h"
30
31#define DEBUG_TYPE "unify-loop-exits"
32
33using namespace llvm;
34
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."));
39
40namespace {
41struct UnifyLoopExitsLegacyPass : public FunctionPass {
42 static char ID;
43 UnifyLoopExitsLegacyPass() : FunctionPass(ID) {
45 }
46
47 void getAnalysisUsage(AnalysisUsage &AU) const override {
52 }
53
54 bool runOnFunction(Function &F) override;
55};
56} // namespace
57
58char UnifyLoopExitsLegacyPass::ID = 0;
59
61 return new UnifyLoopExitsLegacyPass();
62}
63
64INITIALIZE_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 */)
69INITIALIZE_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 */)
72
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.
81//
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.
85//
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
88// to the new PHI.
91 BasicBlock *LoopExitBlock) {
92 using InstVector = SmallVector<Instruction *, 8>;
94 IIMap ExternalUsers;
95 for (auto *BB : L->blocks()) {
96 for (auto &I : *BB) {
97 for (auto &U : I.uses()) {
98 auto UserInst = cast<Instruction>(U.getUser());
99 auto UserBlock = UserInst->getParent();
100 if (UserBlock == LoopExitBlock)
101 continue;
102 if (L->contains(UserBlock))
103 continue;
104 LLVM_DEBUG(dbgs() << "added ext use for " << I.getName() << "("
105 << BB->getName() << ")"
106 << ": " << UserInst->getName() << "("
107 << UserBlock->getName() << ")"
108 << "\n");
109 ExternalUsers[&I].push_back(UserInst);
110 }
111 }
112 }
113
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.
119 auto Def = II.first;
120 LLVM_DEBUG(dbgs() << "externally used: " << Def->getName() << "\n");
121 auto NewPhi =
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);
129 } else {
130 LLVM_DEBUG(dbgs() << "not dominated\n");
131 NewPhi->addIncoming(PoisonValue::get(Def->getType()), In);
132 }
133 }
134
135 LLVM_DEBUG(dbgs() << "external users:");
136 for (auto *U : II.second) {
137 LLVM_DEBUG(dbgs() << " " << U->getName());
138 U->replaceUsesOfWith(Def, NewPhi);
139 }
140 LLVM_DEBUG(dbgs() << "\n");
141 }
142}
143
144static 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);
152
153 // Redirect exiting edges through a control flow hub.
154 ControlFlowHub CHub;
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;
159
160 BasicBlock *Succ1 =
161 Branch->isUnconditional() ? nullptr : Branch->getSuccessor(1);
162 Succ1 = L->contains(Succ1) ? nullptr : Succ1;
163 CHub.addBranch(BB, Succ0, Succ1);
164
165 LLVM_DEBUG(dbgs() << "Added exiting branch: " << BB->getName() << " -> {"
166 << (Succ0 ? Succ0->getName() : "<none>") << ", "
167 << (Succ1 ? Succ1->getName() : "<none>") << "}\n");
168 }
169
171 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
172 BasicBlock *LoopExitBlock = CHub.finalize(
173 &DTU, GuardBlocks, "loop.exit", MaxBooleansInControlFlowHub.getValue());
174
175 restoreSSA(DT, L, ExitingBlocks, LoopExitBlock);
176
177#if defined(EXPENSIVE_CHECKS)
178 assert(DT.verify(DominatorTree::VerificationLevel::Full));
179#else
180 assert(DT.verify(DominatorTree::VerificationLevel::Fast));
181#endif // EXPENSIVE_CHECKS
182 L->verifyLoop();
183
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);
189 }
190 ParentLoop->verifyLoop();
191 }
192
193#if defined(EXPENSIVE_CHECKS)
194 LI.verify(DT);
195#endif // EXPENSIVE_CHECKS
196
197 return true;
198}
199
200static bool runImpl(LoopInfo &LI, DominatorTree &DT) {
201
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);
207 }
208 return Changed;
209}
210
211bool UnifyLoopExitsLegacyPass::runOnFunction(Function &F) {
212 LLVM_DEBUG(dbgs() << "===== Unifying loop exits in function " << F.getName()
213 << "\n");
214 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
215 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
216
217 assert(hasOnlySimpleTerminator(F) && "Unsupported block terminator.");
218
219 return runImpl(LI, DT);
220}
221
222namespace llvm {
223
226 LLVM_DEBUG(dbgs() << "===== Unifying loop exits in function " << F.getName()
227 << "\n");
228 auto &LI = AM.getResult<LoopAnalysis>(F);
229 auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
230
231 if (!runImpl(LI, DT))
232 return PreservedAnalyses::all();
236 return PA;
237}
238} // namespace llvm
aarch64 promote const
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define LLVM_DEBUG(...)
Definition: Debug.h:106
static bool runImpl(Function &F, const TargetLowering &TLI)
Hexagon Hardware Loops
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
This file implements a map that provides insertion order iteration.
uint64_t IntrinsicInst * II
PowerPC TLS Dynamic Call Fixup
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:57
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
unify loop exits
unify loop Fixup each natural loop to have a single exit block
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)
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:410
Represent the analysis usage information of a pass.
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:61
Analysis pass which computes a DominatorTree.
Definition: Dominators.h:279
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:317
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:162
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Definition: Dominators.cpp:122
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
Analysis pass that exposes the LoopInfo for a function.
Definition: LoopInfo.h:566
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:593
Represents a single loop in the control flow graph.
Definition: LoopInfo.h:39
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:36
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 PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:98
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1878
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
void preserve()
Mark an analysis as preserved.
Definition: Analysis.h:131
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool hasOnlySimpleTerminator(const Function &F)
void initializeUnifyLoopExitsLegacyPassPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
FunctionPass * createUnifyLoopExitsPass()
Given a set of branch descriptors [BB, Succ0, Succ1], create a "hub" such that the control flow from ...
BasicBlock * finalize(DomTreeUpdater *DTU, SmallVectorImpl< BasicBlock * > &GuardBlocks, const StringRef Prefix, std::optional< unsigned > MaxControlFlowBooleans=std::nullopt)
void addBranch(BasicBlock *BB, BasicBlock *Succ0, BasicBlock *Succ1)
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...