//===- llvm/Analysis/LoopInfo.h - Natural Loop Calculator -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the LoopInfo class that is used to identify natural loops
// and determine the loop depth of various nodes of the CFG.  A natural loop
// has exactly one entry-point, which is called the header. Note that natural
// loops may actually be several loops that share the same header node.
//
// This analysis calculates the nesting structure of loops in a function.  For
// each natural loop identified, this analysis identifies natural loops
// contained entirely within the loop and the basic blocks the make up the loop.
//
// It can calculate on the fly various bits of information, for example:
//
//  * whether there is a preheader for the loop
//  * the number of back edges to the header
//  * whether or not a particular block branches out of the loop
//  * the successor blocks of the loop
//  * the loop depth
//  * the trip count
//  * etc...
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_ANALYSIS_LOOP_INFO_H
#define LLVM_ANALYSIS_LOOP_INFO_H

#include "llvm/Pass.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <map>

namespace llvm {

template<typename T>
static void RemoveFromVector(std::vector<T*> &V, T *N) {
  typename std::vector<T*>::iterator I = std::find(V.begin(), V.end(), N);
  assert(I != V.end() && "N is not in this list!");
  V.erase(I);
}

class DominatorTree;
class LoopInfo;
class Loop;
class PHINode;
template<class N, class M> class LoopInfoBase;
template<class N, class M> class LoopBase;

//===----------------------------------------------------------------------===//
/// LoopBase class - Instances of this class are used to represent loops that
/// are detected in the flow graph
///
template<class BlockT, class LoopT>
class LoopBase {
  LoopT *ParentLoop;
  // SubLoops - Loops contained entirely within this one.
  std::vector<LoopT *> SubLoops;

  // Blocks - The list of blocks in this loop.  First entry is the header node.
  std::vector<BlockT*> Blocks;

  // DO NOT IMPLEMENT
  LoopBase(const LoopBase<BlockT, LoopT> &);
  // DO NOT IMPLEMENT
  const LoopBase<BlockT, LoopT>&operator=(const LoopBase<BlockT, LoopT> &);
public:
  /// Loop ctor - This creates an empty loop.
  LoopBase() : ParentLoop(0) {}
  ~LoopBase() {
    for (size_t i = 0, e = SubLoops.size(); i != e; ++i)
      delete SubLoops[i];
  }

  /// getLoopDepth - Return the nesting level of this loop.  An outer-most
  /// loop has depth 1, for consistency with loop depth values used for basic
  /// blocks, where depth 0 is used for blocks not inside any loops.
  unsigned getLoopDepth() const {
    unsigned D = 1;
    for (const LoopT *CurLoop = ParentLoop; CurLoop;
         CurLoop = CurLoop->ParentLoop)
      ++D;
    return D;
  }
  BlockT *getHeader() const { return Blocks.front(); }
  LoopT *getParentLoop() const { return ParentLoop; }

  /// contains - Return true if the specified loop is contained within in
  /// this loop.
  ///
  bool contains(const LoopT *L) const {
    if (L == this) return true;
    if (L == 0)    return false;
    return contains(L->getParentLoop());
  }

  /// contains - Return true if the specified basic block is in this loop.
  ///
  bool contains(const BlockT *BB) const {
    return std::find(block_begin(), block_end(), BB) != block_end();
  }

  /// contains - Return true if the specified instruction is in this loop.
  ///
  template<class InstT>
  bool contains(const InstT *Inst) const {
    return contains(Inst->getParent());
  }

  /// iterator/begin/end - Return the loops contained entirely within this loop.
  ///
  const std::vector<LoopT *> &getSubLoops() const { return SubLoops; }
  typedef typename std::vector<LoopT *>::const_iterator iterator;
  iterator begin() const { return SubLoops.begin(); }
  iterator end() const { return SubLoops.end(); }
  bool empty() const { return SubLoops.empty(); }

  /// getBlocks - Get a list of the basic blocks which make up this loop.
  ///
  const std::vector<BlockT*> &getBlocks() const { return Blocks; }
  typedef typename std::vector<BlockT*>::const_iterator block_iterator;
  block_iterator block_begin() const { return Blocks.begin(); }
  block_iterator block_end() const { return Blocks.end(); }

  /// getNumBlocks - Get the number of blocks in this loop in constant time.
  unsigned getNumBlocks() const {
    return Blocks.size();
  }

  /// isLoopExiting - True if terminator in the block can branch to another
  /// block that is outside of the current loop.
  ///
  bool isLoopExiting(const BlockT *BB) const {
    typedef GraphTraits<BlockT*> BlockTraits;
    for (typename BlockTraits::ChildIteratorType SI =
         BlockTraits::child_begin(const_cast<BlockT*>(BB)),
         SE = BlockTraits::child_end(const_cast<BlockT*>(BB)); SI != SE; ++SI) {
      if (!contains(*SI))
        return true;
    }
    return false;
  }

