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: 18*06c3fb27SDimitry Andric /// - llvm/lib/IR/CycleInfo.cpp 19*06c3fb27SDimitry 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 180*06c3fb27SDimitry 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 1870eae32dcSDimitry Andric /// \brief Main function of the cycle info computations. 1880eae32dcSDimitry Andric template <typename ContextT> 1890eae32dcSDimitry Andric void GenericCycleInfoCompute<ContextT>::run(BlockT *EntryBlock) { 1900eae32dcSDimitry Andric LLVM_DEBUG(errs() << "Entry block: " << Info.Context.print(EntryBlock) 1910eae32dcSDimitry Andric << "\n"); 1920eae32dcSDimitry Andric dfs(EntryBlock); 1930eae32dcSDimitry Andric 1940eae32dcSDimitry Andric SmallVector<BlockT *, 8> Worklist; 1950eae32dcSDimitry Andric 1960eae32dcSDimitry Andric for (BlockT *HeaderCandidate : llvm::reverse(BlockPreorder)) { 1970eae32dcSDimitry Andric const DFSInfo CandidateInfo = BlockDFSInfo.lookup(HeaderCandidate); 1980eae32dcSDimitry Andric 1990eae32dcSDimitry Andric for (BlockT *Pred : predecessors(HeaderCandidate)) { 2000eae32dcSDimitry Andric const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred); 2010eae32dcSDimitry Andric if (CandidateInfo.isAncestorOf(PredDFSInfo)) 2020eae32dcSDimitry Andric Worklist.push_back(Pred); 2030eae32dcSDimitry Andric } 2040eae32dcSDimitry Andric if (Worklist.empty()) { 2050eae32dcSDimitry Andric continue; 2060eae32dcSDimitry Andric } 2070eae32dcSDimitry Andric 2080eae32dcSDimitry Andric // Found a cycle with the candidate as its header. 2090eae32dcSDimitry Andric LLVM_DEBUG(errs() << "Found cycle for header: " 2100eae32dcSDimitry Andric << Info.Context.print(HeaderCandidate) << "\n"); 2110eae32dcSDimitry Andric std::unique_ptr<CycleT> NewCycle = std::make_unique<CycleT>(); 2120eae32dcSDimitry Andric NewCycle->appendEntry(HeaderCandidate); 2130eae32dcSDimitry Andric NewCycle->appendBlock(HeaderCandidate); 2140eae32dcSDimitry Andric Info.BlockMap.try_emplace(HeaderCandidate, NewCycle.get()); 2150eae32dcSDimitry Andric 2160eae32dcSDimitry Andric // Helper function to process (non-back-edge) predecessors of a discovered 2170eae32dcSDimitry Andric // block and either add them to the worklist or recognize that the given 2180eae32dcSDimitry Andric // block is an additional cycle entry. 2190eae32dcSDimitry Andric auto ProcessPredecessors = [&](BlockT *Block) { 2200eae32dcSDimitry Andric LLVM_DEBUG(errs() << " block " << Info.Context.print(Block) << ": "); 2210eae32dcSDimitry Andric 2220eae32dcSDimitry Andric bool IsEntry = false; 2230eae32dcSDimitry Andric for (BlockT *Pred : predecessors(Block)) { 2240eae32dcSDimitry Andric const DFSInfo PredDFSInfo = BlockDFSInfo.lookup(Pred); 2250eae32dcSDimitry Andric if (CandidateInfo.isAncestorOf(PredDFSInfo)) { 2260eae32dcSDimitry Andric Worklist.push_back(Pred); 2270eae32dcSDimitry Andric } else { 2280eae32dcSDimitry Andric IsEntry = true; 2290eae32dcSDimitry Andric } 2300eae32dcSDimitry Andric } 2310eae32dcSDimitry Andric if (IsEntry) { 2320eae32dcSDimitry Andric assert(!NewCycle->isEntry(Block)); 2330eae32dcSDimitry Andric LLVM_DEBUG(errs() << "append as entry\n"); 2340eae32dcSDimitry Andric NewCycle->appendEntry(Block); 2350eae32dcSDimitry Andric } else { 2360eae32dcSDimitry Andric LLVM_DEBUG(errs() << "append as child\n"); 2370eae32dcSDimitry Andric } 2380eae32dcSDimitry Andric }; 2390eae32dcSDimitry Andric 2400eae32dcSDimitry Andric do { 2410eae32dcSDimitry Andric BlockT *Block = Worklist.pop_back_val(); 2420eae32dcSDimitry Andric if (Block == HeaderCandidate) 2430eae32dcSDimitry Andric continue; 2440eae32dcSDimitry Andric 2450eae32dcSDimitry Andric // If the block has already been discovered by some cycle 2460eae32dcSDimitry Andric // (possibly by ourself), then the outermost cycle containing it 2470eae32dcSDimitry Andric // should become our child. 2480eae32dcSDimitry Andric if (auto *BlockParent = Info.getTopLevelParentCycle(Block)) { 2490eae32dcSDimitry Andric LLVM_DEBUG(errs() << " block " << Info.Context.print(Block) << ": "); 2500eae32dcSDimitry Andric 2510eae32dcSDimitry Andric if (BlockParent != NewCycle.get()) { 2520eae32dcSDimitry Andric LLVM_DEBUG(errs() 2530eae32dcSDimitry Andric << "discovered child cycle " 2540eae32dcSDimitry Andric << Info.Context.print(BlockParent->getHeader()) << "\n"); 2550eae32dcSDimitry Andric // Make BlockParent the child of NewCycle. 2566246ae0bSDimitry Andric Info.moveTopLevelCycleToNewParent(NewCycle.get(), BlockParent); 2570eae32dcSDimitry Andric 2580eae32dcSDimitry Andric for (auto *ChildEntry : BlockParent->entries()) 2590eae32dcSDimitry Andric ProcessPredecessors(ChildEntry); 2600eae32dcSDimitry Andric } else { 2610eae32dcSDimitry Andric LLVM_DEBUG(errs() 2620eae32dcSDimitry Andric << "known child cycle " 2630eae32dcSDimitry Andric << Info.Context.print(BlockParent->getHeader()) << "\n"); 2640eae32dcSDimitry Andric } 2650eae32dcSDimitry Andric } else { 2660eae32dcSDimitry Andric Info.BlockMap.try_emplace(Block, NewCycle.get()); 2670eae32dcSDimitry Andric assert(!is_contained(NewCycle->Blocks, Block)); 268*06c3fb27SDimitry Andric NewCycle->Blocks.insert(Block); 2690eae32dcSDimitry Andric ProcessPredecessors(Block); 2706246ae0bSDimitry Andric Info.BlockMapTopLevel.try_emplace(Block, NewCycle.get()); 2710eae32dcSDimitry Andric } 2720eae32dcSDimitry Andric } while (!Worklist.empty()); 2730eae32dcSDimitry Andric 2740eae32dcSDimitry Andric Info.TopLevelCycles.push_back(std::move(NewCycle)); 2750eae32dcSDimitry Andric } 2760eae32dcSDimitry Andric 2770eae32dcSDimitry Andric // Fix top-level cycle links and compute cycle depths. 2780eae32dcSDimitry Andric for (auto *TLC : Info.toplevel_cycles()) { 2790eae32dcSDimitry Andric LLVM_DEBUG(errs() << "top-level cycle: " 2800eae32dcSDimitry Andric << Info.Context.print(TLC->getHeader()) << "\n"); 2810eae32dcSDimitry Andric 2820eae32dcSDimitry Andric TLC->ParentCycle = nullptr; 2830eae32dcSDimitry Andric updateDepth(TLC); 2840eae32dcSDimitry Andric } 2850eae32dcSDimitry Andric } 2860eae32dcSDimitry Andric 2870eae32dcSDimitry Andric /// \brief Recompute depth values of \p SubTree and all descendants. 2880eae32dcSDimitry Andric template <typename ContextT> 2890eae32dcSDimitry Andric void GenericCycleInfoCompute<ContextT>::updateDepth(CycleT *SubTree) { 2900eae32dcSDimitry Andric for (CycleT *Cycle : depth_first(SubTree)) 2910eae32dcSDimitry Andric Cycle->Depth = Cycle->ParentCycle ? Cycle->ParentCycle->Depth + 1 : 1; 2920eae32dcSDimitry Andric } 2930eae32dcSDimitry Andric 2940eae32dcSDimitry Andric /// \brief Compute a DFS of basic blocks starting at the function entry. 2950eae32dcSDimitry Andric /// 2960eae32dcSDimitry Andric /// Fills BlockDFSInfo with start/end counters and BlockPreorder. 2970eae32dcSDimitry Andric template <typename ContextT> 2980eae32dcSDimitry Andric void GenericCycleInfoCompute<ContextT>::dfs(BlockT *EntryBlock) { 2990eae32dcSDimitry Andric SmallVector<unsigned, 8> DFSTreeStack; 3000eae32dcSDimitry Andric SmallVector<BlockT *, 8> TraverseStack; 3010eae32dcSDimitry Andric unsigned Counter = 0; 3020eae32dcSDimitry Andric TraverseStack.emplace_back(EntryBlock); 3030eae32dcSDimitry Andric 3040eae32dcSDimitry Andric do { 3050eae32dcSDimitry Andric BlockT *Block = TraverseStack.back(); 3060eae32dcSDimitry Andric LLVM_DEBUG(errs() << "DFS visiting block: " << Info.Context.print(Block) 3070eae32dcSDimitry Andric << "\n"); 3080eae32dcSDimitry Andric if (!BlockDFSInfo.count(Block)) { 3090eae32dcSDimitry Andric // We're visiting the block for the first time. Open its DFSInfo, add 3100eae32dcSDimitry Andric // successors to the traversal stack, and remember the traversal stack 3110eae32dcSDimitry Andric // depth at which the block was opened, so that we can correctly record 3120eae32dcSDimitry Andric // its end time. 3130eae32dcSDimitry Andric LLVM_DEBUG(errs() << " first encountered at depth " 3140eae32dcSDimitry Andric << TraverseStack.size() << "\n"); 3150eae32dcSDimitry Andric 3160eae32dcSDimitry Andric DFSTreeStack.emplace_back(TraverseStack.size()); 3170eae32dcSDimitry Andric llvm::append_range(TraverseStack, successors(Block)); 3180eae32dcSDimitry Andric 3190eae32dcSDimitry Andric bool Added = BlockDFSInfo.try_emplace(Block, ++Counter).second; 32081ad6265SDimitry Andric (void)Added; 3210eae32dcSDimitry Andric assert(Added); 3220eae32dcSDimitry Andric BlockPreorder.push_back(Block); 3230eae32dcSDimitry Andric LLVM_DEBUG(errs() << " preorder number: " << Counter << "\n"); 3240eae32dcSDimitry Andric } else { 3250eae32dcSDimitry Andric assert(!DFSTreeStack.empty()); 3260eae32dcSDimitry Andric if (DFSTreeStack.back() == TraverseStack.size()) { 3270eae32dcSDimitry Andric LLVM_DEBUG(errs() << " ended at " << Counter << "\n"); 3280eae32dcSDimitry Andric BlockDFSInfo.find(Block)->second.End = Counter; 3290eae32dcSDimitry Andric DFSTreeStack.pop_back(); 3300eae32dcSDimitry Andric } else { 3310eae32dcSDimitry Andric LLVM_DEBUG(errs() << " already done\n"); 3320eae32dcSDimitry Andric } 3330eae32dcSDimitry Andric TraverseStack.pop_back(); 3340eae32dcSDimitry Andric } 3350eae32dcSDimitry Andric } while (!TraverseStack.empty()); 3360eae32dcSDimitry Andric assert(DFSTreeStack.empty()); 3370eae32dcSDimitry Andric 3380eae32dcSDimitry Andric LLVM_DEBUG( 3390eae32dcSDimitry Andric errs() << "Preorder:\n"; 3400eae32dcSDimitry Andric for (int i = 0, e = BlockPreorder.size(); i != e; ++i) { 3410eae32dcSDimitry Andric errs() << " " << Info.Context.print(BlockPreorder[i]) << ": " << i << "\n"; 3420eae32dcSDimitry Andric } 3430eae32dcSDimitry Andric ); 3440eae32dcSDimitry Andric } 3450eae32dcSDimitry Andric 3460eae32dcSDimitry Andric /// \brief Reset the object to its initial state. 3470eae32dcSDimitry Andric template <typename ContextT> void GenericCycleInfo<ContextT>::clear() { 3480eae32dcSDimitry Andric TopLevelCycles.clear(); 3490eae32dcSDimitry Andric BlockMap.clear(); 3506246ae0bSDimitry Andric BlockMapTopLevel.clear(); 3510eae32dcSDimitry Andric } 3520eae32dcSDimitry Andric 3530eae32dcSDimitry Andric /// \brief Compute the cycle info for a function. 3540eae32dcSDimitry Andric template <typename ContextT> 3550eae32dcSDimitry Andric void GenericCycleInfo<ContextT>::compute(FunctionT &F) { 3560eae32dcSDimitry Andric GenericCycleInfoCompute<ContextT> Compute(*this); 3570eae32dcSDimitry Andric Context.setFunction(F); 3580eae32dcSDimitry Andric 3590eae32dcSDimitry Andric LLVM_DEBUG(errs() << "Computing cycles for function: " << F.getName() 3600eae32dcSDimitry Andric << "\n"); 3610eae32dcSDimitry Andric Compute.run(ContextT::getEntryBlock(F)); 3620eae32dcSDimitry Andric 3630eae32dcSDimitry Andric assert(validateTree()); 3640eae32dcSDimitry Andric } 3650eae32dcSDimitry Andric 3660eae32dcSDimitry Andric /// \brief Find the innermost cycle containing a given block. 3670eae32dcSDimitry Andric /// 3680eae32dcSDimitry Andric /// \returns the innermost cycle containing \p Block or nullptr if 3690eae32dcSDimitry Andric /// it is not contained in any cycle. 3700eae32dcSDimitry Andric template <typename ContextT> 3710eae32dcSDimitry Andric auto GenericCycleInfo<ContextT>::getCycle(const BlockT *Block) const 3720eae32dcSDimitry Andric -> CycleT * { 3730eae32dcSDimitry Andric auto MapIt = BlockMap.find(Block); 3740eae32dcSDimitry Andric if (MapIt != BlockMap.end()) 3750eae32dcSDimitry Andric return MapIt->second; 3760eae32dcSDimitry Andric return nullptr; 3770eae32dcSDimitry Andric } 3780eae32dcSDimitry Andric 37981ad6265SDimitry Andric /// \brief get the depth for the cycle which containing a given block. 38081ad6265SDimitry Andric /// 38181ad6265SDimitry Andric /// \returns the depth for the innermost cycle containing \p Block or 0 if it is 38281ad6265SDimitry Andric /// not contained in any cycle. 38381ad6265SDimitry Andric template <typename ContextT> 38481ad6265SDimitry Andric unsigned GenericCycleInfo<ContextT>::getCycleDepth(const BlockT *Block) const { 38581ad6265SDimitry Andric CycleT *Cycle = getCycle(Block); 38681ad6265SDimitry Andric if (!Cycle) 38781ad6265SDimitry Andric return 0; 38881ad6265SDimitry Andric return Cycle->getDepth(); 38981ad6265SDimitry Andric } 39081ad6265SDimitry Andric 39181ad6265SDimitry Andric #ifndef NDEBUG 3920eae32dcSDimitry Andric /// \brief Validate the internal consistency of the cycle tree. 3930eae32dcSDimitry Andric /// 3940eae32dcSDimitry Andric /// Note that this does \em not check that cycles are really cycles in the CFG, 3950eae32dcSDimitry Andric /// or that the right set of cycles in the CFG were found. 3960eae32dcSDimitry Andric template <typename ContextT> 3970eae32dcSDimitry Andric bool GenericCycleInfo<ContextT>::validateTree() const { 3980eae32dcSDimitry Andric DenseSet<BlockT *> Blocks; 3990eae32dcSDimitry Andric DenseSet<BlockT *> Entries; 4000eae32dcSDimitry Andric 4010eae32dcSDimitry Andric auto reportError = [](const char *File, int Line, const char *Cond) { 4020eae32dcSDimitry Andric errs() << File << ':' << Line 4030eae32dcSDimitry Andric << ": GenericCycleInfo::validateTree: " << Cond << '\n'; 4040eae32dcSDimitry Andric }; 4050eae32dcSDimitry Andric #define check(cond) \ 4060eae32dcSDimitry Andric do { \ 4070eae32dcSDimitry Andric if (!(cond)) { \ 4080eae32dcSDimitry Andric reportError(__FILE__, __LINE__, #cond); \ 4090eae32dcSDimitry Andric return false; \ 4100eae32dcSDimitry Andric } \ 4110eae32dcSDimitry Andric } while (false) 4120eae32dcSDimitry Andric 4130eae32dcSDimitry Andric for (const auto *TLC : toplevel_cycles()) { 4140eae32dcSDimitry Andric for (const CycleT *Cycle : depth_first(TLC)) { 4150eae32dcSDimitry Andric if (Cycle->ParentCycle) 4160eae32dcSDimitry Andric check(is_contained(Cycle->ParentCycle->children(), Cycle)); 4170eae32dcSDimitry Andric 4180eae32dcSDimitry Andric for (BlockT *Block : Cycle->Blocks) { 4190eae32dcSDimitry Andric auto MapIt = BlockMap.find(Block); 4200eae32dcSDimitry Andric check(MapIt != BlockMap.end()); 4210eae32dcSDimitry Andric check(Cycle->contains(MapIt->second)); 4220eae32dcSDimitry Andric check(Blocks.insert(Block).second); // duplicates in block list? 4230eae32dcSDimitry Andric } 4240eae32dcSDimitry Andric Blocks.clear(); 4250eae32dcSDimitry Andric 4260eae32dcSDimitry Andric check(!Cycle->Entries.empty()); 4270eae32dcSDimitry Andric for (BlockT *Entry : Cycle->Entries) { 4280eae32dcSDimitry Andric check(Entries.insert(Entry).second); // duplicate entry? 4290eae32dcSDimitry Andric check(is_contained(Cycle->Blocks, Entry)); 4300eae32dcSDimitry Andric } 4310eae32dcSDimitry Andric Entries.clear(); 4320eae32dcSDimitry Andric 4330eae32dcSDimitry Andric unsigned ChildDepth = 0; 4340eae32dcSDimitry Andric for (const CycleT *Child : Cycle->children()) { 4350eae32dcSDimitry Andric check(Child->Depth > Cycle->Depth); 4360eae32dcSDimitry Andric if (!ChildDepth) { 4370eae32dcSDimitry Andric ChildDepth = Child->Depth; 4380eae32dcSDimitry Andric } else { 4390eae32dcSDimitry Andric check(ChildDepth == Child->Depth); 4400eae32dcSDimitry Andric } 4410eae32dcSDimitry Andric } 4420eae32dcSDimitry Andric } 4430eae32dcSDimitry Andric } 4440eae32dcSDimitry Andric 4450eae32dcSDimitry Andric for (const auto &Entry : BlockMap) { 4460eae32dcSDimitry Andric BlockT *Block = Entry.first; 4470eae32dcSDimitry Andric for (const CycleT *Cycle = Entry.second; Cycle; 4480eae32dcSDimitry Andric Cycle = Cycle->ParentCycle) { 4490eae32dcSDimitry Andric check(is_contained(Cycle->Blocks, Block)); 4500eae32dcSDimitry Andric } 4510eae32dcSDimitry Andric } 4520eae32dcSDimitry Andric 4530eae32dcSDimitry Andric #undef check 4540eae32dcSDimitry Andric 4550eae32dcSDimitry Andric return true; 4560eae32dcSDimitry Andric } 45781ad6265SDimitry Andric #endif 4580eae32dcSDimitry Andric 4590eae32dcSDimitry Andric /// \brief Print the cycle info. 4600eae32dcSDimitry Andric template <typename ContextT> 4610eae32dcSDimitry Andric void GenericCycleInfo<ContextT>::print(raw_ostream &Out) const { 4620eae32dcSDimitry Andric for (const auto *TLC : toplevel_cycles()) { 4630eae32dcSDimitry Andric for (const CycleT *Cycle : depth_first(TLC)) { 4640eae32dcSDimitry Andric for (unsigned I = 0; I < Cycle->Depth; ++I) 4650eae32dcSDimitry Andric Out << " "; 4660eae32dcSDimitry Andric 4670eae32dcSDimitry Andric Out << Cycle->print(Context) << '\n'; 4680eae32dcSDimitry Andric } 4690eae32dcSDimitry Andric } 4700eae32dcSDimitry Andric } 4710eae32dcSDimitry Andric 4720eae32dcSDimitry Andric } // namespace llvm 4730eae32dcSDimitry Andric 4740eae32dcSDimitry Andric #undef DEBUG_TYPE 4750eae32dcSDimitry Andric 4760eae32dcSDimitry Andric #endif // LLVM_ADT_GENERICCYCLEIMPL_H 477