LLVM 22.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;
173 bool ChangedCFG;
174 std::tie(LoopExitBlock, ChangedCFG) = CHub.finalize(
175 &DTU, GuardBlocks, "loop.exit", MaxBooleansInControlFlowHub.getValue());
176 if (!ChangedCFG)
177 return false;
178
179 restoreSSA(DT, L, ExitingBlocks, LoopExitBlock);
180
181#if defined(EXPENSIVE_CHECKS)
182 assert(DT.verify(DominatorTree::VerificationLevel::Full));
183#else
184 assert(DT.verify(DominatorTree::VerificationLevel::Fast));
185#endif // EXPENSIVE_CHECKS
186 L->verifyLoop();
187
188 // The guard blocks were created outside the loop, so they need to become
189 // members of the parent loop.
190 if (auto ParentLoop = L->getParentLoop()) {
191 for (auto *G : GuardBlocks) {
192 ParentLoop->addBasicBlockToLoop(G, LI);
193 }
194 ParentLoop->verifyLoop();
195 }
196
197#if defined(EXPENSIVE_CHECKS)
198 LI.verify(DT);
199#endif // EXPENSIVE_CHECKS
200
201 return true;
202}
203
204static bool runImpl(LoopInfo &LI, DominatorTree &DT) {
205
206 bool Changed = false;
207 auto Loops = LI.getLoopsInPreorder();
208 for (auto *L : Loops) {
209 LLVM_DEBUG(dbgs() << "Processing loop:\n"; L->print(dbgs()));
210 Changed |= unifyLoopExits(DT, LI, L);
211 }
212 return Changed;
213}
214
215bool UnifyLoopExitsLegacyPass::runOnFunction(Function &F) {
216 LLVM_DEBUG(dbgs() << "===== Unifying loop exits in function " << F.getName()
217 << "\n");
218 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
219 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
220
221 assert(hasOnlySimpleTerminator(F) && "Unsupported block terminator.");
222
223 return runImpl(LI, DT);
224}
225
226namespace llvm {
227
230 LLVM_DEBUG(dbgs() << "===== Unifying loop exits in function " << F.getName()
231 << "\n");
232 auto &LI = AM.getResult<LoopAnalysis>(F);
233 auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
234
235 if (!runImpl(LI, DT))
236 return PreservedAnalyses::all();
240 return PA;
241}
242} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runImpl(Function &F, const TargetLowering &TLI)
Definition: ExpandFp.cpp:597
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: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
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:255
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:412
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:62
Analysis pass which computes a DominatorTree.
Definition: Dominators.h:284
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:322
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:165
LLVM_ABI 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:135
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:314
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:570
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:597
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: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 LLVM_ABI 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:112
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1885
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...
Definition: SmallVector.h:574
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:322
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:444
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
LLVM_ABI bool hasOnlySimpleTerminator(const Function &F)
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:207
LLVM_ABI FunctionPass * createUnifyLoopExitsPass()
Given a set of branch descriptors [BB, Succ0, Succ1], create a "hub" such that the control flow from ...
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.
void addBranch(BasicBlock *BB, BasicBlock *Succ0, BasicBlock *Succ1)
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...