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