  /// getNumBackEdges - Calculate the number of back edges to the loop header
  ///
  unsigned getNumBackEdges() const {
    unsigned NumBackEdges = 0;
    BlockT *H = getHeader();

    typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
    for (typename InvBlockTraits::ChildIteratorType I =
         InvBlockTraits::child_begin(const_cast<BlockT*>(H)),
         E = InvBlockTraits::child_end(const_cast<BlockT*>(H)); I != E; ++I)
      if (contains(*I))
        ++NumBackEdges;

    return NumBackEdges;
  }

  //===--------------------------------------------------------------------===//
  // APIs for simple analysis of the loop.
  //
  // Note that all of these methods can fail on general loops (ie, there may not
  // be a preheader, etc).  For best success, the loop simplification and
  // induction variable canonicalization pass should be used to normalize loops
  // for easy analysis.  These methods assume canonical loops.

  /// getExitingBlocks - Return all blocks inside the loop that have successors
  /// outside of the loop.  These are the blocks _inside of the current loop_
  /// which branch out.  The returned list is always unique.
  ///
  void getExitingBlocks(SmallVectorImpl<BlockT *> &ExitingBlocks) const {
    // Sort the blocks vector so that we can use binary search to do quick
    // lookups.
    SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
    std::sort(LoopBBs.begin(), LoopBBs.end());

    typedef GraphTraits<BlockT*> BlockTraits;
    for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
      for (typename BlockTraits::ChildIteratorType I =
          BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
          I != E; ++I)
        if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I)) {
          // Not in current loop? It must be an exit block.
          ExitingBlocks.push_back(*BI);
          break;
        }
  }

  /// getExitingBlock - If getExitingBlocks would return exactly one block,
  /// return that block. Otherwise return null.
  BlockT *getExitingBlock() const {
    SmallVector<BlockT*, 8> ExitingBlocks;
    getExitingBlocks(ExitingBlocks);
    if (ExitingBlocks.size() == 1)
      return ExitingBlocks[0];
    return 0;
  }

  /// getExitBlocks - Return all of the successor blocks of this loop.  These
  /// are the blocks _outside of the current loop_ which are branched to.
  ///
  void getExitBlocks(SmallVectorImpl<BlockT*> &ExitBlocks) const {
    // Sort the blocks vector so that we can use binary search to do quick
    // lookups.
    SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
    std::sort(LoopBBs.begin(), LoopBBs.end());

    typedef GraphTraits<BlockT*> BlockTraits;
    for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
      for (typename BlockTraits::ChildIteratorType I =
           BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
           I != E; ++I)
        if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
          // Not in current loop? It must be an exit block.
          ExitBlocks.push_back(*I);
  }

  /// getExitBlock - If getExitBlocks would return exactly one block,
  /// return that block. Otherwise return null.
  BlockT *getExitBlock() const {
    SmallVector<BlockT*, 8> ExitBlocks;
    getExitBlocks(ExitBlocks);
    if (ExitBlocks.size() == 1)
      return ExitBlocks[0];
    return 0;
  }

  /// Edge type.
  typedef std::pair<BlockT*, BlockT*> Edge;

  /// getExitEdges - Return all pairs of (_inside_block_,_outside_block_).
  template <typename EdgeT>
  void getExitEdges(SmallVectorImpl<EdgeT> &ExitEdges) const {
    // Sort the blocks vector so that we can use binary search to do quick
    // lookups.
    SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
    array_pod_sort(LoopBBs.begin(), LoopBBs.end());

    typedef GraphTraits<BlockT*> BlockTraits;
    for (block_iterator BI = block_begin(), BE = block_end(); BI != BE; ++BI)
      for (typename BlockTraits::ChildIteratorType I =
           BlockTraits::child_begin(*BI), E = BlockTraits::child_end(*BI);
           I != E; ++I)
        if (!std::binary_search(LoopBBs.begin(), LoopBBs.end(), *I))
          // Not in current loop? It must be an exit block.
          ExitEdges.push_back(EdgeT(*BI, *I));
  }

  /// getLoopPreheader - If there is a preheader for this loop, return it.  A
  /// loop has a preheader if there is only one edge to the header of the loop
  /// from outside of the loop.  If this is the case, the block branching to the
  /// header of the loop is the preheader node.
  ///
  /// This method returns null if there is no preheader for the loop.
  ///
  BlockT *getLoopPreheader() const {
    // Keep track of nodes outside the loop branching to the header...
    BlockT *Out = getLoopPredecessor();
    if (!Out) return 0;

    // Make sure there is only one exit out of the preheader.
    typedef GraphTraits<BlockT*> BlockTraits;
    typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out);
    ++SI;
    if (SI != BlockTraits::child_end(Out))
      return 0;  // Multiple exits from the block, must not be a preheader.

    // The predecessor has exactly one successor, so it is a preheader.
    return Out;
  }

  /// getLoopPredecessor - If the given loop's header has exactly one unique
  /// predecessor outside the loop, return it. Otherwise return null.
  /// This is less strict that the loop "preheader" concept, which requires
  /// the predecessor to have exactly one successor.
  ///
  BlockT *getLoopPredecessor() const {
    // Keep track of nodes outside the loop branching to the header...
    BlockT *Out = 0;

    // Loop over the predecessors of the header node...
    BlockT *Header = getHeader();
    typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
    for (typename InvBlockTraits::ChildIteratorType PI =
         InvBlockTraits::child_begin(Header),
         PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) {
      typename InvBlockTraits::NodeType *N = *PI;
      if (!contains(N)) {     // If the block is not in the loop...
        if (Out && Out != N)
          return 0;             // Multiple predecessors outside the loop
        Out = N;
      }
    }

    // Make sure there is only one exit out of the preheader.
    assert(Out && "Header of loop has no predecessors from outside loop?");
    return Out;
  }

  /// getLoopLatch - If there is a single latch block for this loop, return it.
  /// A latch block is a block that contains a branch back to the header.
  BlockT *getLoopLatch() const {
    BlockT *Header = getHeader();
    typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
    typename InvBlockTraits::ChildIteratorType PI =
                                            InvBlockTraits::child_begin(Header);
    typename InvBlockTraits::ChildIteratorType PE =
                                              InvBlockTraits::child_end(Header);
    BlockT *Latch = 0;
    for (; PI != PE; ++PI) {
      typename InvBlockTraits::NodeType *N = *PI;
      if (contains(N)) {
        if (Latch) return 0;
        Latch = N;
      }
    }

    return Latch;
  }

  //===--------------------------------------------------------------------===//
  // APIs for updating loop information after changing the CFG
  //

  /// addBasicBlockToLoop - This method is used by other analyses to update loop
  /// information.  NewBB is set to be a new member of the current loop.
  /// Because of this, it is added as a member of all parent loops, and is added
  /// to the specified LoopInfo object as being in the current basic block.  It
  /// is not valid to replace the loop header with this method.
  ///
  void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LI);

  /// replaceChildLoopWith - This is used when splitting loops up.  It replaces
  /// the OldChild entry in our children list with NewChild, and updates the
  /// parent pointer of OldChild to be null and the NewChild to be this loop.
  /// This updates the loop depth of the new child.
  void replaceChildLoopWith(LoopT *OldChild,
                            LoopT *NewChild) {
    assert(OldChild->ParentLoop == this && "This loop is already broken!");
    assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!");
    typename std::vector<LoopT *>::iterator I =
                          std::find(SubLoops.begin(), SubLoops.end(), OldChild);
    assert(I != SubLoops.end() && "OldChild not in loop!");
    *I = NewChild;
    OldChild->ParentLoop = 0;
    NewChild->ParentLoop = static_cast<LoopT *>(this);
  }

  /// addChildLoop - Add the specified loop to be a child of this loop.  This
  /// updates the loop depth of the new child.
  ///
  void addChildLoop(LoopT *NewChild) {
    assert(NewChild->ParentLoop == 0 && "NewChild already has a parent!");
    NewChild->ParentLoop = static_cast<LoopT *>(this);
    SubLoops.push_back(NewChild);
  }

  /// removeChildLoop - This removes the specified child from being a subloop of
  /// this loop.  The loop is not deleted, as it will presumably be inserted
  /// into another loop.
  LoopT *removeChildLoop(iterator I) {
    assert(I != SubLoops.end() && "Cannot remove end iterator!");
    LoopT *Child = *I;
    assert(Child->ParentLoop == this && "Child is not a child of this loop!");
    SubLoops.erase(SubLoops.begin()+(I-begin()));
    Child->ParentLoop = 0;
    return Child;
  }

  /// addBlockEntry - This adds a basic block directly to the basic block list.
  /// This should only be used by transformations that create new loops.  Other
  /// transformations should use addBasicBlockToLoop.
  void addBlockEntry(BlockT *BB) {
    Blocks.push_back(BB);
  }

  /// moveToHeader - This method is used to move BB (which must be part of this
  /// loop) to be the loop header of the loop (the block that dominates all
  /// others).
  void moveToHeader(BlockT *BB) {
    if (Blocks[0] == BB) return;
    for (unsigned i = 0; ; ++i) {
      assert(i != Blocks.size() && "Loop does not contain BB!");
      if (Blocks[i] == BB) {
        Blocks[i] = Blocks[0];
        Blocks[0] = BB;
        return;
      }
    }
  }

  /// removeBlockFromLoop - This removes the specified basic block from the
  /// current loop, updating the Blocks as appropriate.  This does not update
  /// the mapping in the LoopInfo class.
  void removeBlockFromLoop(BlockT *BB) {
    RemoveFromVector(Blocks, BB);
  }

  /// verifyLoop - Verify loop structure
  void verifyLoop() const {
#ifndef NDEBUG
    assert(!Blocks.empty() && "Loop header is missing");

    // Sort the blocks vector so that we can use binary search to do quick
    // lookups.
    SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
    std::sort(LoopBBs.begin(), LoopBBs.end());

    // Check the individual blocks.
    for (block_iterator I = block_begin(), E = block_end(); I != E; ++I) {
      BlockT *BB = *I;
      bool HasInsideLoopSuccs = false;
      bool HasInsideLoopPreds = false;
      SmallVector<BlockT *, 2> OutsideLoopPreds;

      typedef GraphTraits<BlockT*> BlockTraits;
      for (typename BlockTraits::ChildIteratorType SI =
           BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB);
           SI != SE; ++SI)
        if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *SI)) {
          HasInsideLoopSuccs = true;
          break;
        }
      typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
      for (typename InvBlockTraits::ChildIteratorType PI =
           InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB);
           PI != PE; ++PI) {
        typename InvBlockTraits::NodeType *N = *PI;
        if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N))
          HasInsideLoopPreds = true;
        else
          OutsideLoopPreds.push_back(N);
      }

      if (BB == getHeader()) {
        assert(!OutsideLoopPreds.empty() && "Loop is unreachable!");
      } else if (!OutsideLoopPreds.empty()) {
        // A non-header loop shouldn't be reachable from outside the loop,
        // though it is permitted if the predecessor is not itself actually
        // reachable.
        BlockT *EntryBB = BB->getParent()->begin();
        for (df_iterator<BlockT *> NI = df_begin(EntryBB),
             NE = df_end(EntryBB); NI != NE; ++NI)
          for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i)
            assert(*NI != OutsideLoopPreds[i] &&
                   "Loop has multiple entry points!");
      }
      assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!");
      assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!");
      assert(BB != getHeader()->getParent()->begin() &&
             "Loop contains function entry block!");
    }

    // Check the subloops.
    for (iterator I = begin(), E = end(); I != E; ++I)
      // Each block in each subloop should be contained within this loop.
      for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end();
           BI != BE; ++BI) {
        assert(std::binary_search(LoopBBs.begin(), LoopBBs.end(), *BI) &&
               "Loop does not contain all the blocks of a subloop!");
      }

    // Check the parent loop pointer.
    if (ParentLoop) {
      assert(std::find(ParentLoop->begin(), ParentLoop->end(), this) !=
               ParentLoop->end() &&
             "Loop is not a subloop of its parent!");
    }
#endif
  }

  /// verifyLoop - Verify loop structure of this loop and all nested loops.
  void verifyLoopNest(DenseSet<const LoopT*> *Loops) const {
    Loops->insert(static_cast<const LoopT *>(this));
    // Verify this loop.
    verifyLoop();
    // Verify the subloops.
    for (iterator I = begin(), E = end(); I != E; ++I)
      (*I)->verifyLoopNest(Loops);
  }

  void print(raw_ostream &OS, unsigned Depth = 0) const {
    OS.indent(Depth*2) << "Loop at depth " << getLoopDepth()
       << " containing: ";

    for (unsigned i = 0; i < getBlocks().size(); ++i) {
      if (i) OS << ",";
      BlockT *BB = getBlocks()[i];
      WriteAsOperand(OS, BB, false);
      if (BB == getHeader())    OS << "<header>";
      if (BB == getLoopLatch()) OS << "<latch>";
      if (isLoopExiting(BB))    OS << "<exiting>";
    }
    OS << "\n";

    for (iterator I = begin(), E = end(); I != E; ++I)
      (*I)->print(OS, Depth+2);
  }

protected:
  friend class LoopInfoBase<BlockT, LoopT>;
  explicit LoopBase(BlockT *BB) : ParentLoop(0) {
    Blocks.push_back(BB);
  }
};

