xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/ADT/GenericCycleImpl.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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>
7081ad6265SDimitry Andric auto GenericCycle<ContextT>::getCyclePreheader() const -> BlockT * {
7181ad6265SDimitry Andric   BlockT *Predecessor = getCyclePredecessor();
7281ad6265SDimitry Andric   if (!Predecessor)
7381ad6265SDimitry Andric     return nullptr;
7481ad6265SDimitry Andric 
7581ad6265SDimitry Andric   assert(isReducible() && "Cycle Predecessor must be in a reducible cycle!");
7681ad6265SDimitry Andric 
7781ad6265SDimitry Andric   if (succ_size(Predecessor) != 1)
7881ad6265SDimitry Andric     return nullptr;
7981ad6265SDimitry Andric 
8081ad6265SDimitry Andric   // Make sure we are allowed to hoist instructions into the predecessor.
8181ad6265SDimitry Andric   if (!Predecessor->isLegalToHoistInto())
8281ad6265SDimitry Andric     return nullptr;
8381ad6265SDimitry Andric 
8481ad6265SDimitry Andric   return Predecessor;
8581ad6265SDimitry Andric }
8681ad6265SDimitry Andric 
8781ad6265SDimitry Andric template <typename ContextT>
8881ad6265SDimitry Andric auto GenericCycle<ContextT>::getCyclePredecessor() const -> BlockT * {
8981ad6265SDimitry Andric   if (!isReducible())
9081ad6265SDimitry Andric     return nullptr;
9181ad6265SDimitry Andric 
9281ad6265SDimitry Andric   BlockT *Out = nullptr;
9381ad6265SDimitry Andric 
9481ad6265SDimitry Andric   // Loop over the predecessors of the header node...
9581ad6265SDimitry Andric   BlockT *Header = getHeader();
9681ad6265SDimitry Andric   for (const auto Pred : predecessors(Header)) {
9781ad6265SDimitry Andric     if (!contains(Pred)) {
9881ad6265SDimitry Andric       if (Out && Out != Pred)
9981ad6265SDimitry Andric         return nullptr;
10081ad6265SDimitry Andric       Out = Pred;
10181ad6265SDimitry Andric     }
10281ad6265SDimitry Andric   }
10381ad6265SDimitry Andric 
10481ad6265SDimitry Andric   return Out;
10581ad6265SDimitry Andric }
10681ad6265SDimitry Andric 
1070eae32dcSDimitry Andric /// \brief Helper class for computing cycle information.
1080eae32dcSDimitry Andric template <typename ContextT> class GenericCycleInfoCompute {
1090eae32dcSDimitry Andric   using BlockT = typename ContextT::BlockT;
1100eae32dcSDimitry Andric   using CycleInfoT = GenericCycleInfo<ContextT>;
1110eae32dcSDimitry Andric   using CycleT = typename CycleInfoT::CycleT;
1120eae32dcSDimitry Andric 
1130eae32dcSDimitry Andric   CycleInfoT &Info;
1140eae32dcSDimitry Andric 
1150eae32dcSDimitry Andric   struct DFSInfo {
1160eae32dcSDimitry Andric     unsigned Start = 0; // DFS start; positive if block is found
1170eae32dcSDimitry Andric     unsigned End = 0;   // DFS end
1180eae32dcSDimitry Andric 
1191fd87a68SDimitry Andric     DFSInfo() = default;
1200eae32dcSDimitry Andric     explicit DFSInfo(unsigned Start) : Start(Start) {}
1210eae32dcSDimitry Andric 
1220eae32dcSDimitry Andric     /// Whether this node is an ancestor (or equal to) the node \p Other
1230eae32dcSDimitry Andric     /// in the DFS tree.
1240eae32dcSDimitry Andric     bool isAncestorOf(const DFSInfo &Other) const {
1250eae32dcSDimitry Andric       return Start <= Other.Start && Other.End <= End;
1260eae32dcSDimitry Andric     }
1270eae32dcSDimitry Andric   };
1280eae32dcSDimitry Andric 
1290eae32dcSDimitry Andric   DenseMap<BlockT *, DFSInfo> BlockDFSInfo;
1300eae32dcSDimitry Andric   SmallVector<BlockT *, 8> BlockPreorder;
1310eae32dcSDimitry Andric 
1320eae32dcSDimitry Andric   GenericCycleInfoCompute(const GenericCycleInfoCompute &) = delete;
1330eae32dcSDimitry Andric   GenericCycleInfoCompute &operator=(const GenericCycleInfoCompute &) = delete;
1340eae32dcSDimitry Andric 
1350eae32dcSDimitry Andric public:
1360eae32dcSDimitry Andric   GenericCycleInfoCompute(CycleInfoT &Info) : Info(Info) {}
1370eae32dcSDimitry Andric 
1380eae32dcSDimitry Andric   void run(BlockT *EntryBlock);
1390eae32dcSDimitry Andric 
1400eae32dcSDimitry Andric   static void updateDepth(CycleT *SubTree);
1410eae32dcSDimitry Andric 
1420eae32dcSDimitry Andric private:
1430eae32dcSDimitry Andric   void dfs(BlockT *EntryBlock);
1440eae32dcSDimitry Andric };
1450eae32dcSDimitry Andric 
1460eae32dcSDimitry Andric template <typename ContextT>
1476246ae0bSDimitry Andric auto GenericCycleInfo<ContextT>::getTopLevelParentCycle(BlockT *Block)
1486246ae0bSDimitry Andric     -> CycleT * {
1496246ae0bSDimitry Andric   auto Cycle = BlockMapTopLevel.find(Block);
1506246ae0bSDimitry Andric   if (Cycle != BlockMapTopLevel.end())
1516246ae0bSDimitry Andric     return Cycle->second;
1526246ae0bSDimitry Andric 
1530eae32dcSDimitry Andric   auto MapIt = BlockMap.find(Block);
1540eae32dcSDimitry Andric   if (MapIt == BlockMap.end())
1550eae32dcSDimitry Andric     return nullptr;
1560eae32dcSDimitry Andric 
1570eae32dcSDimitry Andric   auto *C = MapIt->second;
1580eae32dcSDimitry Andric   while (C->ParentCycle)
1590eae32dcSDimitry Andric     C = C->ParentCycle;
1606246ae0bSDimitry Andric   BlockMapTopLevel.try_emplace(Block, C);
1610eae32dcSDimitry Andric   return C;
1620eae32dcSDimitry Andric }
1630eae32dcSDimitry Andric 
1640eae32dcSDimitry Andric template <typename ContextT>
1656246ae0bSDimitry Andric void GenericCycleInfo<ContextT>::moveTopLevelCycleToNewParent(CycleT *NewParent,
1660eae32dcSDimitry Andric                                                               CycleT *Child) {
1676246ae0bSDimitry Andric   assert((!Child->ParentCycle && !NewParent->ParentCycle) &&
1686246ae0bSDimitry Andric          "NewParent and Child must be both top level cycle!\n");
1690eae32dcSDimitry Andric   auto &CurrentContainer =
1700eae32dcSDimitry Andric       Child->ParentCycle ? Child->ParentCycle->Children : TopLevelCycles;
1710eae32dcSDimitry Andric   auto Pos = llvm::find_if(CurrentContainer, [=](const auto &Ptr) -> bool {
1720eae32dcSDimitry Andric     return Child == Ptr.get();
1730eae32dcSDimitry Andric   });
1740eae32dcSDimitry Andric   assert(Pos != CurrentContainer.end());
1750eae32dcSDimitry Andric   NewParent->Children.push_back(std::move(*Pos));
1760eae32dcSDimitry Andric   *Pos = std::move(CurrentContainer.back());
1770eae32dcSDimitry Andric   CurrentContainer.pop_back();
1780eae32dcSDimitry Andric   Child->ParentCycle = NewParent;
1796246ae0bSDimitry Andric 
18006c3fb27SDimitry Andric   NewParent->Blocks.insert(Child->block_begin(), Child->block_end());
1816246ae0bSDimitry Andric 
1826246ae0bSDimitry Andric   for (auto &It : BlockMapTopLevel)
1836246ae0bSDimitry Andric     if (It.second == Child)
1846246ae0bSDimitry Andric       It.second = NewParent;
1850eae32dcSDimitry Andric }
1860eae32dcSDimitry Andric 
187*5f757f3fSDimitry Andric template <typename ContextT>
188*5f757f3fSDimitry Andric void GenericCycleInfo<ContextT>::addBlockToCycle(BlockT *Block, CycleT *Cycle) {
189*5f757f3fSDimitry Andric   // FixMe: Appending NewBlock is fine as a set of blocks in a cycle. When
190*5f757f3fSDimitry Andric   // printing, cycle NewBlock is at the end of list but it should be in the
191*5f757f3fSDimitry Andric   // middle to represent actual traversal of a cycle.
192*5f757f3fSDimitry Andric   Cycle->appendBlock(Block);
193*5f757f3fSDimitry Andric   BlockMap.try_emplace(Block, Cycle);
194*5f757f3fSDimitry Andric 
195*5f757f3fSDimitry Andric   CycleT *ParentCycle = Cycle->getParentCycle();
196*5f757f3fSDimitry Andric   while (ParentCycle) {
197*5f757f3fSDimitry Andric     Cycle = ParentCycle;
198*5f757f3fSDimitry Andric     Cycle->appendBlock(Block);
199*5f757f3fSDimitry Andric     ParentCycle = Cycle->getParentCycle();
200*5f757f3fSDimitry Andric   }
201*5f757f3fSDimitry Andric 
202*5f757f3fSDimitry Andric   BlockMapTopLevel.try_emplace(Block, Cycle);
203*5f757f3fSDimitry Andric }
204*5f757f3fSDimitry Andric 
2050eae32dcSDimitry Andric /// \brief Main function of the cycle info computations.
2060eae32dcSDimitry Andric template <typename ContextT>
2070eae32dcSDimitry Andric void GenericCycleInfoCompute<ContextT>::run(BlockT *EntryBlock) {
2080eae32dcSDimitry Andric   LLVM_DEBUG(errs() << "Entry block: " << Info.Context.print(EntryBlock)
2090eae32dcSDimitry Andric                     << "\n");
2100eae32dcSDimitry Andric   dfs(EntryBlock);
2110eae32dcSDimitry Andric 
2120eae32dcSDimitry Andric   SmallVector<BlockT *, 8> Worklist;
2130eae32dcSDimitry Andric 
2140eae32dcSDimitry Andric   for (BlockT *HeaderCandidate : llvm::reverse(BlockPreorder)) {
2150eae32dcSDimitry Andric     const DFSInfo CandidateInfo = BlockDFSInfo.lookup(HeaderCandidate);
2160eae32dcSDimitry Andric 
2170eae32dcSDimitry Andric     for (BlockT *Pred : predecessors(HeaderCandidate)) {
2180eae32dcSDimitry Andric       const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred);
2190eae32dcSDimitry Andric       if (CandidateInfo.isAncestorOf(PredDFSInfo))
2200eae32dcSDimitry Andric         Worklist.push_back(Pred);
2210eae32dcSDimitry Andric     }
2220eae32dcSDimitry Andric     if (Worklist.empty()) {
2230eae32dcSDimitry Andric       continue;
2240eae32dcSDimitry Andric     }
2250eae32dcSDimitry Andric 
2260eae32dcSDimitry Andric     // Found a cycle with the candidate as its header.
2270eae32dcSDimitry Andric     LLVM_DEBUG(errs() << "Found cycle for header: "
2280eae32dcSDimitry Andric                       << Info.Context.print(HeaderCandidate) << "\n");
2290eae32dcSDimitry Andric     std::unique_ptr<CycleT> NewCycle = std::make_unique<CycleT>();
2300eae32dcSDimitry Andric     NewCycle->appendEntry(HeaderCandidate);
2310eae32dcSDimitry Andric     NewCycle->appendBlock(HeaderCandidate);
2320eae32dcSDimitry Andric     Info.BlockMap.try_emplace(HeaderCandidate, NewCycle.get());
2330eae32dcSDimitry Andric 
2340eae32dcSDimitry Andric     // Helper function to process (non-back-edge) predecessors of a discovered
2350eae32dcSDimitry Andric     // block and either add them to the worklist or recognize that the given
2360eae32dcSDimitry Andric     // block is an additional cycle entry.
2370eae32dcSDimitry Andric     auto ProcessPredecessors = [&](BlockT *Block) {
2380eae32dcSDimitry Andric       LLVM_DEBUG(errs() << "  block " << Info.Context.print(Block) << ": ");
2390eae32dcSDimitry Andric 
2400eae32dcSDimitry Andric       bool IsEntry = false;
2410eae32dcSDimitry Andric       for (BlockT *Pred : predecessors(Block)) {
2420eae32dcSDimitry Andric         const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred);
2430eae32dcSDimitry Andric         if (CandidateInfo.isAncestorOf(PredDFSInfo)) {
2440eae32dcSDimitry Andric           Worklist.push_back(Pred);
2450eae32dcSDimitry Andric         } else {
2460eae32dcSDimitry Andric           IsEntry = true;
2470eae32dcSDimitry Andric         }
2480eae32dcSDimitry Andric       }
2490eae32dcSDimitry Andric       if (IsEntry) {
2500eae32dcSDimitry Andric         assert(!NewCycle->isEntry(Block));
2510eae32dcSDimitry Andric         LLVM_DEBUG(errs() << "append as entry\n");
2520eae32dcSDimitry Andric         NewCycle->appendEntry(Block);
2530eae32dcSDimitry Andric       } else {
2540eae32dcSDimitry Andric         LLVM_DEBUG(errs() << "append as child\n");
2550eae32dcSDimitry Andric       }
2560eae32dcSDimitry Andric     };
2570eae32dcSDimitry Andric 
2580eae32dcSDimitry Andric     do {
2590eae32dcSDimitry Andric       BlockT *Block = Worklist.pop_back_val();
2600eae32dcSDimitry Andric       if (Block == HeaderCandidate)
2610eae32dcSDimitry Andric         continue;
2620eae32dcSDimitry Andric 
2630eae32dcSDimitry Andric       // If the block has already been discovered by some cycle
2640eae32dcSDimitry Andric       // (possibly by ourself), then the outermost cycle containing it
2650eae32dcSDimitry Andric       // should become our child.
2660eae32dcSDimitry Andric       if (auto *BlockParent = Info.getTopLevelParentCycle(Block)) {
2670eae32dcSDimitry Andric         LLVM_DEBUG(errs() << "  block " << Info.Context.print(Block) << ": ");
2680eae32dcSDimitry Andric 
2690eae32dcSDimitry Andric         if (BlockParent != NewCycle.get()) {
2700eae32dcSDimitry Andric           LLVM_DEBUG(errs()
2710eae32dcSDimitry Andric                      << "discovered child cycle "
2720eae32dcSDimitry Andric                      << Info.Context.print(BlockParent->getHeader()) << "\n");
2730eae32dcSDimitry Andric           // Make BlockParent the child of NewCycle.
2746246ae0bSDimitry Andric           Info.moveTopLevelCycleToNewParent(NewCycle.get(), BlockParent);
2750eae32dcSDimitry Andric 
2760eae32dcSDimitry Andric           for (auto *ChildEntry : BlockParent->entries())
2770eae32dcSDimitry Andric             ProcessPredecessors(ChildEntry);
2780eae32dcSDimitry Andric         } else {
2790eae32dcSDimitry Andric           LLVM_DEBUG(errs()
2800eae32dcSDimitry Andric                      << "known child cycle "
2810eae32dcSDimitry Andric                      << Info.Context.print(BlockParent->getHeader()) << "\n");
2820eae32dcSDimitry Andric         }
2830eae32dcSDimitry Andric       } else {
2840eae32dcSDimitry Andric         Info.BlockMap.try_emplace(Block, NewCycle.get());
2850eae32dcSDimitry Andric         assert(!is_contained(NewCycle->Blocks, Block));
28606c3fb27SDimitry Andric         NewCycle->Blocks.insert(Block);
2870eae32dcSDimitry Andric         ProcessPredecessors(Block);
2886246ae0bSDimitry Andric         Info.BlockMapTopLevel.try_emplace(Block, NewCycle.get());
2890eae32dcSDimitry Andric       }
2900eae32dcSDimitry Andric     } while (!Worklist.empty());
2910eae32dcSDimitry Andric 
2920eae32dcSDimitry Andric     Info.TopLevelCycles.push_back(std::move(NewCycle));
2930eae32dcSDimitry Andric   }
2940eae32dcSDimitry Andric 
2950eae32dcSDimitry Andric   // Fix top-level cycle links and compute cycle depths.
2960eae32dcSDimitry Andric   for (auto *TLC : Info.toplevel_cycles()) {
2970eae32dcSDimitry Andric     LLVM_DEBUG(errs() << "top-level cycle: "
2980eae32dcSDimitry Andric                       << Info.Context.print(TLC->getHeader()) << "\n");
2990eae32dcSDimitry Andric 
3000eae32dcSDimitry Andric     TLC->ParentCycle = nullptr;
3010eae32dcSDimitry Andric     updateDepth(TLC);
3020eae32dcSDimitry Andric   }
3030eae32dcSDimitry Andric }
3040eae32dcSDimitry Andric 
3050eae32dcSDimitry Andric /// \brief Recompute depth values of \p SubTree and all descendants.
3060eae32dcSDimitry Andric template <typename ContextT>
3070eae32dcSDimitry Andric void GenericCycleInfoCompute<ContextT>::updateDepth(CycleT *SubTree) {
3080eae32dcSDimitry Andric   for (CycleT *Cycle : depth_first(SubTree))
3090eae32dcSDimitry Andric     Cycle->Depth = Cycle->ParentCycle ? Cycle->ParentCycle->Depth + 1 : 1;
3100eae32dcSDimitry Andric }
3110eae32dcSDimitry Andric 
3120eae32dcSDimitry Andric /// \brief Compute a DFS of basic blocks starting at the function entry.
3130eae32dcSDimitry Andric ///
3140eae32dcSDimitry Andric /// Fills BlockDFSInfo with start/end counters and BlockPreorder.
3150eae32dcSDimitry Andric template <typename ContextT>
3160eae32dcSDimitry Andric void GenericCycleInfoCompute<ContextT>::dfs(BlockT *EntryBlock) {
3170eae32dcSDimitry Andric   SmallVector<unsigned, 8> DFSTreeStack;
3180eae32dcSDimitry Andric   SmallVector<BlockT *, 8> TraverseStack;
3190eae32dcSDimitry Andric   unsigned Counter = 0;
3200eae32dcSDimitry Andric   TraverseStack.emplace_back(EntryBlock);
3210eae32dcSDimitry Andric 
3220eae32dcSDimitry Andric   do {
3230eae32dcSDimitry Andric     BlockT *Block = TraverseStack.back();
3240eae32dcSDimitry Andric     LLVM_DEBUG(errs() << "DFS visiting block: " << Info.Context.print(Block)
3250eae32dcSDimitry Andric                       << "\n");
3260eae32dcSDimitry Andric     if (!BlockDFSInfo.count(Block)) {
3270eae32dcSDimitry Andric       // We're visiting the block for the first time. Open its DFSInfo, add
3280eae32dcSDimitry Andric       // successors to the traversal stack, and remember the traversal stack
3290eae32dcSDimitry Andric       // depth at which the block was opened, so that we can correctly record
3300eae32dcSDimitry Andric       // its end time.
3310eae32dcSDimitry Andric       LLVM_DEBUG(errs() << "  first encountered at depth "
3320eae32dcSDimitry Andric                         << TraverseStack.size() << "\n");
3330eae32dcSDimitry Andric 
3340eae32dcSDimitry Andric       DFSTreeStack.emplace_back(TraverseStack.size());
3350eae32dcSDimitry Andric       llvm::append_range(TraverseStack, successors(Block));
3360eae32dcSDimitry Andric 
3370eae32dcSDimitry Andric       bool Added = BlockDFSInfo.try_emplace(Block, ++Counter).second;
33881ad6265SDimitry Andric       (void)Added;
3390eae32dcSDimitry Andric       assert(Added);
3400eae32dcSDimitry Andric       BlockPreorder.push_back(Block);
3410eae32dcSDimitry Andric       LLVM_DEBUG(errs() << "  preorder number: " << Counter << "\n");
3420eae32dcSDimitry Andric     } else {
3430eae32dcSDimitry Andric       assert(!DFSTreeStack.empty());
3440eae32dcSDimitry Andric       if (DFSTreeStack.back() == TraverseStack.size()) {
3450eae32dcSDimitry Andric         LLVM_DEBUG(errs() << "  ended at " << Counter << "\n");
3460eae32dcSDimitry Andric         BlockDFSInfo.find(Block)->second.End = Counter;
3470eae32dcSDimitry Andric         DFSTreeStack.pop_back();
3480eae32dcSDimitry Andric       } else {
3490eae32dcSDimitry Andric         LLVM_DEBUG(errs() << "  already done\n");
3500eae32dcSDimitry Andric       }
3510eae32dcSDimitry Andric       TraverseStack.pop_back();
3520eae32dcSDimitry Andric     }
3530eae32dcSDimitry Andric   } while (!TraverseStack.empty());
3540eae32dcSDimitry Andric   assert(DFSTreeStack.empty());
3550eae32dcSDimitry Andric 
3560eae32dcSDimitry Andric   LLVM_DEBUG(
3570eae32dcSDimitry Andric     errs() << "Preorder:\n";
3580eae32dcSDimitry Andric     for (int i = 0, e = BlockPreorder.size(); i != e; ++i) {
3590eae32dcSDimitry Andric       errs() << "  " << Info.Context.print(BlockPreorder[i]) << ": " << i << "\n";
3600eae32dcSDimitry Andric     }
3610eae32dcSDimitry Andric   );
3620eae32dcSDimitry Andric }
3630eae32dcSDimitry Andric 
3640eae32dcSDimitry Andric /// \brief Reset the object to its initial state.
3650eae32dcSDimitry Andric template <typename ContextT> void GenericCycleInfo<ContextT>::clear() {
3660eae32dcSDimitry Andric   TopLevelCycles.clear();
3670eae32dcSDimitry Andric   BlockMap.clear();
3686246ae0bSDimitry Andric   BlockMapTopLevel.clear();
3690eae32dcSDimitry Andric }
3700eae32dcSDimitry Andric 
3710eae32dcSDimitry Andric /// \brief Compute the cycle info for a function.
3720eae32dcSDimitry Andric template <typename ContextT>
3730eae32dcSDimitry Andric void GenericCycleInfo<ContextT>::compute(FunctionT &F) {
3740eae32dcSDimitry Andric   GenericCycleInfoCompute<ContextT> Compute(*this);
375*5f757f3fSDimitry Andric   Context = ContextT(&F);
3760eae32dcSDimitry Andric 
3770eae32dcSDimitry Andric   LLVM_DEBUG(errs() << "Computing cycles for function: " << F.getName()
3780eae32dcSDimitry Andric                     << "\n");
379*5f757f3fSDimitry Andric   Compute.run(&F.front());
3800eae32dcSDimitry Andric 
3810eae32dcSDimitry Andric   assert(validateTree());
3820eae32dcSDimitry Andric }
3830eae32dcSDimitry Andric 
384*5f757f3fSDimitry Andric template <typename ContextT>
385*5f757f3fSDimitry Andric void GenericCycleInfo<ContextT>::splitCriticalEdge(BlockT *Pred, BlockT *Succ,
386*5f757f3fSDimitry Andric                                                    BlockT *NewBlock) {
387*5f757f3fSDimitry Andric   // Edge Pred-Succ is replaced by edges Pred-NewBlock and NewBlock-Succ, all
388*5f757f3fSDimitry Andric   // cycles that had blocks Pred and Succ also get NewBlock.
389*5f757f3fSDimitry Andric   CycleT *Cycle = getSmallestCommonCycle(getCycle(Pred), getCycle(Succ));
390*5f757f3fSDimitry Andric   if (!Cycle)
391*5f757f3fSDimitry Andric     return;
392*5f757f3fSDimitry Andric 
393*5f757f3fSDimitry Andric   addBlockToCycle(NewBlock, Cycle);
394*5f757f3fSDimitry Andric   assert(validateTree());
395*5f757f3fSDimitry Andric }
396*5f757f3fSDimitry Andric 
3970eae32dcSDimitry Andric /// \brief Find the innermost cycle containing a given block.
3980eae32dcSDimitry Andric ///
3990eae32dcSDimitry Andric /// \returns the innermost cycle containing \p Block or nullptr if
4000eae32dcSDimitry Andric ///          it is not contained in any cycle.
4010eae32dcSDimitry Andric template <typename ContextT>
4020eae32dcSDimitry Andric auto GenericCycleInfo<ContextT>::getCycle(const BlockT *Block) const
4030eae32dcSDimitry Andric     -> CycleT * {
404*5f757f3fSDimitry Andric   return BlockMap.lookup(Block);
405*5f757f3fSDimitry Andric }
406*5f757f3fSDimitry Andric 
407*5f757f3fSDimitry Andric /// \brief Find the innermost cycle containing both given cycles.
408*5f757f3fSDimitry Andric ///
409*5f757f3fSDimitry Andric /// \returns the innermost cycle containing both \p A and \p B
410*5f757f3fSDimitry Andric ///          or nullptr if there is no such cycle.
411*5f757f3fSDimitry Andric template <typename ContextT>
412*5f757f3fSDimitry Andric auto GenericCycleInfo<ContextT>::getSmallestCommonCycle(CycleT *A,
413*5f757f3fSDimitry Andric                                                         CycleT *B) const
414*5f757f3fSDimitry Andric     -> CycleT * {
415*5f757f3fSDimitry Andric   if (!A || !B)
4160eae32dcSDimitry Andric     return nullptr;
417*5f757f3fSDimitry Andric 
418*5f757f3fSDimitry Andric   // If cycles A and B have different depth replace them with parent cycle
419*5f757f3fSDimitry Andric   // until they have the same depth.
420*5f757f3fSDimitry Andric   while (A->getDepth() > B->getDepth())
421*5f757f3fSDimitry Andric     A = A->getParentCycle();
422*5f757f3fSDimitry Andric   while (B->getDepth() > A->getDepth())
423*5f757f3fSDimitry Andric     B = B->getParentCycle();
424*5f757f3fSDimitry Andric 
425*5f757f3fSDimitry Andric   // Cycles A and B are at same depth but may be disjoint, replace them with
426*5f757f3fSDimitry Andric   // parent cycles until we find cycle that contains both or we run out of
427*5f757f3fSDimitry Andric   // parent cycles.
428*5f757f3fSDimitry Andric   while (A != B) {
429*5f757f3fSDimitry Andric     A = A->getParentCycle();
430*5f757f3fSDimitry Andric     B = B->getParentCycle();
431*5f757f3fSDimitry Andric   }
432*5f757f3fSDimitry Andric 
433*5f757f3fSDimitry Andric   return A;
4340eae32dcSDimitry Andric }
4350eae32dcSDimitry Andric 
43681ad6265SDimitry Andric /// \brief get the depth for the cycle which containing a given block.
43781ad6265SDimitry Andric ///
43881ad6265SDimitry Andric /// \returns the depth for the innermost cycle containing \p Block or 0 if it is
43981ad6265SDimitry Andric ///          not contained in any cycle.
44081ad6265SDimitry Andric template <typename ContextT>
44181ad6265SDimitry Andric unsigned GenericCycleInfo<ContextT>::getCycleDepth(const BlockT *Block) const {
44281ad6265SDimitry Andric   CycleT *Cycle = getCycle(Block);
44381ad6265SDimitry Andric   if (!Cycle)
44481ad6265SDimitry Andric     return 0;
44581ad6265SDimitry Andric   return Cycle->getDepth();
44681ad6265SDimitry Andric }
44781ad6265SDimitry Andric 
44881ad6265SDimitry Andric #ifndef NDEBUG
4490eae32dcSDimitry Andric /// \brief Validate the internal consistency of the cycle tree.
4500eae32dcSDimitry Andric ///
4510eae32dcSDimitry Andric /// Note that this does \em not check that cycles are really cycles in the CFG,
4520eae32dcSDimitry Andric /// or that the right set of cycles in the CFG were found.
4530eae32dcSDimitry Andric template <typename ContextT>
4540eae32dcSDimitry Andric bool GenericCycleInfo<ContextT>::validateTree() const {
4550eae32dcSDimitry Andric   DenseSet<BlockT *> Blocks;
4560eae32dcSDimitry Andric   DenseSet<BlockT *> Entries;
4570eae32dcSDimitry Andric 
4580eae32dcSDimitry Andric   auto reportError = [](const char *File, int Line, const char *Cond) {
4590eae32dcSDimitry Andric     errs() << File << ':' << Line
4600eae32dcSDimitry Andric            << ": GenericCycleInfo::validateTree: " << Cond << '\n';
4610eae32dcSDimitry Andric   };
4620eae32dcSDimitry Andric #define check(cond)                                                            \
4630eae32dcSDimitry Andric   do {                                                                         \
4640eae32dcSDimitry Andric     if (!(cond)) {                                                             \
4650eae32dcSDimitry Andric       reportError(__FILE__, __LINE__, #cond);                                  \
4660eae32dcSDimitry Andric       return false;                                                            \
4670eae32dcSDimitry Andric     }                                                                          \
4680eae32dcSDimitry Andric   } while (false)
4690eae32dcSDimitry Andric 
4700eae32dcSDimitry Andric   for (const auto *TLC : toplevel_cycles()) {
4710eae32dcSDimitry Andric     for (const CycleT *Cycle : depth_first(TLC)) {
4720eae32dcSDimitry Andric       if (Cycle->ParentCycle)
4730eae32dcSDimitry Andric         check(is_contained(Cycle->ParentCycle->children(), Cycle));
4740eae32dcSDimitry Andric 
4750eae32dcSDimitry Andric       for (BlockT *Block : Cycle->Blocks) {
4760eae32dcSDimitry Andric         auto MapIt = BlockMap.find(Block);
4770eae32dcSDimitry Andric         check(MapIt != BlockMap.end());
4780eae32dcSDimitry Andric         check(Cycle->contains(MapIt->second));
4790eae32dcSDimitry Andric         check(Blocks.insert(Block).second); // duplicates in block list?
4800eae32dcSDimitry Andric       }
4810eae32dcSDimitry Andric       Blocks.clear();
4820eae32dcSDimitry Andric 
4830eae32dcSDimitry Andric       check(!Cycle->Entries.empty());
4840eae32dcSDimitry Andric       for (BlockT *Entry : Cycle->Entries) {
4850eae32dcSDimitry Andric         check(Entries.insert(Entry).second); // duplicate entry?
4860eae32dcSDimitry Andric         check(is_contained(Cycle->Blocks, Entry));
4870eae32dcSDimitry Andric       }
4880eae32dcSDimitry Andric       Entries.clear();
4890eae32dcSDimitry Andric 
4900eae32dcSDimitry Andric       unsigned ChildDepth = 0;
4910eae32dcSDimitry Andric       for (const CycleT *Child : Cycle->children()) {
4920eae32dcSDimitry Andric         check(Child->Depth > Cycle->Depth);
4930eae32dcSDimitry Andric         if (!ChildDepth) {
4940eae32dcSDimitry Andric           ChildDepth = Child->Depth;
4950eae32dcSDimitry Andric         } else {
4960eae32dcSDimitry Andric           check(ChildDepth == Child->Depth);
4970eae32dcSDimitry Andric         }
4980eae32dcSDimitry Andric       }
4990eae32dcSDimitry Andric     }
5000eae32dcSDimitry Andric   }
5010eae32dcSDimitry Andric 
5020eae32dcSDimitry Andric   for (const auto &Entry : BlockMap) {
5030eae32dcSDimitry Andric     BlockT *Block = Entry.first;
5040eae32dcSDimitry Andric     for (const CycleT *Cycle = Entry.second; Cycle;
5050eae32dcSDimitry Andric          Cycle = Cycle->ParentCycle) {
5060eae32dcSDimitry Andric       check(is_contained(Cycle->Blocks, Block));
5070eae32dcSDimitry Andric     }
5080eae32dcSDimitry Andric   }
5090eae32dcSDimitry Andric 
5100eae32dcSDimitry Andric #undef check
5110eae32dcSDimitry Andric 
5120eae32dcSDimitry Andric   return true;
5130eae32dcSDimitry Andric }
51481ad6265SDimitry Andric #endif
5150eae32dcSDimitry Andric 
5160eae32dcSDimitry Andric /// \brief Print the cycle info.
5170eae32dcSDimitry Andric template <typename ContextT>
5180eae32dcSDimitry Andric void GenericCycleInfo<ContextT>::print(raw_ostream &Out) const {
5190eae32dcSDimitry Andric   for (const auto *TLC : toplevel_cycles()) {
5200eae32dcSDimitry Andric     for (const CycleT *Cycle : depth_first(TLC)) {
5210eae32dcSDimitry Andric       for (unsigned I = 0; I < Cycle->Depth; ++I)
5220eae32dcSDimitry Andric         Out << "    ";
5230eae32dcSDimitry Andric 
5240eae32dcSDimitry Andric       Out << Cycle->print(Context) << '\n';
5250eae32dcSDimitry Andric     }
5260eae32dcSDimitry Andric   }
5270eae32dcSDimitry Andric }
5280eae32dcSDimitry Andric 
5290eae32dcSDimitry Andric } // namespace llvm
5300eae32dcSDimitry Andric 
5310eae32dcSDimitry Andric #undef DEBUG_TYPE
5320eae32dcSDimitry Andric 
5330eae32dcSDimitry Andric #endif // LLVM_ADT_GENERICCYCLEIMPL_H
534