//===- RegionInfoImpl.h - SESE region detection analysis --------*- C++ -*-===//
//
//                     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.
//===----------------------------------------------------------------------===//

#ifndef LLVM_ANALYSIS_REGIONINFOIMPL_H
#define LLVM_ANALYSIS_REGIONINFOIMPL_H

#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/DominanceFrontier.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionIterator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <iterator>
#include <memory>
#include <set>
#include <string>
#include <type_traits>
#include <vector>

#define DEBUG_TYPE "region"

namespace llvm {

//===----------------------------------------------------------------------===//
/// RegionBase Implementation
template <class Tr>
RegionBase<Tr>::RegionBase(BlockT *Entry, BlockT *Exit,
                           typename Tr::RegionInfoT *RInfo, DomTreeT *dt,
                           RegionT *Parent)
    : RegionNodeBase<Tr>(Parent, Entry, 1), RI(RInfo), DT(dt), exit(Exit) {}

template <class Tr>
RegionBase<Tr>::~RegionBase() {
  // Only clean the cache for this Region. Caches of child Regions will be
  // cleaned when the child Regions are deleted.
  BBNodeMap.clear();
}

template <class Tr>
void RegionBase<Tr>::replaceEntry(BlockT *BB) {
  this->entry.setPointer(BB);
}

template <class Tr>
void RegionBase<Tr>::replaceExit(BlockT *BB) {
  assert(exit && "No exit to replace!");
  exit = BB;
}

template <class Tr>
void RegionBase<Tr>::replaceEntryRecursive(BlockT *NewEntry) {
  std::vector<RegionT *> RegionQueue;
  BlockT *OldEntry = getEntry();

  RegionQueue.push_back(static_cast<RegionT *>(this));
  while (!RegionQueue.empty()) {
    RegionT *R = RegionQueue.back();
    RegionQueue.pop_back();

    R->replaceEntry(NewEntry);
    for (std::unique_ptr<RegionT> &Child : *R) {
      if (Child->getEntry() == OldEntry)
        RegionQueue.push_back(Child.get());
    }
  }
}

template <class Tr>
void RegionBase<Tr>::replaceExitRecursive(BlockT *NewExit) {
  std::vector<RegionT *> RegionQueue;
  BlockT *OldExit = getExit();

  RegionQueue.push_back(static_cast<RegionT *>(this));
  while (!RegionQueue.empty()) {
    RegionT *R = RegionQueue.back();
    RegionQueue.pop_back();

    R->replaceExit(NewExit);
    for (std::unique_ptr<RegionT> &Child : *R) {
      if (Child->getExit() == OldExit)
        RegionQueue.push_back(Child.get());
    }
  }
}

template <class Tr>
bool RegionBase<Tr>::contains(const BlockT *B) const {
  BlockT *BB = const_cast<BlockT *>(B);

  if (!DT->getNode(BB))
    return false;

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

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

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

template <class Tr>
bool RegionBase<Tr>::contains(const LoopT *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)
    return getExit() == nullptr;

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

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

  for (BlockT *BB : ExitingBlocks) {
    if (!contains(BB))
      return false;
  }

  return true;
}

template <class Tr>
typename Tr::LoopT *RegionBase<Tr>::outermostLoopInRegion(LoopT *L) const {
  if (!contains(L))
    return nullptr;

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

  return L;
}

template <class Tr>
typename Tr::LoopT *RegionBase<Tr>::outermostLoopInRegion(LoopInfoT *LI,
                                                          BlockT *BB) const {
  assert(LI && BB && "LI and BB cannot be null!");
  LoopT *L = LI->getLoopFor(BB);
  return outermostLoopInRegion(L);
}

template <class Tr>
typename RegionBase<Tr>::BlockT *RegionBase<Tr>::getEnteringBlock() const {
  BlockT *entry = getEntry();
  BlockT *enteringBlock = nullptr;

  for (BlockT *Pred : make_range(InvBlockTraits::child_begin(entry),
                                 InvBlockTraits::child_end(entry))) {
    if (DT->getNode(Pred) && !contains(Pred)) {
      if (enteringBlock)
        return nullptr;

      enteringBlock = Pred;
    }
  }

  return enteringBlock;
}

template <class Tr>
typename RegionBase<Tr>::BlockT *RegionBase<Tr>::getExitingBlock() const {
  BlockT *exit = getExit();
  BlockT *exitingBlock = nullptr;

  if (!exit)
    return nullptr;

  for (BlockT *Pred : make_range(InvBlockTraits::child_begin(exit),
                                 InvBlockTraits::child_end(exit))) {
    if (contains(Pred)) {
      if (exitingBlock)
        return nullptr;

      exitingBlock = Pred;
    }
  }

  return exitingBlock;
}

template <class Tr>
bool RegionBase<Tr>::isSimple() const {
  return !isTopLevelRegion() && getEnteringBlock() && getExitingBlock();
}

template <class Tr>
std::string RegionBase<Tr>::getNameStr() const {
  std::string exitName;
  std::string entryName;

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

    getEntry()->printAsOperand(OS, false);
  } else
    entryName = getEntry()->getName();

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

