LLVM 19.0.0git
SimplifyCFGPass.cpp
Go to the documentation of this file.
1//===- SimplifyCFGPass.cpp - CFG Simplification Pass ----------------------===//
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// This file implements dead code elimination and basic block merging, along
10// with a collection of other peephole control flow optimizations. For example:
11//
12// * Removes basic blocks with no predecessors.
13// * Merges a basic block into its predecessor if there is only one and the
14// predecessor only has one successor.
15// * Eliminates PHI nodes for basic blocks with a single predecessor.
16// * Eliminates a basic block that only contains an unconditional branch.
17// * Changes invoke instructions to nounwind functions to be calls.
18// * Change things like "if (x) if (y)" into "if (x&y)".
19// * etc..
20//
21//===----------------------------------------------------------------------===//
22
23#include "llvm/ADT/MapVector.h"
26#include "llvm/ADT/Statistic.h"
28#include "llvm/Analysis/CFG.h"
32#include "llvm/IR/Attributes.h"
33#include "llvm/IR/CFG.h"
35#include "llvm/IR/Dominators.h"
38#include "llvm/IR/ValueHandle.h"
40#include "llvm/Pass.h"
46#include <utility>
47using namespace llvm;
48
49#define DEBUG_TYPE "simplifycfg"
50
52 "bonus-inst-threshold", cl::Hidden, cl::init(1),
53 cl::desc("Control the number of bonus instructions (default = 1)"));
54
56 "keep-loops", cl::Hidden, cl::init(true),
57 cl::desc("Preserve canonical loop structure (default = true)"));
58
60 "switch-range-to-icmp", cl::Hidden, cl::init(false),
62 "Convert switches into an integer range comparison (default = false)"));
63
65 "switch-to-lookup", cl::Hidden, cl::init(false),
66 cl::desc("Convert switches to lookup tables (default = false)"));
67
69 "forward-switch-cond", cl::Hidden, cl::init(false),
70 cl::desc("Forward switch condition to phi ops (default = false)"));
71
73 "hoist-common-insts", cl::Hidden, cl::init(false),
74 cl::desc("hoist common instructions (default = false)"));
75
77 "sink-common-insts", cl::Hidden, cl::init(false),
78 cl::desc("Sink common instructions (default = false)"));
79
80
81STATISTIC(NumSimpl, "Number of blocks simplified");
82
83static bool
85 std::vector<DominatorTree::UpdateType> *Updates) {
87
88 // We don't want to change IR just because we can.
89 // Only do that if there are at least two blocks we'll tail-merge.
90 if (BBs.size() < 2)
91 return false;
92
93 if (Updates)
94 Updates->reserve(Updates->size() + BBs.size());
95
96 BasicBlock *CanonicalBB;
97 Instruction *CanonicalTerm;
98 {
99 auto *Term = BBs[0]->getTerminator();
100
101 // Create a canonical block for this function terminator type now,
102 // placing it *before* the first block that will branch to it.
103 CanonicalBB = BasicBlock::Create(
104 F.getContext(), Twine("common.") + Term->getOpcodeName(), &F, BBs[0]);
105 // We'll also need a PHI node per each operand of the terminator.
106 NewOps.resize(Term->getNumOperands());
107 for (auto I : zip(Term->operands(), NewOps)) {
108 std::get<1>(I) = PHINode::Create(std::get<0>(I)->getType(),
109 /*NumReservedValues=*/BBs.size(),
110 CanonicalBB->getName() + ".op");
111 std::get<1>(I)->insertInto(CanonicalBB, CanonicalBB->end());
112 }
113 // Make it so that this canonical block actually has the right
114 // terminator.
115 CanonicalTerm = Term->clone();
116 CanonicalTerm->insertInto(CanonicalBB, CanonicalBB->end());
117 // If the canonical terminator has operands, rewrite it to take PHI's.
118 for (auto I : zip(NewOps, CanonicalTerm->operands()))
119 std::get<1>(I) = std::get<0>(I);
120 }
121
122 // Now, go through each block (with the current terminator type)
123 // we've recorded, and rewrite it to branch to the new common block.
124 DILocation *CommonDebugLoc = nullptr;
125 for (BasicBlock *BB : BBs) {
126 auto *Term = BB->getTerminator();
127 assert(Term->getOpcode() == CanonicalTerm->getOpcode() &&
128 "All blocks to be tail-merged must be the same "
129 "(function-terminating) terminator type.");
130
131 // Aha, found a new non-canonical function terminator. If it has operands,
132 // forward them to the PHI nodes in the canonical block.
133 for (auto I : zip(Term->operands(), NewOps))
134 std::get<1>(I)->addIncoming(std::get<0>(I), BB);
135
136 // Compute the debug location common to all the original terminators.
137 if (!CommonDebugLoc)
138 CommonDebugLoc = Term->getDebugLoc();
139 else
140 CommonDebugLoc =
141 DILocation::getMergedLocation(CommonDebugLoc, Term->getDebugLoc());
142
143 // And turn BB into a block that just unconditionally branches
144 // to the canonical block.
145 Term->eraseFromParent();
146 BranchInst::Create(CanonicalBB, BB);
147 if (Updates)
148 Updates->push_back({DominatorTree::Insert, BB, CanonicalBB});
149 }
150
151 CanonicalTerm->setDebugLoc(CommonDebugLoc);
152
153 return true;
154}
155
157 DomTreeUpdater *DTU) {
158 SmallMapVector<unsigned /*TerminatorOpcode*/, SmallVector<BasicBlock *, 2>, 4>
159 Structure;
160
161 // Scan all the blocks in the function, record the interesting-ones.
162 for (BasicBlock &BB : F) {
163 if (DTU && DTU->isBBPendingDeletion(&BB))
164 continue;
165
166 // We are only interested in function-terminating blocks.
167 if (!succ_empty(&BB))
168 continue;
169
170 auto *Term = BB.getTerminator();
171
172 // Fow now only support `ret`/`resume` function terminators.
173 // FIXME: lift this restriction.
174 switch (Term->getOpcode()) {
175 case Instruction::Ret:
176 case Instruction::Resume:
177 break;
178 default:
179 continue;
180 }
181
182 // We can't tail-merge block that contains a musttail call.
183 if (BB.getTerminatingMustTailCall())
184 continue;
185
186 // Calls to experimental_deoptimize must be followed by a return
187 // of the value computed by experimental_deoptimize.
188 // I.e., we can not change `ret` to `br` for this block.
189 if (auto *CI =
190 dyn_cast_or_null<CallInst>(Term->getPrevNonDebugInstruction())) {
191 if (Function *F = CI->getCalledFunction())
192 if (Intrinsic::ID ID = F->getIntrinsicID())
193 if (ID == Intrinsic::experimental_deoptimize)
194 continue;
195 }
196
197 // PHI nodes cannot have token type, so if the terminator has an operand
198 // with token type, we can not tail-merge this kind of function terminators.
199 if (any_of(Term->operands(),
200 [](Value *Op) { return Op->getType()->isTokenTy(); }))
201 continue;
202
203 // Canonical blocks are uniqued based on the terminator type (opcode).
204 Structure[Term->getOpcode()].emplace_back(&BB);
205 }
206
207 bool Changed = false;
208
209 std::vector<DominatorTree::UpdateType> Updates;
210
211 for (ArrayRef<BasicBlock *> BBs : make_second_range(Structure))
212 Changed |= performBlockTailMerging(F, BBs, DTU ? &Updates : nullptr);
213
214 if (DTU)
215 DTU->applyUpdates(Updates);
216
217 return Changed;
218}
219
220/// Call SimplifyCFG on all the blocks in the function,
221/// iterating until no more changes are made.
223 DomTreeUpdater *DTU,
225 bool Changed = false;
226 bool LocalChange = true;
227
229 FindFunctionBackedges(F, Edges);
230 SmallPtrSet<BasicBlock *, 16> UniqueLoopHeaders;
231 for (const auto &Edge : Edges)
232 UniqueLoopHeaders.insert(const_cast<BasicBlock *>(Edge.second));
233
234 SmallVector<WeakVH, 16> LoopHeaders(UniqueLoopHeaders.begin(),
235 UniqueLoopHeaders.end());
236
237 unsigned IterCnt = 0;
238 (void)IterCnt;
239 while (LocalChange) {
240 assert(IterCnt++ < 1000 && "Iterative simplification didn't converge!");
241 LocalChange = false;
242
243 // Loop over all of the basic blocks and remove them if they are unneeded.
244 for (Function::iterator BBIt = F.begin(); BBIt != F.end(); ) {
245 BasicBlock &BB = *BBIt++;
246 if (DTU) {
247 assert(
248 !DTU->isBBPendingDeletion(&BB) &&
249 "Should not end up trying to simplify blocks marked for removal.");
250 // Make sure that the advanced iterator does not point at the blocks
251 // that are marked for removal, skip over all such blocks.
252 while (BBIt != F.end() && DTU->isBBPendingDeletion(&*BBIt))
253 ++BBIt;
254 }
255 if (simplifyCFG(&BB, TTI, DTU, Options, LoopHeaders)) {
256 LocalChange = true;
257 ++NumSimpl;
258 }
259 }
260 Changed |= LocalChange;
261 }
262 return Changed;
263}
264
266 DominatorTree *DT,
268 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
269
270 bool EverChanged = removeUnreachableBlocks(F, DT ? &DTU : nullptr);
271 EverChanged |=
273 EverChanged |= iterativelySimplifyCFG(F, TTI, DT ? &DTU : nullptr, Options);
274
275 // If neither pass changed anything, we're done.
276 if (!EverChanged) return false;
277
278 // iterativelySimplifyCFG can (rarely) make some loops dead. If this happens,
279 // removeUnreachableBlocks is needed to nuke them, which means we should
280 // iterate between the two optimizations. We structure the code like this to
281 // avoid rerunning iterativelySimplifyCFG if the second pass of
282 // removeUnreachableBlocks doesn't do anything.
283 if (!removeUnreachableBlocks(F, DT ? &DTU : nullptr))
284 return true;
285
286 do {
287 EverChanged = iterativelySimplifyCFG(F, TTI, DT ? &DTU : nullptr, Options);
288 EverChanged |= removeUnreachableBlocks(F, DT ? &DTU : nullptr);
289 } while (EverChanged);
290
291 return true;
292}
293
295 DominatorTree *DT,
298 (DT && DT->verify(DominatorTree::VerificationLevel::Full))) &&
299 "Original domtree is invalid?");
300
301 bool Changed = simplifyFunctionCFGImpl(F, TTI, DT, Options);
302
304 (DT && DT->verify(DominatorTree::VerificationLevel::Full))) &&
305 "Failed to maintain validity of domtree!");
306
307 return Changed;
308}
309
310// Command-line settings override compile-time settings.
312 if (UserBonusInstThreshold.getNumOccurrences())
313 Options.BonusInstThreshold = UserBonusInstThreshold;
314 if (UserForwardSwitchCond.getNumOccurrences())
315 Options.ForwardSwitchCondToPhi = UserForwardSwitchCond;
316 if (UserSwitchRangeToICmp.getNumOccurrences())
317 Options.ConvertSwitchRangeToICmp = UserSwitchRangeToICmp;
318 if (UserSwitchToLookup.getNumOccurrences())
319 Options.ConvertSwitchToLookupTable = UserSwitchToLookup;
320 if (UserKeepLoops.getNumOccurrences())
321 Options.NeedCanonicalLoop = UserKeepLoops;
322 if (UserHoistCommonInsts.getNumOccurrences())
323 Options.HoistCommonInsts = UserHoistCommonInsts;
324 if (UserSinkCommonInsts.getNumOccurrences())
325 Options.SinkCommonInsts = UserSinkCommonInsts;
326}
327
330}
331
333 : Options(Opts) {
335}
336
338 raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
339 static_cast<PassInfoMixin<SimplifyCFGPass> *>(this)->printPipeline(
340 OS, MapClassName2PassName);
341 OS << '<';
342 OS << "bonus-inst-threshold=" << Options.BonusInstThreshold << ';';
343 OS << (Options.ForwardSwitchCondToPhi ? "" : "no-") << "forward-switch-cond;";
344 OS << (Options.ConvertSwitchRangeToICmp ? "" : "no-")
345 << "switch-range-to-icmp;";
346 OS << (Options.ConvertSwitchToLookupTable ? "" : "no-")
347 << "switch-to-lookup;";
348 OS << (Options.NeedCanonicalLoop ? "" : "no-") << "keep-loops;";
349 OS << (Options.HoistCommonInsts ? "" : "no-") << "hoist-common-insts;";
350 OS << (Options.SinkCommonInsts ? "" : "no-") << "sink-common-insts;";
351 OS << (Options.SpeculateBlocks ? "" : "no-") << "speculate-blocks;";
352 OS << (Options.SimplifyCondBranch ? "" : "no-") << "simplify-cond-branch";
353 OS << '>';
354}
355
358 auto &TTI = AM.getResult<TargetIRAnalysis>(F);
359 Options.AC = &AM.getResult<AssumptionAnalysis>(F);
360 DominatorTree *DT = nullptr;
363 if (!simplifyFunctionCFG(F, TTI, DT, Options))
364 return PreservedAnalyses::all();
368 return PA;
369}
370
371namespace {
372struct CFGSimplifyPass : public FunctionPass {
373 static char ID;
375 std::function<bool(const Function &)> PredicateFtor;
376
377 CFGSimplifyPass(SimplifyCFGOptions Options_ = SimplifyCFGOptions(),
378 std::function<bool(const Function &)> Ftor = nullptr)
379 : FunctionPass(ID), Options(Options_), PredicateFtor(std::move(Ftor)) {
380
382
383 // Check for command-line overrides of options for debug/customization.
385 }
386
387 bool runOnFunction(Function &F) override {
388 if (skipFunction(F) || (PredicateFtor && !PredicateFtor(F)))
389 return false;
390
391 Options.AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
392 DominatorTree *DT = nullptr;
394 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
395
396 auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
397 return simplifyFunctionCFG(F, TTI, DT, Options);
398 }
399 void getAnalysisUsage(AnalysisUsage &AU) const override {
407 }
408};
409}
410
411char CFGSimplifyPass::ID = 0;
412INITIALIZE_PASS_BEGIN(CFGSimplifyPass, "simplifycfg", "Simplify the CFG", false,
413 false)
417INITIALIZE_PASS_END(CFGSimplifyPass, "simplifycfg", "Simplify the CFG", false,
418 false)
419
420// Public interface to the CFGSimplification pass
423 std::function<bool(const Function &)> Ftor) {
424 return new CFGSimplifyPass(Options, std::move(Ftor));
425}
aarch64 promote const
This file contains the simple types necessary to represent the attributes associated with functions a...
Performs the initial survey of the specified function
static bool runOnFunction(Function &F, bool PostInlining)
Flatten the CFG
This is the interface for a simple mod/ref and alias analysis over globals.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
static LVOptions Options
Definition: LVOptions.cpp:25
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file implements a map that provides insertion order iteration.
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:59
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
static cl::opt< bool > UserSwitchRangeToICmp("switch-range-to-icmp", cl::Hidden, cl::init(false), cl::desc("Convert switches into an integer range comparison (default = false)"))
static cl::opt< bool > UserSinkCommonInsts("sink-common-insts", cl::Hidden, cl::init(false), cl::desc("Sink common instructions (default = false)"))
static bool iterativelySimplifyCFG(Function &F, const TargetTransformInfo &TTI, DomTreeUpdater *DTU, const SimplifyCFGOptions &Options)
Call SimplifyCFG on all the blocks in the function, iterating until no more changes are made.
static cl::opt< unsigned > UserBonusInstThreshold("bonus-inst-threshold", cl::Hidden, cl::init(1), cl::desc("Control the number of bonus instructions (default = 1)"))
static bool simplifyFunctionCFGImpl(Function &F, const TargetTransformInfo &TTI, DominatorTree *DT, const SimplifyCFGOptions &Options)
static bool simplifyFunctionCFG(Function &F, const TargetTransformInfo &TTI, DominatorTree *DT, const SimplifyCFGOptions &Options)
static cl::opt< bool > UserSwitchToLookup("switch-to-lookup", cl::Hidden, cl::init(false), cl::desc("Convert switches to lookup tables (default = false)"))
static cl::opt< bool > UserKeepLoops("keep-loops", cl::Hidden, cl::init(true), cl::desc("Preserve canonical loop structure (default = true)"))
static cl::opt< bool > UserHoistCommonInsts("hoist-common-insts", cl::Hidden, cl::init(false), cl::desc("hoist common instructions (default = false)"))
simplifycfg
static void applyCommandLineOverridesToOptions(SimplifyCFGOptions &Options)
static bool tailMergeBlocksWithSimilarFunctionTerminators(Function &F, DomTreeUpdater *DTU)
static cl::opt< bool > UserForwardSwitchCond("forward-switch-cond", cl::Hidden, cl::init(false), cl::desc("Forward switch condition to phi ops (default = false)"))
static bool performBlockTailMerging(Function &F, ArrayRef< BasicBlock * > BBs, std::vector< DominatorTree::UpdateType > *Updates)
This file provides the interface for the pass responsible for both simplifying and canonicalizing the...
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
static SymbolRef::Type getType(const Symbol *Sym)
Definition: TapiFile.cpp:40
This pass exposes codegen information to IR-level passes.
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:348
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:500
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
LLVM Basic Block Representation.
Definition: BasicBlock.h:60
iterator end()
Definition: BasicBlock.h:442
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:198
static BranchInst * Create(BasicBlock *IfTrue, BasicBlock::iterator InsertBefore)
Debug location.
static DILocation * getMergedLocation(DILocation *LocA, DILocation *LocB)
When two instructions are combined into a single instruction we also need to combine the original loc...
This class represents an Operation in the Expression.
bool isBBPendingDeletion(BasicBlock *DelBB) const
Returns true if DelBB is awaiting deletion.
void applyUpdates(ArrayRef< DominatorTree::UpdateType > Updates)
Submit updates to all available trees.
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
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
BasicBlockListType::iterator iterator
Definition: Function.h:67
Legacy wrapper pass to provide the GlobalsAAResult object.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Definition: Instruction.h:251
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Definition: Instruction.h:450
InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr, BasicBlock::iterator InsertBefore)
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...
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:109
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:115
void preserve()
Mark an analysis as preserved.
Definition: Analysis.h:129
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
SimplifyCFGPass()
The default constructor sets the pass options to create canonical IR, rather than optimal IR.
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
iterator end() const
Definition: SmallPtrSet.h:385
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:342
iterator begin() const
Definition: SmallPtrSet.h:380
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:427
void reserve(size_type N)
Definition: SmallVector.h:676
void resize(size_type N)
Definition: SmallVector.h:651
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Analysis pass providing the TargetTransformInfo.
Wrapper pass for TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
op_range operands()
Definition: User.h:242
LLVM Value Representation.
Definition: Value.h:74
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
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:450
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
Definition: STLExtras.h:862
FunctionPass * createCFGSimplificationPass(SimplifyCFGOptions Options=SimplifyCFGOptions(), std::function< bool(const Function &)> Ftor=nullptr)
bool succ_empty(const Instruction *I)
Definition: CFG.h:255
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1738
void initializeCFGSimplifyPassPass(PassRegistry &)
cl::opt< bool > RequireAndPreserveDomTree
This function is used to do simplification of a CFG.
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
Definition: STLExtras.h:1441
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1858
bool simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, DomTreeUpdater *DTU=nullptr, const SimplifyCFGOptions &Options={}, ArrayRef< WeakVH > LoopHeaders={})
void FindFunctionBackedges(const Function &F, SmallVectorImpl< std::pair< const BasicBlock *, const BasicBlock * > > &Result)
Analyze the specified function to find all of the loop backedges in the function and return them.
Definition: CFG.cpp:34
bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
Definition: Local.cpp:3180
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
A CRTP mix-in to automatically provide informational APIs needed for passes.
Definition: PassManager.h:91
A MapVector that performs no allocations if smaller than a certain size.
Definition: MapVector.h:254