//===- RegionInfo.cpp - SESE region detection analysis --------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// Detects single entry single exit regions in the control flow graph.
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionIterator.h"

#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Analysis/LoopInfo.h"

#define DEBUG_TYPE "region"
#include "llvm/Support/Debug.h"

#include <set>
#include <algorithm>

using namespace llvm;

// Always verify if expensive checking is enabled.
#ifdef XDEBUG
static bool VerifyRegionInfo = true;
#else
static bool VerifyRegionInfo = false;
#endif

static cl::opt<bool,true>
VerifyRegionInfoX("verify-region-info", cl::location(VerifyRegionInfo),
                cl::desc("Verify region info (time consuming)"));

STATISTIC(numRegions,       "The # of regions");
STATISTIC(numSimpleRegions, "The # of simple regions");

//===----------------------------------------------------------------------===//
/// PrintStyle - Print region in difference ways.
enum PrintStyle { PrintNone, PrintBB, PrintRN  };

cl::opt<enum PrintStyle> printStyle("print-region-style", cl::Hidden,
  cl::desc("style of printing regions"),
  cl::values(
    clEnumValN(PrintNone, "none",  "print no details"),
    clEnumValN(PrintBB, "bb",  "print regions in detail with block_iterator"),
    clEnumValN(PrintRN, "rn",  "print regions in detail with element_iterator"),
    clEnumValEnd));
//===----------------------------------------------------------------------===//
/// Region Implementation
Region::Region(BasicBlock *Entry, BasicBlock *Exit, RegionInfo* RInfo,
               DominatorTree *dt, Region *Parent)
               : RegionNode(Parent, Entry, 1), RI(RInfo), DT(dt), exit(Exit) {}

Region::~Region() {
  // Free the cached nodes.
  for (BBNodeMapT::iterator it = BBNodeMap.begin(),
         ie = BBNodeMap.end(); it != ie; ++it)
    delete it->second;

  // Only clean the cache for this Region. Caches of child Regions will be
  // cleaned when the child Regions are deleted.
  BBNodeMap.clear();

  for (iterator I = begin(), E = end(); I != E; ++I)
    delete *I;
}

bool Region::contains(const BasicBlock *B) const {
  BasicBlock *BB = const_cast<BasicBlock*>(B);

  assert(DT->getNode(BB) && "BB not part of the dominance tree");

  BasicBlock *entry = getEntry(), *exit = getExit();

  // Toplevel region.
  if (!exit)
    return true;

  return (DT->dominates(entry, BB)
    && !(DT->dominates(exit, BB) && DT->dominates(entry, exit)));
}

bool Region::contains(const Loop *L) const {
  // BBs that are not part of any loop are element of the Loop
  // described by the NULL pointer. This loop is not part of any region,
  // except if the region describes the whole function.
  if (L == 0)
    return getExit() == 0;

  if (!contains(L->getHeader()))
    return false;

  SmallVector<BasicBlock *, 8> ExitingBlocks;
  L->getExitingBlocks(ExitingBlocks);

  for (SmallVectorImpl<BasicBlock*>::iterator BI = ExitingBlocks.begin(),
       BE = ExitingBlocks.end(); BI != BE; ++BI)
    if (!contains(*BI))
      return false;

  return true;
}

Loop *Region::outermostLoopInRegion(Loop *L) const {
  if (!contains(L))
    return 0;

  while (L && contains(L->getParentLoop())) {
    L = L->getParentLoop();
  }

  return L;
}

Loop *Region::outermostLoopInRegion(LoopInfo *LI, BasicBlock* BB) const {
  assert(LI && BB && "LI and BB cannot be null!");
  Loop *L = LI->getLoopFor(BB);
  return outermostLoopInRegion(L);
}

bool Region::isSimple() const {
  bool isSimple = true;
  bool found = false;

  BasicBlock *entry = getEntry(), *exit = getExit();

  // TopLevelRegion
  if (!exit)
    return false;

  for (pred_iterator PI = pred_begin(entry), PE = pred_end(entry); PI != PE;
       ++PI) {
    BasicBlock *Pred = *PI;
    if (DT->getNode(Pred) && !contains(Pred)) {
      if (found) {
        isSimple = false;
        break;
      }
      found = true;
    }
  }

  found = false;

  for (pred_iterator PI = pred_begin(exit), PE = pred_end(exit); PI != PE;
       ++PI)
    if (contains(*PI)) {
      if (found) {
        isSimple = false;
        break;
      }
      found = true;
    }

  return isSimple;
}

