47#define DEBUG_TYPE "simplifycfg"
53 std::vector<DominatorTree::UpdateType> *Updates) {
62 Updates->reserve(Updates->size() + BBs.
size());
67 auto *Term = BBs[0]->getTerminator();
72 F.getContext(),
Twine(
"common.") + Term->getOpcodeName(), &
F, BBs[0]);
74 NewOps.
resize(Term->getNumOperands());
75 for (
auto I :
zip(Term->operands(), NewOps)) {
78 CanonicalBB->
getName() +
".op");
79 std::get<1>(
I)->insertInto(CanonicalBB, CanonicalBB->
end());
83 CanonicalTerm = Term->clone();
87 std::get<1>(
I) = std::get<0>(
I);
94 auto *Term = BB->getTerminator();
96 "All blocks to be tail-merged must be the same "
97 "(function-terminating) terminator type.");
101 for (
auto I :
zip(Term->operands(), NewOps))
102 std::get<1>(
I)->addIncoming(std::get<0>(
I), BB);
106 CommonDebugLoc = Term->getDebugLoc();
115 Term->eraseFromParent();
140 auto *Term = BB.getTerminator();
144 switch (Term->getOpcode()) {
145 case Instruction::Ret:
146 case Instruction::Resume:
153 if (BB.getTerminatingMustTailCall())
160 if (
Function *
F = CI->getCalledFunction())
162 if (ID == Intrinsic::experimental_deoptimize)
168 if (
any_of(Term->operands(),
169 [](
Value *
Op) { return Op->getType()->isTokenTy(); }))
173 Structure[Term->getOpcode()].emplace_back(&BB);
178 std::vector<DominatorTree::UpdateType> Updates;
195 bool LocalChange =
true;
200 for (
const auto &Edge : Edges)
204 UniqueLoopHeaders.
end());
206 unsigned IterCnt = 0;
208 while (LocalChange) {
209 assert(IterCnt++ < 2000 &&
"Iterative simplification didn't converge!");
218 "Should not end up trying to simplify blocks marked for removal.");
245 if (!EverChanged)
return false;
262 }
while (EverChanged);
271 (DT && DT->
verify(DominatorTree::VerificationLevel::Full))) &&
272 "Original domtree is invalid?");
277 (DT && DT->
verify(DominatorTree::VerificationLevel::Full))) &&
278 "Failed to maintain validity of domtree!");
285 const ScalarOptions &Opts = ScalarOptions::Global;
286 if (Opts.bonus_inst_threshold)
287 Options.BonusInstThreshold = *Opts.bonus_inst_threshold;
288 Options.ForwardSwitchCondToPhi =
289 valueOr(Opts.forward_switch_cond,
Options.ForwardSwitchCondToPhi);
290 Options.ConvertSwitchRangeToICmp =
291 valueOr(Opts.switch_range_to_icmp,
Options.ConvertSwitchRangeToICmp);
292 Options.ConvertSwitchToLookupTable =
293 valueOr(Opts.switch_to_lookup,
Options.ConvertSwitchToLookupTable);
298 Options.HoistLoadsStoresWithCondFaulting =
299 valueOr(Opts.hoist_loads_stores_with_cond_faulting,
300 Options.HoistLoadsStoresWithCondFaulting);
303 Options.SpeculateUnpredictables =
304 valueOr(Opts.speculate_unpredictables,
Options.SpeculateUnpredictables);
318 static_cast<PassInfoMixin<SimplifyCFGPass> *
>(
this)->
printPipeline(
319 OS, MapClassName2PassName);
321 OS <<
"bonus-inst-threshold=" << Options.BonusInstThreshold <<
';';
322 OS << (Options.ForwardSwitchCondToPhi ?
"" :
"no-") <<
"forward-switch-cond;";
323 OS << (Options.ConvertSwitchRangeToICmp ?
"" :
"no-")
324 <<
"switch-range-to-icmp;";
325 OS << (Options.ConvertSwitchToArithmetic ?
"" :
"no-")
326 <<
"switch-to-arithmetic;";
327 OS << (Options.ConvertSwitchToLookupTable ?
"" :
"no-")
328 <<
"switch-to-lookup;";
329 OS << (Options.NeedCanonicalLoop ?
"" :
"no-") <<
"keep-loops;";
330 OS << (Options.HoistCommonInsts ?
"" :
"no-") <<
"hoist-common-insts;";
331 OS << (Options.HoistLoadsStoresWithCondFaulting ?
"" :
"no-")
332 <<
"hoist-loads-stores-with-cond-faulting;";
333 OS << (Options.SinkCommonInsts ?
"" :
"no-") <<
"sink-common-insts;";
334 OS << (Options.SpeculateBlocks ?
"" :
"no-") <<
"speculate-blocks;";
335 OS << (Options.SimplifyCondBranch ?
"" :
"no-") <<
"simplify-cond-branch;";
336 OS << (Options.SpeculateUnpredictables ?
"" :
"no-")
337 <<
"speculate-unpredictables";
354 DT->updateBlockNumbers();
367 std::function<
bool(
const Function &)> Ftor =
nullptr)
377 if (skipFunction(
F) || (PredicateFtor && !PredicateFtor(
F)))
380 Options.AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
F);
383 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
385 auto &
TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
388 void getAnalysisUsage(AnalysisUsage &AU)
const override {
400char CFGSimplifyPass::ID = 0;
413 return new CFGSimplifyPass(
Options, std::move(Ftor));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains the simple types necessary to represent the attributes associated with functions a...
static bool runOnFunction(Function &F, bool PostInlining)
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...
This file implements a map that provides insertion order iteration.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
dot regions Print regions of function to dot true view regions View regions of function(with no function bodies)"
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 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 void applyCommandLineOverridesToOptions(SimplifyCFGOptions &Options)
static bool tailMergeBlocksWithSimilarFunctionTerminators(Function &F, DomTreeUpdater *DTU)
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)
static SymbolRef::Type getType(const Symbol *Sym)
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
A function analysis which provides an AssumptionCache.
An immutable pass that tracks lazily created AssumptionCache objects.
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
static LLVM_ABI DebugLoc getMergedLocation(DebugLoc LocA, DebugLoc LocB)
When two instructions are combined into a single instruction we also need to combine the original loc...
Analysis pass which computes a DominatorTree.
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
static constexpr UpdateKind Insert
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
FunctionPass class - This class is used to implement most global optimizations.
BasicBlockListType::iterator iterator
void applyUpdates(ArrayRef< UpdateT > Updates)
Submit updates to all available trees.
bool isBBPendingDeletion(BasicBlockT *DelBB) const
Returns true if DelBB is awaiting deletion.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI 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 LLVM_ABI 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.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Run the pass over the function.
LLVM_ABI SimplifyCFGPass()
The default constructor sets the pass options to create canonical IR, rather than optimal IR.
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Analysis pass providing the TargetTransformInfo.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
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.
This is an optimization pass for GlobalISel generic memory operations.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
LLVM_ABI FunctionPass * createCFGSimplificationPass(SimplifyCFGOptions Options=SimplifyCFGOptions(), std::function< bool(const Function &)> Ftor=nullptr)
bool succ_empty(const Instruction *I)
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool FoldInstsToUnreachable=true)
Remove all blocks that can not be reached from the function's entry.
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI cl::opt< bool > RequireAndPreserveDomTree
This function is used to do simplification of a CFG.
DWARFExpression::Operation Op
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, DomTreeUpdater *DTU=nullptr, const SimplifyCFGOptions &Options={}, ArrayRef< WeakVH > LoopHeaders={})
constexpr bool valueOr(BoolOrDefault X, bool Default)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI 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.
LLVM_ABI void initializeCFGSimplifyPassPass(PassRegistry &)
Implement std::hash so that hash_code can be used in STL containers.
A MapVector that performs no allocations if smaller than a certain size.