//===--- LoopInfo.h - SIL Loop Analysis -------------------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef SWIFT_SIL_LOOPINFO_H #define SWIFT_SIL_LOOPINFO_H #include "swift/SIL/CFG.h" #include "swift/SIL/SILBasicBlock.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/ADT/iterator_range.h" namespace swift { class DominanceInfo; class SILLoop; class SILPassManager; } // Implementation in LoopInfoImpl.h #ifdef __GNUC__ __extension__ extern template class llvm::LoopBase; __extension__ extern template class llvm::LoopInfoBase; #endif namespace swift { class SILLoop; /// Information about a single natural loop. class SILLoop : public llvm::LoopBase { public: SILLoop() {} void dump() const; iterator_range getSubLoopRange() const { return make_range(begin(), end()); } void getExitingAndLatchBlocks( SmallVectorImpl &ExitingAndLatchBlocks) const { this->getExitingBlocks(ExitingAndLatchBlocks); SILBasicBlock *header = getHeader(); for (auto *predBB : header->getPredecessorBlocks()) { if (contains(predBB) && !this->isLoopExiting(predBB)) ExitingAndLatchBlocks.push_back(predBB); } } SILFunction *getFunction() const { return getHeader()->getParent(); } private: friend class llvm::LoopInfoBase; explicit SILLoop(SILBasicBlock *BB) : llvm::LoopBase(BB) {} }; /// Information about loops in a function. class SILLoopInfo { friend class llvm::LoopBase; using SILLoopInfoBase = llvm::LoopInfoBase; SILLoopInfoBase LI; DominanceInfo *Dominance; void operator=(const SILLoopInfo &) = delete; SILLoopInfo(const SILLoopInfo &) = delete; public: SILLoopInfo(SILFunction *F, DominanceInfo *DT); SILLoopInfoBase &getBase() { return LI; } /// Verify loop information. This is very expensive. void verify() const; /// The iterator interface to the top-level loops in the current /// function. using iterator = SILLoopInfoBase::iterator; iterator begin() const { return LI.begin(); } iterator end() const { return LI.end(); } bool empty() const { return LI.empty(); } iterator_range getTopLevelLoops() const { return make_range(begin(), end()); } /// Return the inner most loop that BB lives in. If a basic block is in no /// loop (for example the entry node), null is returned. SILLoop *getLoopFor(const SILBasicBlock *BB) const { return LI.getLoopFor(BB); } /// Return the inner most loop that BB lives in. If a basic block is in no /// loop (for example the entry node), null is returned. const SILLoop *operator[](const SILBasicBlock *BB) const { return LI.getLoopFor(BB); } /// Return the loop nesting level of the specified block. unsigned getLoopDepth(const SILBasicBlock *BB) const { return LI.getLoopDepth(BB); } /// True if the block is a loop header node. bool isLoopHeader(SILBasicBlock *BB) const { return LI.isLoopHeader(BB); } /// This removes the specified top-level loop from this loop info object. The /// loop is not deleted, as it will presumably be inserted into another loop. SILLoop *removeLoop(iterator I) { return LI.removeLoop(I); } /// Change the top-level loop that contains BB to the specified loop. This /// should be used by transformations that restructure the loop hierarchy /// tree. void changeLoopFor(SILBasicBlock *BB, SILLoop *L) { LI.changeLoopFor(BB, L); } /// Replace the specified loop in the top-level loops list with the indicated /// loop. void changeTopLevelLoop(SILLoop *OldLoop, SILLoop *NewLoop) { LI.changeTopLevelLoop(OldLoop, NewLoop); } /// This adds the specified loop to the collection of top-level loops. void addTopLevelLoop(SILLoop *New) { LI.addTopLevelLoop(New); } /// This method completely removes BB from all data structures, including all /// of the Loop objects it is nested in and our mapping from SILBasicBlocks to /// loops. void removeBlock(SILBasicBlock *BB) { LI.removeBlock(BB); } }; } // end namespace swift #endif