//===- 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<BlockT*> BlockTraits;
    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...
        TodoStack.insert(TodoStack.end(), InvBlockTraits::child_begin(X),
                         InvBlockTraits::child_end(X));
      }
    }

    // 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
