143#define DEBUG_TYPE "fix-irreducible"
166char FixIrreducible::ID = 0;
171 "Convert irreducible control-flow into natural loops",
176 "Convert irreducible control-flow into natural loops",
183 auto &CandidateLoops = ParentLoop ? ParentLoop->getSubLoopsVector()
184 : LI.getTopLevelLoopsVector();
188 return NewLoop == L || !NewLoop->contains(L->getHeader());
191 CandidateLoops.
erase(FirstChild, CandidateLoops.end());
193 for (
Loop *Child : ChildLoops) {
194 LLVM_DEBUG(
dbgs() <<
"child loop: " << Child->getHeader()->getName()
198 if (Child->getHeader() == OldHeader) {
199 for (
auto *BB : Child->blocks()) {
200 if (LI.getLoopFor(BB) != Child)
202 LI.changeLoopFor(BB, NewLoop);
206 std::vector<Loop *> GrandChildLoops;
207 std::swap(GrandChildLoops, Child->getSubLoopsVector());
208 for (
auto *GrandChildLoop : GrandChildLoops) {
209 GrandChildLoop->setParentLoop(
nullptr);
210 NewLoop->addChildLoop(GrandChildLoop);
217 Child->setParentLoop(
nullptr);
218 NewLoop->addChildLoop(Child);
230 if (ParentLoop && ParentLoop->
getHeader() == CycleHeader)
246 for (
auto *
G : GuardBlocks) {
247 LLVM_DEBUG(
dbgs() <<
"added guard block to loop: " <<
G->getName() <<
"\n");
248 NewLoop->addBasicBlockToLoop(
G, LI);
252 NewLoop->addBlockEntry(BB);
258 LLVM_DEBUG(
dbgs() <<
"added block from child: " << BB->getName() <<
"\n");
262 << NewLoop->getHeader()->getName() <<
"\n");
267 NewLoop->verifyLoop();
297 assert(Term->getSuccessor(0) == Header);
303 BasicBlock *Succ0 = Branch->getSuccessor(0) == Header ? Header :
nullptr;
304 BasicBlock *Succ1 = Branch->getSuccessor(1) == Header ? Header :
nullptr;
314 for (
unsigned I = 0;
I < Term->getNumSuccessors(); ++
I) {
327 "unsupported block terminator: fix-irreducible "
328 "only supports br, callbr, and switch instructions");
333 Predecessors.
clear();
345 Succ0 = CI.
contains(
C, Succ0) ? Succ0 :
nullptr;
352 Succ0 = CI.
contains(
C, Succ0) ? Succ0 :
nullptr;
354 Succ1 = CI.
contains(
C, Succ1) ? Succ1 :
nullptr;
363 for (
unsigned I = 0;
I < Term->getNumSuccessors(); ++
I) {
367 auto It = MultiBrTargets.
find(Succ);
369 (It != MultiBrTargets.
end()) ? It->second :
nullptr;
373 if (!ExistingTarget) {
375 MultiBrTargets[Succ] = NewSucc;
383 "unsupported block terminator: fix-irreducible "
384 "only supports br, callbr, and switch instructions");
401 CHub.
finalize(&DTU, GuardBlocks,
"irr");
402#if defined(EXPENSIVE_CHECKS)
403 assert(DT.
verify(DominatorTree::VerificationLevel::Full));
405 assert(DT.
verify(DominatorTree::VerificationLevel::Fast));
413 for (
auto *
G : GuardBlocks) {
430 LLVM_DEBUG(
dbgs() <<
"===== Fix irreducible control-flow in function: "
431 <<
F.getName() <<
"\n");
440#if defined(EXPENSIVE_CHECKS)
450bool FixIrreducible::runOnFunction(
Function &
F) {
451 auto *LIWP = getAnalysisIfAvailable<LoopInfoWrapperPass>();
452 LoopInfo *LI = LIWP ? &LIWP->getLoopInfo() :
nullptr;
453 auto &CI = getAnalysis<CycleInfoWrapperPass>().getResult();
454 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file declares an analysis pass that computes CycleInfo for LLVM IR, specialized from GenericCycl...
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
fix Convert irreducible control flow into natural static false void reconnectChildLoops(LoopInfo &LI, Loop *ParentLoop, Loop *NewLoop, BasicBlock *OldHeader)
static bool FixIrreducibleImpl(Function &F, CycleInfo &CI, DominatorTree &DT, LoopInfo *LI)
static void updateLoopInfo(CycleInfo &CI, LoopInfo &LI, CycleRef C, ArrayRef< BasicBlock * > GuardBlocks)
static bool fixIrreducible(CycleRef C, CycleInfo &CI, DominatorTree &DT, LoopInfo *LI)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
Conditional Branch instruction.
Analysis pass which computes a CycleInfo.
Legacy analysis pass which computes a CycleInfo.
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
iterator find(const_arg_type_t< KeyT > Val)
Analysis pass which computes a DominatorTree.
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
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.
void verify() const
Verify that the entire cycle tree well-formed.
auto cycles() const
All cycles in forest preorder.
void verifyCycle(CycleRef C) const
Verify that C is actually a well-formed cycle in the CFG.
bool isReducible(CycleRef C) const
CycleRef getParentCycle(CycleRef C) const
void print(raw_ostream &Out) const
Print the cycle info.
ArrayRef< BlockT * > getEntries(CycleRef C) const
void setSingleEntry(CycleRef C, BlockT *Block)
void addBlockToCycle(BlockT *Block, CycleRef C)
Assumes that C is the innermost cycle containing Block.
ArrayRef< BlockT * > getBlocks(CycleRef C) const
Return the blocks of C, including those of nested cycles.
bool contains(CycleRef Outer, CycleRef Inner) const
Returns true iff Outer contains Inner. O(1). Non-strict.
BlockT * getHeader(CycleRef C) const
Analysis pass that exposes the LoopInfo for a function.
void verifyLoop() const
Verify loop structure.
BlockT * getHeader() const
void print(raw_ostream &OS, bool Verbose=false, bool PrintNested=true, unsigned Depth=0) const
Print loop with all the BBs inside it.
void addChildLoop(LoopT *NewChild)
Add the specified loop to be a child of this loop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
void verify(const DominatorTreeBase< BlockT, false > &DomTree) const
void addTopLevelLoop(LoopT *New)
This adds the specified loop to the collection of top-level loops.
LoopT * AllocateLoop(ArgsTy &&...Args)
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
void changeLoopFor(const BlockT *BB, LoopT *L)
Change the top-level loop that contains BB to the specified loop.
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
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.
A vector that has set insertion semantics.
void clear()
Completely clear the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
iterator erase(const_iterator CI)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Unconditional Branch instruction.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI BasicBlock * SplitMultiBrEdge(BasicBlock *MultiBrBlock, BasicBlock *Succ, unsigned SuccIdx, BasicBlock *BrTarget=nullptr, DomTreeUpdater *DTU=nullptr, CycleInfo *CI=nullptr, LoopInfo *LI=nullptr, bool *UpdatedLI=nullptr)
Create a new intermediate target block for a callbr or switch edge.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI FunctionPass * createFixIrreduciblePass()
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
auto partition(R &&Range, UnaryPredicate P)
Provide wrappers to std::partition which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI Printable printBasicBlock(const BasicBlock *BB)
Print BasicBlock BB as an operand or print "<nullptr>" if BB is a nullptr.
auto predecessors(const MachineBasicBlock *BB)
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void initializeFixIrreduciblePass(PassRegistry &)
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Given a set of branch descriptors [BB, Succ0, Succ1], create a "hub" such that the control flow from ...
void addBranch(BasicBlock *BB, BasicBlock *Succ0, BasicBlock *Succ1=nullptr)
LLVM_ABI std::pair< BasicBlock *, bool > finalize(DomTreeUpdater *DTU, SmallVectorImpl< BasicBlock * > &GuardBlocks, const StringRef Prefix, std::optional< unsigned > MaxControlFlowBooleans=std::nullopt)
Return the unified loop exit block and a flag indicating if the CFG was changed at all.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)