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