//===- 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/Analysis/LoopInfo.h"
#include "llvm/Assembly/Writer.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  };

static 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;
}

void Region::replaceEntry(BasicBlock *BB) {
  entry.setPointer(BB);
}

void Region::replaceExit(BasicBlock *BB) {
  assert(exit && "No exit to replace!");
  exit = BB;
}

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();

  if (isTopLevelRegion())
    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, bool moveChildren) {
  assert(SubRegion->parent == 0 && "SubRegion already has a parent!");
  assert(std::find(begin(), end(), SubRegion) == children.end()
         && "Subregion already exists!");

  SubRegion->parent = this;
  children.push_back(SubRegion);

  if (!moveChildren)
    return;

  assert(SubRegion->children.size() == 0
         && "SubRegions that contain children are not supported");

  for (element_iterator I = element_begin(), E = element_end(); I != E; ++I)
    if (!(*I)->isSubRegion()) {
      BasicBlock *BB = (*I)->getNodeAs<BasicBlock>();

      if (SubRegion->contains(BB))
        RI->setRegionFor(BB, SubRegion);
    }

  std::vector<Region*> Keep;
  for (iterator I = begin(), E = end(); I != E; ++I)
    if (SubRegion->contains(*I) && *I != SubRegion) {
      SubRegion->children.push_back(*I);
      (*I)->parent = SubRegion;
    } else
      Keep.push_back(*I);

  children.clear();
  children.insert(children.begin(), Keep.begin(), Keep.end());
}


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;
}

Region *Region::getExpandedRegion() const {
  unsigned NumSuccessors = exit->getTerminator()->getNumSuccessors();

  if (NumSuccessors == 0)
    return NULL;

  for (pred_iterator PI = pred_begin(getExit()), PE = pred_end(getExit());
       PI != PE; ++PI)
    if (!DT->dominates(getEntry(), *PI))
      return NULL;

  Region *R = RI->getRegionFor(exit);

  if (R->getEntry() != exit) {
    if (exit->getTerminator()->getNumSuccessors() == 1)
      return new Region(getEntry(), *succ_begin(exit), RI, DT);
    else
      return NULL;
  }

  while (R->getParent() && R->getParent()->getEntry() == exit)
    R = R->getParent();

  if (!DT->dominates(getEntry(), R->getExit()))
    for (pred_iterator PI = pred_begin(getExit()), PE = pred_end(getExit());
         PI != PE; ++PI)
    if (!DT->dominates(R->getExit(), *PI))
      return NULL;

  return new Region(getEntry(), R->getExit(), RI, DT);
}

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; ++I)
    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) {
  initializeRegionInfoPass(*PassRegistry::getPassRegistry());
  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;
}

void RegionInfo::setRegionFor(BasicBlock *BB, Region *R) {
  BBtoRegion[BB] = R;
}

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;
}

void RegionInfo::splitBlock(BasicBlock* NewBB, BasicBlock *OldBB)
{
  Region *R = getRegionFor(OldBB);

  setRegionFor(NewBB, R);

  while (R->getEntry() == OldBB && !R->isTopLevelRegion()) {
    R->replaceEntry(NewBB);
    R = R->getParent();
  }

  setRegionFor(OldBB, R);
}

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();
  }
}

