aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm14/include/llvm/Analysis/RegionInfoImpl.h
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
committervitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
commit6ffe9e53658409f212834330e13564e4952558f6 (patch)
tree85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/llvm14/include/llvm/Analysis/RegionInfoImpl.h
parent726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff)
downloadydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/llvm14/include/llvm/Analysis/RegionInfoImpl.h')
-rw-r--r--contrib/libs/llvm14/include/llvm/Analysis/RegionInfoImpl.h942
1 files changed, 942 insertions, 0 deletions
diff --git a/contrib/libs/llvm14/include/llvm/Analysis/RegionInfoImpl.h b/contrib/libs/llvm14/include/llvm/Analysis/RegionInfoImpl.h
new file mode 100644
index 0000000000..11c12808ff
--- /dev/null
+++ b/contrib/libs/llvm14/include/llvm/Analysis/RegionInfoImpl.h
@@ -0,0 +1,942 @@
+#pragma once
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+//===- RegionInfoImpl.h - SESE region detection analysis --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// 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/Config/llvm-config.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>
+bool RegionBase<Tr>::getExitingBlocks(
+ SmallVectorImpl<BlockT *> &Exitings) const {
+ bool CoverAll = true;
+
+ if (!exit)
+ return CoverAll;
+
+ for (PredIterTy PI = InvBlockTraits::child_begin(exit),
+ PE = InvBlockTraits::child_end(exit);
+ PI != PE; ++PI) {
+ BlockT *Pred = *PI;
+ if (contains(Pred)) {
+ Exitings.push_back(Pred);
+ continue;
+ }
+
+ CoverAll = false;
+ }
+
+ return CoverAll;
+}
+
+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 = std::string(getEntry()->getName());
+
+ if (getExit()) {
+ if (getExit()->getName().empty()) {
+ raw_string_ostream OS(exitName);
+
+ getExit()->printAsOperand(OS, false);
+ } else
+ exitName = std::string(getExit()->getName());
+ } else
+ exitName = "<Function Return>";
+
+ return entryName + " => " + exitName;
+}
+
+template <class Tr>
+void RegionBase<Tr>::verifyBBInRegion(BlockT *BB) const {
+ if (!contains(BB))
+ report_fatal_error("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)
+ report_fatal_error("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))
+ report_fatal_error("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,
+ std::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)
+ report_fatal_error("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 (BlockT *successor : *entrySuccs) {
+ if (successor != exit && successor != 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
+ LLVM_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 = std::add_pointer_t<FuncT>;
+
+ 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 {
+ return BBtoRegion.lookup(BB);
+}
+
+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 {
+ auto next = BlockTraits::child_begin(BB);
+ ++next;
+ if (next == 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.pop_back_val();
+
+ 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 = std::add_pointer_t<FuncT>;
+
+ // 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
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif