78#define DEBUG_TYPE "fix-irreducible"
100char FixIrreducible::ID = 0;
105 "Convert irreducible control-flow into natural loops",
118 auto &CandidateLoops = ParentLoop ? ParentLoop->getSubLoopsVector()
119 : LI.getTopLevelLoopsVector();
123 auto FirstChild = std::partition(
124 CandidateLoops.begin(), CandidateLoops.end(), [&](
Loop *L) {
125 return L == NewLoop || !Blocks.contains(L->getHeader());
128 CandidateLoops.erase(FirstChild, CandidateLoops.end());
130 for (
Loop *Child : ChildLoops) {
131 LLVM_DEBUG(
dbgs() <<
"child loop: " << Child->getHeader()->getName()
136 if (Headers.count(Child->getHeader())) {
137 for (
auto *BB : Child->blocks()) {
138 if (LI.getLoopFor(BB) != Child)
140 LI.changeLoopFor(BB, NewLoop);
144 std::vector<Loop *> GrandChildLoops;
145 std::swap(GrandChildLoops, Child->getSubLoopsVector());
146 for (
auto *GrandChildLoop : GrandChildLoops) {
147 GrandChildLoop->setParentLoop(
nullptr);
148 NewLoop->addChildLoop(GrandChildLoop);
155 Child->setParentLoop(
nullptr);
156 NewLoop->addChildLoop(Child);
170 for (
auto *
H : Headers) {
176 for (
auto *
H : Headers) {
183 dbgs() <<
"Found predecessors:";
184 for (
auto P : Predecessors) {
185 dbgs() <<
" " <<
P->getName();
194 auto *Branch = cast<BranchInst>(
P->getTerminator());
196 Succ0 = Headers.
count(Succ0) ? Succ0 :
nullptr;
198 Branch->isUnconditional() ? nullptr : Branch->getSuccessor(1);
199 Succ1 = Succ1 && Headers.
count(Succ1) ? Succ1 :
nullptr;
200 CHub.addBranch(
P, Succ0, Succ1);
203 << (Succ0 ? Succ0->
getName() :
"") <<
" "
204 << (Succ1 ? Succ1->
getName() :
"") <<
"\n");
209 CHub.finalize(&DTU, GuardBlocks,
"irr");
210#if defined(EXPENSIVE_CHECKS)
211 assert(DT.
verify(DominatorTree::VerificationLevel::Full));
213 assert(DT.
verify(DominatorTree::VerificationLevel::Fast));
229 for (
auto *
G : GuardBlocks) {
231 NewLoop->addBasicBlockToLoop(
G, LI);
236 NewLoop->addBlockEntry(BB);
242 LLVM_DEBUG(
dbgs() <<
"added block from child: " << BB->getName() <<
"\n");
246 << NewLoop->getHeader()->getName() <<
"\n");
250 NewLoop->verifyLoop();
254#if defined(EXPENSIVE_CHECKS)
281template <
class Graph>
283 bool Changed =
false;
284 for (
auto Scc =
scc_begin(
G); !Scc.isAtEnd(); ++Scc) {
289 for (
auto N : *Scc) {
317 if (Headers.
size() == 1) {
319 LLVM_DEBUG(
dbgs() <<
"Natural loop with a single header: skipped\n");
329 LLVM_DEBUG(
dbgs() <<
"===== Fix irreducible control-flow in function: "
330 <<
F.getName() <<
"\n");
334 bool Changed =
false;
344 while (!WorkList.
empty()) {
347 << L->getHeader()->getName() <<
"\n");
351 WorkList.
append(L->begin(), L->end());
357bool FixIrreducible::runOnFunction(
Function &
F) {
358 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
359 auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DenseMap< Block *, BlockRelaxAux > Blocks
static void createNaturalLoop(LoopInfo &LI, DominatorTree &DT, Function *F, SetVector< BasicBlock * > &Blocks, SetVector< BasicBlock * > &Headers)
static bool FixIrreducibleImpl(Function &F, LoopInfo &LI, DominatorTree &DT)
fix Convert irreducible control flow into natural static false void reconnectChildLoops(LoopInfo &LI, Loop *ParentLoop, Loop *NewLoop, SetVector< BasicBlock * > &Blocks, SetVector< BasicBlock * > &Headers)
static BasicBlock * unwrapBlock(BasicBlock *B)
fix Convert irreducible control flow into natural loops
static bool makeReducible(LoopInfo &LI, DominatorTree &DT, Graph &&G)
static void createNaturalLoopInternal(LoopInfo &LI, DominatorTree &DT, Loop *ParentLoop, SetVector< BasicBlock * > &Blocks, SetVector< BasicBlock * > &Headers)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
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.
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.
LLVM Basic Block Representation.
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.
bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
Analysis pass that exposes the LoopInfo for a function.
void verifyLoop() const
Verify loop structure.
void addChildLoop(LoopT *NewChild)
Add the specified loop to be a child of this loop.
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)
bool isLoopHeader(const BlockT *BB) const
void changeLoopFor(BlockT *BB, LoopT *L)
Change the top-level loop that contains BB to the specified loop.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
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.
void preserve()
Mark an analysis as preserved.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
const value_type & front() const
Return the first element of the SetVector.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef getName() const
Return a constant reference to the value's name.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
bool hasOnlySimpleTerminator(const Function &F)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
auto reverse(ContainerTy &&C)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createFixIrreduciblePass()
void initializeFixIrreduciblePass(PassRegistry &)
auto predecessors(const MachineBasicBlock *BB)
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 ...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
std::pair< const Loop *, BasicBlock * > NodeRef