      getExit()->printAsOperand(OS, false);
    } else
      exitName = getExit()->getName();
  } else
    exitName = "<Function Return>";

  return entryName + " => " + exitName;
}

template <class Tr>
void RegionBase<Tr>::verifyBBInRegion(BlockT *BB) const {
  if (!contains(BB))
    llvm_unreachable("Broken region found: enumerated BB not in region!");

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

  for (BlockT *Succ :
       make_range(BlockTraits::child_begin(BB), BlockTraits::child_end(BB))) {
    if (!contains(Succ) && exit != Succ)
      llvm_unreachable("Broken region found: edges leaving the region must go "
                       "to the exit node!");
  }

  if (entry != BB) {
    for (BlockT *Pred : make_range(InvBlockTraits::child_begin(BB),
                                   InvBlockTraits::child_end(BB))) {
      if (!contains(Pred))
        llvm_unreachable("Broken region found: edges entering the region must "
                         "go to the entry node!");
    }
  }
}

template <class Tr>
void RegionBase<Tr>::verifyWalk(BlockT *BB, std::set<BlockT *> *visited) const {
  BlockT *exit = getExit();

  visited->insert(BB);

  verifyBBInRegion(BB);

  for (BlockT *Succ :
       make_range(BlockTraits::child_begin(BB), BlockTraits::child_end(BB))) {
    if (Succ != exit && visited->find(Succ) == visited->end())
      verifyWalk(Succ, visited);
  }
}

template <class Tr>
void RegionBase<Tr>::verifyRegion() 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 (!RegionInfoBase<Tr>::VerifyRegionInfo)
    return;

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

template <class Tr>
void RegionBase<Tr>::verifyRegionNest() const {
  for (const std::unique_ptr<RegionT> &R : *this)
    R->verifyRegionNest();

  verifyRegion();
}

template <class Tr>
typename RegionBase<Tr>::element_iterator RegionBase<Tr>::element_begin() {
  return GraphTraits<RegionT *>::nodes_begin(static_cast<RegionT *>(this));
}

template <class Tr>
typename RegionBase<Tr>::element_iterator RegionBase<Tr>::element_end() {
  return GraphTraits<RegionT *>::nodes_end(static_cast<RegionT *>(this));
}

template <class Tr>
typename RegionBase<Tr>::const_element_iterator
RegionBase<Tr>::element_begin() const {
  return GraphTraits<const RegionT *>::nodes_begin(
      static_cast<const RegionT *>(this));
}

template <class Tr>
typename RegionBase<Tr>::const_element_iterator
RegionBase<Tr>::element_end() const {
  return GraphTraits<const RegionT *>::nodes_end(
      static_cast<const RegionT *>(this));
}

template <class Tr>
typename Tr::RegionT *RegionBase<Tr>::getSubRegionNode(BlockT *BB) const {
  using RegionT = typename Tr::RegionT;

  RegionT *R = RI->getRegionFor(BB);

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

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

  return R;
}

template <class Tr>
typename Tr::RegionNodeT *RegionBase<Tr>::getBBNode(BlockT *BB) const {
  assert(contains(BB) && "Can get BB node out of this region!");

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

  if (at == BBNodeMap.end()) {
    auto Deconst = const_cast<RegionBase<Tr> *>(this);
    typename BBNodeMapT::value_type V = {
        BB,
        llvm::make_unique<RegionNodeT>(static_cast<RegionT *>(Deconst), BB)};
    at = BBNodeMap.insert(std::move(V)).first;
  }
  return at->second.get();
}

template <class Tr>
typename Tr::RegionNodeT *RegionBase<Tr>::getNode(BlockT *BB) const {
  assert(contains(BB) && "Can get BB node out of this region!");
  if (RegionT *Child = getSubRegionNode(BB))
    return Child->getNode();

  return getBBNode(BB);
}

