Movatterモバイル変換


[0]ホーム

URL:


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
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"
30
31#define DEBUG_TYPE "unify-loop-exits"
32
33using namespacellvm;
34
35staticcl::opt<unsigned>MaxBooleansInControlFlowHub(
36"max-booleans-in-control-flow-hub",cl::init(32),cl::Hidden,
37cl::desc("Set the maximum number of outgoing blocks for using a boolean "
38"value to record the exiting block in the ControlFlowHub."));
39
40namespace{
41structUnifyLoopExitsLegacyPass :publicFunctionPass {
42staticcharID;
43 UnifyLoopExitsLegacyPass() :FunctionPass(ID) {
44initializeUnifyLoopExitsLegacyPassPass(*PassRegistry::getPassRegistry());
45 }
46
47voidgetAnalysisUsage(AnalysisUsage &AU) const override{
48 AU.addRequired<LoopInfoWrapperPass>();
49 AU.addRequired<DominatorTreeWrapperPass>();
50 AU.addPreserved<LoopInfoWrapperPass>();
51 AU.addPreserved<DominatorTreeWrapperPass>();
52 }
53
54boolrunOnFunction(Function &F)override;
55};
56}// namespace
57
58char UnifyLoopExitsLegacyPass::ID = 0;
59
60FunctionPass *llvm::createUnifyLoopExitsPass() {
61returnnew UnifyLoopExitsLegacyPass();
62}
63
64INITIALIZE_PASS_BEGIN(UnifyLoopExitsLegacyPass,"unify-loop-exits",
65"Fixup each natural loop to have a single exit block",
66false/* Only looks at CFG */,false/* Analysis Pass */)
67INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
68INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
69INITIALIZE_PASS_END(UnifyLoopExitsLegacyPass, "unify-loop-exits",
70 "Fixup each natural loop to have a single exitblock",
71false/* 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.
89staticvoidrestoreSSA(constDominatorTree &DT,constLoop *L,
90SmallVectorImpl<BasicBlock *> &Incoming,
91BasicBlock *LoopExitBlock) {
92usingInstVector =SmallVector<Instruction *, 8>;
93usingIIMap =MapVector<Instruction *, InstVector>;
94 IIMap ExternalUsers;
95for (auto *BB : L->blocks()) {
96for (auto &I : *BB) {
97for (auto &U :I.uses()) {
98auto UserInst = cast<Instruction>(U.getUser());
99auto UserBlock = UserInst->getParent();
100if (UserBlock == LoopExitBlock)
101continue;
102if (L->contains(UserBlock))
103continue;
104LLVM_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
114for (constauto &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.
119auto Def =II.first;
120LLVM_DEBUG(dbgs() <<"externally used: " << Def->getName() <<"\n");
121auto NewPhi =
122PHINode::Create(Def->getType(),Incoming.size(),
123 Def->getName() +".moved", LoopExitBlock->begin());
124for (auto *In :Incoming) {
125LLVM_DEBUG(dbgs() <<"predecessor " << In->getName() <<": ");
126if (Def->getParent() == In || DT.dominates(Def, In)) {
127LLVM_DEBUG(dbgs() <<"dominated\n");
128 NewPhi->addIncoming(Def, In);
129 }else {
130LLVM_DEBUG(dbgs() <<"not dominated\n");
131 NewPhi->addIncoming(PoisonValue::get(Def->getType()), In);
132 }
133 }
134
135LLVM_DEBUG(dbgs() <<"external users:");
136for (auto *U :II.second) {
137LLVM_DEBUG(dbgs() <<" " << U->getName());
138 U->replaceUsesOfWith(Def, NewPhi);
139 }
140LLVM_DEBUG(dbgs() <<"\n");
141 }
142}
143
144staticboolunifyLoopExits(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.
150SmallVector<BasicBlock *, 8> ExitingBlocks;
151 L->getExitingBlocks(ExitingBlocks);
152
153// Redirect exiting edges through a control flow hub.
154ControlFlowHub CHub;
155for (auto *BB : ExitingBlocks) {
156auto *Branch = cast<BranchInst>(BB->getTerminator());
157BasicBlock *Succ0 = Branch->getSuccessor(0);
158 Succ0 = L->contains(Succ0) ? nullptr : Succ0;
159
160BasicBlock *Succ1 =
161 Branch->isUnconditional() ? nullptr : Branch->getSuccessor(1);
162 Succ1 = L->contains(Succ1) ? nullptr : Succ1;
163 CHub.addBranch(BB, Succ0, Succ1);
164
165LLVM_DEBUG(dbgs() <<"Added exiting branch: " << BB->getName() <<" -> {"
166 << (Succ0 ? Succ0->getName() :"<none>") <<", "
167 << (Succ1 ? Succ1->getName() :"<none>") <<"}\n");
168 }
169
170SmallVector<BasicBlock *, 8> GuardBlocks;
171DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
172BasicBlock *LoopExitBlock = CHub.finalize(
173 &DTU, GuardBlocks,"loop.exit",MaxBooleansInControlFlowHub.getValue());
174
175restoreSSA(DT, L, ExitingBlocks, LoopExitBlock);
176
177#if defined(EXPENSIVE_CHECKS)
178assert(DT.verify(DominatorTree::VerificationLevel::Full));
179#else
180assert(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.
186if (auto ParentLoop = L->getParentLoop()) {
187for (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
197returntrue;
198}
199
200staticboolrunImpl(LoopInfo &LI,DominatorTree &DT) {
201
202bool Changed =false;
203autoLoops = LI.getLoopsInPreorder();
204for (auto *L :Loops) {
205LLVM_DEBUG(dbgs() <<"Processing loop:\n"; L->print(dbgs()));
206 Changed |=unifyLoopExits(DT, LI, L);
207 }
208return Changed;
209}
210
211bool UnifyLoopExitsLegacyPass::runOnFunction(Function &F) {
212LLVM_DEBUG(dbgs() <<"===== Unifying loop exits in function " <<F.getName()
213 <<"\n");
214auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
215auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
216
217assert(hasOnlySimpleTerminator(F) &&"Unsupported block terminator.");
218
219returnrunImpl(LI, DT);
220}
221
222namespacellvm {
223
224PreservedAnalysesUnifyLoopExitsPass::run(Function &F,
225FunctionAnalysisManager &AM) {
226LLVM_DEBUG(dbgs() <<"===== Unifying loop exits in function " <<F.getName()
227 <<"\n");
228auto &LI = AM.getResult<LoopAnalysis>(F);
229auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
230
231if (!runImpl(LI, DT))
232returnPreservedAnalyses::all();
233PreservedAnalyses PA;
234 PA.preserve<LoopAnalysis>();
235 PA.preserve<DominatorTreeAnalysis>();
236return PA;
237}
238}// namespace llvm
const
aarch64 promote const
Definition:AArch64PromoteConstant.cpp:230
BasicBlockUtils.h
CommandLine.h
Constants.h
This file contains the declarations for the subclasses of Constant, which represent the different fla...
ControlFlowUtils.h
LLVM_DEBUG
#define LLVM_DEBUG(...)
Definition:Debug.h:106
DomTreeUpdater.h
Dominators.h
runImpl
static bool runImpl(Function &F, const TargetLowering &TLI)
Definition:ExpandLargeDivRem.cpp:79
Loops
Hexagon Hardware Loops
Definition:HexagonHardwareLoops.cpp:373
InitializePasses.h
LoopInfo.h
F
#define F(x, y, z)
Definition:MD5.cpp:55
I
#define I(x, y, z)
Definition:MD5.cpp:58
G
#define G(x, y, z)
Definition:MD5.cpp:56
MapVector.h
This file implements a map that provides insertion order iteration.
II
uint64_t IntrinsicInst * II
Definition:NVVMIntrRange.cpp:51
Fixup
PowerPC TLS Dynamic Call Fixup
Definition:PPCTLSDynamicCall.cpp:339
INITIALIZE_PASS_DEPENDENCY
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition:PassSupport.h:55
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition:PassSupport.h:57
INITIALIZE_PASS_BEGIN
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition:PassSupport.h:52
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Utils.h
exits
unify loop exits
Definition:UnifyLoopExits.cpp:69
block
unify loop Fixup each natural loop to have a single exit block
Definition:UnifyLoopExits.cpp:70
unifyLoopExits
static bool unifyLoopExits(DominatorTree &DT, LoopInfo &LI, Loop *L)
Definition:UnifyLoopExits.cpp:144
restoreSSA
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)
Definition:UnifyLoopExits.cpp:89
MaxBooleansInControlFlowHub
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."))
runImpl
static bool runImpl(LoopInfo &LI, DominatorTree &DT)
Definition:UnifyLoopExits.cpp:200
UnifyLoopExits.h
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition:PassManager.h:253
llvm::AnalysisManager::getResult
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition:PassManager.h:410
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition:PassAnalysisSupport.h:47
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition:PassAnalysisSupport.h:75
llvm::AnalysisUsage::addPreserved
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Definition:PassAnalysisSupport.h:98
llvm::BasicBlock
LLVM Basic Block Representation.
Definition:BasicBlock.h:61
llvm::DomTreeUpdater
Definition:DomTreeUpdater.h:30
llvm::DominatorTreeAnalysis
Analysis pass which computes a DominatorTree.
Definition:Dominators.h:279
llvm::DominatorTreeBase::verify
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
Definition:GenericDomTree.h:905
llvm::DominatorTreeWrapperPass
Legacy analysis pass which computes a DominatorTree.
Definition:Dominators.h:317
llvm::DominatorTree
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition:Dominators.h:162
llvm::DominatorTree::dominates
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
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition:Pass.h:310
llvm::FunctionPass::runOnFunction
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
llvm::Function
Definition:Function.h:63
llvm::LoopAnalysis
Analysis pass that exposes the LoopInfo for a function.
Definition:LoopInfo.h:566
llvm::LoopInfoBase::verify
void verify(const DominatorTreeBase< BlockT, false > &DomTree) const
Definition:GenericLoopInfoImpl.h:718
llvm::LoopInfoBase::getLoopsInPreorder
SmallVector< LoopT *, 4 > getLoopsInPreorder() const
Return all of the loops in the function in preorder across the loop nests, with siblings in forward p...
Definition:GenericLoopInfoImpl.h:606
llvm::LoopInfoWrapperPass
The legacy pass manager's analysis pass to compute loop information.
Definition:LoopInfo.h:593
llvm::LoopInfo
Definition:LoopInfo.h:407
llvm::Loop
Represents a single loop in the control flow graph.
Definition:LoopInfo.h:39
llvm::MapVector
This class implements a map that also provides access to all stored values in a deterministic order.
Definition:MapVector.h:36
llvm::PHINode::Create
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...
Definition:Instructions.h:2635
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition:PassRegistry.cpp:24
llvm::Pass::getAnalysisUsage
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition:Pass.cpp:98
llvm::PoisonValue::get
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition:Constants.cpp:1878
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition:Analysis.h:111
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition:Analysis.h:117
llvm::PreservedAnalyses::preserve
void preserve()
Mark an analysis as preserved.
Definition:Analysis.h:131
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition:SmallVector.h:573
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition:SmallVector.h:1196
llvm::UnifyLoopExitsPass::run
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition:UnifyLoopExits.cpp:224
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition:Value.cpp:309
llvm::cl::opt
Definition:CommandLine.h:1423
unsigned
false
Definition:StackSlotColoring.cpp:193
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition:CallingConv.h:24
llvm::cl::Hidden
@ Hidden
Definition:CommandLine.h:137
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition:CommandLine.h:443
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition:AddressRanges.h:18
llvm::hasOnlySimpleTerminator
bool hasOnlySimpleTerminator(const Function &F)
Definition:BasicBlockUtils.cpp:1910
llvm::initializeUnifyLoopExitsLegacyPassPass
void initializeUnifyLoopExitsLegacyPassPass(PassRegistry &)
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition:Debug.cpp:163
llvm::createUnifyLoopExitsPass
FunctionPass * createUnifyLoopExitsPass()
Definition:UnifyLoopExits.cpp:60
llvm::ControlFlowHub
Given a set of branch descriptors [BB, Succ0, Succ1], create a "hub" such that the control flow from ...
Definition:ControlFlowUtils.h:97
llvm::ControlFlowHub::finalize
BasicBlock * finalize(DomTreeUpdater *DTU, SmallVectorImpl< BasicBlock * > &GuardBlocks, const StringRef Prefix, std::optional< unsigned > MaxControlFlowBooleans=std::nullopt)
Definition:ControlFlowUtils.cpp:273
llvm::ControlFlowHub::addBranch
void addBranch(BasicBlock *BB, BasicBlock *Succ0, BasicBlock *Succ1)
Definition:ControlFlowUtils.h:107
llvm::Incoming
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...
Definition:SILowerI1Copies.h:25
llvm::cl::desc
Definition:CommandLine.h:409

Generated on Thu Jul 17 2025 17:55:40 for LLVM by doxygen 1.9.6
[8]ページ先頭

©2009-2025 Movatter.jp