LLVM 20.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"
37#include "llvm/IR/ValueHandle.h"
39#include "llvm/Pass.h"
45#include <utility>
46using namespace llvm;
47
48#define DEBUG_TYPE "simplifycfg"
49
51 "bonus-inst-threshold", cl::Hidden, cl::init(1),
52 cl::desc("Control the number of bonus instructions (default = 1)"));
53
55 "keep-loops", cl::Hidden, cl::init(true),
56 cl::desc("Preserve canonical loop structure (default = true)"));
57
59 "switch-range-to-icmp", cl::Hidden, cl::init(false),
61 "Convert switches into an integer range comparison (default = false)"));
62
64 "switch-to-lookup", cl::Hidden, cl::init(false),
65 cl::desc("Convert switches to lookup tables (default = false)"));
66
68 "forward-switch-cond", cl::Hidden, cl::init(false),
69 cl::desc("Forward switch condition to phi ops (default = false)"));
70
72 "hoist-common-insts", cl::Hidden, cl::init(false),
73 cl::desc("hoist common instructions (default = false)"));
74
76 "hoist-loads-stores-with-cond-faulting", cl::Hidden, cl::init(false),
77 cl::desc("Hoist loads/stores if the target supports conditional faulting "
78 "(default = false)"));
79
81 "sink-common-insts", cl::Hidden, cl::init(false),
82 cl::desc("Sink common instructions (default = false)"));
83
85 "speculate-unpredictables", cl::Hidden, cl::init(false),
86 cl::desc("Speculate unpredictable branches (default = false)"));
87
88STATISTIC(NumSimpl, "Number of blocks simplified");
89
90static bool
92 std::vector<DominatorTree::UpdateType> *Updates) {
94
95 // We don't want to change IR just because we can.
96 // Only do that if there are at least two blocks we'll tail-merge.
97 if (BBs.size() < 2)
98 return false;
99
100 if (Updates)
101 Updates->reserve(Updates->size() + BBs.size());
102
103 BasicBlock *CanonicalBB;
104 Instruction *CanonicalTerm;
105 {
106 auto *Term = BBs[0]->getTerminator();
107
108 // Create a canonical block for this function terminator type now,
109 // placing it *before* the first block that will branch to it.
110 CanonicalBB = BasicBlock::Create(
111 F.getContext(), Twine("common.") + Term->getOpcodeName(), &F, BBs[0]);
112 // We'll also need a PHI node per each operand of the terminator.
113 NewOps.resize(Term->getNumOperands());
114 for (auto I : zip(Term->operands(), NewOps)) {
115 std::get<1>(I) = PHINode::Create(std::get<0>(I)->getType(),
116 /*NumReservedValues=*/BBs.size(),
117 CanonicalBB->getName() + ".op");
118 std::get<1>(I)->insertInto(CanonicalBB, CanonicalBB->end());
119 }
120 // Make it so that this canonical block actually has the right
121 // terminator.
122 CanonicalTerm = Term->clone();
123 CanonicalTerm->insertInto(CanonicalBB, CanonicalBB->end());
124 // If the canonical terminator has operands, rewrite it to take PHI's.
125 for (auto I : zip(NewOps, CanonicalTerm->operands()))
126 std::get<1>(I) = std::get<0>(I);
127 }
128
129 // Now, go through each block (with the current terminator type)
130 // we've recorded, and rewrite it to branch to the new common block.
131 DILocation *CommonDebugLoc = nullptr;
132 for (BasicBlock *BB : BBs) {
133 auto *Term = BB->getTerminator();
134 assert(Term->getOpcode() == CanonicalTerm->getOpcode() &&
135 "All blocks to be tail-merged must be the same "
136 "(function-terminating) terminator type.");
137
138 // Aha, found a new non-canonical function terminator. If it has operands,
139 // forward them to the PHI nodes in the canonical block.
140 for (auto I : zip(Term->operands(), NewOps))
141 std::get<1>(I)->addIncoming(std::get<0>(I), BB);
142
143 // Compute the debug location common to all the original terminators.
144 if (!CommonDebugLoc)
145 CommonDebugLoc = Term->getDebugLoc();
146 else
147 CommonDebugLoc =
148 DILocation::getMergedLocation(CommonDebugLoc, Term->getDebugLoc());
149
150 // And turn BB into a block that just unconditionally branches
151 // to the canonical block.
152 Instruction *BI = BranchInst::Create(CanonicalBB, BB);
153 BI->setDebugLoc(Term->getDebugLoc());
154 Term->eraseFromParent();
155
156 if (Updates)
157 Updates->push_back({DominatorTree::Insert, BB, CanonicalBB});
158 }
159
160 CanonicalTerm->setDebugLoc(CommonDebugLoc);
161
162 return true;
163}
164
166 DomTreeUpdater *DTU) {
167 SmallMapVector<unsigned /*TerminatorOpcode*/, SmallVector<BasicBlock *, 2>, 4>
168 Structure;
169
170 // Scan all the blocks in the function, record the interesting-ones.
171 for (BasicBlock &BB : F) {
172 if (DTU && DTU->isBBPendingDeletion(&BB))
173 continue;
174
175 // We are only interested in function-terminating blocks.
176 if (!succ_empty(&BB))
177 continue;
178
179 auto *Term = BB.getTerminator();
180
181 // Fow now only support `ret`/`resume` function terminators.
182 // FIXME: lift this restriction.
183 switch (Term->getOpcode()) {
184 case Instruction::Ret:
185 case Instruction::Resume:
186 break;
187 default:
188 continue;
189 }
190
191 // We can't tail-merge block that contains a musttail call.
192 if (BB.getTerminatingMustTailCall())
193 continue;
194
195 // Calls to experimental_deoptimize must be followed by a return
196 // of the value computed by experimental_deoptimize.
197 // I.e., we can not change `ret` to `br` for this block.
198 if (auto *CI =
199 dyn_cast_or_null<CallInst>(Term->getPrevNonDebugInstruction())) {
200 if (Function *F = CI->getCalledFunction())
201 if (Intrinsic::ID ID = F->getIntrinsicID())
202 if (ID == Intrinsic::experimental_deoptimize)
203 continue;
204 }
205
206 // PHI nodes cannot have token type, so if the terminator has an operand
207 // with token type, we can not tail-merge this kind of function terminators.
208 if (any_of(Term->operands(),
209 [](Value *Op) { return Op->getType()->isTokenTy(); }))
210 continue;
211
212 // Canonical blocks are uniqued based on the terminator type (opcode).
213 Structure[Term->getOpcode()].emplace_back(&BB);
214 }
215
216 bool Changed = false;
217
218 std::vector<DominatorTree::UpdateType> Updates;
219
220 for (ArrayRef<BasicBlock *> BBs : make_second_range(Structure))
221 Changed |= performBlockTailMerging(F, BBs, DTU ? &Updates : nullptr);
222
223 if (DTU)
224 DTU->applyUpdates(Updates);
225
226 return Changed;
227}
228
229/// Call SimplifyCFG on all the blocks in the function,
230/// iterating until no more changes are made.
232 DomTreeUpdater *DTU,
234 bool Changed = false;
235 bool LocalChange = true;
236
238 FindFunctionBackedges(F, Edges);
239 SmallPtrSet<BasicBlock *, 16> UniqueLoopHeaders;
240 for (const auto &Edge : Edges)
241 UniqueLoopHeaders.insert(const_cast<BasicBlock *>(Edge.second));
242
243 SmallVector<WeakVH, 16> LoopHeaders(UniqueLoopHeaders.begin(),
244 UniqueLoopHeaders.end());
245
246 unsigned IterCnt = 0;
247 (void)IterCnt;
248 while (LocalChange) {
249 assert(IterCnt++ < 1000 && "Iterative simplification didn't converge!");
250 LocalChange = false;
251
252 // Loop over all of the basic blocks and remove them if they are unneeded.
253 for (Function::iterator BBIt = F.begin(); BBIt != F.end(); ) {
254 BasicBlock &BB = *BBIt++;
255 if (DTU) {
256 assert(
257 !DTU->isBBPendingDeletion(&BB) &&
258 "Should not end up trying to simplify blocks marked for removal.");
259 // Make sure that the advanced iterator does not point at the blocks
260 // that are marked for removal, skip over all such blocks.
261 while (BBIt != F.end() && DTU->isBBPendingDeletion(&*BBIt))
262 ++BBIt;
263 }
264 if (simplifyCFG(&BB, TTI, DTU, Options, LoopHeaders)) {
265 LocalChange = true;
266 ++NumSimpl;
267 }
268 }
269 Changed |= LocalChange;
270 }
271 return Changed;
272}
273
275 DominatorTree *DT,
277 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);
278
279 bool EverChanged = removeUnreachableBlocks(F, DT ? &DTU : nullptr);
280 EverChanged |=
282 EverChanged |= iterativelySimplifyCFG(F, TTI, DT ? &DTU : nullptr, Options);
283
284 // If neither pass changed anything, we're done.
285 if (!EverChanged) return false;
286
287 // iterativelySimplifyCFG can (rarely) make some loops dead. If this happens,
288 // removeUnreachableBlocks is needed to nuke them, which means we should
289 // iterate between the two optimizations. We structure the code like this to
290 // avoid rerunning iterativelySimplifyCFG if the second pass of
291 // removeUnreachableBlocks doesn't do anything.
292 if (!removeUnreachableBlocks(F, DT ? &DTU : nullptr))
293 return true;
294
295 do {
296 EverChanged = iterativelySimplifyCFG(F, TTI, DT ? &DTU : nullptr, Options);
297 EverChanged |= removeUnreachableBlocks(F, DT ? &DTU : nullptr);
298 } while (EverChanged);
299
300 return true;
301}
302
304 DominatorTree *DT,
307 (DT && DT->verify(DominatorTree::VerificationLevel::Full))) &&
308 "Original domtree is invalid?");
309
310 bool Changed = simplifyFunctionCFGImpl(F, TTI, DT, Options);
311
313 (DT && DT->verify(DominatorTree::VerificationLevel::Full))) &&
314 "Failed to maintain validity of domtree!");
315
316 return Changed;
317}
318
319// Command-line settings override compile-time settings.
321 if (UserBonusInstThreshold.getNumOccurrences())
322 Options.BonusInstThreshold = UserBonusInstThreshold;
323 if (UserForwardSwitchCond.getNumOccurrences())
324 Options.ForwardSwitchCondToPhi = UserForwardSwitchCond;
325 if (UserSwitchRangeToICmp.getNumOccurrences())
326 Options.ConvertSwitchRangeToICmp = UserSwitchRangeToICmp;
327 if (UserSwitchToLookup.getNumOccurrences())
328 Options.ConvertSwitchToLookupTable = UserSwitchToLookup;
329 if (UserKeepLoops.getNumOccurrences())
330 Options.NeedCanonicalLoop = UserKeepLoops;
331 if (UserHoistCommonInsts.getNumOccurrences())
332 Options.HoistCommonInsts = UserHoistCommonInsts;
333 if (UserHoistLoadsStoresWithCondFaulting.getNumOccurrences())
334 Options.HoistLoadsStoresWithCondFaulting =
336 if (UserSinkCommonInsts.getNumOccurrences())
337 Options.SinkCommonInsts = UserSinkCommonInsts;
338 if (UserSpeculateUnpredictables.getNumOccurrences())
339 Options.SpeculateUnpredictables = UserSpeculateUnpredictables;
340}
341
344}
345
347 : Options(Opts) {
349}
350
352 raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
353 static_cast<PassInfoMixin<SimplifyCFGPass> *>(this)->printPipeline(
354 OS, MapClassName2PassName);
355 OS << '<';
356 OS << "bonus-inst-threshold=" << Options.BonusInstThreshold << ';';
357 OS << (Options.ForwardSwitchCondToPhi ? "" : "no-") << "forward-switch-cond;";
358 OS << (Options.ConvertSwitchRangeToICmp ? "" : "no-")
359 << "switch-range-to-icmp;";
360 OS << (Options.ConvertSwitchToLookupTable ? "" : "no-")
361 << "switch-to-lookup;";
362 OS << (Options.NeedCanonicalLoop ? "" : "no-") << "keep-loops;";
363 OS << (Options.HoistCommonInsts ? "" : "no-") << "hoist-common-insts;";
364 OS << (Options.HoistLoadsStoresWithCondFaulting ? "" : "no-")
365 << "hoist-loads-stores-with-cond-faulting;";
366 OS << (Options.SinkCommonInsts ? "" : "no-") << "sink-common-insts;";
367 OS << (Options.SpeculateBlocks ? "" : "no-") << "speculate-blocks;";
368 OS << (Options.SimplifyCondBranch ? "" : "no-") << "simplify-cond-branch;";
369 OS << (Options.SpeculateUnpredictables ? "" : "no-")
370 << "speculate-unpredictables";
371 OS << '>';
372}
373
376 auto &TTI = AM.getResult<TargetIRAnalysis>(F);
377 Options.AC = &AM.getResult<AssumptionAnalysis>(F);
378 DominatorTree *DT = nullptr;
381 if (!simplifyFunctionCFG(F, TTI, DT, Options))
382 return PreservedAnalyses::all();
386 return PA;
387}
388
389namespace {
390struct CFGSimplifyPass : public FunctionPass {
391 static char ID;
393 std::function<bool(const Function &)> PredicateFtor;
394
395 CFGSimplifyPass(SimplifyCFGOptions Options_ = SimplifyCFGOptions(),
396 std::function<bool(const Function &)> Ftor = nullptr)
397 : FunctionPass(ID), Options(Options_), PredicateFtor(std::move(Ftor)) {
398
400
401 // Check for command-line overrides of options for debug/customization.
403 }
404
405 bool runOnFunction(Function &F) override {
406 if (skipFunction(F) || (PredicateFtor && !PredicateFtor(F)))
407 return false;
408
409 Options.AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
410 DominatorTree *DT = nullptr;
412 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
413
414 auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
415 return simplifyFunctionCFG(F, TTI, DT, Options);
416 }
417 void getAnalysisUsage(AnalysisUsage &AU) const override {
425 }
426};
427}
428
429char CFGSimplifyPass::ID = 0;
430INITIALIZE_PASS_BEGIN(CFGSimplifyPass, "simplifycfg", "Simplify the CFG", false,
431 false)
435INITIALIZE_PASS_END(CFGSimplifyPass, "simplifycfg", "Simplify the CFG", false,
436 false)
437
438// Public interface to the CFGSimplification pass
441 std::function<bool(const Function &)> Ftor) {
442 return new CFGSimplifyPass(Options, std::move(Ftor));
443}
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:57
#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 > UserHoistLoadsStoresWithCondFaulting("hoist-loads-stores-with-cond-faulting", cl::Hidden, cl::init(false), cl::desc("Hoist loads/stores if the target supports conditional faulting " "(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 cl::opt< bool > UserSpeculateUnpredictables("speculate-unpredictables", cl::Hidden, cl::init(false), cl::desc("Speculate unpredictable branches (default = false)"))
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:166
static SymbolRef::Type getType(const Symbol *Sym)
Definition: TapiFile.cpp:39
This pass exposes codegen information to IR-level passes.
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.
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:168
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
iterator end()
Definition: BasicBlock.h:461
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:212
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
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.
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:310
BasicBlockListType::iterator iterator
Definition: Function.h:68
void applyUpdates(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
bool isBBPendingDeletion(BasicBlockT *DelBB) const
Returns true if DelBB is awaiting deletion.
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:274
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Definition: Instruction.h:468
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="", 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...
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
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:477
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:384
iterator begin() const
Definition: SmallPtrSet.h:472
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:519
void reserve(size_type N)
Definition: SmallVector.h:663
void resize(size_type N)
Definition: SmallVector.h:638
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
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:288
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:443
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:854
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:1746
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:1449
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:1873
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:3271
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:69
A MapVector that performs no allocations if smaller than a certain size.
Definition: MapVector.h:254