1*5ffd83dbSDimitry Andric //===- FixIrreducible.cpp - Convert irreducible control-flow into loops ---===// 2*5ffd83dbSDimitry Andric // 3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5ffd83dbSDimitry Andric // 7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 8*5ffd83dbSDimitry Andric // 9*5ffd83dbSDimitry Andric // An irreducible SCC is one which has multiple "header" blocks, i.e., blocks 10*5ffd83dbSDimitry Andric // with control-flow edges incident from outside the SCC. This pass converts a 11*5ffd83dbSDimitry Andric // irreducible SCC into a natural loop by applying the following transformation: 12*5ffd83dbSDimitry Andric // 13*5ffd83dbSDimitry Andric // 1. Collect the set of headers H of the SCC. 14*5ffd83dbSDimitry Andric // 2. Collect the set of predecessors P of these headers. These may be inside as 15*5ffd83dbSDimitry Andric // well as outside the SCC. 16*5ffd83dbSDimitry Andric // 3. Create block N and redirect every edge from set P to set H through N. 17*5ffd83dbSDimitry Andric // 18*5ffd83dbSDimitry Andric // This converts the SCC into a natural loop with N as the header: N is the only 19*5ffd83dbSDimitry Andric // block with edges incident from outside the SCC, and all backedges in the SCC 20*5ffd83dbSDimitry Andric // are incident on N, i.e., for every backedge, the head now dominates the tail. 21*5ffd83dbSDimitry Andric // 22*5ffd83dbSDimitry Andric // INPUT CFG: The blocks A and B form an irreducible loop with two headers. 23*5ffd83dbSDimitry Andric // 24*5ffd83dbSDimitry Andric // Entry 25*5ffd83dbSDimitry Andric // / \ 26*5ffd83dbSDimitry Andric // v v 27*5ffd83dbSDimitry Andric // A ----> B 28*5ffd83dbSDimitry Andric // ^ /| 29*5ffd83dbSDimitry Andric // `----' | 30*5ffd83dbSDimitry Andric // v 31*5ffd83dbSDimitry Andric // Exit 32*5ffd83dbSDimitry Andric // 33*5ffd83dbSDimitry Andric // OUTPUT CFG: Edges incident on A and B are now redirected through a 34*5ffd83dbSDimitry Andric // new block N, forming a natural loop consisting of N, A and B. 35*5ffd83dbSDimitry Andric // 36*5ffd83dbSDimitry Andric // Entry 37*5ffd83dbSDimitry Andric // | 38*5ffd83dbSDimitry Andric // v 39*5ffd83dbSDimitry Andric // .---> N <---. 40*5ffd83dbSDimitry Andric // / / \ \ 41*5ffd83dbSDimitry Andric // | / \ | 42*5ffd83dbSDimitry Andric // \ v v / 43*5ffd83dbSDimitry Andric // `-- A B --' 44*5ffd83dbSDimitry Andric // | 45*5ffd83dbSDimitry Andric // v 46*5ffd83dbSDimitry Andric // Exit 47*5ffd83dbSDimitry Andric // 48*5ffd83dbSDimitry Andric // The transformation is applied to every maximal SCC that is not already 49*5ffd83dbSDimitry Andric // recognized as a loop. The pass operates on all maximal SCCs found in the 50*5ffd83dbSDimitry Andric // function body outside of any loop, as well as those found inside each loop, 51*5ffd83dbSDimitry Andric // including inside any newly created loops. This ensures that any SCC hidden 52*5ffd83dbSDimitry Andric // inside a maximal SCC is also transformed. 53*5ffd83dbSDimitry Andric // 54*5ffd83dbSDimitry Andric // The actual transformation is handled by function CreateControlFlowHub, which 55*5ffd83dbSDimitry Andric // takes a set of incoming blocks (the predecessors) and outgoing blocks (the 56*5ffd83dbSDimitry Andric // headers). The function also moves every PHINode in an outgoing block to the 57*5ffd83dbSDimitry Andric // hub. Since the hub dominates all the outgoing blocks, each such PHINode 58*5ffd83dbSDimitry Andric // continues to dominate its uses. Since every header in an SCC has at least two 59*5ffd83dbSDimitry Andric // predecessors, every value used in the header (or later) but defined in a 60*5ffd83dbSDimitry Andric // predecessor (or earlier) is represented by a PHINode in a header. Hence the 61*5ffd83dbSDimitry Andric // above handling of PHINodes is sufficient and no further processing is 62*5ffd83dbSDimitry Andric // required to restore SSA. 63*5ffd83dbSDimitry Andric // 64*5ffd83dbSDimitry Andric // Limitation: The pass cannot handle switch statements and indirect 65*5ffd83dbSDimitry Andric // branches. Both must be lowered to plain branches first. 66*5ffd83dbSDimitry Andric // 67*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 68*5ffd83dbSDimitry Andric 69*5ffd83dbSDimitry Andric #include "llvm/ADT/SCCIterator.h" 70*5ffd83dbSDimitry Andric #include "llvm/Analysis/LoopIterator.h" 71*5ffd83dbSDimitry Andric #include "llvm/InitializePasses.h" 72*5ffd83dbSDimitry Andric #include "llvm/Pass.h" 73*5ffd83dbSDimitry Andric #include "llvm/Transforms/Utils.h" 74*5ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 75*5ffd83dbSDimitry Andric 76*5ffd83dbSDimitry Andric #define DEBUG_TYPE "fix-irreducible" 77*5ffd83dbSDimitry Andric 78*5ffd83dbSDimitry Andric using namespace llvm; 79*5ffd83dbSDimitry Andric 80*5ffd83dbSDimitry Andric namespace { 81*5ffd83dbSDimitry Andric struct FixIrreducible : public FunctionPass { 82*5ffd83dbSDimitry Andric static char ID; 83*5ffd83dbSDimitry Andric FixIrreducible() : FunctionPass(ID) { 84*5ffd83dbSDimitry Andric initializeFixIrreduciblePass(*PassRegistry::getPassRegistry()); 85*5ffd83dbSDimitry Andric } 86*5ffd83dbSDimitry Andric 87*5ffd83dbSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 88*5ffd83dbSDimitry Andric AU.addRequiredID(LowerSwitchID); 89*5ffd83dbSDimitry Andric AU.addRequired<DominatorTreeWrapperPass>(); 90*5ffd83dbSDimitry Andric AU.addRequired<LoopInfoWrapperPass>(); 91*5ffd83dbSDimitry Andric AU.addPreservedID(LowerSwitchID); 92*5ffd83dbSDimitry Andric AU.addPreserved<DominatorTreeWrapperPass>(); 93*5ffd83dbSDimitry Andric AU.addPreserved<LoopInfoWrapperPass>(); 94*5ffd83dbSDimitry Andric } 95*5ffd83dbSDimitry Andric 96*5ffd83dbSDimitry Andric bool runOnFunction(Function &F) override; 97*5ffd83dbSDimitry Andric }; 98*5ffd83dbSDimitry Andric } // namespace 99*5ffd83dbSDimitry Andric 100*5ffd83dbSDimitry Andric char FixIrreducible::ID = 0; 101*5ffd83dbSDimitry Andric 102*5ffd83dbSDimitry Andric FunctionPass *llvm::createFixIrreduciblePass() { return new FixIrreducible(); } 103*5ffd83dbSDimitry Andric 104*5ffd83dbSDimitry Andric INITIALIZE_PASS_BEGIN(FixIrreducible, "fix-irreducible", 105*5ffd83dbSDimitry Andric "Convert irreducible control-flow into natural loops", 106*5ffd83dbSDimitry Andric false /* Only looks at CFG */, false /* Analysis Pass */) 107*5ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(LowerSwitch) 108*5ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 109*5ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) 110*5ffd83dbSDimitry Andric INITIALIZE_PASS_END(FixIrreducible, "fix-irreducible", 111*5ffd83dbSDimitry Andric "Convert irreducible control-flow into natural loops", 112*5ffd83dbSDimitry Andric false /* Only looks at CFG */, false /* Analysis Pass */) 113*5ffd83dbSDimitry Andric 114*5ffd83dbSDimitry Andric // When a new loop is created, existing children of the parent loop may now be 115*5ffd83dbSDimitry Andric // fully inside the new loop. Reconnect these as children of the new loop. 116*5ffd83dbSDimitry Andric static void reconnectChildLoops(LoopInfo &LI, Loop *ParentLoop, Loop *NewLoop, 117*5ffd83dbSDimitry Andric SetVector<BasicBlock *> &Blocks, 118*5ffd83dbSDimitry Andric SetVector<BasicBlock *> &Headers) { 119*5ffd83dbSDimitry Andric auto &CandidateLoops = ParentLoop ? ParentLoop->getSubLoopsVector() 120*5ffd83dbSDimitry Andric : LI.getTopLevelLoopsVector(); 121*5ffd83dbSDimitry Andric // The new loop cannot be its own child, and any candidate is a 122*5ffd83dbSDimitry Andric // child iff its header is owned by the new loop. Move all the 123*5ffd83dbSDimitry Andric // children to a new vector. 124*5ffd83dbSDimitry Andric auto FirstChild = std::partition( 125*5ffd83dbSDimitry Andric CandidateLoops.begin(), CandidateLoops.end(), [&](Loop *L) { 126*5ffd83dbSDimitry Andric return L == NewLoop || Blocks.count(L->getHeader()) == 0; 127*5ffd83dbSDimitry Andric }); 128*5ffd83dbSDimitry Andric SmallVector<Loop *, 8> ChildLoops(FirstChild, CandidateLoops.end()); 129*5ffd83dbSDimitry Andric CandidateLoops.erase(FirstChild, CandidateLoops.end()); 130*5ffd83dbSDimitry Andric 131*5ffd83dbSDimitry Andric for (auto II = ChildLoops.begin(), IE = ChildLoops.end(); II != IE; ++II) { 132*5ffd83dbSDimitry Andric auto Child = *II; 133*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "child loop: " << Child->getHeader()->getName() 134*5ffd83dbSDimitry Andric << "\n"); 135*5ffd83dbSDimitry Andric // TODO: A child loop whose header is also a header in the current 136*5ffd83dbSDimitry Andric // SCC gets destroyed since its backedges are removed. That may 137*5ffd83dbSDimitry Andric // not be necessary if we can retain such backedges. 138*5ffd83dbSDimitry Andric if (Headers.count(Child->getHeader())) { 139*5ffd83dbSDimitry Andric for (auto BB : Child->blocks()) { 140*5ffd83dbSDimitry Andric LI.changeLoopFor(BB, NewLoop); 141*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "moved block from child: " << BB->getName() 142*5ffd83dbSDimitry Andric << "\n"); 143*5ffd83dbSDimitry Andric } 144*5ffd83dbSDimitry Andric LI.destroy(Child); 145*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "subsumed child loop (common header)\n"); 146*5ffd83dbSDimitry Andric continue; 147*5ffd83dbSDimitry Andric } 148*5ffd83dbSDimitry Andric 149*5ffd83dbSDimitry Andric Child->setParentLoop(nullptr); 150*5ffd83dbSDimitry Andric NewLoop->addChildLoop(Child); 151*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "added child loop to new loop\n"); 152*5ffd83dbSDimitry Andric } 153*5ffd83dbSDimitry Andric } 154*5ffd83dbSDimitry Andric 155*5ffd83dbSDimitry Andric // Given a set of blocks and headers in an irreducible SCC, convert it into a 156*5ffd83dbSDimitry Andric // natural loop. Also insert this new loop at its appropriate place in the 157*5ffd83dbSDimitry Andric // hierarchy of loops. 158*5ffd83dbSDimitry Andric static void createNaturalLoopInternal(LoopInfo &LI, DominatorTree &DT, 159*5ffd83dbSDimitry Andric Loop *ParentLoop, 160*5ffd83dbSDimitry Andric SetVector<BasicBlock *> &Blocks, 161*5ffd83dbSDimitry Andric SetVector<BasicBlock *> &Headers) { 162*5ffd83dbSDimitry Andric #ifndef NDEBUG 163*5ffd83dbSDimitry Andric // All headers are part of the SCC 164*5ffd83dbSDimitry Andric for (auto H : Headers) { 165*5ffd83dbSDimitry Andric assert(Blocks.count(H)); 166*5ffd83dbSDimitry Andric } 167*5ffd83dbSDimitry Andric #endif 168*5ffd83dbSDimitry Andric 169*5ffd83dbSDimitry Andric SetVector<BasicBlock *> Predecessors; 170*5ffd83dbSDimitry Andric for (auto H : Headers) { 171*5ffd83dbSDimitry Andric for (auto P : predecessors(H)) { 172*5ffd83dbSDimitry Andric Predecessors.insert(P); 173*5ffd83dbSDimitry Andric } 174*5ffd83dbSDimitry Andric } 175*5ffd83dbSDimitry Andric 176*5ffd83dbSDimitry Andric LLVM_DEBUG( 177*5ffd83dbSDimitry Andric dbgs() << "Found predecessors:"; 178*5ffd83dbSDimitry Andric for (auto P : Predecessors) { 179*5ffd83dbSDimitry Andric dbgs() << " " << P->getName(); 180*5ffd83dbSDimitry Andric } 181*5ffd83dbSDimitry Andric dbgs() << "\n"); 182*5ffd83dbSDimitry Andric 183*5ffd83dbSDimitry Andric // Redirect all the backedges through a "hub" consisting of a series 184*5ffd83dbSDimitry Andric // of guard blocks that manage the flow of control from the 185*5ffd83dbSDimitry Andric // predecessors to the headers. 186*5ffd83dbSDimitry Andric SmallVector<BasicBlock *, 8> GuardBlocks; 187*5ffd83dbSDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); 188*5ffd83dbSDimitry Andric CreateControlFlowHub(&DTU, GuardBlocks, Predecessors, Headers, "irr"); 189*5ffd83dbSDimitry Andric #if defined(EXPENSIVE_CHECKS) 190*5ffd83dbSDimitry Andric assert(DT.verify(DominatorTree::VerificationLevel::Full)); 191*5ffd83dbSDimitry Andric #else 192*5ffd83dbSDimitry Andric assert(DT.verify(DominatorTree::VerificationLevel::Fast)); 193*5ffd83dbSDimitry Andric #endif 194*5ffd83dbSDimitry Andric 195*5ffd83dbSDimitry Andric // Create a new loop from the now-transformed cycle 196*5ffd83dbSDimitry Andric auto NewLoop = LI.AllocateLoop(); 197*5ffd83dbSDimitry Andric if (ParentLoop) { 198*5ffd83dbSDimitry Andric ParentLoop->addChildLoop(NewLoop); 199*5ffd83dbSDimitry Andric } else { 200*5ffd83dbSDimitry Andric LI.addTopLevelLoop(NewLoop); 201*5ffd83dbSDimitry Andric } 202*5ffd83dbSDimitry Andric 203*5ffd83dbSDimitry Andric // Add the guard blocks to the new loop. The first guard block is 204*5ffd83dbSDimitry Andric // the head of all the backedges, and it is the first to be inserted 205*5ffd83dbSDimitry Andric // in the loop. This ensures that it is recognized as the 206*5ffd83dbSDimitry Andric // header. Since the new loop is already in LoopInfo, the new blocks 207*5ffd83dbSDimitry Andric // are also propagated up the chain of parent loops. 208*5ffd83dbSDimitry Andric for (auto G : GuardBlocks) { 209*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "added guard block: " << G->getName() << "\n"); 210*5ffd83dbSDimitry Andric NewLoop->addBasicBlockToLoop(G, LI); 211*5ffd83dbSDimitry Andric } 212*5ffd83dbSDimitry Andric 213*5ffd83dbSDimitry Andric // Add the SCC blocks to the new loop. 214*5ffd83dbSDimitry Andric for (auto BB : Blocks) { 215*5ffd83dbSDimitry Andric NewLoop->addBlockEntry(BB); 216*5ffd83dbSDimitry Andric if (LI.getLoopFor(BB) == ParentLoop) { 217*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "moved block from parent: " << BB->getName() 218*5ffd83dbSDimitry Andric << "\n"); 219*5ffd83dbSDimitry Andric LI.changeLoopFor(BB, NewLoop); 220*5ffd83dbSDimitry Andric } else { 221*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "added block from child: " << BB->getName() << "\n"); 222*5ffd83dbSDimitry Andric } 223*5ffd83dbSDimitry Andric } 224*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "header for new loop: " 225*5ffd83dbSDimitry Andric << NewLoop->getHeader()->getName() << "\n"); 226*5ffd83dbSDimitry Andric 227*5ffd83dbSDimitry Andric reconnectChildLoops(LI, ParentLoop, NewLoop, Blocks, Headers); 228*5ffd83dbSDimitry Andric 229*5ffd83dbSDimitry Andric NewLoop->verifyLoop(); 230*5ffd83dbSDimitry Andric if (ParentLoop) { 231*5ffd83dbSDimitry Andric ParentLoop->verifyLoop(); 232*5ffd83dbSDimitry Andric } 233*5ffd83dbSDimitry Andric #if defined(EXPENSIVE_CHECKS) 234*5ffd83dbSDimitry Andric LI.verify(DT); 235*5ffd83dbSDimitry Andric #endif // EXPENSIVE_CHECKS 236*5ffd83dbSDimitry Andric } 237*5ffd83dbSDimitry Andric 238*5ffd83dbSDimitry Andric namespace llvm { 239*5ffd83dbSDimitry Andric // Enable the graph traits required for traversing a Loop body. 240*5ffd83dbSDimitry Andric template <> struct GraphTraits<Loop> : LoopBodyTraits {}; 241*5ffd83dbSDimitry Andric } // namespace llvm 242*5ffd83dbSDimitry Andric 243*5ffd83dbSDimitry Andric // Overloaded wrappers to go with the function template below. 244*5ffd83dbSDimitry Andric static BasicBlock *unwrapBlock(BasicBlock *B) { return B; } 245*5ffd83dbSDimitry Andric static BasicBlock *unwrapBlock(LoopBodyTraits::NodeRef &N) { return N.second; } 246*5ffd83dbSDimitry Andric 247*5ffd83dbSDimitry Andric static void createNaturalLoop(LoopInfo &LI, DominatorTree &DT, Function *F, 248*5ffd83dbSDimitry Andric SetVector<BasicBlock *> &Blocks, 249*5ffd83dbSDimitry Andric SetVector<BasicBlock *> &Headers) { 250*5ffd83dbSDimitry Andric createNaturalLoopInternal(LI, DT, nullptr, Blocks, Headers); 251*5ffd83dbSDimitry Andric } 252*5ffd83dbSDimitry Andric 253*5ffd83dbSDimitry Andric static void createNaturalLoop(LoopInfo &LI, DominatorTree &DT, Loop &L, 254*5ffd83dbSDimitry Andric SetVector<BasicBlock *> &Blocks, 255*5ffd83dbSDimitry Andric SetVector<BasicBlock *> &Headers) { 256*5ffd83dbSDimitry Andric createNaturalLoopInternal(LI, DT, &L, Blocks, Headers); 257*5ffd83dbSDimitry Andric } 258*5ffd83dbSDimitry Andric 259*5ffd83dbSDimitry Andric // Convert irreducible SCCs; Graph G may be a Function* or a Loop&. 260*5ffd83dbSDimitry Andric template <class Graph> 261*5ffd83dbSDimitry Andric static bool makeReducible(LoopInfo &LI, DominatorTree &DT, Graph &&G) { 262*5ffd83dbSDimitry Andric bool Changed = false; 263*5ffd83dbSDimitry Andric for (auto Scc = scc_begin(G); !Scc.isAtEnd(); ++Scc) { 264*5ffd83dbSDimitry Andric if (Scc->size() < 2) 265*5ffd83dbSDimitry Andric continue; 266*5ffd83dbSDimitry Andric SetVector<BasicBlock *> Blocks; 267*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Found SCC:"); 268*5ffd83dbSDimitry Andric for (auto N : *Scc) { 269*5ffd83dbSDimitry Andric auto BB = unwrapBlock(N); 270*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << " " << BB->getName()); 271*5ffd83dbSDimitry Andric Blocks.insert(BB); 272*5ffd83dbSDimitry Andric } 273*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 274*5ffd83dbSDimitry Andric 275*5ffd83dbSDimitry Andric // Minor optimization: The SCC blocks are usually discovered in an order 276*5ffd83dbSDimitry Andric // that is the opposite of the order in which these blocks appear as branch 277*5ffd83dbSDimitry Andric // targets. This results in a lot of condition inversions in the control 278*5ffd83dbSDimitry Andric // flow out of the new ControlFlowHub, which can be mitigated if the orders 279*5ffd83dbSDimitry Andric // match. So we discover the headers using the reverse of the block order. 280*5ffd83dbSDimitry Andric SetVector<BasicBlock *> Headers; 281*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Found headers:"); 282*5ffd83dbSDimitry Andric for (auto BB : reverse(Blocks)) { 283*5ffd83dbSDimitry Andric for (const auto P : predecessors(BB)) { 284*5ffd83dbSDimitry Andric // Skip unreachable predecessors. 285*5ffd83dbSDimitry Andric if (!DT.isReachableFromEntry(P)) 286*5ffd83dbSDimitry Andric continue; 287*5ffd83dbSDimitry Andric if (!Blocks.count(P)) { 288*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << " " << BB->getName()); 289*5ffd83dbSDimitry Andric Headers.insert(BB); 290*5ffd83dbSDimitry Andric break; 291*5ffd83dbSDimitry Andric } 292*5ffd83dbSDimitry Andric } 293*5ffd83dbSDimitry Andric } 294*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 295*5ffd83dbSDimitry Andric 296*5ffd83dbSDimitry Andric if (Headers.size() == 1) { 297*5ffd83dbSDimitry Andric assert(LI.isLoopHeader(Headers.front())); 298*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "Natural loop with a single header: skipped\n"); 299*5ffd83dbSDimitry Andric continue; 300*5ffd83dbSDimitry Andric } 301*5ffd83dbSDimitry Andric createNaturalLoop(LI, DT, G, Blocks, Headers); 302*5ffd83dbSDimitry Andric Changed = true; 303*5ffd83dbSDimitry Andric } 304*5ffd83dbSDimitry Andric return Changed; 305*5ffd83dbSDimitry Andric } 306*5ffd83dbSDimitry Andric 307*5ffd83dbSDimitry Andric bool FixIrreducible::runOnFunction(Function &F) { 308*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "===== Fix irreducible control-flow in function: " 309*5ffd83dbSDimitry Andric << F.getName() << "\n"); 310*5ffd83dbSDimitry Andric auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); 311*5ffd83dbSDimitry Andric auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 312*5ffd83dbSDimitry Andric 313*5ffd83dbSDimitry Andric bool Changed = false; 314*5ffd83dbSDimitry Andric SmallVector<Loop *, 8> WorkList; 315*5ffd83dbSDimitry Andric 316*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "visiting top-level\n"); 317*5ffd83dbSDimitry Andric Changed |= makeReducible(LI, DT, &F); 318*5ffd83dbSDimitry Andric 319*5ffd83dbSDimitry Andric // Any SCCs reduced are now already in the list of top-level loops, so simply 320*5ffd83dbSDimitry Andric // add them all to the worklist. 321*5ffd83dbSDimitry Andric for (auto L : LI) { 322*5ffd83dbSDimitry Andric WorkList.push_back(L); 323*5ffd83dbSDimitry Andric } 324*5ffd83dbSDimitry Andric 325*5ffd83dbSDimitry Andric while (!WorkList.empty()) { 326*5ffd83dbSDimitry Andric auto L = WorkList.back(); 327*5ffd83dbSDimitry Andric WorkList.pop_back(); 328*5ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "visiting loop with header " 329*5ffd83dbSDimitry Andric << L->getHeader()->getName() << "\n"); 330*5ffd83dbSDimitry Andric Changed |= makeReducible(LI, DT, *L); 331*5ffd83dbSDimitry Andric // Any SCCs reduced are now already in the list of child loops, so simply 332*5ffd83dbSDimitry Andric // add them all to the worklist. 333*5ffd83dbSDimitry Andric WorkList.append(L->begin(), L->end()); 334*5ffd83dbSDimitry Andric } 335*5ffd83dbSDimitry Andric 336*5ffd83dbSDimitry Andric return Changed; 337*5ffd83dbSDimitry Andric } 338