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 {
48 AU.addRequired<LoopInfoWrapperPass>();
49 AU.addRequired<DominatorTreeWrapperPass>();
50 AU.addPreserved<LoopInfoWrapperPass>();
51 AU.addPreserved<DominatorTreeWrapperPass>();
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 runOnFunction(Function &F, bool PostInlining)
static bool runImpl(Function &F, const TargetLowering &TLI, AssumptionCache *AC)
Definition ExpandFp.cpp:992
Hexagon Hardware Loops
#define F(x, y, z)
Definition MD5.cpp:55
#define G(x, y, z)
Definition MD5.cpp:56
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:114
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
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
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:569
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:596
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...
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...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
Changed
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
initializer< Ty > init(const Ty &Val)
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
This is an optimization pass for GlobalISel generic memory operations.
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()
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
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...