template<class BlockT, class LoopT>
raw_ostream& operator<<(raw_ostream &OS, const LoopBase<BlockT, LoopT> &Loop) {
  Loop.print(OS);
  return OS;
}

class Loop : public LoopBase<BasicBlock, Loop> {
public:
  Loop() {}

  /// isLoopInvariant - Return true if the specified value is loop invariant
  ///
  bool isLoopInvariant(Value *V) const;

  /// hasLoopInvariantOperands - Return true if all the operands of the
  /// specified instruction are loop invariant.
  bool hasLoopInvariantOperands(Instruction *I) const;

  /// makeLoopInvariant - If the given value is an instruction inside of the
  /// loop and it can be hoisted, do so to make it trivially loop-invariant.
  /// Return true if the value after any hoisting is loop invariant. This
  /// function can be used as a slightly more aggressive replacement for
  /// isLoopInvariant.
  ///
  /// If InsertPt is specified, it is the point to hoist instructions to.
  /// If null, the terminator of the loop preheader is used.
  ///
  bool makeLoopInvariant(Value *V, bool &Changed,
                         Instruction *InsertPt = 0) const;

  /// makeLoopInvariant - If the given instruction is inside of the
  /// loop and it can be hoisted, do so to make it trivially loop-invariant.
  /// Return true if the instruction after any hoisting is loop invariant. This
  /// function can be used as a slightly more aggressive replacement for
  /// isLoopInvariant.
  ///
  /// If InsertPt is specified, it is the point to hoist instructions to.
  /// If null, the terminator of the loop preheader is used.
  ///
  bool makeLoopInvariant(Instruction *I, bool &Changed,
                         Instruction *InsertPt = 0) const;

  /// getCanonicalInductionVariable - Check to see if the loop has a canonical
  /// induction variable: an integer recurrence that starts at 0 and increments
  /// by one each time through the loop.  If so, return the phi node that
  /// corresponds to it.
  ///
  /// The IndVarSimplify pass transforms loops to have a canonical induction
  /// variable.
  ///
  PHINode *getCanonicalInductionVariable() const;