std::string Region::getNameStr() const {
  std::string exitName;
  std::string entryName;

  if (getEntry()->getName().empty()) {
    raw_string_ostream OS(entryName);

    WriteAsOperand(OS, getEntry(), false);
    entryName = OS.str();
  } else
    entryName = getEntry()->getNameStr();

  if (getExit()) {
    if (getExit()->getName().empty()) {
      raw_string_ostream OS(exitName);

      WriteAsOperand(OS, getExit(), false);
      exitName = OS.str();
    } else
      exitName = getExit()->getNameStr();
  } else
    exitName = "<Function Return>";

  return entryName + " => " + exitName;
}

void Region::verifyBBInRegion(BasicBlock *BB) const {
  if (!contains(BB))
    llvm_unreachable("Broken region found!");

  BasicBlock *entry = getEntry(), *exit = getExit();

  for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
    if (!contains(*SI) && exit != *SI)
      llvm_unreachable("Broken region found!");

  if (entry != BB)
    for (pred_iterator SI = pred_begin(BB), SE = pred_end(BB); SI != SE; ++SI)
      if (!contains(*SI))
        llvm_unreachable("Broken region found!");
}

void Region::verifyWalk(BasicBlock *BB, std::set<BasicBlock*> *visited) const {
  BasicBlock *exit = getExit();

  visited->insert(BB);

  verifyBBInRegion(BB);

  for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
    if (*SI != exit && visited->find(*SI) == visited->end())
        verifyWalk(*SI, visited);
}

void Region::verifyRegion() const {
  // Only do verification when user wants to, otherwise this expensive
  // check will be invoked by PassManager.
  if (!VerifyRegionInfo) return;

  std::set<BasicBlock*> visited;
  verifyWalk(getEntry(), &visited);
}

void Region::verifyRegionNest() const {
  for (Region::const_iterator RI = begin(), RE = end(); RI != RE; ++RI)
    (*RI)->verifyRegionNest();

  verifyRegion();
}

Region::block_iterator Region::block_begin() {
  return GraphTraits<FlatIt<Region*> >::nodes_begin(this);
}

Region::block_iterator Region::block_end() {
  return GraphTraits<FlatIt<Region*> >::nodes_end(this);
}

Region::const_block_iterator Region::block_begin() const {
  return GraphTraits<FlatIt<const Region*> >::nodes_begin(this);
}

Region::const_block_iterator Region::block_end() const {
  return GraphTraits<FlatIt<const Region*> >::nodes_end(this);
}

Region::element_iterator Region::element_begin() {
  return GraphTraits<Region*>::nodes_begin(this);
}

Region::element_iterator Region::element_end() {
  return GraphTraits<Region*>::nodes_end(this);
}

Region::const_element_iterator Region::element_begin() const {
  return GraphTraits<const Region*>::nodes_begin(this);
}

Region::const_element_iterator Region::element_end() const {
  return GraphTraits<const Region*>::nodes_end(this);
}

Region* Region::getSubRegionNode(BasicBlock *BB) const {
  Region *R = RI->getRegionFor(BB);

  if (!R || R == this)
    return 0;

  // If we pass the BB out of this region, that means our code is broken.
  assert(contains(R) && "BB not in current region!");

  while (contains(R->getParent()) && R->getParent() != this)
    R = R->getParent();

  if (R->getEntry() != BB)
    return 0;

  return R;
}

RegionNode* Region::getBBNode(BasicBlock *BB) const {
  assert(contains(BB) && "Can get BB node out of this region!");

  BBNodeMapT::const_iterator at = BBNodeMap.find(BB);

  if (at != BBNodeMap.end())
    return at->second;

  RegionNode *NewNode = new RegionNode(const_cast<Region*>(this), BB);
  BBNodeMap.insert(std::make_pair(BB, NewNode));
  return NewNode;
}

RegionNode* Region::getNode(BasicBlock *BB) const {
  assert(contains(BB) && "Can get BB node out of this region!");
  if (Region* Child = getSubRegionNode(BB))
    return Child->getNode();

  return getBBNode(BB);
}

void Region::transferChildrenTo(Region *To) {
  for (iterator I = begin(), E = end(); I != E; ++I) {
    (*I)->parent = To;
    To->children.push_back(*I);
  }
  children.clear();
}

void Region::addSubRegion(Region *SubRegion) {
  assert(SubRegion->parent == 0 && "SubRegion already has a parent!");
  SubRegion->parent = this;
  // Set up the region node.
  assert(std::find(children.begin(), children.end(), SubRegion) == children.end()
         && "Node already exist!");
  children.push_back(SubRegion);
}


