15ffd83dbSDimitry Andric //===- llvm/Analysis/LoopNestAnalysis.h -------------------------*- C++ -*-===// 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 /// This file defines the interface for the loop nest analysis. 115ffd83dbSDimitry Andric /// 125ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 135ffd83dbSDimitry Andric 145ffd83dbSDimitry Andric #ifndef LLVM_ANALYSIS_LOOPNESTANALYSIS_H 155ffd83dbSDimitry Andric #define LLVM_ANALYSIS_LOOPNESTANALYSIS_H 165ffd83dbSDimitry Andric 17e8d8bef9SDimitry Andric #include "llvm/ADT/STLExtras.h" 185ffd83dbSDimitry Andric #include "llvm/Analysis/LoopAnalysisManager.h" 195ffd83dbSDimitry Andric #include "llvm/Analysis/LoopInfo.h" 205ffd83dbSDimitry Andric 215ffd83dbSDimitry Andric namespace llvm { 225ffd83dbSDimitry Andric 235ffd83dbSDimitry Andric using LoopVectorTy = SmallVector<Loop *, 8>; 24349cc55cSDimitry Andric 255ffd83dbSDimitry Andric class LPMUpdater; 265ffd83dbSDimitry Andric 275ffd83dbSDimitry Andric /// This class represents a loop nest and can be used to query its properties. 2869ade1e0SDimitry Andric class LLVM_EXTERNAL_VISIBILITY LoopNest { 295ffd83dbSDimitry Andric public: 30349cc55cSDimitry Andric using InstrVectorTy = SmallVector<const Instruction *>; 31349cc55cSDimitry Andric 325ffd83dbSDimitry Andric /// Construct a loop nest rooted by loop \p Root. 335ffd83dbSDimitry Andric LoopNest(Loop &Root, ScalarEvolution &SE); 345ffd83dbSDimitry Andric 355ffd83dbSDimitry Andric LoopNest() = delete; 365ffd83dbSDimitry Andric 375ffd83dbSDimitry Andric /// Construct a LoopNest object. 385ffd83dbSDimitry Andric static std::unique_ptr<LoopNest> getLoopNest(Loop &Root, ScalarEvolution &SE); 395ffd83dbSDimitry Andric 405ffd83dbSDimitry Andric /// Return true if the given loops \p OuterLoop and \p InnerLoop are 415ffd83dbSDimitry Andric /// perfectly nested with respect to each other, and false otherwise. 425ffd83dbSDimitry Andric /// Example: 435ffd83dbSDimitry Andric /// \code 445ffd83dbSDimitry Andric /// for(i) 455ffd83dbSDimitry Andric /// for(j) 465ffd83dbSDimitry Andric /// for(k) 475ffd83dbSDimitry Andric /// \endcode 485ffd83dbSDimitry Andric /// arePerfectlyNested(loop_i, loop_j, SE) would return true. 495ffd83dbSDimitry Andric /// arePerfectlyNested(loop_j, loop_k, SE) would return true. 505ffd83dbSDimitry Andric /// arePerfectlyNested(loop_i, loop_k, SE) would return false. 515ffd83dbSDimitry Andric static bool arePerfectlyNested(const Loop &OuterLoop, const Loop &InnerLoop, 525ffd83dbSDimitry Andric ScalarEvolution &SE); 535ffd83dbSDimitry Andric 54349cc55cSDimitry Andric /// Return a vector of instructions that prevent the LoopNest given 55349cc55cSDimitry Andric /// by loops \p OuterLoop and \p InnerLoop from being perfect. 56349cc55cSDimitry Andric static InstrVectorTy getInterveningInstructions(const Loop &OuterLoop, 57349cc55cSDimitry Andric const Loop &InnerLoop, 58349cc55cSDimitry Andric ScalarEvolution &SE); 59349cc55cSDimitry Andric 605ffd83dbSDimitry Andric /// Return the maximum nesting depth of the loop nest rooted by loop \p Root. 615ffd83dbSDimitry Andric /// For example given the loop nest: 625ffd83dbSDimitry Andric /// \code 635ffd83dbSDimitry Andric /// for(i) // loop at level 1 and Root of the nest 645ffd83dbSDimitry Andric /// for(j) // loop at level 2 655ffd83dbSDimitry Andric /// <code> 665ffd83dbSDimitry Andric /// for(k) // loop at level 3 675ffd83dbSDimitry Andric /// \endcode 685ffd83dbSDimitry Andric /// getMaxPerfectDepth(Loop_i) would return 2. 695ffd83dbSDimitry Andric static unsigned getMaxPerfectDepth(const Loop &Root, ScalarEvolution &SE); 705ffd83dbSDimitry Andric 71e8d8bef9SDimitry Andric /// Recursivelly traverse all empty 'single successor' basic blocks of \p From 72fe6060f1SDimitry Andric /// (if there are any). When \p CheckUniquePred is set to true, check if 73fe6060f1SDimitry Andric /// each of the empty single successors has a unique predecessor. Return 74fe6060f1SDimitry Andric /// the last basic block found or \p End if it was reached during the search. 75e8d8bef9SDimitry Andric static const BasicBlock &skipEmptyBlockUntil(const BasicBlock *From, 76fe6060f1SDimitry Andric const BasicBlock *End, 77fe6060f1SDimitry Andric bool CheckUniquePred = false); 78e8d8bef9SDimitry Andric 795ffd83dbSDimitry Andric /// Return the outermost loop in the loop nest. getOutermostLoop()805ffd83dbSDimitry Andric Loop &getOutermostLoop() const { return *Loops.front(); } 815ffd83dbSDimitry Andric 825ffd83dbSDimitry Andric /// Return the innermost loop in the loop nest if the nest has only one 835ffd83dbSDimitry Andric /// innermost loop, and a nullptr otherwise. 845ffd83dbSDimitry Andric /// Note: the innermost loop returned is not necessarily perfectly nested. getInnermostLoop()855ffd83dbSDimitry Andric Loop *getInnermostLoop() const { 865ffd83dbSDimitry Andric if (Loops.size() == 1) 875ffd83dbSDimitry Andric return Loops.back(); 885ffd83dbSDimitry Andric 895ffd83dbSDimitry Andric // The loops in the 'Loops' vector have been collected in breadth first 905ffd83dbSDimitry Andric // order, therefore if the last 2 loops in it have the same nesting depth 915ffd83dbSDimitry Andric // there isn't a unique innermost loop in the nest. 925ffd83dbSDimitry Andric Loop *LastLoop = Loops.back(); 935ffd83dbSDimitry Andric auto SecondLastLoopIter = ++Loops.rbegin(); 945ffd83dbSDimitry Andric return (LastLoop->getLoopDepth() == (*SecondLastLoopIter)->getLoopDepth()) 955ffd83dbSDimitry Andric ? nullptr 965ffd83dbSDimitry Andric : LastLoop; 975ffd83dbSDimitry Andric } 985ffd83dbSDimitry Andric 995ffd83dbSDimitry Andric /// Return the loop at the given \p Index. getLoop(unsigned Index)1005ffd83dbSDimitry Andric Loop *getLoop(unsigned Index) const { 1015ffd83dbSDimitry Andric assert(Index < Loops.size() && "Index is out of bounds"); 1025ffd83dbSDimitry Andric return Loops[Index]; 1035ffd83dbSDimitry Andric } 1045ffd83dbSDimitry Andric 10504eeddc0SDimitry Andric /// Get the loop index of the given loop \p L. getLoopIndex(const Loop & L)10604eeddc0SDimitry Andric unsigned getLoopIndex(const Loop &L) const { 10704eeddc0SDimitry Andric for (unsigned I = 0; I < getNumLoops(); ++I) 10804eeddc0SDimitry Andric if (getLoop(I) == &L) 10904eeddc0SDimitry Andric return I; 11004eeddc0SDimitry Andric llvm_unreachable("Loop not in the loop nest"); 11104eeddc0SDimitry Andric } 11204eeddc0SDimitry Andric 1135ffd83dbSDimitry Andric /// Return the number of loops in the nest. getNumLoops()1145ffd83dbSDimitry Andric size_t getNumLoops() const { return Loops.size(); } 1155ffd83dbSDimitry Andric 1165ffd83dbSDimitry Andric /// Get the loops in the nest. getLoops()1175ffd83dbSDimitry Andric ArrayRef<Loop *> getLoops() const { return Loops; } 1185ffd83dbSDimitry Andric 11904eeddc0SDimitry Andric /// Get the loops in the nest at the given \p Depth. getLoopsAtDepth(unsigned Depth)12004eeddc0SDimitry Andric LoopVectorTy getLoopsAtDepth(unsigned Depth) const { 12104eeddc0SDimitry Andric assert(Depth >= Loops.front()->getLoopDepth() && 12204eeddc0SDimitry Andric Depth <= Loops.back()->getLoopDepth() && "Invalid depth"); 12304eeddc0SDimitry Andric LoopVectorTy Result; 12404eeddc0SDimitry Andric for (unsigned I = 0; I < getNumLoops(); ++I) { 12504eeddc0SDimitry Andric Loop *L = getLoop(I); 12604eeddc0SDimitry Andric if (L->getLoopDepth() == Depth) 12704eeddc0SDimitry Andric Result.push_back(L); 12804eeddc0SDimitry Andric else if (L->getLoopDepth() > Depth) 12904eeddc0SDimitry Andric break; 13004eeddc0SDimitry Andric } 13104eeddc0SDimitry Andric return Result; 13204eeddc0SDimitry Andric } 13304eeddc0SDimitry Andric 1345ffd83dbSDimitry Andric /// Retrieve a vector of perfect loop nests contained in the current loop 1355ffd83dbSDimitry Andric /// nest. For example, given the following nest containing 4 loops, this 1365ffd83dbSDimitry Andric /// member function would return {{L1,L2},{L3,L4}}. 1375ffd83dbSDimitry Andric /// \code 1385ffd83dbSDimitry Andric /// for(i) // L1 1395ffd83dbSDimitry Andric /// for(j) // L2 1405ffd83dbSDimitry Andric /// <code> 1415ffd83dbSDimitry Andric /// for(k) // L3 1425ffd83dbSDimitry Andric /// for(l) // L4 1435ffd83dbSDimitry Andric /// \endcode 1445ffd83dbSDimitry Andric SmallVector<LoopVectorTy, 4> getPerfectLoops(ScalarEvolution &SE) const; 1455ffd83dbSDimitry Andric 1465ffd83dbSDimitry Andric /// Return the loop nest depth (i.e. the loop depth of the 'deepest' loop) 1475ffd83dbSDimitry Andric /// For example given the loop nest: 1485ffd83dbSDimitry Andric /// \code 1495ffd83dbSDimitry Andric /// for(i) // loop at level 1 and Root of the nest 1505ffd83dbSDimitry Andric /// for(j1) // loop at level 2 1515ffd83dbSDimitry Andric /// for(k) // loop at level 3 1525ffd83dbSDimitry Andric /// for(j2) // loop at level 2 1535ffd83dbSDimitry Andric /// \endcode 1545ffd83dbSDimitry Andric /// getNestDepth() would return 3. getNestDepth()1555ffd83dbSDimitry Andric unsigned getNestDepth() const { 1565ffd83dbSDimitry Andric int NestDepth = 1575ffd83dbSDimitry Andric Loops.back()->getLoopDepth() - Loops.front()->getLoopDepth() + 1; 1585ffd83dbSDimitry Andric assert(NestDepth > 0 && "Expecting NestDepth to be at least 1"); 1595ffd83dbSDimitry Andric return NestDepth; 1605ffd83dbSDimitry Andric } 1615ffd83dbSDimitry Andric 1625ffd83dbSDimitry Andric /// Return the maximum perfect nesting depth. getMaxPerfectDepth()1635ffd83dbSDimitry Andric unsigned getMaxPerfectDepth() const { return MaxPerfectDepth; } 1645ffd83dbSDimitry Andric 1655ffd83dbSDimitry Andric /// Return true if all loops in the loop nest are in simplify form. areAllLoopsSimplifyForm()1665ffd83dbSDimitry Andric bool areAllLoopsSimplifyForm() const { 167e8d8bef9SDimitry Andric return all_of(Loops, [](const Loop *L) { return L->isLoopSimplifyForm(); }); 1685ffd83dbSDimitry Andric } 1695ffd83dbSDimitry Andric 170e8d8bef9SDimitry Andric /// Return true if all loops in the loop nest are in rotated form. areAllLoopsRotatedForm()171e8d8bef9SDimitry Andric bool areAllLoopsRotatedForm() const { 172e8d8bef9SDimitry Andric return all_of(Loops, [](const Loop *L) { return L->isRotatedForm(); }); 173e8d8bef9SDimitry Andric } 174e8d8bef9SDimitry Andric 175fe6060f1SDimitry Andric /// Return the function to which the loop-nest belongs. getParent()176fe6060f1SDimitry Andric Function *getParent() const { 177fe6060f1SDimitry Andric return Loops.front()->getHeader()->getParent(); 178fe6060f1SDimitry Andric } 179fe6060f1SDimitry Andric getName()180e8d8bef9SDimitry Andric StringRef getName() const { return Loops.front()->getName(); } 181e8d8bef9SDimitry Andric 1825ffd83dbSDimitry Andric protected: 1835ffd83dbSDimitry Andric const unsigned MaxPerfectDepth; // maximum perfect nesting depth level. 1845ffd83dbSDimitry Andric LoopVectorTy Loops; // the loops in the nest (in breadth first order). 185349cc55cSDimitry Andric 186349cc55cSDimitry Andric private: 187349cc55cSDimitry Andric enum LoopNestEnum { 188349cc55cSDimitry Andric PerfectLoopNest, 189349cc55cSDimitry Andric ImperfectLoopNest, 190349cc55cSDimitry Andric InvalidLoopStructure, 191349cc55cSDimitry Andric OuterLoopLowerBoundUnknown 192349cc55cSDimitry Andric }; 193349cc55cSDimitry Andric static LoopNestEnum analyzeLoopNestForPerfectNest(const Loop &OuterLoop, 194349cc55cSDimitry Andric const Loop &InnerLoop, 195349cc55cSDimitry Andric ScalarEvolution &SE); 1965ffd83dbSDimitry Andric }; 1975ffd83dbSDimitry Andric 1985ffd83dbSDimitry Andric raw_ostream &operator<<(raw_ostream &, const LoopNest &); 1995ffd83dbSDimitry Andric 2005ffd83dbSDimitry Andric /// This analysis provides information for a loop nest. The analysis runs on 2015ffd83dbSDimitry Andric /// demand and can be initiated via AM.getResult<LoopNestAnalysis>. 2025ffd83dbSDimitry Andric class LoopNestAnalysis : public AnalysisInfoMixin<LoopNestAnalysis> { 2035ffd83dbSDimitry Andric friend AnalysisInfoMixin<LoopNestAnalysis>; 2045ffd83dbSDimitry Andric static AnalysisKey Key; 2055ffd83dbSDimitry Andric 2065ffd83dbSDimitry Andric public: 2075ffd83dbSDimitry Andric using Result = LoopNest; 2085ffd83dbSDimitry Andric Result run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR); 2095ffd83dbSDimitry Andric }; 2105ffd83dbSDimitry Andric 2115ffd83dbSDimitry Andric /// Printer pass for the \c LoopNest results. 2125ffd83dbSDimitry Andric class LoopNestPrinterPass : public PassInfoMixin<LoopNestPrinterPass> { 2135ffd83dbSDimitry Andric raw_ostream &OS; 2145ffd83dbSDimitry Andric 2155ffd83dbSDimitry Andric public: LoopNestPrinterPass(raw_ostream & OS)2165ffd83dbSDimitry Andric explicit LoopNestPrinterPass(raw_ostream &OS) : OS(OS) {} 2175ffd83dbSDimitry Andric 2185ffd83dbSDimitry Andric PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, 2195ffd83dbSDimitry Andric LoopStandardAnalysisResults &AR, LPMUpdater &U); 220*1db9f3b2SDimitry Andric isRequired()221*1db9f3b2SDimitry Andric static bool isRequired() { return true; } 2225ffd83dbSDimitry Andric }; 2235ffd83dbSDimitry Andric 2245ffd83dbSDimitry Andric } // namespace llvm 2255ffd83dbSDimitry Andric 2265ffd83dbSDimitry Andric #endif // LLVM_ANALYSIS_LOOPNESTANALYSIS_H 227