  /// getTripCount - Return a loop-invariant LLVM value indicating the number of
  /// times the loop will be executed.  Note that this means that the backedge
  /// of the loop executes N-1 times.  If the trip-count cannot be determined,
  /// this returns null.
  ///
  /// The IndVarSimplify pass transforms loops to have a form that this
  /// function easily understands.
  ///
  Value *getTripCount() const;

  /// getSmallConstantTripCount - Returns the trip count of this loop as a
  /// normal unsigned value, if possible. Returns 0 if the trip count is unknown
  /// of not constant. Will also return 0 if the trip count is very large
  /// (>= 2^32)
  ///
  /// The IndVarSimplify pass transforms loops to have a form that this
  /// function easily understands.
  ///
  unsigned getSmallConstantTripCount() const;

  /// getSmallConstantTripMultiple - Returns the largest constant divisor of the
  /// trip count of this loop as a normal unsigned value, if possible. This
  /// means that the actual trip count is always a multiple of the returned
  /// value (don't forget the trip count could very well be zero as well!).
  ///
  /// Returns 1 if the trip count is unknown or not guaranteed to be the
  /// multiple of a constant (which is also the case if the trip count is simply
  /// constant, use getSmallConstantTripCount for that case), Will also return 1
  /// if the trip count is very large (>= 2^32).
  unsigned getSmallConstantTripMultiple() const;

  /// isLCSSAForm - Return true if the Loop is in LCSSA form
  bool isLCSSAForm(DominatorTree &DT) const;

  /// isLoopSimplifyForm - Return true if the Loop is in the form that
  /// the LoopSimplify form transforms loops to, which is sometimes called
  /// normal form.
  bool isLoopSimplifyForm() const;

  /// hasDedicatedExits - Return true if no exit block for the loop
  /// has a predecessor that is outside the loop.
  bool hasDedicatedExits() const;

  /// getUniqueExitBlocks - Return all unique successor blocks of this loop.
  /// These are the blocks _outside of the current loop_ which are branched to.
  /// This assumes that loop exits are in canonical form.
  ///
  void getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const;

  /// getUniqueExitBlock - If getUniqueExitBlocks would return exactly one
  /// block, return that block. Otherwise return null.
  BasicBlock *getUniqueExitBlock() const;

  void dump() const;

private:
  friend class LoopInfoBase<BasicBlock, Loop>;
  explicit Loop(BasicBlock *BB) : LoopBase<BasicBlock, Loop>(BB) {}
};

//===----------------------------------------------------------------------===//
/// LoopInfo - This class builds and contains all of the top level loop
/// structures in the specified function.
///

template<class BlockT, class LoopT>
class LoopInfoBase {
  // BBMap - Mapping of basic blocks to the inner most loop they occur in
  DenseMap<BlockT *, LoopT *> BBMap;
  std::vector<LoopT *> TopLevelLoops;
  friend class LoopBase<BlockT, LoopT>;
  friend class LoopInfo;

  void operator=(const LoopInfoBase &); // do not implement
  LoopInfoBase(const LoopInfo &);       // do not implement
public:
  LoopInfoBase() { }
  ~LoopInfoBase() { releaseMemory(); }

  void releaseMemory() {
    for (typename std::vector<LoopT *>::iterator I =
         TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I)
      delete *I;   // Delete all of the loops...

    BBMap.clear();                           // Reset internal state of analysis
    TopLevelLoops.clear();
  }

  /// iterator/begin/end - The interface to the top-level loops in the current
  /// function.
  ///
  typedef typename std::vector<LoopT *>::const_iterator iterator;
  iterator begin() const { return TopLevelLoops.begin(); }
  iterator end() const { return TopLevelLoops.end(); }
  bool empty() const { return TopLevelLoops.empty(); }

  /// getLoopFor - 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.
  ///
  LoopT *getLoopFor(const BlockT *BB) const {
    typename DenseMap<BlockT *, LoopT *>::const_iterator I=
      BBMap.find(const_cast<BlockT*>(BB));
    return I != BBMap.end() ? I->second : 0;
  }

  /// operator[] - same as getLoopFor...
  ///
  const LoopT *operator[](const BlockT *BB) const {
    return getLoopFor(BB);
  }

  /// getLoopDepth - Return the loop nesting level of the specified block.  A
  /// depth of 0 means the block is not inside any loop.
  ///
  unsigned getLoopDepth(const BlockT *BB) const {
    const LoopT *L = getLoopFor(BB);
    return L ? L->getLoopDepth() : 0;
  }

  // isLoopHeader - True if the block is a loop header node
  bool isLoopHeader(BlockT *BB) const {
    const LoopT *L = getLoopFor(BB);
    return L && L->getHeader() == BB;
  }

  /// removeLoop - 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.
  LoopT *removeLoop(iterator I) {
    assert(I != end() && "Cannot remove end iterator!");
    LoopT *L = *I;
    assert(L->getParentLoop() == 0 && "Not a top-level loop!");
    TopLevelLoops.erase(TopLevelLoops.begin() + (I-begin()));
    return L;
  }

