29#define DEBUG_TYPE "must-execute"
39 ColorsForNewBlock = ColorsForOldBlock;
52 assert(CurLoop !=
nullptr &&
"CurLoop can't be null");
56 MayThrow = HeaderMayThrow;
61 "First block must be header");
80 assert(CurLoop !=
nullptr &&
"CurLoop can't be null");
85 for (
const auto &BB : CurLoop->
blocks())
119 const Loop *CurLoop) {
124 assert(CurLoop->
contains(CondExitBlock) &&
"meaning of exit block");
125 auto *BI = dyn_cast<BranchInst>(CondExitBlock->getTerminator());
126 if (!BI || !BI->isConditional())
130 if (
auto *
Cond = dyn_cast<ConstantInt>(BI->getCondition()))
131 return BI->getSuccessor(
Cond->getZExtValue() ? 1 : 0) == ExitBlock;
132 auto *
Cond = dyn_cast<CmpInst>(BI->getCondition());
139 auto *
LHS = dyn_cast<PHINode>(
Cond->getOperand(0));
140 auto *
RHS =
Cond->getOperand(1);
142 Pred =
Cond->getSwappedPredicate();
143 LHS = dyn_cast<PHINode>(
Cond->getOperand(1));
152 Pred, IVStart,
RHS, {
DL,
nullptr, DT,
nullptr, BI});
153 auto *SimpleCst = dyn_cast_or_null<Constant>(SimpleValOrNull);
156 if (ExitBlock == BI->getSuccessor(0))
157 return SimpleCst->isZeroValue();
158 assert(ExitBlock == BI->getSuccessor(1) &&
"implied by above");
159 return SimpleCst->isAllOnesValue();
168 assert(Predecessors.
empty() &&
"Garbage in predecessors set?");
169 assert(CurLoop->
contains(BB) &&
"Should only be called for loop blocks!");
174 Predecessors.
insert(Pred);
177 while (!WorkList.
empty()) {
179 assert(CurLoop->
contains(Pred) &&
"Should only reach loop blocks!");
190 if (Predecessors.
insert(PredPred).second)
198 assert(CurLoop->
contains(BB) &&
"Should only be called for loop blocks!");
225 for (
const auto *Pred : Predecessors) {
236 if (CheckedSuccessors.
insert(Succ).second &&
237 Succ != BB && !Predecessors.
count(Succ))
265 const Loop *CurLoop)
const {
274 return !HeaderMayThrow ||
275 Inst.
getParent()->getFirstNonPHIOrDbg() == &Inst;
284 const Loop *CurLoop)
const {
290 const Loop *CurLoop)
const {
291 assert(CurLoop->
contains(BB) &&
"Should only be called for loop blocks!");
303 for (
const auto *Pred : Predecessors)
310 const Loop *CurLoop)
const {
311 auto *BB =
I.getParent();
312 assert(CurLoop->
contains(BB) &&
"Should only be called for loop blocks!");
334 MustExecuteAnnotatedWriter(
const Function &
F,
340 MustExec[&
I].push_back(L);
342 L =
L->getParentLoop();
346 MustExecuteAnnotatedWriter(
const Module &M,
348 for (
const auto &
F : M)
353 MustExec[&
I].push_back(L);
355 L =
L->getParentLoop();
362 if (!MustExec.
count(&V))
366 const auto NumLoops =
Loops.size();
368 OS <<
" ; (mustexec in " << NumLoops <<
" loops: ";
370 OS <<
" ; (mustexec in: ";
374 OS <<
LS <<
L->getHeader()->getName();
382 if (L.getHeader()->getParent()->hasFnAttribute(Attribute::WillReturn))
393 RPOTraversal FuncRPOT(&
F);
400template <
typename K,
typename V,
typename FnTy,
typename... ArgsTy>
402 FnTy &&Fn, ArgsTy &&...
args) {
403 std::optional<V> &OptVal = Map[Key];
405 OptVal = Fn(std::forward<ArgsTy>(
args)...);
415 << (LI ?
" [LI]" :
"") << (PDT ?
" [PDT]" :
""));
419 const BasicBlock *HeaderBB = L ? L->getHeader() : InitBB;
420 bool WillReturnAndNoThrow = (
F.hasFnAttribute(Attribute::WillReturn) ||
424 << (WillReturnAndNoThrow ?
" [WillReturn] [NoUnwind]" :
"")
431 bool IsLatch = SuccBB == HeaderBB;
434 if (!WillReturnAndNoThrow || !IsLatch)
440 if (Worklist.
empty())
444 if (Worklist.
size() == 1)
452 if (
const auto *InitNode = PDT->
getNode(InitBB))
453 if (
const auto *IDomNode = InitNode->getIDom())
454 JoinBB = IDomNode->getBlock();
456 if (!JoinBB && Worklist.
size() == 2) {
461 if (Succ0UniqueSucc == InitBB) {
465 }
else if (Succ1UniqueSucc == InitBB) {
469 }
else if (Succ0 == Succ1UniqueSucc) {
473 }
else if (Succ1 == Succ0UniqueSucc) {
477 }
else if (Succ0UniqueSucc == Succ1UniqueSucc) {
480 JoinBB = Succ0UniqueSucc;
485 JoinBB = L->getUniqueExitBlock();
500 if (!
F.hasFnAttribute(Attribute::WillReturn) || !
F.doesNotThrow()) {
502 auto BlockTransfersExecutionToSuccessor = [](
const BasicBlock *BB) {
507 while (!Worklist.
empty()) {
513 if (!Visited.
insert(ToBB).second) {
514 if (!
F.hasFnAttribute(Attribute::WillReturn)) {
520 if (MayContainIrreducibleControl)
534 ToBB, BlockTransferMap, BlockTransfersExecutionToSuccessor, ToBB);
535 if (!TransfersExecution)
550 << (LI ?
" [LI]" :
"") << (DT ?
" [DT]" :
""));
556 if (
const auto *InitNode = DT->
getNode(InitBB))
557 if (
const auto *IDomNode = InitNode->getIDom())
558 return IDomNode->getBlock();
561 const BasicBlock *HeaderBB = L ? L->getHeader() :
nullptr;
567 (PredBB == InitBB) || (HeaderBB == InitBB && L->contains(PredBB));
575 if (Worklist.
empty())
579 if (Worklist.
size() == 1)
583 if (Worklist.
size() == 2) {
588 if (Pred0 == Pred1UniquePred) {
592 }
else if (Pred1 == Pred0UniquePred) {
596 }
else if (Pred0UniquePred == Pred1UniquePred) {
599 JoinBB = Pred0UniquePred;
604 JoinBB = L->getHeader();
617 LLVM_DEBUG(
dbgs() <<
"Find next instruction for " << *PP <<
"\n");
621 LLVM_DEBUG(
dbgs() <<
"\tReached terminator in intra-block mode, done\n");
629 if (!TransfersExecution)
638 LLVM_DEBUG(
dbgs() <<
"\tIntermediate instruction does transfer control\n");
655 dbgs() <<
"\tUnconditional terminator, continue with successor\n");
663 return &JoinBB->front();
677 << (IsFirst ?
" [IsFirst]" :
"") <<
"\n");
682 LLVM_DEBUG(
dbgs() <<
"\tReached block front in intra-block mode, done\n");
694 dbgs() <<
"\tIntermediate instruction, continue with previous\n");
704 return &JoinBB->back();
712 : Explorer(Explorer), CurInst(
I) {
716void MustBeExecutedIterator::reset(
const Instruction *
I) {
721void MustBeExecutedIterator::resetInstruction(
const Instruction *
I) {
723 Head = Tail =
nullptr;
732const Instruction *MustBeExecutedIterator::advance() {
733 assert(CurInst &&
"Cannot advance an end iterator!");
735 if (Head && Visited.
insert({Head, ExplorationDirection ::FORWARD}).second)
740 if (Tail && Visited.
insert({Tail, ExplorationDirection ::BACKWARD}).second)
751 MustExecuteAnnotatedWriter Writer(
F, DT, LI);
752 F.print(
OS, &Writer);
760 GetterTy<const LoopInfo> LIGetter = [&](
const Function &
F) {
763 GetterTy<const DominatorTree> DTGetter = [&](
const Function &
F) {
766 GetterTy<const PostDominatorTree> PDTGetter = [&](
const Function &
F) {
773 true, LIGetter, DTGetter, PDTGetter);
777 OS <<
"-- Explore context of: " <<
I <<
"\n";
779 OS <<
" [F: " << CI->getFunction()->getName() <<
"] " << *CI <<
"\n";
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
Module.h This file contains the declarations for the Module class.
static void collectTransitivePredecessors(const Loop *CurLoop, const BasicBlock *BB, SmallPtrSetImpl< const BasicBlock * > &Predecessors)
Collect all blocks from CurLoop which lie on all possible paths from the header of CurLoop (inclusive...
static bool maybeEndlessLoop(const Loop &L)
Return true if L might be an endless loop.
static V getOrCreateCachedOptional(K Key, DenseMap< K, std::optional< V > > &Map, FnTy &&Fn, ArgsTy &&...args)
Lookup Key in Map and return the result, potentially after initializing the optional through Fn(args)...
static bool isMustExecuteIn(const Instruction &I, Loop *L, DominatorTree *DT)
static bool CanProveNotTakenFirstIteration(const BasicBlock *ExitBlock, const DominatorTree *DT, const Loop *CurLoop)
Return true if we can prove that the given ExitBlock is not reached on the first iteration of the giv...
Contains a collection of routines for determining if a given instruction is guaranteed to execute if ...
FunctionAnalysisManager FAM
This header defines various interfaces for pass management in LLVM.
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
const Instruction & front() const
const BasicBlock * getUniqueSuccessor() const
Return the successor of this block if it has a unique successor.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const BasicBlock * getUniquePredecessor() const
Return the predecessor of this block if it has a unique predecessor block.
const Function * getParent() const
Return the enclosing method, or null if none.
const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
This is an important base class in LLVM.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
bool hasPersonalityFn() const
Check whether this function has a personality function.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
bool blockMayThrow(const BasicBlock *BB) const override
Returns true iff the block BB potentially may throw exception.
bool doesNotWriteMemoryBefore(const BasicBlock *BB, const Loop *CurLoop) const
Returns true if we could not execute a memory-modifying instruction before we enter BB under assumpti...
void removeInstruction(const Instruction *Inst)
Inform safety info that we are planning to remove the instruction Inst from its block.
bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT, const Loop *CurLoop) const override
Returns true if the instruction in a loop is guaranteed to execute at least once (under the assumptio...
bool anyBlockMayThrow() const override
Returns true iff any block of the loop for which this info is contains an instruction that may throw ...
void computeLoopSafetyInfo(const Loop *CurLoop) override
Computes safety information for a loop checks loop body & header for the possibility of may throw exc...
void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB)
Inform the safety info that we are planning to insert a new instruction Inst into the basic block BB.
bool isDominatedByICFIFromSameBlock(const Instruction *Insn)
Returns true if the first ICFI of Insn's block exists and dominates Insn.
bool hasICF(const BasicBlock *BB)
Returns true if at least one instruction from the given basic block has implicit control flow.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
void clear()
Invalidates all information from this tracking.
void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB)
Notifies this tracking that we are going to insert a new instruction Inst to the basic block BB.
void removeInstruction(const Instruction *Inst)
Notifies this tracking that we are going to remove the instruction Inst It makes all necessary update...
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
bool isTerminator() const
Analysis pass that exposes the LoopInfo for a function.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within in this loop.
BlockT * getHeader() const
iterator_range< block_iterator > blocks() const
BlockT * getLoopPreheader() const
If there is a preheader for this loop, return it.
ArrayRef< BlockT * > getBlocks() const
Get a list of the basic blocks which make up this loop.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
bool allLoopPathsLeadToBlock(const Loop *CurLoop, const BasicBlock *BB, const DominatorTree *DT) const
Return true if we must reach the block BB under assumption that the loop CurLoop is entered.
void copyColors(BasicBlock *New, BasicBlock *Old)
Copy colors of block Old into the block New.
void computeBlockColors(const Loop *CurLoop)
Computes block colors.
const DenseMap< BasicBlock *, ColorVector > & getBlockColors() const
Returns block colors map that is used to update funclet operand bundles.
virtual bool blockMayThrow(const BasicBlock *BB) const =0
Returns true iff the block BB potentially may throw exception.
Represents a single loop in the control flow graph.
bool mayWriteToMemory(const BasicBlock *BB)
Returns true if at least one instruction from the given basic block may write memory.
bool isDominatedByMemoryWriteFromSameBlock(const Instruction *Insn)
Returns true if the first memory writing instruction of Insn's block exists and dominates Insn.
A Module instance is used to store all the information related to an LLVM module.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Analysis pass which computes a PostDominatorTree.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
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.
Simple and conservative implementation of LoopSafetyInfo that can give false-positive answers to its ...
bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT, const Loop *CurLoop) const override
Returns true if the instruction in a loop is guaranteed to execute at least once.
void computeLoopSafetyInfo(const Loop *CurLoop) override
Computes safety information for a loop checks loop body & header for the possibility of may throw exc...
bool anyBlockMayThrow() const override
Returns true iff any block of the loop for which this info is contains an instruction that may throw ...
bool blockMayThrow(const BasicBlock *BB) const override
Returns true iff the block BB potentially may throw exception.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
const ParentTy * getParent() const
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
auto successors(const MachineBasicBlock *BB)
bool isGuaranteedToExecuteForEveryIteration(const Instruction *I, const Loop *L)
Return true if this function can prove that the instruction I is executed for every iteration of the ...
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
DenseMap< BasicBlock *, ColorVector > colorEHFunclets(Function &F)
If an EH funclet personality is in use (see isFuncletEHPersonality), this will recompute which blocks...
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
bool containsIrreducibleCFG(RPOTraversalT &RPOTraversal, const LoopInfoT &LI)
Return true if the control flow in RPOTraversal is irreducible.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
Value * simplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)
Return true if this function can prove that the instruction I will always transfer execution to one o...
auto predecessors(const MachineBasicBlock *BB)
bool mayContainIrreducibleControl(const Function &F, const LoopInfo *LI)
A "must be executed context" for a given program point PP is the set of instructions,...
const bool ExploreInterBlock
Parameter that limit the performed exploration.
const BasicBlock * findBackwardJoinPoint(const BasicBlock *InitBB)
Find the next join point from InitBB in backward direction.
const Instruction * getMustBeExecutedNextInstruction(MustBeExecutedIterator &It, const Instruction *PP)
Return the next instruction that is guaranteed to be executed after PP.
const bool ExploreCFGBackward
const bool ExploreCFGForward
llvm::iterator_range< iterator > range(const Instruction *PP)
}
const Instruction * getMustBeExecutedPrevInstruction(MustBeExecutedIterator &It, const Instruction *PP)
Return the previous instr.
const BasicBlock * findForwardJoinPoint(const BasicBlock *InitBB)
Find the next join point from InitBB in forward direction.
Must be executed iterators visit stretches of instructions that are guaranteed to be executed togethe...
MustBeExecutedIterator(const MustBeExecutedIterator &Other)=default