template <class Tr>
void RegionBase<Tr>::transferChildrenTo(RegionT *To) {
  for (std::unique_ptr<RegionT> &R : *this) {
    R->parent = To;
    To->children.push_back(std::move(R));
  }
  children.clear();
}

template <class Tr>
void RegionBase<Tr>::addSubRegion(RegionT *SubRegion, bool moveChildren) {
  assert(!SubRegion->parent && "SubRegion already has a parent!");
  assert(llvm::find_if(*this,
                       [&](const std::unique_ptr<RegionT> &R) {
                         return R.get() == SubRegion;
                       }) == children.end() &&
         "Subregion already exists!");

  SubRegion->parent = static_cast<RegionT *>(this);
  children.push_back(std::unique_ptr<RegionT>(SubRegion));

  if (!moveChildren)
    return;

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

  for (RegionNodeT *Element : elements()) {
    if (!Element->isSubRegion()) {
      BlockT *BB = Element->template getNodeAs<BlockT>();

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

  std::vector<std::unique_ptr<RegionT>> Keep;
  for (std::unique_ptr<RegionT> &R : *this) {
    if (SubRegion->contains(R.get()) && R.get() != SubRegion) {
      R->parent = SubRegion;
      SubRegion->children.push_back(std::move(R));
    } else
      Keep.push_back(std::move(R));
  }

  children.clear();
  children.insert(
      children.begin(),
      std::move_iterator<typename RegionSet::iterator>(Keep.begin()),
      std::move_iterator<typename RegionSet::iterator>(Keep.end()));
}

template <class Tr>
typename Tr::RegionT *RegionBase<Tr>::removeSubRegion(RegionT *Child) {
  assert(Child->parent == this && "Child is not a child of this region!");
  Child->parent = nullptr;
  typename RegionSet::iterator I =
      llvm::find_if(children, [&](const std::unique_ptr<RegionT> &R) {
        return R.get() == Child;
      });
  assert(I != children.end() && "Region does not exit. Unable to remove.");
  children.erase(children.begin() + (I - begin()));
  return Child;
}

template <class Tr>
unsigned RegionBase<Tr>::getDepth() const {
  unsigned Depth = 0;

  for (RegionT *R = getParent(); R != nullptr; R = R->getParent())
    ++Depth;

  return Depth;
}

template <class Tr>
typename Tr::RegionT *RegionBase<Tr>::getExpandedRegion() const {
  unsigned NumSuccessors = Tr::getNumSuccessors(exit);

  if (NumSuccessors == 0)
    return nullptr;

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

  if (R->getEntry() != exit) {
    for (BlockT *Pred : make_range(InvBlockTraits::child_begin(getExit()),
                                   InvBlockTraits::child_end(getExit())))
      if (!contains(Pred))
        return nullptr;
    if (Tr::getNumSuccessors(exit) == 1)
      return new RegionT(getEntry(), *BlockTraits::child_begin(exit), RI, DT);
    return nullptr;
  }

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

  for (BlockT *Pred : make_range(InvBlockTraits::child_begin(getExit()),
                                 InvBlockTraits::child_end(getExit()))) {
    if (!(contains(Pred) || R->contains(Pred)))
      return nullptr;
  }

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

template <class Tr>
void RegionBase<Tr>::print(raw_ostream &OS, bool print_tree, unsigned level,
                           PrintStyle Style) const {
  if (print_tree)
    OS.indent(level * 2) << '[' << level << "] " << getNameStr();
  else
    OS.indent(level * 2) << getNameStr();

  OS << '\n';

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

    if (Style == PrintBB) {
      for (const auto *BB : blocks())
        OS << BB->getName() << ", "; // TODO: remove the last ","
    } else if (Style == PrintRN) {
      for (const RegionNodeT *Element : elements()) {
        OS << *Element << ", "; // TODO: remove the last ",
      }
    }

    OS << '\n';
  }

  if (print_tree) {
    for (const std::unique_ptr<RegionT> &R : *this)
      R->print(OS, print_tree, level + 1, Style);
  }

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

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
template <class Tr>
void RegionBase<Tr>::dump() const {
  print(dbgs(), true, getDepth(), RegionInfoBase<Tr>::printStyle);
}
#endif

template <class Tr>
void RegionBase<Tr>::clearNodeCache() {
  BBNodeMap.clear();
  for (std::unique_ptr<RegionT> &R : *this)
    R->clearNodeCache();
}

//===----------------------------------------------------------------------===//
// RegionInfoBase implementation
//

template <class Tr>
RegionInfoBase<Tr>::RegionInfoBase() = default;

template <class Tr>
RegionInfoBase<Tr>::~RegionInfoBase() {
  releaseMemory();
}

template <class Tr>
void RegionInfoBase<Tr>::verifyBBMap(const RegionT *R) const {
  assert(R && "Re must be non-null");
  for (const typename Tr::RegionNodeT *Element : R->elements()) {
    if (Element->isSubRegion()) {
      const RegionT *SR = Element->template getNodeAs<RegionT>();
      verifyBBMap(SR);
    } else {
      BlockT *BB = Element->template getNodeAs<BlockT>();
      if (getRegionFor(BB) != R)
        llvm_unreachable("BB map does not match region nesting");
    }
  }
}

template <class Tr>
bool RegionInfoBase<Tr>::isCommonDomFrontier(BlockT *BB, BlockT *entry,
                                             BlockT *exit) const {
  for (BlockT *P : make_range(InvBlockTraits::child_begin(BB),
                              InvBlockTraits::child_end(BB))) {
    if (DT->dominates(entry, P) && !DT->dominates(exit, P))
      return false;
  }

  return true;
}

template <class Tr>
bool RegionInfoBase<Tr>::isRegion(BlockT *entry, BlockT *exit) const {
  assert(entry && exit && "entry and exit must not be null!");

  using DST = typename DomFrontierT::DomSetType;

  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 (typename 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 (BlockT *Succ : *entrySuccs) {
    if (Succ == exit || Succ == entry)
      continue;
    if (exitSuccs->find(Succ) == exitSuccs->end())
      return false;
    if (!isCommonDomFrontier(Succ, entry, exit))
      return false;
  }

  // Do not allow edges pointing into the region.
  for (BlockT *Succ : *exitSuccs) {
    if (DT->properlyDominates(entry, Succ) && Succ != exit)
      return false;
  }

  return true;
}

template <class Tr>
void RegionInfoBase<Tr>::insertShortCut(BlockT *entry, BlockT *exit,
                                        BBtoBBMap *ShortCut) const {
  assert(entry && exit && "entry and exit must not be null!");

  typename 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.
    BlockT *BB = e->second;
    (*ShortCut)[entry] = BB;
  }
}

template <class Tr>
typename Tr::DomTreeNodeT *
RegionInfoBase<Tr>::getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const {
  typename BBtoBBMap::iterator e = ShortCut->find(N->getBlock());

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

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

template <class Tr>
bool RegionInfoBase<Tr>::isTrivialRegion(BlockT *entry, BlockT *exit) const {
  assert(entry && exit && "entry and exit must not be null!");

  unsigned num_successors =
      BlockTraits::child_end(entry) - BlockTraits::child_begin(entry);

  if (num_successors <= 1 && exit == *(BlockTraits::child_begin(entry)))
    return true;

  return false;
}

template <class Tr>
typename Tr::RegionT *RegionInfoBase<Tr>::createRegion(BlockT *entry,
                                                       BlockT *exit) {
  assert(entry && exit && "entry and exit must not be null!");

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

  RegionT *region =
      new RegionT(entry, exit, static_cast<RegionInfoT *>(this), DT);
  BBtoRegion.insert({entry, region});

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

  updateStatistics(region);
  return region;
}

template <class Tr>
void RegionInfoBase<Tr>::findRegionsWithEntry(BlockT *entry,
                                              BBtoBBMap *ShortCut) {
  assert(entry);

  DomTreeNodeT *N = PDT->getNode(entry);
  if (!N)
    return;

  RegionT *lastRegion = nullptr;
  BlockT *lastExit = entry;

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

    if (!exit)
      break;

    if (isRegion(entry, exit)) {
      RegionT *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);
}

template <class Tr>
void RegionInfoBase<Tr>::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) {
  using FuncPtrT = typename std::add_pointer<FuncT>::type;

  BlockT *entry = GraphTraits<FuncPtrT>::getEntryNode(&F);
  DomTreeNodeT *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 (auto DomNode : post_order(N))
    findRegionsWithEntry(DomNode->getBlock(), ShortCut);
}

template <class Tr>
typename Tr::RegionT *RegionInfoBase<Tr>::getTopMostParent(RegionT *region) {
  while (region->getParent())
    region = region->getParent();

  return region;
}

template <class Tr>
void RegionInfoBase<Tr>::buildRegionsTree(DomTreeNodeT *N, RegionT *region) {
  BlockT *BB = N->getBlock();

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

  typename 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()) {
    RegionT *newRegion = it->second;
    region->addSubRegion(getTopMostParent(newRegion));
    region = newRegion;
  } else {
    BBtoRegion[BB] = region;
  }

  for (DomTreeNodeBase<BlockT> *C : *N) {
    buildRegionsTree(C, region);
  }
}

#ifdef EXPENSIVE_CHECKS
template <class Tr>
bool RegionInfoBase<Tr>::VerifyRegionInfo = true;
#else
template <class Tr>
bool RegionInfoBase<Tr>::VerifyRegionInfo = false;
#endif

template <class Tr>
typename Tr::RegionT::PrintStyle RegionInfoBase<Tr>::printStyle =
    RegionBase<Tr>::PrintNone;

template <class Tr>
void RegionInfoBase<Tr>::print(raw_ostream &OS) const {
  OS << "Region tree:\n";
  TopLevelRegion->print(OS, true, 0, printStyle);
  OS << "End region tree\n";
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
template <class Tr>
void RegionInfoBase<Tr>::dump() const { print(dbgs()); }
#endif

template <class Tr>
void RegionInfoBase<Tr>::releaseMemory() {
  BBtoRegion.clear();
  if (TopLevelRegion)
    delete TopLevelRegion;
  TopLevelRegion = nullptr;
}

template <class Tr>
void RegionInfoBase<Tr>::verifyAnalysis() const {
  // Do only verify regions if explicitely activated using EXPENSIVE_CHECKS or
  // -verify-region-info
  if (!RegionInfoBase<Tr>::VerifyRegionInfo)
    return;

  TopLevelRegion->verifyRegionNest();

  verifyBBMap(TopLevelRegion);
}

// Region pass manager support.
template <class Tr>
typename Tr::RegionT *RegionInfoBase<Tr>::getRegionFor(BlockT *BB) const {
  typename BBtoRegionMap::const_iterator I = BBtoRegion.find(BB);
  return I != BBtoRegion.end() ? I->second : nullptr;
}

template <class Tr>
void RegionInfoBase<Tr>::setRegionFor(BlockT *BB, RegionT *R) {
  BBtoRegion[BB] = R;
}

template <class Tr>
typename Tr::RegionT *RegionInfoBase<Tr>::operator[](BlockT *BB) const {
  return getRegionFor(BB);
}

template <class Tr>
typename RegionInfoBase<Tr>::BlockT *
RegionInfoBase<Tr>::getMaxRegionExit(BlockT *BB) const {
  BlockT *Exit = nullptr;

  while (true) {
    // Get largest region that starts at BB.
    RegionT *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 (++BlockTraits::child_begin(BB) == BlockTraits::child_end(BB))
      Exit = *BlockTraits::child_begin(BB);
    else // No single exit exists.
      return Exit;

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

    for (BlockT *Pred : make_range(InvBlockTraits::child_begin(Exit),
                                   InvBlockTraits::child_end(Exit))) {
      if (!R->contains(Pred) && !ExitR->contains(Pred))
        break;
    }

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

    BB = Exit;
  }

  return Exit;
}

template <class Tr>
typename Tr::RegionT *RegionInfoBase<Tr>::getCommonRegion(RegionT *A,
                                                          RegionT *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;
}

template <class Tr>
typename Tr::RegionT *
RegionInfoBase<Tr>::getCommonRegion(SmallVectorImpl<RegionT *> &Regions) const {
  RegionT *ret = Regions.back();
  Regions.pop_back();

  for (RegionT *R : Regions)
    ret = getCommonRegion(ret, R);

  return ret;
}

template <class Tr>
typename Tr::RegionT *
RegionInfoBase<Tr>::getCommonRegion(SmallVectorImpl<BlockT *> &BBs) const {
  RegionT *ret = getRegionFor(BBs.back());
  BBs.pop_back();

  for (BlockT *BB : BBs)
    ret = getCommonRegion(ret, getRegionFor(BB));

  return ret;
}

template <class Tr>
void RegionInfoBase<Tr>::calculate(FuncT &F) {
  using FuncPtrT = typename std::add_pointer<FuncT>::type;

  // 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);
  BlockT *BB = GraphTraits<FuncPtrT>::getEntryNode(&F);
  buildRegionsTree(DT->getNode(BB), TopLevelRegion);
}

} // end namespace llvm

#undef DEBUG_TYPE

#endif // LLVM_ANALYSIS_REGIONINFOIMPL_H