  /// changeLoopFor - 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(BlockT *BB, LoopT *L) {
    if (!L) {
      typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB);
      if (I != BBMap.end())
        BBMap.erase(I);
      return;
    }
    BBMap[BB] = L;
  }

  /// changeTopLevelLoop - Replace the specified loop in the top-level loops
  /// list with the indicated loop.
  void changeTopLevelLoop(LoopT *OldLoop,
                          LoopT *NewLoop) {
    typename std::vector<LoopT *>::iterator I =
                 std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop);
    assert(I != TopLevelLoops.end() && "Old loop not at top level!");
    *I = NewLoop;
    assert(NewLoop->ParentLoop == 0 && OldLoop->ParentLoop == 0 &&
           "Loops already embedded into a subloop!");
  }

  /// addTopLevelLoop - This adds the specified loop to the collection of
  /// top-level loops.
  void addTopLevelLoop(LoopT *New) {
    assert(New->getParentLoop() == 0 && "Loop already in subloop!");
    TopLevelLoops.push_back(New);
  }

  /// removeBlock - This method completely removes BB from all data structures,
  /// including all of the Loop objects it is nested in and our mapping from
  /// BasicBlocks to loops.
  void removeBlock(BlockT *BB) {
    typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB);
    if (I != BBMap.end()) {
      for (LoopT *L = I->second; L; L = L->getParentLoop())
        L->removeBlockFromLoop(BB);

      BBMap.erase(I);
    }
  }

  // Internals

  static bool isNotAlreadyContainedIn(const LoopT *SubLoop,
                                      const LoopT *ParentLoop) {
    if (SubLoop == 0) return true;
    if (SubLoop == ParentLoop) return false;
    return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop);
  }

  void Calculate(DominatorTreeBase<BlockT> &DT) {
    BlockT *RootNode = DT.getRootNode()->getBlock();

    for (df_iterator<BlockT*> NI = df_begin(RootNode),
           NE = df_end(RootNode); NI != NE; ++NI)
      if (LoopT *L = ConsiderForLoop(*NI, DT))
        TopLevelLoops.push_back(L);
  }

  LoopT *ConsiderForLoop(BlockT *BB, DominatorTreeBase<BlockT> &DT) {
    if (BBMap.find(BB) != BBMap.end()) return 0;// Haven't processed this node?

    std::vector<BlockT *> TodoStack;

    // Scan the predecessors of BB, checking to see if BB dominates any of
    // them.  This identifies backedges which target this node...
    typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
    for (typename InvBlockTraits::ChildIteratorType I =
         InvBlockTraits::child_begin(BB), E = InvBlockTraits::child_end(BB);
         I != E; ++I) {
      typename InvBlockTraits::NodeType *N = *I;
      if (DT.dominates(BB, N))   // If BB dominates its predecessor...
          TodoStack.push_back(N);
    }

    if (TodoStack.empty()) return 0;  // No backedges to this block...

    // Create a new loop to represent this basic block...
    LoopT *L = new LoopT(BB);
    BBMap[BB] = L;

    BlockT *EntryBlock = BB->getParent()->begin();

    while (!TodoStack.empty()) {  // Process all the nodes in the loop
      BlockT *X = TodoStack.back();
      TodoStack.pop_back();

      if (!L->contains(X) &&         // As of yet unprocessed??
          DT.dominates(EntryBlock, X)) {   // X is reachable from entry block?
        // Check to see if this block already belongs to a loop.  If this occurs
        // then we have a case where a loop that is supposed to be a child of
        // the current loop was processed before the current loop.  When this
        // occurs, this child loop gets added to a part of the current loop,
        // making it a sibling to the current loop.  We have to reparent this
        // loop.
        if (LoopT *SubLoop =
            const_cast<LoopT *>(getLoopFor(X)))
          if (SubLoop->getHeader() == X && isNotAlreadyContainedIn(SubLoop, L)){
            // Remove the subloop from its current parent...
            assert(SubLoop->ParentLoop && SubLoop->ParentLoop != L);
            LoopT *SLP = SubLoop->ParentLoop;  // SubLoopParent
            typename std::vector<LoopT *>::iterator I =
              std::find(SLP->SubLoops.begin(), SLP->SubLoops.end(), SubLoop);
            assert(I != SLP->SubLoops.end() &&"SubLoop not a child of parent?");
            SLP->SubLoops.erase(I);   // Remove from parent...

            // Add the subloop to THIS loop...
            SubLoop->ParentLoop = L;
            L->SubLoops.push_back(SubLoop);
          }

        // Normal case, add the block to our loop...
        L->Blocks.push_back(X);

        typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;

        // Add all of the predecessors of X to the end of the work stack...
        for (typename InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(X), PE = InvBlockTraits::child_end(X); PI != PE; ++PI) {
          typename InvBlockTraits::NodeType *N = *PI;
          TodoStack.push_back(N);
        }
      }
    }

    // If there are any loops nested within this loop, create them now!
    for (typename std::vector<BlockT*>::iterator I = L->Blocks.begin(),
         E = L->Blocks.end(); I != E; ++I)
      if (LoopT *NewLoop = ConsiderForLoop(*I, DT)) {
        L->SubLoops.push_back(NewLoop);
        NewLoop->ParentLoop = L;
      }

    // Add the basic blocks that comprise this loop to the BBMap so that this
    // loop can be found for them.
    //
    for (typename std::vector<BlockT*>::iterator I = L->Blocks.begin(),
           E = L->Blocks.end(); I != E; ++I)
      BBMap.insert(std::make_pair(*I, L));

    // Now that we have a list of all of the child loops of this loop, check to
    // see if any of them should actually be nested inside of each other.  We
    // can accidentally pull loops our of their parents, so we must make sure to
    // organize the loop nests correctly now.
    {
      std::map<BlockT *, LoopT *> ContainingLoops;
      for (unsigned i = 0; i != L->SubLoops.size(); ++i) {
        LoopT *Child = L->SubLoops[i];
        assert(Child->getParentLoop() == L && "Not proper child loop?");

        if (LoopT *ContainingLoop = ContainingLoops[Child->getHeader()]) {
          // If there is already a loop which contains this loop, move this loop
          // into the containing loop.
          MoveSiblingLoopInto(Child, ContainingLoop);
          --i;  // The loop got removed from the SubLoops list.
        } else {
          // This is currently considered to be a top-level loop.  Check to see
          // if any of the contained blocks are loop headers for subloops we
          // have already processed.
          for (unsigned b = 0, e = Child->Blocks.size(); b != e; ++b) {
            LoopT *&BlockLoop = ContainingLoops[Child->Blocks[b]];
            if (BlockLoop == 0) {   // Child block not processed yet...
              BlockLoop = Child;
            } else if (BlockLoop != Child) {
              LoopT *SubLoop = BlockLoop;
              // Reparent all of the blocks which used to belong to BlockLoops
              for (unsigned j = 0, f = SubLoop->Blocks.size(); j != f; ++j)
                ContainingLoops[SubLoop->Blocks[j]] = Child;

              // There is already a loop which contains this block, that means
              // that we should reparent the loop which the block is currently
              // considered to belong to to be a child of this loop.
              MoveSiblingLoopInto(SubLoop, Child);
              --i;  // We just shrunk the SubLoops list.
            }
          }
        }
      }
    }

    return L;
  }

  /// MoveSiblingLoopInto - This method moves the NewChild loop to live inside
  /// of the NewParent Loop, instead of being a sibling of it.
  void MoveSiblingLoopInto(LoopT *NewChild,
                           LoopT *NewParent) {
    LoopT *OldParent = NewChild->getParentLoop();
    assert(OldParent && OldParent == NewParent->getParentLoop() &&
           NewChild != NewParent && "Not sibling loops!");

    // Remove NewChild from being a child of OldParent
    typename std::vector<LoopT *>::iterator I =
      std::find(OldParent->SubLoops.begin(), OldParent->SubLoops.end(),
                NewChild);
    assert(I != OldParent->SubLoops.end() && "Parent fields incorrect??");
    OldParent->SubLoops.erase(I);   // Remove from parent's subloops list
    NewChild->ParentLoop = 0;

    InsertLoopInto(NewChild, NewParent);
  }

  /// InsertLoopInto - This inserts loop L into the specified parent loop.  If
  /// the parent loop contains a loop which should contain L, the loop gets
  /// inserted into L instead.
  void InsertLoopInto(LoopT *L, LoopT *Parent) {
    BlockT *LHeader = L->getHeader();
    assert(Parent->contains(LHeader) &&
           "This loop should not be inserted here!");

    // Check to see if it belongs in a child loop...
    for (unsigned i = 0, e = static_cast<unsigned>(Parent->SubLoops.size());
         i != e; ++i)
      if (Parent->SubLoops[i]->contains(LHeader)) {
        InsertLoopInto(L, Parent->SubLoops[i]);
        return;
      }

    // If not, insert it here!
    Parent->SubLoops.push_back(L);
    L->ParentLoop = Parent;
  }

  // Debugging

  void print(raw_ostream &OS) const {
    for (unsigned i = 0; i < TopLevelLoops.size(); ++i)
      TopLevelLoops[i]->print(OS);
  #if 0
    for (DenseMap<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(),
           E = BBMap.end(); I != E; ++I)
      OS << "BB '" << I->first->getName() << "' level = "
         << I->second->getLoopDepth() << "\n";
  #endif
  }
};

