xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/LoopNestAnalysis.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
15ffd83dbSDimitry Andric //===- LoopNestAnalysis.cpp - Loop Nest Analysis --------------------------==//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric ///
95ffd83dbSDimitry Andric /// \file
105ffd83dbSDimitry Andric /// The implementation for the loop nest analysis.
115ffd83dbSDimitry Andric ///
125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
135ffd83dbSDimitry Andric 
145ffd83dbSDimitry Andric #include "llvm/Analysis/LoopNestAnalysis.h"
155ffd83dbSDimitry Andric #include "llvm/ADT/BreadthFirstIterator.h"
1681ad6265SDimitry Andric #include "llvm/ADT/DepthFirstIterator.h"
175ffd83dbSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
185ffd83dbSDimitry Andric 
195ffd83dbSDimitry Andric using namespace llvm;
205ffd83dbSDimitry Andric 
215ffd83dbSDimitry Andric #define DEBUG_TYPE "loopnest"
225ffd83dbSDimitry Andric #ifndef NDEBUG
235ffd83dbSDimitry Andric static const char *VerboseDebug = DEBUG_TYPE "-verbose";
245ffd83dbSDimitry Andric #endif
255ffd83dbSDimitry Andric 
265ffd83dbSDimitry Andric /// Determine whether the loops structure violates basic requirements for
275ffd83dbSDimitry Andric /// perfect nesting:
285ffd83dbSDimitry Andric ///  - the inner loop should be the outer loop's only child
295ffd83dbSDimitry Andric ///  - the outer loop header should 'flow' into the inner loop preheader
305ffd83dbSDimitry Andric ///    or jump around the inner loop to the outer loop latch
315ffd83dbSDimitry Andric ///  - if the inner loop latch exits the inner loop, it should 'flow' into
325ffd83dbSDimitry Andric ///    the outer loop latch.
335ffd83dbSDimitry Andric /// Returns true if the loop structure satisfies the basic requirements and
345ffd83dbSDimitry Andric /// false otherwise.
355ffd83dbSDimitry Andric static bool checkLoopsStructure(const Loop &OuterLoop, const Loop &InnerLoop,
365ffd83dbSDimitry Andric                                 ScalarEvolution &SE);
375ffd83dbSDimitry Andric 
385ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
395ffd83dbSDimitry Andric // LoopNest implementation
405ffd83dbSDimitry Andric //
415ffd83dbSDimitry Andric 
LoopNest(Loop & Root,ScalarEvolution & SE)425ffd83dbSDimitry Andric LoopNest::LoopNest(Loop &Root, ScalarEvolution &SE)
435ffd83dbSDimitry Andric     : MaxPerfectDepth(getMaxPerfectDepth(Root, SE)) {
44e8d8bef9SDimitry Andric   append_range(Loops, breadth_first(&Root));
455ffd83dbSDimitry Andric }
465ffd83dbSDimitry Andric 
getLoopNest(Loop & Root,ScalarEvolution & SE)475ffd83dbSDimitry Andric std::unique_ptr<LoopNest> LoopNest::getLoopNest(Loop &Root,
485ffd83dbSDimitry Andric                                                 ScalarEvolution &SE) {
495ffd83dbSDimitry Andric   return std::make_unique<LoopNest>(Root, SE);
505ffd83dbSDimitry Andric }
515ffd83dbSDimitry Andric 
getOuterLoopLatchCmp(const Loop & OuterLoop)52349cc55cSDimitry Andric static CmpInst *getOuterLoopLatchCmp(const Loop &OuterLoop) {
53349cc55cSDimitry Andric 
54349cc55cSDimitry Andric   const BasicBlock *Latch = OuterLoop.getLoopLatch();
55349cc55cSDimitry Andric   assert(Latch && "Expecting a valid loop latch");
56349cc55cSDimitry Andric 
57349cc55cSDimitry Andric   const BranchInst *BI = dyn_cast<BranchInst>(Latch->getTerminator());
58349cc55cSDimitry Andric   assert(BI && BI->isConditional() &&
59349cc55cSDimitry Andric          "Expecting loop latch terminator to be a branch instruction");
60349cc55cSDimitry Andric 
61349cc55cSDimitry Andric   CmpInst *OuterLoopLatchCmp = dyn_cast<CmpInst>(BI->getCondition());
62349cc55cSDimitry Andric   DEBUG_WITH_TYPE(
63349cc55cSDimitry Andric       VerboseDebug, if (OuterLoopLatchCmp) {
64349cc55cSDimitry Andric         dbgs() << "Outer loop latch compare instruction: " << *OuterLoopLatchCmp
65349cc55cSDimitry Andric                << "\n";
66349cc55cSDimitry Andric       });
67349cc55cSDimitry Andric   return OuterLoopLatchCmp;
68349cc55cSDimitry Andric }
69349cc55cSDimitry Andric 
getInnerLoopGuardCmp(const Loop & InnerLoop)70349cc55cSDimitry Andric static CmpInst *getInnerLoopGuardCmp(const Loop &InnerLoop) {
71349cc55cSDimitry Andric 
72349cc55cSDimitry Andric   BranchInst *InnerGuard = InnerLoop.getLoopGuardBranch();
73349cc55cSDimitry Andric   CmpInst *InnerLoopGuardCmp =
74349cc55cSDimitry Andric       (InnerGuard) ? dyn_cast<CmpInst>(InnerGuard->getCondition()) : nullptr;
75349cc55cSDimitry Andric 
76349cc55cSDimitry Andric   DEBUG_WITH_TYPE(
77349cc55cSDimitry Andric       VerboseDebug, if (InnerLoopGuardCmp) {
78349cc55cSDimitry Andric         dbgs() << "Inner loop guard compare instruction: " << *InnerLoopGuardCmp
79349cc55cSDimitry Andric                << "\n";
80349cc55cSDimitry Andric       });
81349cc55cSDimitry Andric   return InnerLoopGuardCmp;
82349cc55cSDimitry Andric }
83349cc55cSDimitry Andric 
checkSafeInstruction(const Instruction & I,const CmpInst * InnerLoopGuardCmp,const CmpInst * OuterLoopLatchCmp,std::optional<Loop::LoopBounds> OuterLoopLB)84349cc55cSDimitry Andric static bool checkSafeInstruction(const Instruction &I,
85349cc55cSDimitry Andric                                  const CmpInst *InnerLoopGuardCmp,
86349cc55cSDimitry Andric                                  const CmpInst *OuterLoopLatchCmp,
87*bdd1243dSDimitry Andric                                  std::optional<Loop::LoopBounds> OuterLoopLB) {
88349cc55cSDimitry Andric 
89349cc55cSDimitry Andric   bool IsAllowed =
90349cc55cSDimitry Andric       isSafeToSpeculativelyExecute(&I) || isa<PHINode>(I) || isa<BranchInst>(I);
91349cc55cSDimitry Andric   if (!IsAllowed)
92349cc55cSDimitry Andric     return false;
93349cc55cSDimitry Andric   // The only binary instruction allowed is the outer loop step instruction,
94349cc55cSDimitry Andric   // the only comparison instructions allowed are the inner loop guard
95349cc55cSDimitry Andric   // compare instruction and the outer loop latch compare instruction.
96349cc55cSDimitry Andric   if ((isa<BinaryOperator>(I) && &I != &OuterLoopLB->getStepInst()) ||
97349cc55cSDimitry Andric       (isa<CmpInst>(I) && &I != OuterLoopLatchCmp && &I != InnerLoopGuardCmp)) {
98349cc55cSDimitry Andric     return false;
99349cc55cSDimitry Andric   }
100349cc55cSDimitry Andric   return true;
101349cc55cSDimitry Andric }
102349cc55cSDimitry Andric 
arePerfectlyNested(const Loop & OuterLoop,const Loop & InnerLoop,ScalarEvolution & SE)1035ffd83dbSDimitry Andric bool LoopNest::arePerfectlyNested(const Loop &OuterLoop, const Loop &InnerLoop,
1045ffd83dbSDimitry Andric                                   ScalarEvolution &SE) {
105349cc55cSDimitry Andric   return (analyzeLoopNestForPerfectNest(OuterLoop, InnerLoop, SE) ==
106349cc55cSDimitry Andric           PerfectLoopNest);
107349cc55cSDimitry Andric }
108349cc55cSDimitry Andric 
analyzeLoopNestForPerfectNest(const Loop & OuterLoop,const Loop & InnerLoop,ScalarEvolution & SE)109349cc55cSDimitry Andric LoopNest::LoopNestEnum LoopNest::analyzeLoopNestForPerfectNest(
110349cc55cSDimitry Andric     const Loop &OuterLoop, const Loop &InnerLoop, ScalarEvolution &SE) {
111349cc55cSDimitry Andric 
112e8d8bef9SDimitry Andric   assert(!OuterLoop.isInnermost() && "Outer loop should have subloops");
113e8d8bef9SDimitry Andric   assert(!InnerLoop.isOutermost() && "Inner loop should have a parent");
1145ffd83dbSDimitry Andric   LLVM_DEBUG(dbgs() << "Checking whether loop '" << OuterLoop.getName()
1155ffd83dbSDimitry Andric                     << "' and '" << InnerLoop.getName()
1165ffd83dbSDimitry Andric                     << "' are perfectly nested.\n");
1175ffd83dbSDimitry Andric 
1185ffd83dbSDimitry Andric   // Determine whether the loops structure satisfies the following requirements:
1195ffd83dbSDimitry Andric   //  - the inner loop should be the outer loop's only child
1205ffd83dbSDimitry Andric   //  - the outer loop header should 'flow' into the inner loop preheader
1215ffd83dbSDimitry Andric   //    or jump around the inner loop to the outer loop latch
1225ffd83dbSDimitry Andric   //  - if the inner loop latch exits the inner loop, it should 'flow' into
1235ffd83dbSDimitry Andric   //    the outer loop latch.
1245ffd83dbSDimitry Andric   if (!checkLoopsStructure(OuterLoop, InnerLoop, SE)) {
1255ffd83dbSDimitry Andric     LLVM_DEBUG(dbgs() << "Not perfectly nested: invalid loop structure.\n");
126349cc55cSDimitry Andric     return InvalidLoopStructure;
1275ffd83dbSDimitry Andric   }
1285ffd83dbSDimitry Andric 
1295ffd83dbSDimitry Andric   // Bail out if we cannot retrieve the outer loop bounds.
1305ffd83dbSDimitry Andric   auto OuterLoopLB = OuterLoop.getBounds(SE);
131*bdd1243dSDimitry Andric   if (OuterLoopLB == std::nullopt) {
1325ffd83dbSDimitry Andric     LLVM_DEBUG(dbgs() << "Cannot compute loop bounds of OuterLoop: "
1335ffd83dbSDimitry Andric                       << OuterLoop << "\n";);
134349cc55cSDimitry Andric     return OuterLoopLowerBoundUnknown;
1355ffd83dbSDimitry Andric   }
1365ffd83dbSDimitry Andric 
137349cc55cSDimitry Andric   CmpInst *OuterLoopLatchCmp = getOuterLoopLatchCmp(OuterLoop);
138349cc55cSDimitry Andric   CmpInst *InnerLoopGuardCmp = getInnerLoopGuardCmp(InnerLoop);
1395ffd83dbSDimitry Andric 
1405ffd83dbSDimitry Andric   // Determine whether instructions in a basic block are one of:
1415ffd83dbSDimitry Andric   //  - the inner loop guard comparison
1425ffd83dbSDimitry Andric   //  - the outer loop latch comparison
1435ffd83dbSDimitry Andric   //  - the outer loop induction variable increment
1445ffd83dbSDimitry Andric   //  - a phi node, a cast or a branch
1455ffd83dbSDimitry Andric   auto containsOnlySafeInstructions = [&](const BasicBlock &BB) {
1465ffd83dbSDimitry Andric     return llvm::all_of(BB, [&](const Instruction &I) {
147349cc55cSDimitry Andric       bool IsSafeInstr = checkSafeInstruction(I, InnerLoopGuardCmp,
148349cc55cSDimitry Andric                                               OuterLoopLatchCmp, OuterLoopLB);
149349cc55cSDimitry Andric       if (IsSafeInstr) {
1505ffd83dbSDimitry Andric         DEBUG_WITH_TYPE(VerboseDebug, {
1515ffd83dbSDimitry Andric           dbgs() << "Instruction: " << I << "\nin basic block:" << BB
1525ffd83dbSDimitry Andric                  << "is unsafe.\n";
1535ffd83dbSDimitry Andric         });
1545ffd83dbSDimitry Andric       }
155349cc55cSDimitry Andric       return IsSafeInstr;
1565ffd83dbSDimitry Andric     });
1575ffd83dbSDimitry Andric   };
1585ffd83dbSDimitry Andric 
1595ffd83dbSDimitry Andric   // Check the code surrounding the inner loop for instructions that are deemed
1605ffd83dbSDimitry Andric   // unsafe.
1615ffd83dbSDimitry Andric   const BasicBlock *OuterLoopHeader = OuterLoop.getHeader();
1625ffd83dbSDimitry Andric   const BasicBlock *OuterLoopLatch = OuterLoop.getLoopLatch();
1635ffd83dbSDimitry Andric   const BasicBlock *InnerLoopPreHeader = InnerLoop.getLoopPreheader();
1645ffd83dbSDimitry Andric 
1655ffd83dbSDimitry Andric   if (!containsOnlySafeInstructions(*OuterLoopHeader) ||
1665ffd83dbSDimitry Andric       !containsOnlySafeInstructions(*OuterLoopLatch) ||
1675ffd83dbSDimitry Andric       (InnerLoopPreHeader != OuterLoopHeader &&
1685ffd83dbSDimitry Andric        !containsOnlySafeInstructions(*InnerLoopPreHeader)) ||
1695ffd83dbSDimitry Andric       !containsOnlySafeInstructions(*InnerLoop.getExitBlock())) {
1705ffd83dbSDimitry Andric     LLVM_DEBUG(dbgs() << "Not perfectly nested: code surrounding inner loop is "
1715ffd83dbSDimitry Andric                          "unsafe\n";);
172349cc55cSDimitry Andric     return ImperfectLoopNest;
1735ffd83dbSDimitry Andric   }
1745ffd83dbSDimitry Andric 
1755ffd83dbSDimitry Andric   LLVM_DEBUG(dbgs() << "Loop '" << OuterLoop.getName() << "' and '"
1765ffd83dbSDimitry Andric                     << InnerLoop.getName() << "' are perfectly nested.\n");
1775ffd83dbSDimitry Andric 
178349cc55cSDimitry Andric   return PerfectLoopNest;
179349cc55cSDimitry Andric }
180349cc55cSDimitry Andric 
getInterveningInstructions(const Loop & OuterLoop,const Loop & InnerLoop,ScalarEvolution & SE)181349cc55cSDimitry Andric LoopNest::InstrVectorTy LoopNest::getInterveningInstructions(
182349cc55cSDimitry Andric     const Loop &OuterLoop, const Loop &InnerLoop, ScalarEvolution &SE) {
183349cc55cSDimitry Andric   InstrVectorTy Instr;
184349cc55cSDimitry Andric   switch (analyzeLoopNestForPerfectNest(OuterLoop, InnerLoop, SE)) {
185349cc55cSDimitry Andric   case PerfectLoopNest:
186349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "The loop Nest is Perfect, returning empty "
187349cc55cSDimitry Andric                          "instruction vector. \n";);
188349cc55cSDimitry Andric     return Instr;
189349cc55cSDimitry Andric 
190349cc55cSDimitry Andric   case InvalidLoopStructure:
191349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "Not perfectly nested: invalid loop structure. "
192349cc55cSDimitry Andric                          "Instruction vector is empty.\n";);
193349cc55cSDimitry Andric     return Instr;
194349cc55cSDimitry Andric 
195349cc55cSDimitry Andric   case OuterLoopLowerBoundUnknown:
196349cc55cSDimitry Andric     LLVM_DEBUG(dbgs() << "Cannot compute loop bounds of OuterLoop: "
197349cc55cSDimitry Andric                       << OuterLoop << "\nInstruction vector is empty.\n";);
198349cc55cSDimitry Andric     return Instr;
199349cc55cSDimitry Andric 
200349cc55cSDimitry Andric   case ImperfectLoopNest:
201349cc55cSDimitry Andric     break;
202349cc55cSDimitry Andric   }
203349cc55cSDimitry Andric 
204349cc55cSDimitry Andric   // Identify the outer loop latch comparison instruction.
205349cc55cSDimitry Andric   auto OuterLoopLB = OuterLoop.getBounds(SE);
206349cc55cSDimitry Andric 
207349cc55cSDimitry Andric   CmpInst *OuterLoopLatchCmp = getOuterLoopLatchCmp(OuterLoop);
208349cc55cSDimitry Andric   CmpInst *InnerLoopGuardCmp = getInnerLoopGuardCmp(InnerLoop);
209349cc55cSDimitry Andric 
210349cc55cSDimitry Andric   auto GetUnsafeInstructions = [&](const BasicBlock &BB) {
211349cc55cSDimitry Andric     for (const Instruction &I : BB) {
212349cc55cSDimitry Andric       if (!checkSafeInstruction(I, InnerLoopGuardCmp, OuterLoopLatchCmp,
213349cc55cSDimitry Andric                                 OuterLoopLB)) {
214349cc55cSDimitry Andric         Instr.push_back(&I);
215349cc55cSDimitry Andric         DEBUG_WITH_TYPE(VerboseDebug, {
216349cc55cSDimitry Andric           dbgs() << "Instruction: " << I << "\nin basic block:" << BB
217349cc55cSDimitry Andric                  << "is unsafe.\n";
218349cc55cSDimitry Andric         });
219349cc55cSDimitry Andric       }
220349cc55cSDimitry Andric     }
221349cc55cSDimitry Andric   };
222349cc55cSDimitry Andric 
223349cc55cSDimitry Andric   // Check the code surrounding the inner loop for instructions that are deemed
224349cc55cSDimitry Andric   // unsafe.
225349cc55cSDimitry Andric   const BasicBlock *OuterLoopHeader = OuterLoop.getHeader();
226349cc55cSDimitry Andric   const BasicBlock *OuterLoopLatch = OuterLoop.getLoopLatch();
227349cc55cSDimitry Andric   const BasicBlock *InnerLoopPreHeader = InnerLoop.getLoopPreheader();
228349cc55cSDimitry Andric   const BasicBlock *InnerLoopExitBlock = InnerLoop.getExitBlock();
229349cc55cSDimitry Andric 
230349cc55cSDimitry Andric   GetUnsafeInstructions(*OuterLoopHeader);
231349cc55cSDimitry Andric   GetUnsafeInstructions(*OuterLoopLatch);
232349cc55cSDimitry Andric   GetUnsafeInstructions(*InnerLoopExitBlock);
233349cc55cSDimitry Andric 
234349cc55cSDimitry Andric   if (InnerLoopPreHeader != OuterLoopHeader) {
235349cc55cSDimitry Andric     GetUnsafeInstructions(*InnerLoopPreHeader);
236349cc55cSDimitry Andric   }
237349cc55cSDimitry Andric   return Instr;
2385ffd83dbSDimitry Andric }
2395ffd83dbSDimitry Andric 
2405ffd83dbSDimitry Andric SmallVector<LoopVectorTy, 4>
getPerfectLoops(ScalarEvolution & SE) const2415ffd83dbSDimitry Andric LoopNest::getPerfectLoops(ScalarEvolution &SE) const {
2425ffd83dbSDimitry Andric   SmallVector<LoopVectorTy, 4> LV;
2435ffd83dbSDimitry Andric   LoopVectorTy PerfectNest;
2445ffd83dbSDimitry Andric 
2455ffd83dbSDimitry Andric   for (Loop *L : depth_first(const_cast<Loop *>(Loops.front()))) {
2465ffd83dbSDimitry Andric     if (PerfectNest.empty())
2475ffd83dbSDimitry Andric       PerfectNest.push_back(L);
2485ffd83dbSDimitry Andric 
2495ffd83dbSDimitry Andric     auto &SubLoops = L->getSubLoops();
2505ffd83dbSDimitry Andric     if (SubLoops.size() == 1 && arePerfectlyNested(*L, *SubLoops.front(), SE)) {
2515ffd83dbSDimitry Andric       PerfectNest.push_back(SubLoops.front());
2525ffd83dbSDimitry Andric     } else {
2535ffd83dbSDimitry Andric       LV.push_back(PerfectNest);
2545ffd83dbSDimitry Andric       PerfectNest.clear();
2555ffd83dbSDimitry Andric     }
2565ffd83dbSDimitry Andric   }
2575ffd83dbSDimitry Andric 
2585ffd83dbSDimitry Andric   return LV;
2595ffd83dbSDimitry Andric }
2605ffd83dbSDimitry Andric 
getMaxPerfectDepth(const Loop & Root,ScalarEvolution & SE)2615ffd83dbSDimitry Andric unsigned LoopNest::getMaxPerfectDepth(const Loop &Root, ScalarEvolution &SE) {
2625ffd83dbSDimitry Andric   LLVM_DEBUG(dbgs() << "Get maximum perfect depth of loop nest rooted by loop '"
2635ffd83dbSDimitry Andric                     << Root.getName() << "'\n");
2645ffd83dbSDimitry Andric 
2655ffd83dbSDimitry Andric   const Loop *CurrentLoop = &Root;
2665ffd83dbSDimitry Andric   const auto *SubLoops = &CurrentLoop->getSubLoops();
2675ffd83dbSDimitry Andric   unsigned CurrentDepth = 1;
2685ffd83dbSDimitry Andric 
2695ffd83dbSDimitry Andric   while (SubLoops->size() == 1) {
2705ffd83dbSDimitry Andric     const Loop *InnerLoop = SubLoops->front();
2715ffd83dbSDimitry Andric     if (!arePerfectlyNested(*CurrentLoop, *InnerLoop, SE)) {
2725ffd83dbSDimitry Andric       LLVM_DEBUG({
2735ffd83dbSDimitry Andric         dbgs() << "Not a perfect nest: loop '" << CurrentLoop->getName()
2745ffd83dbSDimitry Andric                << "' is not perfectly nested with loop '"
2755ffd83dbSDimitry Andric                << InnerLoop->getName() << "'\n";
2765ffd83dbSDimitry Andric       });
2775ffd83dbSDimitry Andric       break;
2785ffd83dbSDimitry Andric     }
2795ffd83dbSDimitry Andric 
2805ffd83dbSDimitry Andric     CurrentLoop = InnerLoop;
2815ffd83dbSDimitry Andric     SubLoops = &CurrentLoop->getSubLoops();
2825ffd83dbSDimitry Andric     ++CurrentDepth;
2835ffd83dbSDimitry Andric   }
2845ffd83dbSDimitry Andric 
2855ffd83dbSDimitry Andric   return CurrentDepth;
2865ffd83dbSDimitry Andric }
2875ffd83dbSDimitry Andric 
skipEmptyBlockUntil(const BasicBlock * From,const BasicBlock * End,bool CheckUniquePred)288e8d8bef9SDimitry Andric const BasicBlock &LoopNest::skipEmptyBlockUntil(const BasicBlock *From,
289fe6060f1SDimitry Andric                                                 const BasicBlock *End,
290fe6060f1SDimitry Andric                                                 bool CheckUniquePred) {
291e8d8bef9SDimitry Andric   assert(From && "Expecting valid From");
292e8d8bef9SDimitry Andric   assert(End && "Expecting valid End");
293e8d8bef9SDimitry Andric 
294fe6060f1SDimitry Andric   if (From == End || !From->getUniqueSuccessor())
295e8d8bef9SDimitry Andric     return *From;
296e8d8bef9SDimitry Andric 
297e8d8bef9SDimitry Andric   auto IsEmpty = [](const BasicBlock *BB) {
298*bdd1243dSDimitry Andric     return (BB->size() == 1);
299e8d8bef9SDimitry Andric   };
300e8d8bef9SDimitry Andric 
301e8d8bef9SDimitry Andric   // Visited is used to avoid running into an infinite loop.
302e8d8bef9SDimitry Andric   SmallPtrSet<const BasicBlock *, 4> Visited;
303fe6060f1SDimitry Andric   const BasicBlock *BB = From->getUniqueSuccessor();
304fe6060f1SDimitry Andric   const BasicBlock *PredBB = From;
305fe6060f1SDimitry Andric   while (BB && BB != End && IsEmpty(BB) && !Visited.count(BB) &&
306fe6060f1SDimitry Andric          (!CheckUniquePred || BB->getUniquePredecessor())) {
307e8d8bef9SDimitry Andric     Visited.insert(BB);
308e8d8bef9SDimitry Andric     PredBB = BB;
309fe6060f1SDimitry Andric     BB = BB->getUniqueSuccessor();
310e8d8bef9SDimitry Andric   }
311e8d8bef9SDimitry Andric 
312e8d8bef9SDimitry Andric   return (BB == End) ? *End : *PredBB;
313e8d8bef9SDimitry Andric }
314e8d8bef9SDimitry Andric 
checkLoopsStructure(const Loop & OuterLoop,const Loop & InnerLoop,ScalarEvolution & SE)3155ffd83dbSDimitry Andric static bool checkLoopsStructure(const Loop &OuterLoop, const Loop &InnerLoop,
3165ffd83dbSDimitry Andric                                 ScalarEvolution &SE) {
3175ffd83dbSDimitry Andric   // The inner loop must be the only outer loop's child.
3185ffd83dbSDimitry Andric   if ((OuterLoop.getSubLoops().size() != 1) ||
3195ffd83dbSDimitry Andric       (InnerLoop.getParentLoop() != &OuterLoop))
3205ffd83dbSDimitry Andric     return false;
3215ffd83dbSDimitry Andric 
3225ffd83dbSDimitry Andric   // We expect loops in normal form which have a preheader, header, latch...
3235ffd83dbSDimitry Andric   if (!OuterLoop.isLoopSimplifyForm() || !InnerLoop.isLoopSimplifyForm())
3245ffd83dbSDimitry Andric     return false;
3255ffd83dbSDimitry Andric 
3265ffd83dbSDimitry Andric   const BasicBlock *OuterLoopHeader = OuterLoop.getHeader();
3275ffd83dbSDimitry Andric   const BasicBlock *OuterLoopLatch = OuterLoop.getLoopLatch();
3285ffd83dbSDimitry Andric   const BasicBlock *InnerLoopPreHeader = InnerLoop.getLoopPreheader();
3295ffd83dbSDimitry Andric   const BasicBlock *InnerLoopLatch = InnerLoop.getLoopLatch();
3305ffd83dbSDimitry Andric   const BasicBlock *InnerLoopExit = InnerLoop.getExitBlock();
3315ffd83dbSDimitry Andric 
3325ffd83dbSDimitry Andric   // We expect rotated loops. The inner loop should have a single exit block.
3335ffd83dbSDimitry Andric   if (OuterLoop.getExitingBlock() != OuterLoopLatch ||
3345ffd83dbSDimitry Andric       InnerLoop.getExitingBlock() != InnerLoopLatch || !InnerLoopExit)
3355ffd83dbSDimitry Andric     return false;
3365ffd83dbSDimitry Andric 
337e8d8bef9SDimitry Andric   // Returns whether the block `ExitBlock` contains at least one LCSSA Phi node.
338e8d8bef9SDimitry Andric   auto ContainsLCSSAPhi = [](const BasicBlock &ExitBlock) {
339e8d8bef9SDimitry Andric     return any_of(ExitBlock.phis(), [](const PHINode &PN) {
340e8d8bef9SDimitry Andric       return PN.getNumIncomingValues() == 1;
341e8d8bef9SDimitry Andric     });
342e8d8bef9SDimitry Andric   };
343e8d8bef9SDimitry Andric 
344e8d8bef9SDimitry Andric   // Returns whether the block `BB` qualifies for being an extra Phi block. The
345e8d8bef9SDimitry Andric   // extra Phi block is the additional block inserted after the exit block of an
346e8d8bef9SDimitry Andric   // "guarded" inner loop which contains "only" Phi nodes corresponding to the
347e8d8bef9SDimitry Andric   // LCSSA Phi nodes in the exit block.
348e8d8bef9SDimitry Andric   auto IsExtraPhiBlock = [&](const BasicBlock &BB) {
349e8d8bef9SDimitry Andric     return BB.getFirstNonPHI() == BB.getTerminator() &&
350e8d8bef9SDimitry Andric            all_of(BB.phis(), [&](const PHINode &PN) {
351e8d8bef9SDimitry Andric              return all_of(PN.blocks(), [&](const BasicBlock *IncomingBlock) {
352e8d8bef9SDimitry Andric                return IncomingBlock == InnerLoopExit ||
353e8d8bef9SDimitry Andric                       IncomingBlock == OuterLoopHeader;
354e8d8bef9SDimitry Andric              });
355e8d8bef9SDimitry Andric            });
356e8d8bef9SDimitry Andric   };
357e8d8bef9SDimitry Andric 
358e8d8bef9SDimitry Andric   const BasicBlock *ExtraPhiBlock = nullptr;
3595ffd83dbSDimitry Andric   // Ensure the only branch that may exist between the loops is the inner loop
3605ffd83dbSDimitry Andric   // guard.
3615ffd83dbSDimitry Andric   if (OuterLoopHeader != InnerLoopPreHeader) {
362e8d8bef9SDimitry Andric     const BasicBlock &SingleSucc =
363e8d8bef9SDimitry Andric         LoopNest::skipEmptyBlockUntil(OuterLoopHeader, InnerLoopPreHeader);
364e8d8bef9SDimitry Andric 
365e8d8bef9SDimitry Andric     // no conditional branch present
366e8d8bef9SDimitry Andric     if (&SingleSucc != InnerLoopPreHeader) {
367e8d8bef9SDimitry Andric       const BranchInst *BI = dyn_cast<BranchInst>(SingleSucc.getTerminator());
3685ffd83dbSDimitry Andric 
3695ffd83dbSDimitry Andric       if (!BI || BI != InnerLoop.getLoopGuardBranch())
3705ffd83dbSDimitry Andric         return false;
3715ffd83dbSDimitry Andric 
372e8d8bef9SDimitry Andric       bool InnerLoopExitContainsLCSSA = ContainsLCSSAPhi(*InnerLoopExit);
373e8d8bef9SDimitry Andric 
3745ffd83dbSDimitry Andric       // The successors of the inner loop guard should be the inner loop
375e8d8bef9SDimitry Andric       // preheader or the outer loop latch possibly through empty blocks.
3765ffd83dbSDimitry Andric       for (const BasicBlock *Succ : BI->successors()) {
377e8d8bef9SDimitry Andric         const BasicBlock *PotentialInnerPreHeader = Succ;
378e8d8bef9SDimitry Andric         const BasicBlock *PotentialOuterLatch = Succ;
379e8d8bef9SDimitry Andric 
380e8d8bef9SDimitry Andric         // Ensure the inner loop guard successor is empty before skipping
381e8d8bef9SDimitry Andric         // blocks.
382*bdd1243dSDimitry Andric         if (Succ->size() == 1) {
383e8d8bef9SDimitry Andric           PotentialInnerPreHeader =
384e8d8bef9SDimitry Andric               &LoopNest::skipEmptyBlockUntil(Succ, InnerLoopPreHeader);
385e8d8bef9SDimitry Andric           PotentialOuterLatch =
386e8d8bef9SDimitry Andric               &LoopNest::skipEmptyBlockUntil(Succ, OuterLoopLatch);
387e8d8bef9SDimitry Andric         }
388e8d8bef9SDimitry Andric 
389e8d8bef9SDimitry Andric         if (PotentialInnerPreHeader == InnerLoopPreHeader)
3905ffd83dbSDimitry Andric           continue;
391e8d8bef9SDimitry Andric         if (PotentialOuterLatch == OuterLoopLatch)
3925ffd83dbSDimitry Andric           continue;
3935ffd83dbSDimitry Andric 
394e8d8bef9SDimitry Andric         // If `InnerLoopExit` contains LCSSA Phi instructions, additional block
395e8d8bef9SDimitry Andric         // may be inserted before the `OuterLoopLatch` to which `BI` jumps. The
396e8d8bef9SDimitry Andric         // loops are still considered perfectly nested if the extra block only
397e8d8bef9SDimitry Andric         // contains Phi instructions from InnerLoopExit and OuterLoopHeader.
398e8d8bef9SDimitry Andric         if (InnerLoopExitContainsLCSSA && IsExtraPhiBlock(*Succ) &&
399e8d8bef9SDimitry Andric             Succ->getSingleSuccessor() == OuterLoopLatch) {
400e8d8bef9SDimitry Andric           // Points to the extra block so that we can reference it later in the
401e8d8bef9SDimitry Andric           // final check. We can also conclude that the inner loop is
402e8d8bef9SDimitry Andric           // guarded and there exists LCSSA Phi node in the exit block later if
403e8d8bef9SDimitry Andric           // we see a non-null `ExtraPhiBlock`.
404e8d8bef9SDimitry Andric           ExtraPhiBlock = Succ;
405e8d8bef9SDimitry Andric           continue;
406e8d8bef9SDimitry Andric         }
407e8d8bef9SDimitry Andric 
4085ffd83dbSDimitry Andric         DEBUG_WITH_TYPE(VerboseDebug, {
4095ffd83dbSDimitry Andric           dbgs() << "Inner loop guard successor " << Succ->getName()
4105ffd83dbSDimitry Andric                  << " doesn't lead to inner loop preheader or "
4115ffd83dbSDimitry Andric                     "outer loop latch.\n";
4125ffd83dbSDimitry Andric         });
4135ffd83dbSDimitry Andric         return false;
4145ffd83dbSDimitry Andric       }
4155ffd83dbSDimitry Andric     }
416e8d8bef9SDimitry Andric   }
4175ffd83dbSDimitry Andric 
418e8d8bef9SDimitry Andric   // Ensure the inner loop exit block lead to the outer loop latch possibly
419e8d8bef9SDimitry Andric   // through empty blocks.
420fe6060f1SDimitry Andric   if ((!ExtraPhiBlock ||
421fe6060f1SDimitry Andric        &LoopNest::skipEmptyBlockUntil(InnerLoop.getExitBlock(),
422fe6060f1SDimitry Andric                                       ExtraPhiBlock) != ExtraPhiBlock) &&
423fe6060f1SDimitry Andric       (&LoopNest::skipEmptyBlockUntil(InnerLoop.getExitBlock(),
424fe6060f1SDimitry Andric                                       OuterLoopLatch) != OuterLoopLatch)) {
4255ffd83dbSDimitry Andric     DEBUG_WITH_TYPE(
4265ffd83dbSDimitry Andric         VerboseDebug,
4275ffd83dbSDimitry Andric         dbgs() << "Inner loop exit block " << *InnerLoopExit
4285ffd83dbSDimitry Andric                << " does not directly lead to the outer loop latch.\n";);
4295ffd83dbSDimitry Andric     return false;
4305ffd83dbSDimitry Andric   }
4315ffd83dbSDimitry Andric 
4325ffd83dbSDimitry Andric   return true;
4335ffd83dbSDimitry Andric }
4345ffd83dbSDimitry Andric 
435e8d8bef9SDimitry Andric AnalysisKey LoopNestAnalysis::Key;
436e8d8bef9SDimitry Andric 
operator <<(raw_ostream & OS,const LoopNest & LN)4375ffd83dbSDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const LoopNest &LN) {
4385ffd83dbSDimitry Andric   OS << "IsPerfect=";
4395ffd83dbSDimitry Andric   if (LN.getMaxPerfectDepth() == LN.getNestDepth())
4405ffd83dbSDimitry Andric     OS << "true";
4415ffd83dbSDimitry Andric   else
4425ffd83dbSDimitry Andric     OS << "false";
4435ffd83dbSDimitry Andric   OS << ", Depth=" << LN.getNestDepth();
4445ffd83dbSDimitry Andric   OS << ", OutermostLoop: " << LN.getOutermostLoop().getName();
4455ffd83dbSDimitry Andric   OS << ", Loops: ( ";
4465ffd83dbSDimitry Andric   for (const Loop *L : LN.getLoops())
4475ffd83dbSDimitry Andric     OS << L->getName() << " ";
4485ffd83dbSDimitry Andric   OS << ")";
4495ffd83dbSDimitry Andric 
4505ffd83dbSDimitry Andric   return OS;
4515ffd83dbSDimitry Andric }
4525ffd83dbSDimitry Andric 
4535ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
4545ffd83dbSDimitry Andric // LoopNestPrinterPass implementation
4555ffd83dbSDimitry Andric //
4565ffd83dbSDimitry Andric 
run(Loop & L,LoopAnalysisManager & AM,LoopStandardAnalysisResults & AR,LPMUpdater & U)4575ffd83dbSDimitry Andric PreservedAnalyses LoopNestPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
4585ffd83dbSDimitry Andric                                            LoopStandardAnalysisResults &AR,
4595ffd83dbSDimitry Andric                                            LPMUpdater &U) {
4605ffd83dbSDimitry Andric   if (auto LN = LoopNest::getLoopNest(L, AR.SE))
4615ffd83dbSDimitry Andric     OS << *LN << "\n";
4625ffd83dbSDimitry Andric 
4635ffd83dbSDimitry Andric   return PreservedAnalyses::all();
4645ffd83dbSDimitry Andric }
465