xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/ADT/GenericCycleImpl.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10eae32dcSDimitry Andric //===- GenericCycleImpl.h -------------------------------------*- C++ -*---===//
20eae32dcSDimitry Andric //
30eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60eae32dcSDimitry Andric //
70eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
81fd87a68SDimitry Andric ///
91fd87a68SDimitry Andric /// \file
101fd87a68SDimitry Andric /// This template implementation resides in a separate file so that it
111fd87a68SDimitry Andric /// does not get injected into every .cpp file that includes the
121fd87a68SDimitry Andric /// generic header.
131fd87a68SDimitry Andric ///
141fd87a68SDimitry Andric /// DO NOT INCLUDE THIS FILE WHEN MERELY USING CYCLEINFO.
151fd87a68SDimitry Andric ///
161fd87a68SDimitry Andric /// This file should only be included by files that implement a
171fd87a68SDimitry Andric /// specialization of the relevant templates. Currently these are:
1806c3fb27SDimitry Andric /// - llvm/lib/IR/CycleInfo.cpp
1906c3fb27SDimitry Andric /// - llvm/lib/CodeGen/MachineCycleAnalysis.cpp
201fd87a68SDimitry Andric ///
210eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
220eae32dcSDimitry Andric 
230eae32dcSDimitry Andric #ifndef LLVM_ADT_GENERICCYCLEIMPL_H
240eae32dcSDimitry Andric #define LLVM_ADT_GENERICCYCLEIMPL_H
250eae32dcSDimitry Andric 
260eae32dcSDimitry Andric #include "llvm/ADT/DenseSet.h"
270eae32dcSDimitry Andric #include "llvm/ADT/DepthFirstIterator.h"
280eae32dcSDimitry Andric #include "llvm/ADT/GenericCycleInfo.h"
290eae32dcSDimitry Andric 
300eae32dcSDimitry Andric #define DEBUG_TYPE "generic-cycle-impl"
310eae32dcSDimitry Andric 
320eae32dcSDimitry Andric namespace llvm {
330eae32dcSDimitry Andric 
340eae32dcSDimitry Andric template <typename ContextT>
350eae32dcSDimitry Andric bool GenericCycle<ContextT>::contains(const GenericCycle *C) const {
360eae32dcSDimitry Andric   if (!C)
370eae32dcSDimitry Andric     return false;
380eae32dcSDimitry Andric 
390eae32dcSDimitry Andric   if (Depth > C->Depth)
400eae32dcSDimitry Andric     return false;
410eae32dcSDimitry Andric   while (Depth < C->Depth)
420eae32dcSDimitry Andric     C = C->ParentCycle;
430eae32dcSDimitry Andric   return this == C;
440eae32dcSDimitry Andric }
450eae32dcSDimitry Andric 
460eae32dcSDimitry Andric template <typename ContextT>
470eae32dcSDimitry Andric void GenericCycle<ContextT>::getExitBlocks(
480eae32dcSDimitry Andric     SmallVectorImpl<BlockT *> &TmpStorage) const {
490eae32dcSDimitry Andric   TmpStorage.clear();
500eae32dcSDimitry Andric 
510eae32dcSDimitry Andric   size_t NumExitBlocks = 0;
520eae32dcSDimitry Andric   for (BlockT *Block : blocks()) {
530eae32dcSDimitry Andric     llvm::append_range(TmpStorage, successors(Block));
540eae32dcSDimitry Andric 
550eae32dcSDimitry Andric     for (size_t Idx = NumExitBlocks, End = TmpStorage.size(); Idx < End;
560eae32dcSDimitry Andric          ++Idx) {
570eae32dcSDimitry Andric       BlockT *Succ = TmpStorage[Idx];
580eae32dcSDimitry Andric       if (!contains(Succ)) {
590eae32dcSDimitry Andric         auto ExitEndIt = TmpStorage.begin() + NumExitBlocks;
600eae32dcSDimitry Andric         if (std::find(TmpStorage.begin(), ExitEndIt, Succ) == ExitEndIt)
610eae32dcSDimitry Andric           TmpStorage[NumExitBlocks++] = Succ;
620eae32dcSDimitry Andric       }
630eae32dcSDimitry Andric     }
640eae32dcSDimitry Andric 
650eae32dcSDimitry Andric     TmpStorage.resize(NumExitBlocks);
660eae32dcSDimitry Andric   }
670eae32dcSDimitry Andric }
680eae32dcSDimitry Andric 
6981ad6265SDimitry Andric template <typename ContextT>
70*0fca6ea1SDimitry Andric void GenericCycle<ContextT>::getExitingBlocks(
71*0fca6ea1SDimitry Andric     SmallVectorImpl<BlockT *> &TmpStorage) const {
72*0fca6ea1SDimitry Andric   TmpStorage.clear();
73*0fca6ea1SDimitry Andric 
74*0fca6ea1SDimitry Andric   for (BlockT *Block : blocks()) {
75*0fca6ea1SDimitry Andric     for (BlockT *Succ : successors(Block)) {
76*0fca6ea1SDimitry Andric       if (!contains(Succ)) {
77*0fca6ea1SDimitry Andric         TmpStorage.push_back(Block);
78*0fca6ea1SDimitry Andric         break;
79*0fca6ea1SDimitry Andric       }
80*0fca6ea1SDimitry Andric     }
81*0fca6ea1SDimitry Andric   }
82*0fca6ea1SDimitry Andric }
83*0fca6ea1SDimitry Andric 
84*0fca6ea1SDimitry Andric template <typename ContextT>
8581ad6265SDimitry Andric auto GenericCycle<ContextT>::getCyclePreheader() const -> BlockT * {
8681ad6265SDimitry Andric   BlockT *Predecessor = getCyclePredecessor();
8781ad6265SDimitry Andric   if (!Predecessor)
8881ad6265SDimitry Andric     return nullptr;
8981ad6265SDimitry Andric 
9081ad6265SDimitry Andric   assert(isReducible() && "Cycle Predecessor must be in a reducible cycle!");
9181ad6265SDimitry Andric 
9281ad6265SDimitry Andric   if (succ_size(Predecessor) != 1)
9381ad6265SDimitry Andric     return nullptr;
9481ad6265SDimitry Andric 
9581ad6265SDimitry Andric   // Make sure we are allowed to hoist instructions into the predecessor.
9681ad6265SDimitry Andric   if (!Predecessor->isLegalToHoistInto())
9781ad6265SDimitry Andric     return nullptr;
9881ad6265SDimitry Andric 
9981ad6265SDimitry Andric   return Predecessor;
10081ad6265SDimitry Andric }
10181ad6265SDimitry Andric 
10281ad6265SDimitry Andric template <typename ContextT>
10381ad6265SDimitry Andric auto GenericCycle<ContextT>::getCyclePredecessor() const -> BlockT * {
10481ad6265SDimitry Andric   if (!isReducible())
10581ad6265SDimitry Andric     return nullptr;
10681ad6265SDimitry Andric 
10781ad6265SDimitry Andric   BlockT *Out = nullptr;
10881ad6265SDimitry Andric 
10981ad6265SDimitry Andric   // Loop over the predecessors of the header node...
11081ad6265SDimitry Andric   BlockT *Header = getHeader();
11181ad6265SDimitry Andric   for (const auto Pred : predecessors(Header)) {
11281ad6265SDimitry Andric     if (!contains(Pred)) {
11381ad6265SDimitry Andric       if (Out && Out != Pred)
11481ad6265SDimitry Andric         return nullptr;
11581ad6265SDimitry Andric       Out = Pred;
11681ad6265SDimitry Andric     }
11781ad6265SDimitry Andric   }
11881ad6265SDimitry Andric 
11981ad6265SDimitry Andric   return Out;
12081ad6265SDimitry Andric }
12181ad6265SDimitry Andric 
1220eae32dcSDimitry Andric /// \brief Helper class for computing cycle information.
1230eae32dcSDimitry Andric template <typename ContextT> class GenericCycleInfoCompute {
1240eae32dcSDimitry Andric   using BlockT = typename ContextT::BlockT;
1250eae32dcSDimitry Andric   using CycleInfoT = GenericCycleInfo<ContextT>;
1260eae32dcSDimitry Andric   using CycleT = typename CycleInfoT::CycleT;
1270eae32dcSDimitry Andric 
1280eae32dcSDimitry Andric   CycleInfoT &Info;
1290eae32dcSDimitry Andric 
1300eae32dcSDimitry Andric   struct DFSInfo {
1310eae32dcSDimitry Andric     unsigned Start = 0; // DFS start; positive if block is found
1320eae32dcSDimitry Andric     unsigned End = 0;   // DFS end
1330eae32dcSDimitry Andric 
1341fd87a68SDimitry Andric     DFSInfo() = default;
1350eae32dcSDimitry Andric     explicit DFSInfo(unsigned Start) : Start(Start) {}
1360eae32dcSDimitry Andric 
1370eae32dcSDimitry Andric     /// Whether this node is an ancestor (or equal to) the node \p Other
1380eae32dcSDimitry Andric     /// in the DFS tree.
1390eae32dcSDimitry Andric     bool isAncestorOf(const DFSInfo &Other) const {
1400eae32dcSDimitry Andric       return Start <= Other.Start && Other.End <= End;
1410eae32dcSDimitry Andric     }
1420eae32dcSDimitry Andric   };
1430eae32dcSDimitry Andric 
1440eae32dcSDimitry Andric   DenseMap<BlockT *, DFSInfo> BlockDFSInfo;
1450eae32dcSDimitry Andric   SmallVector<BlockT *, 8> BlockPreorder;
1460eae32dcSDimitry Andric 
1470eae32dcSDimitry Andric   GenericCycleInfoCompute(const GenericCycleInfoCompute &) = delete;
1480eae32dcSDimitry Andric   GenericCycleInfoCompute &operator=(const GenericCycleInfoCompute &) = delete;
1490eae32dcSDimitry Andric 
1500eae32dcSDimitry Andric public:
1510eae32dcSDimitry Andric   GenericCycleInfoCompute(CycleInfoT &Info) : Info(Info) {}
1520eae32dcSDimitry Andric 
1530eae32dcSDimitry Andric   void run(BlockT *EntryBlock);
1540eae32dcSDimitry Andric 
1550eae32dcSDimitry Andric   static void updateDepth(CycleT *SubTree);
1560eae32dcSDimitry Andric 
1570eae32dcSDimitry Andric private:
1580eae32dcSDimitry Andric   void dfs(BlockT *EntryBlock);
1590eae32dcSDimitry Andric };
1600eae32dcSDimitry Andric 
1610eae32dcSDimitry Andric template <typename ContextT>
1626246ae0bSDimitry Andric auto GenericCycleInfo<ContextT>::getTopLevelParentCycle(BlockT *Block)
1636246ae0bSDimitry Andric     -> CycleT * {
1646246ae0bSDimitry Andric   auto Cycle = BlockMapTopLevel.find(Block);
1656246ae0bSDimitry Andric   if (Cycle != BlockMapTopLevel.end())
1666246ae0bSDimitry Andric     return Cycle->second;
1676246ae0bSDimitry Andric 
1680eae32dcSDimitry Andric   auto MapIt = BlockMap.find(Block);
1690eae32dcSDimitry Andric   if (MapIt == BlockMap.end())
1700eae32dcSDimitry Andric     return nullptr;
1710eae32dcSDimitry Andric 
1720eae32dcSDimitry Andric   auto *C = MapIt->second;
1730eae32dcSDimitry Andric   while (C->ParentCycle)
1740eae32dcSDimitry Andric     C = C->ParentCycle;
1756246ae0bSDimitry Andric   BlockMapTopLevel.try_emplace(Block, C);
1760eae32dcSDimitry Andric   return C;
1770eae32dcSDimitry Andric }
1780eae32dcSDimitry Andric 
1790eae32dcSDimitry Andric template <typename ContextT>
1806246ae0bSDimitry Andric void GenericCycleInfo<ContextT>::moveTopLevelCycleToNewParent(CycleT *NewParent,
1810eae32dcSDimitry Andric                                                               CycleT *Child) {
1826246ae0bSDimitry Andric   assert((!Child->ParentCycle && !NewParent->ParentCycle) &&
1836246ae0bSDimitry Andric          "NewParent and Child must be both top level cycle!\n");
1840eae32dcSDimitry Andric   auto &CurrentContainer =
1850eae32dcSDimitry Andric       Child->ParentCycle ? Child->ParentCycle->Children : TopLevelCycles;
1860eae32dcSDimitry Andric   auto Pos = llvm::find_if(CurrentContainer, [=](const auto &Ptr) -> bool {
1870eae32dcSDimitry Andric     return Child == Ptr.get();
1880eae32dcSDimitry Andric   });
1890eae32dcSDimitry Andric   assert(Pos != CurrentContainer.end());
1900eae32dcSDimitry Andric   NewParent->Children.push_back(std::move(*Pos));
1910eae32dcSDimitry Andric   *Pos = std::move(CurrentContainer.back());
1920eae32dcSDimitry Andric   CurrentContainer.pop_back();
1930eae32dcSDimitry Andric   Child->ParentCycle = NewParent;
1946246ae0bSDimitry Andric 
19506c3fb27SDimitry Andric   NewParent->Blocks.insert(Child->block_begin(), Child->block_end());
1966246ae0bSDimitry Andric 
1976246ae0bSDimitry Andric   for (auto &It : BlockMapTopLevel)
1986246ae0bSDimitry Andric     if (It.second == Child)
1996246ae0bSDimitry Andric       It.second = NewParent;
2000eae32dcSDimitry Andric }
2010eae32dcSDimitry Andric 
2025f757f3fSDimitry Andric template <typename ContextT>
2035f757f3fSDimitry Andric void GenericCycleInfo<ContextT>::addBlockToCycle(BlockT *Block, CycleT *Cycle) {
2045f757f3fSDimitry Andric   // FixMe: Appending NewBlock is fine as a set of blocks in a cycle. When
2055f757f3fSDimitry Andric   // printing, cycle NewBlock is at the end of list but it should be in the
2065f757f3fSDimitry Andric   // middle to represent actual traversal of a cycle.
2075f757f3fSDimitry Andric   Cycle->appendBlock(Block);
2085f757f3fSDimitry Andric   BlockMap.try_emplace(Block, Cycle);
2095f757f3fSDimitry Andric 
2105f757f3fSDimitry Andric   CycleT *ParentCycle = Cycle->getParentCycle();
2115f757f3fSDimitry Andric   while (ParentCycle) {
2125f757f3fSDimitry Andric     Cycle = ParentCycle;
2135f757f3fSDimitry Andric     Cycle->appendBlock(Block);
2145f757f3fSDimitry Andric     ParentCycle = Cycle->getParentCycle();
2155f757f3fSDimitry Andric   }
2165f757f3fSDimitry Andric 
2175f757f3fSDimitry Andric   BlockMapTopLevel.try_emplace(Block, Cycle);
2185f757f3fSDimitry Andric }
2195f757f3fSDimitry Andric 
2200eae32dcSDimitry Andric /// \brief Main function of the cycle info computations.
2210eae32dcSDimitry Andric template <typename ContextT>
2220eae32dcSDimitry Andric void GenericCycleInfoCompute<ContextT>::run(BlockT *EntryBlock) {
2230eae32dcSDimitry Andric   LLVM_DEBUG(errs() << "Entry block: " << Info.Context.print(EntryBlock)
2240eae32dcSDimitry Andric                     << "\n");
2250eae32dcSDimitry Andric   dfs(EntryBlock);
2260eae32dcSDimitry Andric 
2270eae32dcSDimitry Andric   SmallVector<BlockT *, 8> Worklist;
2280eae32dcSDimitry Andric 
2290eae32dcSDimitry Andric   for (BlockT *HeaderCandidate : llvm::reverse(BlockPreorder)) {
2300eae32dcSDimitry Andric     const DFSInfo CandidateInfo = BlockDFSInfo.lookup(HeaderCandidate);
2310eae32dcSDimitry Andric 
2320eae32dcSDimitry Andric     for (BlockT *Pred : predecessors(HeaderCandidate)) {
2330eae32dcSDimitry Andric       const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred);
2340eae32dcSDimitry Andric       if (CandidateInfo.isAncestorOf(PredDFSInfo))
2350eae32dcSDimitry Andric         Worklist.push_back(Pred);
2360eae32dcSDimitry Andric     }
2370eae32dcSDimitry Andric     if (Worklist.empty()) {
2380eae32dcSDimitry Andric       continue;
2390eae32dcSDimitry Andric     }
2400eae32dcSDimitry Andric 
2410eae32dcSDimitry Andric     // Found a cycle with the candidate as its header.
2420eae32dcSDimitry Andric     LLVM_DEBUG(errs() << "Found cycle for header: "
2430eae32dcSDimitry Andric                       << Info.Context.print(HeaderCandidate) << "\n");
2440eae32dcSDimitry Andric     std::unique_ptr<CycleT> NewCycle = std::make_unique<CycleT>();
2450eae32dcSDimitry Andric     NewCycle->appendEntry(HeaderCandidate);
2460eae32dcSDimitry Andric     NewCycle->appendBlock(HeaderCandidate);
2470eae32dcSDimitry Andric     Info.BlockMap.try_emplace(HeaderCandidate, NewCycle.get());
2480eae32dcSDimitry Andric 
2490eae32dcSDimitry Andric     // Helper function to process (non-back-edge) predecessors of a discovered
2500eae32dcSDimitry Andric     // block and either add them to the worklist or recognize that the given
2510eae32dcSDimitry Andric     // block is an additional cycle entry.
2520eae32dcSDimitry Andric     auto ProcessPredecessors = [&](BlockT *Block) {
2530eae32dcSDimitry Andric       LLVM_DEBUG(errs() << "  block " << Info.Context.print(Block) << ": ");
2540eae32dcSDimitry Andric 
2550eae32dcSDimitry Andric       bool IsEntry = false;
2560eae32dcSDimitry Andric       for (BlockT *Pred : predecessors(Block)) {
2570eae32dcSDimitry Andric         const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred);
2580eae32dcSDimitry Andric         if (CandidateInfo.isAncestorOf(PredDFSInfo)) {
2590eae32dcSDimitry Andric           Worklist.push_back(Pred);
2600eae32dcSDimitry Andric         } else {
2610eae32dcSDimitry Andric           IsEntry = true;
2620eae32dcSDimitry Andric         }
2630eae32dcSDimitry Andric       }
2640eae32dcSDimitry Andric       if (IsEntry) {
2650eae32dcSDimitry Andric         assert(!NewCycle->isEntry(Block));
2660eae32dcSDimitry Andric         LLVM_DEBUG(errs() << "append as entry\n");
2670eae32dcSDimitry Andric         NewCycle->appendEntry(Block);
2680eae32dcSDimitry Andric       } else {
2690eae32dcSDimitry Andric         LLVM_DEBUG(errs() << "append as child\n");
2700eae32dcSDimitry Andric       }
2710eae32dcSDimitry Andric     };
2720eae32dcSDimitry Andric 
2730eae32dcSDimitry Andric     do {
2740eae32dcSDimitry Andric       BlockT *Block = Worklist.pop_back_val();
2750eae32dcSDimitry Andric       if (Block == HeaderCandidate)
2760eae32dcSDimitry Andric         continue;
2770eae32dcSDimitry Andric 
2780eae32dcSDimitry Andric       // If the block has already been discovered by some cycle
2790eae32dcSDimitry Andric       // (possibly by ourself), then the outermost cycle containing it
2800eae32dcSDimitry Andric       // should become our child.
2810eae32dcSDimitry Andric       if (auto *BlockParent = Info.getTopLevelParentCycle(Block)) {
2820eae32dcSDimitry Andric         LLVM_DEBUG(errs() << "  block " << Info.Context.print(Block) << ": ");
2830eae32dcSDimitry Andric 
2840eae32dcSDimitry Andric         if (BlockParent != NewCycle.get()) {
2850eae32dcSDimitry Andric           LLVM_DEBUG(errs()
2860eae32dcSDimitry Andric                      << "discovered child cycle "
2870eae32dcSDimitry Andric                      << Info.Context.print(BlockParent->getHeader()) << "\n");
2880eae32dcSDimitry Andric           // Make BlockParent the child of NewCycle.
2896246ae0bSDimitry Andric           Info.moveTopLevelCycleToNewParent(NewCycle.get(), BlockParent);
2900eae32dcSDimitry Andric 
2910eae32dcSDimitry Andric           for (auto *ChildEntry : BlockParent->entries())
2920eae32dcSDimitry Andric             ProcessPredecessors(ChildEntry);
2930eae32dcSDimitry Andric         } else {
2940eae32dcSDimitry Andric           LLVM_DEBUG(errs()
2950eae32dcSDimitry Andric                      << "known child cycle "
2960eae32dcSDimitry Andric                      << Info.Context.print(BlockParent->getHeader()) << "\n");
2970eae32dcSDimitry Andric         }
2980eae32dcSDimitry Andric       } else {
2990eae32dcSDimitry Andric         Info.BlockMap.try_emplace(Block, NewCycle.get());
3000eae32dcSDimitry Andric         assert(!is_contained(NewCycle->Blocks, Block));
30106c3fb27SDimitry Andric         NewCycle->Blocks.insert(Block);
3020eae32dcSDimitry Andric         ProcessPredecessors(Block);
3036246ae0bSDimitry Andric         Info.BlockMapTopLevel.try_emplace(Block, NewCycle.get());
3040eae32dcSDimitry Andric       }
3050eae32dcSDimitry Andric     } while (!Worklist.empty());
3060eae32dcSDimitry Andric 
3070eae32dcSDimitry Andric     Info.TopLevelCycles.push_back(std::move(NewCycle));
3080eae32dcSDimitry Andric   }
3090eae32dcSDimitry Andric 
3100eae32dcSDimitry Andric   // Fix top-level cycle links and compute cycle depths.
3110eae32dcSDimitry Andric   for (auto *TLC : Info.toplevel_cycles()) {
3120eae32dcSDimitry Andric     LLVM_DEBUG(errs() << "top-level cycle: "
3130eae32dcSDimitry Andric                       << Info.Context.print(TLC->getHeader()) << "\n");
3140eae32dcSDimitry Andric 
3150eae32dcSDimitry Andric     TLC->ParentCycle = nullptr;
3160eae32dcSDimitry Andric     updateDepth(TLC);
3170eae32dcSDimitry Andric   }
3180eae32dcSDimitry Andric }
3190eae32dcSDimitry Andric 
3200eae32dcSDimitry Andric /// \brief Recompute depth values of \p SubTree and all descendants.
3210eae32dcSDimitry Andric template <typename ContextT>
3220eae32dcSDimitry Andric void GenericCycleInfoCompute<ContextT>::updateDepth(CycleT *SubTree) {
3230eae32dcSDimitry Andric   for (CycleT *Cycle : depth_first(SubTree))
3240eae32dcSDimitry Andric     Cycle->Depth = Cycle->ParentCycle ? Cycle->ParentCycle->Depth + 1 : 1;
3250eae32dcSDimitry Andric }
3260eae32dcSDimitry Andric 
3270eae32dcSDimitry Andric /// \brief Compute a DFS of basic blocks starting at the function entry.
3280eae32dcSDimitry Andric ///
3290eae32dcSDimitry Andric /// Fills BlockDFSInfo with start/end counters and BlockPreorder.
3300eae32dcSDimitry Andric template <typename ContextT>
3310eae32dcSDimitry Andric void GenericCycleInfoCompute<ContextT>::dfs(BlockT *EntryBlock) {
3320eae32dcSDimitry Andric   SmallVector<unsigned, 8> DFSTreeStack;
3330eae32dcSDimitry Andric   SmallVector<BlockT *, 8> TraverseStack;
3340eae32dcSDimitry Andric   unsigned Counter = 0;
3350eae32dcSDimitry Andric   TraverseStack.emplace_back(EntryBlock);
3360eae32dcSDimitry Andric 
3370eae32dcSDimitry Andric   do {
3380eae32dcSDimitry Andric     BlockT *Block = TraverseStack.back();
3390eae32dcSDimitry Andric     LLVM_DEBUG(errs() << "DFS visiting block: " << Info.Context.print(Block)
3400eae32dcSDimitry Andric                       << "\n");
3410eae32dcSDimitry Andric     if (!BlockDFSInfo.count(Block)) {
3420eae32dcSDimitry Andric       // We're visiting the block for the first time. Open its DFSInfo, add
3430eae32dcSDimitry Andric       // successors to the traversal stack, and remember the traversal stack
3440eae32dcSDimitry Andric       // depth at which the block was opened, so that we can correctly record
3450eae32dcSDimitry Andric       // its end time.
3460eae32dcSDimitry Andric       LLVM_DEBUG(errs() << "  first encountered at depth "
3470eae32dcSDimitry Andric                         << TraverseStack.size() << "\n");
3480eae32dcSDimitry Andric 
3490eae32dcSDimitry Andric       DFSTreeStack.emplace_back(TraverseStack.size());
3500eae32dcSDimitry Andric       llvm::append_range(TraverseStack, successors(Block));
3510eae32dcSDimitry Andric 
3520eae32dcSDimitry Andric       bool Added = BlockDFSInfo.try_emplace(Block, ++Counter).second;
35381ad6265SDimitry Andric       (void)Added;
3540eae32dcSDimitry Andric       assert(Added);
3550eae32dcSDimitry Andric       BlockPreorder.push_back(Block);
3560eae32dcSDimitry Andric       LLVM_DEBUG(errs() << "  preorder number: " << Counter << "\n");
3570eae32dcSDimitry Andric     } else {
3580eae32dcSDimitry Andric       assert(!DFSTreeStack.empty());
3590eae32dcSDimitry Andric       if (DFSTreeStack.back() == TraverseStack.size()) {
3600eae32dcSDimitry Andric         LLVM_DEBUG(errs() << "  ended at " << Counter << "\n");
3610eae32dcSDimitry Andric         BlockDFSInfo.find(Block)->second.End = Counter;
3620eae32dcSDimitry Andric         DFSTreeStack.pop_back();
3630eae32dcSDimitry Andric       } else {
3640eae32dcSDimitry Andric         LLVM_DEBUG(errs() << "  already done\n");
3650eae32dcSDimitry Andric       }
3660eae32dcSDimitry Andric       TraverseStack.pop_back();
3670eae32dcSDimitry Andric     }
3680eae32dcSDimitry Andric   } while (!TraverseStack.empty());
3690eae32dcSDimitry Andric   assert(DFSTreeStack.empty());
3700eae32dcSDimitry Andric 
3710eae32dcSDimitry Andric   LLVM_DEBUG(
3720eae32dcSDimitry Andric     errs() << "Preorder:\n";
3730eae32dcSDimitry Andric     for (int i = 0, e = BlockPreorder.size(); i != e; ++i) {
3740eae32dcSDimitry Andric       errs() << "  " << Info.Context.print(BlockPreorder[i]) << ": " << i << "\n";
3750eae32dcSDimitry Andric     }
3760eae32dcSDimitry Andric   );
3770eae32dcSDimitry Andric }
3780eae32dcSDimitry Andric 
3790eae32dcSDimitry Andric /// \brief Reset the object to its initial state.
3800eae32dcSDimitry Andric template <typename ContextT> void GenericCycleInfo<ContextT>::clear() {
3810eae32dcSDimitry Andric   TopLevelCycles.clear();
3820eae32dcSDimitry Andric   BlockMap.clear();
3836246ae0bSDimitry Andric   BlockMapTopLevel.clear();
3840eae32dcSDimitry Andric }
3850eae32dcSDimitry Andric 
3860eae32dcSDimitry Andric /// \brief Compute the cycle info for a function.
3870eae32dcSDimitry Andric template <typename ContextT>
3880eae32dcSDimitry Andric void GenericCycleInfo<ContextT>::compute(FunctionT &F) {
3890eae32dcSDimitry Andric   GenericCycleInfoCompute<ContextT> Compute(*this);
3905f757f3fSDimitry Andric   Context = ContextT(&F);
3910eae32dcSDimitry Andric 
3920eae32dcSDimitry Andric   LLVM_DEBUG(errs() << "Computing cycles for function: " << F.getName()
3930eae32dcSDimitry Andric                     << "\n");
3945f757f3fSDimitry Andric   Compute.run(&F.front());
3950eae32dcSDimitry Andric 
3960eae32dcSDimitry Andric   assert(validateTree());
3970eae32dcSDimitry Andric }
3980eae32dcSDimitry Andric 
3995f757f3fSDimitry Andric template <typename ContextT>
4005f757f3fSDimitry Andric void GenericCycleInfo<ContextT>::splitCriticalEdge(BlockT *Pred, BlockT *Succ,
4015f757f3fSDimitry Andric                                                    BlockT *NewBlock) {
4025f757f3fSDimitry Andric   // Edge Pred-Succ is replaced by edges Pred-NewBlock and NewBlock-Succ, all
4035f757f3fSDimitry Andric   // cycles that had blocks Pred and Succ also get NewBlock.
4045f757f3fSDimitry Andric   CycleT *Cycle = getSmallestCommonCycle(getCycle(Pred), getCycle(Succ));
4055f757f3fSDimitry Andric   if (!Cycle)
4065f757f3fSDimitry Andric     return;
4075f757f3fSDimitry Andric 
4085f757f3fSDimitry Andric   addBlockToCycle(NewBlock, Cycle);
4095f757f3fSDimitry Andric   assert(validateTree());
4105f757f3fSDimitry Andric }
4115f757f3fSDimitry Andric 
4120eae32dcSDimitry Andric /// \brief Find the innermost cycle containing a given block.
4130eae32dcSDimitry Andric ///
4140eae32dcSDimitry Andric /// \returns the innermost cycle containing \p Block or nullptr if
4150eae32dcSDimitry Andric ///          it is not contained in any cycle.
4160eae32dcSDimitry Andric template <typename ContextT>
4170eae32dcSDimitry Andric auto GenericCycleInfo<ContextT>::getCycle(const BlockT *Block) const
4180eae32dcSDimitry Andric     -> CycleT * {
4195f757f3fSDimitry Andric   return BlockMap.lookup(Block);
4205f757f3fSDimitry Andric }
4215f757f3fSDimitry Andric 
4225f757f3fSDimitry Andric /// \brief Find the innermost cycle containing both given cycles.
4235f757f3fSDimitry Andric ///
4245f757f3fSDimitry Andric /// \returns the innermost cycle containing both \p A and \p B
4255f757f3fSDimitry Andric ///          or nullptr if there is no such cycle.
4265f757f3fSDimitry Andric template <typename ContextT>
4275f757f3fSDimitry Andric auto GenericCycleInfo<ContextT>::getSmallestCommonCycle(CycleT *A,
4285f757f3fSDimitry Andric                                                         CycleT *B) const
4295f757f3fSDimitry Andric     -> CycleT * {
4305f757f3fSDimitry Andric   if (!A || !B)
4310eae32dcSDimitry Andric     return nullptr;
4325f757f3fSDimitry Andric 
4335f757f3fSDimitry Andric   // If cycles A and B have different depth replace them with parent cycle
4345f757f3fSDimitry Andric   // until they have the same depth.
4355f757f3fSDimitry Andric   while (A->getDepth() > B->getDepth())
4365f757f3fSDimitry Andric     A = A->getParentCycle();
4375f757f3fSDimitry Andric   while (B->getDepth() > A->getDepth())
4385f757f3fSDimitry Andric     B = B->getParentCycle();
4395f757f3fSDimitry Andric 
4405f757f3fSDimitry Andric   // Cycles A and B are at same depth but may be disjoint, replace them with
4415f757f3fSDimitry Andric   // parent cycles until we find cycle that contains both or we run out of
4425f757f3fSDimitry Andric   // parent cycles.
4435f757f3fSDimitry Andric   while (A != B) {
4445f757f3fSDimitry Andric     A = A->getParentCycle();
4455f757f3fSDimitry Andric     B = B->getParentCycle();
4465f757f3fSDimitry Andric   }
4475f757f3fSDimitry Andric 
4485f757f3fSDimitry Andric   return A;
4490eae32dcSDimitry Andric }
4500eae32dcSDimitry Andric 
45181ad6265SDimitry Andric /// \brief get the depth for the cycle which containing a given block.
45281ad6265SDimitry Andric ///
45381ad6265SDimitry Andric /// \returns the depth for the innermost cycle containing \p Block or 0 if it is
45481ad6265SDimitry Andric ///          not contained in any cycle.
45581ad6265SDimitry Andric template <typename ContextT>
45681ad6265SDimitry Andric unsigned GenericCycleInfo<ContextT>::getCycleDepth(const BlockT *Block) const {
45781ad6265SDimitry Andric   CycleT *Cycle = getCycle(Block);
45881ad6265SDimitry Andric   if (!Cycle)
45981ad6265SDimitry Andric     return 0;
46081ad6265SDimitry Andric   return Cycle->getDepth();
46181ad6265SDimitry Andric }
46281ad6265SDimitry Andric 
46381ad6265SDimitry Andric #ifndef NDEBUG
4640eae32dcSDimitry Andric /// \brief Validate the internal consistency of the cycle tree.
4650eae32dcSDimitry Andric ///
4660eae32dcSDimitry Andric /// Note that this does \em not check that cycles are really cycles in the CFG,
4670eae32dcSDimitry Andric /// or that the right set of cycles in the CFG were found.
4680eae32dcSDimitry Andric template <typename ContextT>
4690eae32dcSDimitry Andric bool GenericCycleInfo<ContextT>::validateTree() const {
4700eae32dcSDimitry Andric   DenseSet<BlockT *> Blocks;
4710eae32dcSDimitry Andric   DenseSet<BlockT *> Entries;
4720eae32dcSDimitry Andric 
4730eae32dcSDimitry Andric   auto reportError = [](const char *File, int Line, const char *Cond) {
4740eae32dcSDimitry Andric     errs() << File << ':' << Line
4750eae32dcSDimitry Andric            << ": GenericCycleInfo::validateTree: " << Cond << '\n';
4760eae32dcSDimitry Andric   };
4770eae32dcSDimitry Andric #define check(cond)                                                            \
4780eae32dcSDimitry Andric   do {                                                                         \
4790eae32dcSDimitry Andric     if (!(cond)) {                                                             \
4800eae32dcSDimitry Andric       reportError(__FILE__, __LINE__, #cond);                                  \
4810eae32dcSDimitry Andric       return false;                                                            \
4820eae32dcSDimitry Andric     }                                                                          \
4830eae32dcSDimitry Andric   } while (false)
4840eae32dcSDimitry Andric 
4850eae32dcSDimitry Andric   for (const auto *TLC : toplevel_cycles()) {
4860eae32dcSDimitry Andric     for (const CycleT *Cycle : depth_first(TLC)) {
4870eae32dcSDimitry Andric       if (Cycle->ParentCycle)
4880eae32dcSDimitry Andric         check(is_contained(Cycle->ParentCycle->children(), Cycle));
4890eae32dcSDimitry Andric 
4900eae32dcSDimitry Andric       for (BlockT *Block : Cycle->Blocks) {
4910eae32dcSDimitry Andric         auto MapIt = BlockMap.find(Block);
4920eae32dcSDimitry Andric         check(MapIt != BlockMap.end());
4930eae32dcSDimitry Andric         check(Cycle->contains(MapIt->second));
4940eae32dcSDimitry Andric         check(Blocks.insert(Block).second); // duplicates in block list?
4950eae32dcSDimitry Andric       }
4960eae32dcSDimitry Andric       Blocks.clear();
4970eae32dcSDimitry Andric 
4980eae32dcSDimitry Andric       check(!Cycle->Entries.empty());
4990eae32dcSDimitry Andric       for (BlockT *Entry : Cycle->Entries) {
5000eae32dcSDimitry Andric         check(Entries.insert(Entry).second); // duplicate entry?
5010eae32dcSDimitry Andric         check(is_contained(Cycle->Blocks, Entry));
5020eae32dcSDimitry Andric       }
5030eae32dcSDimitry Andric       Entries.clear();
5040eae32dcSDimitry Andric 
5050eae32dcSDimitry Andric       unsigned ChildDepth = 0;
5060eae32dcSDimitry Andric       for (const CycleT *Child : Cycle->children()) {
5070eae32dcSDimitry Andric         check(Child->Depth > Cycle->Depth);
5080eae32dcSDimitry Andric         if (!ChildDepth) {
5090eae32dcSDimitry Andric           ChildDepth = Child->Depth;
5100eae32dcSDimitry Andric         } else {
5110eae32dcSDimitry Andric           check(ChildDepth == Child->Depth);
5120eae32dcSDimitry Andric         }
5130eae32dcSDimitry Andric       }
5140eae32dcSDimitry Andric     }
5150eae32dcSDimitry Andric   }
5160eae32dcSDimitry Andric 
5170eae32dcSDimitry Andric   for (const auto &Entry : BlockMap) {
5180eae32dcSDimitry Andric     BlockT *Block = Entry.first;
5190eae32dcSDimitry Andric     for (const CycleT *Cycle = Entry.second; Cycle;
5200eae32dcSDimitry Andric          Cycle = Cycle->ParentCycle) {
5210eae32dcSDimitry Andric       check(is_contained(Cycle->Blocks, Block));
5220eae32dcSDimitry Andric     }
5230eae32dcSDimitry Andric   }
5240eae32dcSDimitry Andric 
5250eae32dcSDimitry Andric #undef check
5260eae32dcSDimitry Andric 
5270eae32dcSDimitry Andric   return true;
5280eae32dcSDimitry Andric }
52981ad6265SDimitry Andric #endif
5300eae32dcSDimitry Andric 
5310eae32dcSDimitry Andric /// \brief Print the cycle info.
5320eae32dcSDimitry Andric template <typename ContextT>
5330eae32dcSDimitry Andric void GenericCycleInfo<ContextT>::print(raw_ostream &Out) const {
5340eae32dcSDimitry Andric   for (const auto *TLC : toplevel_cycles()) {
5350eae32dcSDimitry Andric     for (const CycleT *Cycle : depth_first(TLC)) {
5360eae32dcSDimitry Andric       for (unsigned I = 0; I < Cycle->Depth; ++I)
5370eae32dcSDimitry Andric         Out << "    ";
5380eae32dcSDimitry Andric 
5390eae32dcSDimitry Andric       Out << Cycle->print(Context) << '\n';
5400eae32dcSDimitry Andric     }
5410eae32dcSDimitry Andric   }
5420eae32dcSDimitry Andric }
5430eae32dcSDimitry Andric 
5440eae32dcSDimitry Andric } // namespace llvm
5450eae32dcSDimitry Andric 
5460eae32dcSDimitry Andric #undef DEBUG_TYPE
5470eae32dcSDimitry Andric 
5480eae32dcSDimitry Andric #endif // LLVM_ADT_GENERICCYCLEIMPL_H
549