class LoopInfo : public FunctionPass {
  LoopInfoBase<BasicBlock, Loop> LI;
  friend class LoopBase<BasicBlock, Loop>;

  void operator=(const LoopInfo &); // do not implement
  LoopInfo(const LoopInfo &);       // do not implement
public:
  static char ID; // Pass identification, replacement for typeid

  LoopInfo() : FunctionPass(ID) {
    initializeLoopInfoPass(*PassRegistry::getPassRegistry());
  }

  LoopInfoBase<BasicBlock, Loop>& getBase() { return LI; }

  /// iterator/begin/end - The interface to the top-level loops in the current
  /// function.
  ///
  typedef LoopInfoBase<BasicBlock, Loop>::iterator iterator;
  inline iterator begin() const { return LI.begin(); }
  inline iterator end() const { return LI.end(); }
  bool empty() const { return LI.empty(); }

  /// getLoopFor - 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.
  ///
  inline Loop *getLoopFor(const BasicBlock *BB) const {
    return LI.getLoopFor(BB);
  }

  /// operator[] - same as getLoopFor...
  ///
  inline const Loop *operator[](const BasicBlock *BB) const {
    return LI.getLoopFor(BB);
  }

  /// getLoopDepth - Return the loop nesting level of the specified block.  A
  /// depth of 0 means the block is not inside any loop.
  ///
  inline unsigned getLoopDepth(const BasicBlock *BB) const {
    return LI.getLoopDepth(BB);
  }