Region *Region::removeSubRegion(Region *Child) {
  assert(Child->parent == this && "Child is not a child of this region!");
  Child->parent = 0;
  RegionSet::iterator I = std::find(children.begin(), children.end(), Child);
  assert(I != children.end() && "Region does not exit. Unable to remove.");
  children.erase(children.begin()+(I-begin()));
  return Child;
}

unsigned Region::getDepth() const {
  unsigned Depth = 0;

  for (Region *R = parent; R != 0; R = R->parent)
    ++Depth;

  return Depth;
}

void Region::print(raw_ostream &OS, bool print_tree, unsigned level) const {
  if (print_tree)
    OS.indent(level*2) << "[" << level << "] " << getNameStr();
  else
    OS.indent(level*2) << getNameStr();

  OS << "\n";


  if (printStyle != PrintNone) {
    OS.indent(level*2) << "{\n";
    OS.indent(level*2 + 2);

    if (printStyle == PrintBB) {
      for (const_block_iterator I = block_begin(), E = block_end(); I!=E; ++I)
        OS << **I << ", "; // TODO: remove the last ","
    } else if (printStyle == PrintRN) {
      for (const_element_iterator I = element_begin(), E = element_end(); I!=E; ++I)
        OS << **I << ", "; // TODO: remove the last ",
    }

    OS << "\n";
  }

  if (print_tree)
    for (const_iterator RI = begin(), RE = end(); RI != RE; ++RI)
      (*RI)->print(OS, print_tree, level+1);

  if (printStyle != PrintNone)
    OS.indent(level*2) << "} \n";
}

void Region::dump() const {
  print(dbgs(), true, getDepth());
}

void Region::clearNodeCache() {
  // Free the cached nodes.
  for (BBNodeMapT::iterator I = BBNodeMap.begin(),
       IE = BBNodeMap.end(); I != IE; ++IE)
    delete I->second;

  BBNodeMap.clear();
  for (Region::iterator RI = begin(), RE = end(); RI != RE; ++RI)
    (*RI)->clearNodeCache();
}

//===----------------------------------------------------------------------===//
// RegionInfo implementation
//

bool RegionInfo::isCommonDomFrontier(BasicBlock *BB, BasicBlock *entry,
                                     BasicBlock *exit) const {
  for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) {
    BasicBlock *P = *PI;
    if (DT->dominates(entry, P) && !DT->dominates(exit, P))
      return false;
  }
  return true;
}

bool RegionInfo::isRegion(BasicBlock *entry, BasicBlock *exit) const {
  assert(entry && exit && "entry and exit must not be null!");
  typedef DominanceFrontier::DomSetType DST;

  DST *entrySuccs = &DF->find(entry)->second;

  // Exit is the header of a loop that contains the entry. In this case,
  // the dominance frontier must only contain the exit.
  if (!DT->dominates(entry, exit)) {
    for (DST::iterator SI = entrySuccs->begin(), SE = entrySuccs->end();
         SI != SE; ++SI)
      if (*SI != exit && *SI != entry)
        return false;

    return true;
  }

  DST *exitSuccs = &DF->find(exit)->second;

  // Do not allow edges leaving the region.
  for (DST::iterator SI = entrySuccs->begin(), SE = entrySuccs->end();
       SI != SE; ++SI) {
    if (*SI == exit || *SI == entry)
      continue;
    if (exitSuccs->find(*SI) == exitSuccs->end())
      return false;
    if (!isCommonDomFrontier(*SI, entry, exit))
      return false;
  }

  // Do not allow edges pointing into the region.
  for (DST::iterator SI = exitSuccs->begin(), SE = exitSuccs->end();
       SI != SE; ++SI)
    if (DT->properlyDominates(entry, *SI) && *SI != exit)
      return false;


  return true;
}

void RegionInfo::insertShortCut(BasicBlock *entry, BasicBlock *exit,
                             BBtoBBMap *ShortCut) const {
  assert(entry && exit && "entry and exit must not be null!");

  BBtoBBMap::iterator e = ShortCut->find(exit);

  if (e == ShortCut->end())
    // No further region at exit available.
    (*ShortCut)[entry] = exit;
  else {
    // We found a region e that starts at exit. Therefore (entry, e->second)
    // is also a region, that is larger than (entry, exit). Insert the
    // larger one.
    BasicBlock *BB = e->second;
    (*ShortCut)[entry] = BB;
  }
}

