xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/Analysis/LoopNestAnalysis.h (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
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