  // isLoopHeader - True if the block is a loop header node
  inline bool isLoopHeader(BasicBlock *BB) const {
    return LI.isLoopHeader(BB);
  }

  /// runOnFunction - Calculate the natural loop information.
  ///
  virtual bool runOnFunction(Function &F);

  virtual void verifyAnalysis() const;

  virtual void releaseMemory() { LI.releaseMemory(); }

  virtual void print(raw_ostream &O, const Module* M = 0) const;

  virtual void getAnalysisUsage(AnalysisUsage &AU) const;

  /// removeLoop - 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.
  inline Loop *removeLoop(iterator I) { return LI.removeLoop(I); }

  /// changeLoopFor - Change the top-level loop that contains BB to the
  /// specified loop.  This should be used by transformations that restructure
  /// the loop hierarchy tree.
  inline void changeLoopFor(BasicBlock *BB, Loop *L) {
    LI.changeLoopFor(BB, L);
  }

  /// changeTopLevelLoop - Replace the specified loop in the top-level loops
  /// list with the indicated loop.
  inline void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop) {
    LI.changeTopLevelLoop(OldLoop, NewLoop);
  }

  /// addTopLevelLoop - This adds the specified loop to the collection of
  /// top-level loops.
  inline void addTopLevelLoop(Loop *New) {
    LI.addTopLevelLoop(New);
  }

  /// removeBlock - This method completely removes BB from all data structures,
  /// including all of the Loop objects it is nested in and our mapping from
  /// BasicBlocks to loops.
  void removeBlock(BasicBlock *BB) {
    LI.removeBlock(BB);
  }

  /// updateUnloop - Update LoopInfo after removing the last backedge from a
  /// loop--now the "unloop". This updates the loop forest and parent loops for
  /// each block so that Unloop is no longer referenced, but the caller must
  /// actually delete the Unloop object.
  void updateUnloop(Loop *Unloop);

  /// replacementPreservesLCSSAForm - Returns true if replacing From with To
  /// everywhere is guaranteed to preserve LCSSA form.
  bool replacementPreservesLCSSAForm(Instruction *From, Value *To) {
    // Preserving LCSSA form is only problematic if the replacing value is an
    // instruction.
    Instruction *I = dyn_cast<Instruction>(To);
    if (!I) return true;
    // If both instructions are defined in the same basic block then replacement
    // cannot break LCSSA form.
    if (I->getParent() == From->getParent())
      return true;
    // If the instruction is not defined in a loop then it can safely replace
    // anything.
    Loop *ToLoop = getLoopFor(I->getParent());
    if (!ToLoop) return true;
    // If the replacing instruction is defined in the same loop as the original
    // instruction, or in a loop that contains it as an inner loop, then using
    // it as a replacement will not break LCSSA form.
    return ToLoop->contains(getLoopFor(From->getParent()));
  }
};


// Allow clients to walk the list of nested loops...
template <> struct GraphTraits<const Loop*> {
  typedef const Loop NodeType;
  typedef LoopInfo::iterator ChildIteratorType;

  static NodeType *getEntryNode(const Loop *L) { return L; }
  static inline ChildIteratorType child_begin(NodeType *N) {
    return N->begin();
  }
  static inline ChildIteratorType child_end(NodeType *N) {
    return N->end();
  }
};

template <> struct GraphTraits<Loop*> {
  typedef Loop NodeType;
  typedef LoopInfo::iterator ChildIteratorType;

  static NodeType *getEntryNode(Loop *L) { return L; }
  static inline ChildIteratorType child_begin(NodeType *N) {
    return N->begin();
  }
  static inline ChildIteratorType child_end(NodeType *N) {
    return N->end();
  }
};

template<class BlockT, class LoopT>
void
LoopBase<BlockT, LoopT>::addBasicBlockToLoop(BlockT *NewBB,
                                             LoopInfoBase<BlockT, LoopT> &LIB) {
  assert((Blocks.empty() || LIB[getHeader()] == this) &&
         "Incorrect LI specified for this loop!");
  assert(NewBB && "Cannot add a null basic block to the loop!");
  assert(LIB[NewBB] == 0 && "BasicBlock already in the loop!");

  LoopT *L = static_cast<LoopT *>(this);

  // Add the loop mapping to the LoopInfo object...
  LIB.BBMap[NewBB] = L;

  // Add the basic block to this loop and all parent loops...
  while (L) {
    L->Blocks.push_back(NewBB);
    L = L->getParentLoop();
  }
}

} // End llvm namespace

#endif
