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