DomTreeNode* RegionInfo::getNextPostDom(DomTreeNode* N,
                                        BBtoBBMap *ShortCut) const {
  BBtoBBMap::iterator e = ShortCut->find(N->getBlock());

  if (e == ShortCut->end())
    return N->getIDom();

  return PDT->getNode(e->second)->getIDom();
}

bool RegionInfo::isTrivialRegion(BasicBlock *entry, BasicBlock *exit) const {
  assert(entry && exit && "entry and exit must not be null!");

  unsigned num_successors = succ_end(entry) - succ_begin(entry);

  if (num_successors <= 1 && exit == *(succ_begin(entry)))
    return true;

  return false;
}

void RegionInfo::updateStatistics(Region *R) {
  ++numRegions;

  // TODO: Slow. Should only be enabled if -stats is used.
  if (R->isSimple()) ++numSimpleRegions;
}

Region *RegionInfo::createRegion(BasicBlock *entry, BasicBlock *exit) {
  assert(entry && exit && "entry and exit must not be null!");

  if (isTrivialRegion(entry, exit))
    return 0;

  Region *region = new Region(entry, exit, this, DT);
  BBtoRegion.insert(std::make_pair(entry, region));

 #ifdef XDEBUG
    region->verifyRegion();
 #else
    DEBUG(region->verifyRegion());
 #endif

  updateStatistics(region);
  return region;
}

void RegionInfo::findRegionsWithEntry(BasicBlock *entry, BBtoBBMap *ShortCut) {
  assert(entry);

  DomTreeNode *N = PDT->getNode(entry);

  if (!N)
    return;

  Region *lastRegion= 0;
  BasicBlock *lastExit = entry;

  // As only a BasicBlock that postdominates entry can finish a region, walk the
  // post dominance tree upwards.
  while ((N = getNextPostDom(N, ShortCut))) {
    BasicBlock *exit = N->getBlock();

    if (!exit)
      break;

    if (isRegion(entry, exit)) {
      Region *newRegion = createRegion(entry, exit);

      if (lastRegion)
        newRegion->addSubRegion(lastRegion);

      lastRegion = newRegion;
      lastExit = exit;
    }

    // This can never be a region, so stop the search.
    if (!DT->dominates(entry, exit))
      break;
  }

  // Tried to create regions from entry to lastExit.  Next time take a
  // shortcut from entry to lastExit.
  if (lastExit != entry)
    insertShortCut(entry, lastExit, ShortCut);
}

void RegionInfo::scanForRegions(Function &F, BBtoBBMap *ShortCut) {
  BasicBlock *entry = &(F.getEntryBlock());
  DomTreeNode *N = DT->getNode(entry);

  // Iterate over the dominance tree in post order to start with the small
  // regions from the bottom of the dominance tree.  If the small regions are
  // detected first, detection of bigger regions is faster, as we can jump
  // over the small regions.
  for (po_iterator<DomTreeNode*> FI = po_begin(N), FE = po_end(N); FI != FE;
    ++FI) {
    findRegionsWithEntry(FI->getBlock(), ShortCut);
  }
}

Region *RegionInfo::getTopMostParent(Region *region) {
  while (region->parent)
    region = region->getParent();

  return region;
}

void RegionInfo::buildRegionsTree(DomTreeNode *N, Region *region) {
  BasicBlock *BB = N->getBlock();

  // Passed region exit
  while (BB == region->getExit())
    region = region->getParent();

  BBtoRegionMap::iterator it = BBtoRegion.find(BB);

  // This basic block is a start block of a region. It is already in the
  // BBtoRegion relation. Only the child basic blocks have to be updated.
  if (it != BBtoRegion.end()) {
    Region *newRegion = it->second;;
    region->addSubRegion(getTopMostParent(newRegion));
    region = newRegion;
  } else {
    BBtoRegion[BB] = region;
  }

  for (DomTreeNode::iterator CI = N->begin(), CE = N->end(); CI != CE; ++CI)
    buildRegionsTree(*CI, region);
}

void RegionInfo::releaseMemory() {
  BBtoRegion.clear();
  if (TopLevelRegion)
    delete TopLevelRegion;
  TopLevelRegion = 0;
}

RegionInfo::RegionInfo() : FunctionPass(ID) {
  TopLevelRegion = 0;
}

RegionInfo::~RegionInfo() {
  releaseMemory();
}

void RegionInfo::Calculate(Function &F) {
  // ShortCut a function where for every BB the exit of the largest region
  // starting with BB is stored. These regions can be threated as single BBS.
  // This improves performance on linear CFGs.
  BBtoBBMap ShortCut;

  scanForRegions(F, &ShortCut);
  BasicBlock *BB = &F.getEntryBlock();
  buildRegionsTree(DT->getNode(BB), TopLevelRegion);
}

