blob: 1ab4d6fe0e4ce8d53562c25c6282682038f6bf6a [file] [log] [blame]
//===--- LoopInfo.h - SIL Loop Analysis -------------------------*- C++ -*-===//
// This source file is part of the 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 for license information
// See for the list of Swift project authors
#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<swift::SILBasicBlock, swift::SILLoop>;
__extension__ extern template
class llvm::LoopInfoBase<swift::SILBasicBlock, swift::SILLoop>;
namespace swift {
class SILLoop;
/// Information about a single natural loop.
class SILLoop : public llvm::LoopBase<SILBasicBlock, SILLoop> {
SILLoop() {}
void dump() const;
iterator_range<iterator> getSubLoopRange() const {
return make_range(begin(), end());
/// Check whether it is safe to duplicate this instruction when duplicating
/// this loop by unrolling or versioning.
bool canDuplicate(SILInstruction *Inst) const;
void getExitingAndLatchBlocks(
SmallVectorImpl<SILBasicBlock *> &ExitingAndLatchBlocks) const {
SILBasicBlock *header = getHeader();
for (auto *predBB : header->getPredecessorBlocks()) {
if (contains(predBB) && !this->isLoopExiting(predBB))
SILFunction *getFunction() const { return getHeader()->getParent(); }
friend class llvm::LoopInfoBase<SILBasicBlock, SILLoop>;
explicit SILLoop(SILBasicBlock *BB)
: llvm::LoopBase<SILBasicBlock, SILLoop>(BB) {}
/// Information about loops in a function.
class SILLoopInfo {
friend class llvm::LoopBase<SILBasicBlock, SILLoop>;
using SILLoopInfoBase = llvm::LoopInfoBase<SILBasicBlock, SILLoop>;
SILLoopInfoBase LI;
DominanceInfo *Dominance;
void operator=(const SILLoopInfo &) = delete;
SILLoopInfo(const SILLoopInfo &) = delete;
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<iterator> 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) {
/// 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) {
} // end namespace swift