bool RegionInfo::runOnFunction(Function &F) {
  releaseMemory();

  DT = &getAnalysis<DominatorTree>();
  PDT = &getAnalysis<PostDominatorTree>();
  DF = &getAnalysis<DominanceFrontier>();

  TopLevelRegion = new Region(&F.getEntryBlock(), 0, this, DT, 0);
  updateStatistics(TopLevelRegion);

  Calculate(F);

  return false;
}

void RegionInfo::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequiredTransitive<DominatorTree>();
  AU.addRequired<PostDominatorTree>();
  AU.addRequired<DominanceFrontier>();
}

void RegionInfo::print(raw_ostream &OS, const Module *) const {
  OS << "Region tree:\n";
  TopLevelRegion->print(OS, true, 0);
  OS << "End region tree\n";
}

void RegionInfo::verifyAnalysis() const {
  // Only do verification when user wants to, otherwise this expensive check
  // will be invoked by PMDataManager::verifyPreservedAnalysis when
  // a regionpass (marked PreservedAll) finish.
  if (!VerifyRegionInfo) return;

  TopLevelRegion->verifyRegionNest();
}

// Region pass manager support.
Region *RegionInfo::getRegionFor(BasicBlock *BB) const {
  BBtoRegionMap::const_iterator I=
    BBtoRegion.find(BB);
  return I != BBtoRegion.end() ? I->second : 0;
}

Region *RegionInfo::operator[](BasicBlock *BB) const {
  return getRegionFor(BB);
}


BasicBlock *RegionInfo::getMaxRegionExit(BasicBlock *BB) const {
  BasicBlock *Exit = NULL;

  while (true) {
    // Get largest region that starts at BB.
    Region *R = getRegionFor(BB);
    while (R && R->getParent() && R->getParent()->getEntry() == BB)
      R = R->getParent();

    // Get the single exit of BB.
    if (R && R->getEntry() == BB)
      Exit = R->getExit();
    else if (++succ_begin(BB) == succ_end(BB))
      Exit = *succ_begin(BB);
    else // No single exit exists.
      return Exit;

    // Get largest region that starts at Exit.
    Region *ExitR = getRegionFor(Exit);
    while (ExitR && ExitR->getParent()
           && ExitR->getParent()->getEntry() == Exit)
      ExitR = ExitR->getParent();

    for (pred_iterator PI = pred_begin(Exit), PE = pred_end(Exit); PI != PE;
         ++PI)
      if (!R->contains(*PI) && !ExitR->contains(*PI))
        break;

    // This stops infinite cycles.
    if (DT->dominates(Exit, BB))
      break;

    BB = Exit;
  }

  return Exit;
}

Region*
RegionInfo::getCommonRegion(Region *A, Region *B) const {
  assert (A && B && "One of the Regions is NULL");

  if (A->contains(B)) return A;

  while (!B->contains(A))
    B = B->getParent();

  return B;
}

Region*
RegionInfo::getCommonRegion(SmallVectorImpl<Region*> &Regions) const {
  Region* ret = Regions.back();
  Regions.pop_back();

  for (SmallVectorImpl<Region*>::const_iterator I = Regions.begin(),
       E = Regions.end(); I != E; ++I)
      ret = getCommonRegion(ret, *I);

  return ret;
}

Region*
RegionInfo::getCommonRegion(SmallVectorImpl<BasicBlock*> &BBs) const {
  Region* ret = getRegionFor(BBs.back());
  BBs.pop_back();

  for (SmallVectorImpl<BasicBlock*>::const_iterator I = BBs.begin(),
       E = BBs.end(); I != E; ++I)
      ret = getCommonRegion(ret, getRegionFor(*I));

  return ret;
}

char RegionInfo::ID = 0;
INITIALIZE_PASS_BEGIN(RegionInfo, "regions",
                "Detect single entry single exit regions", true, true)
INITIALIZE_PASS_DEPENDENCY(DominatorTree)
INITIALIZE_PASS_DEPENDENCY(PostDominatorTree)
INITIALIZE_PASS_DEPENDENCY(DominanceFrontier)
INITIALIZE_PASS_END(RegionInfo, "regions",
                "Detect single entry single exit regions", true, true)

// Create methods available outside of this file, to use them
// "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by
// the link time optimization.

namespace llvm {
  FunctionPass *createRegionInfoPass() {
    return new RegionInfo();
  }
}

