Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:16

0001 //===- RegionInfoImpl.h - SESE region detection analysis --------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 // Detects single entry single exit regions in the control flow graph.
0009 //===----------------------------------------------------------------------===//
0010 
0011 #ifndef LLVM_ANALYSIS_REGIONINFOIMPL_H
0012 #define LLVM_ANALYSIS_REGIONINFOIMPL_H
0013 
0014 #include "llvm/ADT/GraphTraits.h"
0015 #include "llvm/ADT/PostOrderIterator.h"
0016 #include "llvm/ADT/STLExtras.h"
0017 #include "llvm/ADT/SmallVector.h"
0018 #include "llvm/Analysis/LoopInfo.h"
0019 #include "llvm/Analysis/PostDominators.h"
0020 #include "llvm/Analysis/RegionInfo.h"
0021 #include "llvm/Analysis/RegionIterator.h"
0022 #include "llvm/Config/llvm-config.h"
0023 #include "llvm/Support/Debug.h"
0024 #include "llvm/Support/ErrorHandling.h"
0025 #include <algorithm>
0026 #include <cassert>
0027 #include <iterator>
0028 #include <memory>
0029 #include <set>
0030 #include <string>
0031 #include <type_traits>
0032 #include <vector>
0033 
0034 #define DEBUG_TYPE "region"
0035 
0036 namespace llvm {
0037 class raw_ostream;
0038 
0039 //===----------------------------------------------------------------------===//
0040 /// RegionBase Implementation
0041 template <class Tr>
0042 RegionBase<Tr>::RegionBase(BlockT *Entry, BlockT *Exit,
0043                            typename Tr::RegionInfoT *RInfo, DomTreeT *dt,
0044                            RegionT *Parent)
0045     : RegionNodeBase<Tr>(Parent, Entry, 1), RI(RInfo), DT(dt), exit(Exit) {}
0046 
0047 template <class Tr>
0048 RegionBase<Tr>::~RegionBase() {
0049   // Only clean the cache for this Region. Caches of child Regions will be
0050   // cleaned when the child Regions are deleted.
0051   BBNodeMap.clear();
0052 }
0053 
0054 template <class Tr>
0055 void RegionBase<Tr>::replaceEntry(BlockT *BB) {
0056   this->entry.setPointer(BB);
0057 }
0058 
0059 template <class Tr>
0060 void RegionBase<Tr>::replaceExit(BlockT *BB) {
0061   assert(exit && "No exit to replace!");
0062   exit = BB;
0063 }
0064 
0065 template <class Tr>
0066 void RegionBase<Tr>::replaceEntryRecursive(BlockT *NewEntry) {
0067   std::vector<RegionT *> RegionQueue;
0068   BlockT *OldEntry = getEntry();
0069 
0070   RegionQueue.push_back(static_cast<RegionT *>(this));
0071   while (!RegionQueue.empty()) {
0072     RegionT *R = RegionQueue.back();
0073     RegionQueue.pop_back();
0074 
0075     R->replaceEntry(NewEntry);
0076     for (std::unique_ptr<RegionT> &Child : *R) {
0077       if (Child->getEntry() == OldEntry)
0078         RegionQueue.push_back(Child.get());
0079     }
0080   }
0081 }
0082 
0083 template <class Tr>
0084 void RegionBase<Tr>::replaceExitRecursive(BlockT *NewExit) {
0085   std::vector<RegionT *> RegionQueue;
0086   BlockT *OldExit = getExit();
0087 
0088   RegionQueue.push_back(static_cast<RegionT *>(this));
0089   while (!RegionQueue.empty()) {
0090     RegionT *R = RegionQueue.back();
0091     RegionQueue.pop_back();
0092 
0093     R->replaceExit(NewExit);
0094     for (std::unique_ptr<RegionT> &Child : *R) {
0095       if (Child->getExit() == OldExit)
0096         RegionQueue.push_back(Child.get());
0097     }
0098   }
0099 }
0100 
0101 template <class Tr>
0102 bool RegionBase<Tr>::contains(const BlockT *B) const {
0103   BlockT *BB = const_cast<BlockT *>(B);
0104 
0105   if (!DT->getNode(BB))
0106     return false;
0107 
0108   BlockT *entry = getEntry(), *exit = getExit();
0109 
0110   // Toplevel region.
0111   if (!exit)
0112     return true;
0113 
0114   return (DT->dominates(entry, BB) &&
0115           !(DT->dominates(exit, BB) && DT->dominates(entry, exit)));
0116 }
0117 
0118 template <class Tr>
0119 bool RegionBase<Tr>::contains(const LoopT *L) const {
0120   // BBs that are not part of any loop are element of the Loop
0121   // described by the NULL pointer. This loop is not part of any region,
0122   // except if the region describes the whole function.
0123   if (!L)
0124     return getExit() == nullptr;
0125 
0126   if (!contains(L->getHeader()))
0127     return false;
0128 
0129   SmallVector<BlockT *, 8> ExitingBlocks;
0130   L->getExitingBlocks(ExitingBlocks);
0131 
0132   for (BlockT *BB : ExitingBlocks) {
0133     if (!contains(BB))
0134       return false;
0135   }
0136 
0137   return true;
0138 }
0139 
0140 template <class Tr>
0141 typename Tr::LoopT *RegionBase<Tr>::outermostLoopInRegion(LoopT *L) const {
0142   if (!contains(L))
0143     return nullptr;
0144 
0145   while (L && contains(L->getParentLoop())) {
0146     L = L->getParentLoop();
0147   }
0148 
0149   return L;
0150 }
0151 
0152 template <class Tr>
0153 typename Tr::LoopT *RegionBase<Tr>::outermostLoopInRegion(LoopInfoT *LI,
0154                                                           BlockT *BB) const {
0155   assert(LI && BB && "LI and BB cannot be null!");
0156   LoopT *L = LI->getLoopFor(BB);
0157   return outermostLoopInRegion(L);
0158 }
0159 
0160 template <class Tr>
0161 typename RegionBase<Tr>::BlockT *RegionBase<Tr>::getEnteringBlock() const {
0162   auto isEnteringBlock = [&](BlockT *Pred, bool AllowRepeats) -> BlockT * {
0163     assert(!AllowRepeats && "Unexpected parameter value.");
0164     return DT->getNode(Pred) && !contains(Pred) ? Pred : nullptr;
0165   };
0166   return find_singleton<BlockT>(llvm::inverse_children<BlockT *>(getEntry()),
0167                                 isEnteringBlock);
0168 }
0169 
0170 template <class Tr>
0171 bool RegionBase<Tr>::getExitingBlocks(
0172     SmallVectorImpl<BlockT *> &Exitings) const {
0173   bool CoverAll = true;
0174 
0175   if (!exit)
0176     return CoverAll;
0177 
0178   for (BlockT *Pred : llvm::inverse_children<BlockT *>(exit)) {
0179     if (contains(Pred)) {
0180       Exitings.push_back(Pred);
0181       continue;
0182     }
0183 
0184     CoverAll = false;
0185   }
0186 
0187   return CoverAll;
0188 }
0189 
0190 template <class Tr>
0191 typename RegionBase<Tr>::BlockT *RegionBase<Tr>::getExitingBlock() const {
0192   BlockT *exit = getExit();
0193   if (!exit)
0194     return nullptr;
0195 
0196   auto isContained = [&](BlockT *Pred, bool AllowRepeats) -> BlockT * {
0197     assert(!AllowRepeats && "Unexpected parameter value.");
0198     return contains(Pred) ? Pred : nullptr;
0199   };
0200   return find_singleton<BlockT>(llvm::inverse_children<BlockT *>(exit),
0201                                 isContained);
0202 }
0203 
0204 template <class Tr>
0205 bool RegionBase<Tr>::isSimple() const {
0206   return !isTopLevelRegion() && getEnteringBlock() && getExitingBlock();
0207 }
0208 
0209 template <class Tr>
0210 std::string RegionBase<Tr>::getNameStr() const {
0211   std::string exitName;
0212   std::string entryName;
0213 
0214   if (getEntry()->getName().empty()) {
0215     raw_string_ostream OS(entryName);
0216 
0217     getEntry()->printAsOperand(OS, false);
0218   } else
0219     entryName = std::string(getEntry()->getName());
0220 
0221   if (getExit()) {
0222     if (getExit()->getName().empty()) {
0223       raw_string_ostream OS(exitName);
0224 
0225       getExit()->printAsOperand(OS, false);
0226     } else
0227       exitName = std::string(getExit()->getName());
0228   } else
0229     exitName = "<Function Return>";
0230 
0231   return entryName + " => " + exitName;
0232 }
0233 
0234 template <class Tr>
0235 void RegionBase<Tr>::verifyBBInRegion(BlockT *BB) const {
0236   if (!contains(BB))
0237     report_fatal_error("Broken region found: enumerated BB not in region!");
0238 
0239   BlockT *entry = getEntry(), *exit = getExit();
0240 
0241   for (BlockT *Succ : llvm::children<BlockT *>(BB)) {
0242     if (!contains(Succ) && exit != Succ)
0243       report_fatal_error("Broken region found: edges leaving the region must go "
0244                          "to the exit node!");
0245   }
0246 
0247   if (entry != BB) {
0248     for (BlockT *Pred : llvm::inverse_children<BlockT *>(BB)) {
0249       // Allow predecessors that are unreachable, as these are ignored during
0250       // region analysis.
0251       if (!contains(Pred) && DT->isReachableFromEntry(Pred))
0252         report_fatal_error("Broken region found: edges entering the region must "
0253                            "go to the entry node!");
0254     }
0255   }
0256 }
0257 
0258 template <class Tr>
0259 void RegionBase<Tr>::verifyWalk(BlockT *BB, std::set<BlockT *> *visited) const {
0260   BlockT *exit = getExit();
0261 
0262   visited->insert(BB);
0263 
0264   verifyBBInRegion(BB);
0265 
0266   for (BlockT *Succ : llvm::children<BlockT *>(BB)) {
0267     if (Succ != exit && visited->find(Succ) == visited->end())
0268       verifyWalk(Succ, visited);
0269   }
0270 }
0271 
0272 template <class Tr>
0273 void RegionBase<Tr>::verifyRegion() const {
0274   // Only do verification when user wants to, otherwise this expensive check
0275   // will be invoked by PMDataManager::verifyPreservedAnalysis when
0276   // a regionpass (marked PreservedAll) finish.
0277   if (!RegionInfoBase<Tr>::VerifyRegionInfo)
0278     return;
0279 
0280   std::set<BlockT *> visited;
0281   verifyWalk(getEntry(), &visited);
0282 }
0283 
0284 template <class Tr>
0285 void RegionBase<Tr>::verifyRegionNest() const {
0286   for (const std::unique_ptr<RegionT> &R : *this)
0287     R->verifyRegionNest();
0288 
0289   verifyRegion();
0290 }
0291 
0292 template <class Tr>
0293 typename RegionBase<Tr>::element_iterator RegionBase<Tr>::element_begin() {
0294   return GraphTraits<RegionT *>::nodes_begin(static_cast<RegionT *>(this));
0295 }
0296 
0297 template <class Tr>
0298 typename RegionBase<Tr>::element_iterator RegionBase<Tr>::element_end() {
0299   return GraphTraits<RegionT *>::nodes_end(static_cast<RegionT *>(this));
0300 }
0301 
0302 template <class Tr>
0303 typename RegionBase<Tr>::const_element_iterator
0304 RegionBase<Tr>::element_begin() const {
0305   return GraphTraits<const RegionT *>::nodes_begin(
0306       static_cast<const RegionT *>(this));
0307 }
0308 
0309 template <class Tr>
0310 typename RegionBase<Tr>::const_element_iterator
0311 RegionBase<Tr>::element_end() const {
0312   return GraphTraits<const RegionT *>::nodes_end(
0313       static_cast<const RegionT *>(this));
0314 }
0315 
0316 template <class Tr>
0317 typename Tr::RegionT *RegionBase<Tr>::getSubRegionNode(BlockT *BB) const {
0318   using RegionT = typename Tr::RegionT;
0319 
0320   RegionT *R = RI->getRegionFor(BB);
0321 
0322   if (!R || R == this)
0323     return nullptr;
0324 
0325   // If we pass the BB out of this region, that means our code is broken.
0326   assert(contains(R) && "BB not in current region!");
0327 
0328   while (contains(R->getParent()) && R->getParent() != this)
0329     R = R->getParent();
0330 
0331   if (R->getEntry() != BB)
0332     return nullptr;
0333 
0334   return R;
0335 }
0336 
0337 template <class Tr>
0338 typename Tr::RegionNodeT *RegionBase<Tr>::getBBNode(BlockT *BB) const {
0339   assert(contains(BB) && "Can get BB node out of this region!");
0340 
0341   auto [at, Inserted] = BBNodeMap.try_emplace(BB);
0342   if (Inserted) {
0343     auto Deconst = const_cast<RegionBase<Tr> *>(this);
0344     at->second =
0345         std::make_unique<RegionNodeT>(static_cast<RegionT *>(Deconst), BB);
0346   }
0347   return at->second.get();
0348 }
0349 
0350 template <class Tr>
0351 typename Tr::RegionNodeT *RegionBase<Tr>::getNode(BlockT *BB) const {
0352   assert(contains(BB) && "Can get BB node out of this region!");
0353   if (RegionT *Child = getSubRegionNode(BB))
0354     return Child->getNode();
0355 
0356   return getBBNode(BB);
0357 }
0358 
0359 template <class Tr>
0360 void RegionBase<Tr>::transferChildrenTo(RegionT *To) {
0361   for (std::unique_ptr<RegionT> &R : *this) {
0362     R->parent = To;
0363     To->children.push_back(std::move(R));
0364   }
0365   children.clear();
0366 }
0367 
0368 template <class Tr>
0369 void RegionBase<Tr>::addSubRegion(RegionT *SubRegion, bool moveChildren) {
0370   assert(!SubRegion->parent && "SubRegion already has a parent!");
0371   assert(llvm::none_of(*this,
0372                        [&](const std::unique_ptr<RegionT> &R) {
0373                          return R.get() == SubRegion;
0374                        }) &&
0375          "Subregion already exists!");
0376 
0377   SubRegion->parent = static_cast<RegionT *>(this);
0378   children.push_back(std::unique_ptr<RegionT>(SubRegion));
0379 
0380   if (!moveChildren)
0381     return;
0382 
0383   assert(SubRegion->children.empty() &&
0384          "SubRegions that contain children are not supported");
0385 
0386   for (RegionNodeT *Element : elements()) {
0387     if (!Element->isSubRegion()) {
0388       BlockT *BB = Element->template getNodeAs<BlockT>();
0389 
0390       if (SubRegion->contains(BB))
0391         RI->setRegionFor(BB, SubRegion);
0392     }
0393   }
0394 
0395   std::vector<std::unique_ptr<RegionT>> Keep;
0396   for (std::unique_ptr<RegionT> &R : *this) {
0397     if (SubRegion->contains(R.get()) && R.get() != SubRegion) {
0398       R->parent = SubRegion;
0399       SubRegion->children.push_back(std::move(R));
0400     } else
0401       Keep.push_back(std::move(R));
0402   }
0403 
0404   children.clear();
0405   children.insert(
0406       children.begin(),
0407       std::move_iterator<typename RegionSet::iterator>(Keep.begin()),
0408       std::move_iterator<typename RegionSet::iterator>(Keep.end()));
0409 }
0410 
0411 template <class Tr>
0412 typename Tr::RegionT *RegionBase<Tr>::removeSubRegion(RegionT *Child) {
0413   assert(Child->parent == this && "Child is not a child of this region!");
0414   Child->parent = nullptr;
0415   typename RegionSet::iterator I =
0416       llvm::find_if(children, [&](const std::unique_ptr<RegionT> &R) {
0417         return R.get() == Child;
0418       });
0419   assert(I != children.end() && "Region does not exit. Unable to remove.");
0420   children.erase(children.begin() + (I - begin()));
0421   return Child;
0422 }
0423 
0424 template <class Tr>
0425 unsigned RegionBase<Tr>::getDepth() const {
0426   unsigned Depth = 0;
0427 
0428   for (RegionT *R = getParent(); R != nullptr; R = R->getParent())
0429     ++Depth;
0430 
0431   return Depth;
0432 }
0433 
0434 template <class Tr>
0435 typename Tr::RegionT *RegionBase<Tr>::getExpandedRegion() const {
0436   unsigned NumSuccessors = Tr::getNumSuccessors(exit);
0437 
0438   if (NumSuccessors == 0)
0439     return nullptr;
0440 
0441   RegionT *R = RI->getRegionFor(exit);
0442 
0443   if (R->getEntry() != exit) {
0444     for (BlockT *Pred : llvm::inverse_children<BlockT *>(getExit()))
0445       if (!contains(Pred))
0446         return nullptr;
0447     if (Tr::getNumSuccessors(exit) == 1)
0448       return new RegionT(getEntry(), *BlockTraits::child_begin(exit), RI, DT);
0449     return nullptr;
0450   }
0451 
0452   while (R->getParent() && R->getParent()->getEntry() == exit)
0453     R = R->getParent();
0454 
0455   for (BlockT *Pred : llvm::inverse_children<BlockT *>(getExit())) {
0456     if (!(contains(Pred) || R->contains(Pred)))
0457       return nullptr;
0458   }
0459 
0460   return new RegionT(getEntry(), R->getExit(), RI, DT);
0461 }
0462 
0463 template <class Tr>
0464 void RegionBase<Tr>::print(raw_ostream &OS, bool print_tree, unsigned level,
0465                            PrintStyle Style) const {
0466   if (print_tree)
0467     OS.indent(level * 2) << '[' << level << "] " << getNameStr();
0468   else
0469     OS.indent(level * 2) << getNameStr();
0470 
0471   OS << '\n';
0472 
0473   if (Style != PrintNone) {
0474     OS.indent(level * 2) << "{\n";
0475     OS.indent(level * 2 + 2);
0476 
0477     if (Style == PrintBB) {
0478       for (const auto *BB : blocks())
0479         OS << BB->getName() << ", "; // TODO: remove the last ","
0480     } else if (Style == PrintRN) {
0481       for (const RegionNodeT *Element : elements()) {
0482         OS << *Element << ", "; // TODO: remove the last ",
0483       }
0484     }
0485 
0486     OS << '\n';
0487   }
0488 
0489   if (print_tree) {
0490     for (const std::unique_ptr<RegionT> &R : *this)
0491       R->print(OS, print_tree, level + 1, Style);
0492   }
0493 
0494   if (Style != PrintNone)
0495     OS.indent(level * 2) << "} \n";
0496 }
0497 
0498 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0499 template <class Tr>
0500 void RegionBase<Tr>::dump() const {
0501   print(dbgs(), true, getDepth(), RegionInfoBase<Tr>::printStyle);
0502 }
0503 #endif
0504 
0505 template <class Tr>
0506 void RegionBase<Tr>::clearNodeCache() {
0507   BBNodeMap.clear();
0508   for (std::unique_ptr<RegionT> &R : *this)
0509     R->clearNodeCache();
0510 }
0511 
0512 //===----------------------------------------------------------------------===//
0513 // RegionInfoBase implementation
0514 //
0515 
0516 template <class Tr>
0517 RegionInfoBase<Tr>::RegionInfoBase() = default;
0518 
0519 template <class Tr>
0520 RegionInfoBase<Tr>::~RegionInfoBase() {
0521   releaseMemory();
0522 }
0523 
0524 template <class Tr>
0525 void RegionInfoBase<Tr>::verifyBBMap(const RegionT *R) const {
0526   assert(R && "Re must be non-null");
0527   for (const typename Tr::RegionNodeT *Element : R->elements()) {
0528     if (Element->isSubRegion()) {
0529       const RegionT *SR = Element->template getNodeAs<RegionT>();
0530       verifyBBMap(SR);
0531     } else {
0532       BlockT *BB = Element->template getNodeAs<BlockT>();
0533       if (getRegionFor(BB) != R)
0534         report_fatal_error("BB map does not match region nesting");
0535     }
0536   }
0537 }
0538 
0539 template <class Tr>
0540 bool RegionInfoBase<Tr>::isCommonDomFrontier(BlockT *BB, BlockT *entry,
0541                                              BlockT *exit) const {
0542   for (BlockT *P : llvm::inverse_children<BlockT *>(BB)) {
0543     if (DT->dominates(entry, P) && !DT->dominates(exit, P))
0544       return false;
0545   }
0546 
0547   return true;
0548 }
0549 
0550 template <class Tr>
0551 bool RegionInfoBase<Tr>::isRegion(BlockT *entry, BlockT *exit) const {
0552   assert(entry && exit && "entry and exit must not be null!");
0553 
0554   using DST = typename DomFrontierT::DomSetType;
0555 
0556   DST *entrySuccs = &DF->find(entry)->second;
0557 
0558   // Exit is the header of a loop that contains the entry. In this case,
0559   // the dominance frontier must only contain the exit.
0560   if (!DT->dominates(entry, exit)) {
0561     for (BlockT *successor : *entrySuccs) {
0562       if (successor != exit && successor != entry)
0563         return false;
0564     }
0565 
0566     return true;
0567   }
0568 
0569   DST *exitSuccs = &DF->find(exit)->second;
0570 
0571   // Do not allow edges leaving the region.
0572   for (BlockT *Succ : *entrySuccs) {
0573     if (Succ == exit || Succ == entry)
0574       continue;
0575     if (!exitSuccs->contains(Succ))
0576       return false;
0577     if (!isCommonDomFrontier(Succ, entry, exit))
0578       return false;
0579   }
0580 
0581   // Do not allow edges pointing into the region.
0582   for (BlockT *Succ : *exitSuccs) {
0583     if (DT->properlyDominates(entry, Succ) && Succ != exit)
0584       return false;
0585   }
0586 
0587   return true;
0588 }
0589 
0590 template <class Tr>
0591 void RegionInfoBase<Tr>::insertShortCut(BlockT *entry, BlockT *exit,
0592                                         BBtoBBMap *ShortCut) const {
0593   assert(entry && exit && "entry and exit must not be null!");
0594 
0595   typename BBtoBBMap::iterator e = ShortCut->find(exit);
0596 
0597   if (e == ShortCut->end())
0598     // No further region at exit available.
0599     (*ShortCut)[entry] = exit;
0600   else {
0601     // We found a region e that starts at exit. Therefore (entry, e->second)
0602     // is also a region, that is larger than (entry, exit). Insert the
0603     // larger one.
0604     BlockT *BB = e->second;
0605     (*ShortCut)[entry] = BB;
0606   }
0607 }
0608 
0609 template <class Tr>
0610 typename Tr::DomTreeNodeT *
0611 RegionInfoBase<Tr>::getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const {
0612   typename BBtoBBMap::iterator e = ShortCut->find(N->getBlock());
0613 
0614   if (e == ShortCut->end())
0615     return N->getIDom();
0616 
0617   return PDT->getNode(e->second)->getIDom();
0618 }
0619 
0620 template <class Tr>
0621 bool RegionInfoBase<Tr>::isTrivialRegion(BlockT *entry, BlockT *exit) const {
0622   assert(entry && exit && "entry and exit must not be null!");
0623 
0624   unsigned num_successors =
0625       BlockTraits::child_end(entry) - BlockTraits::child_begin(entry);
0626 
0627   if (num_successors <= 1 && exit == *(BlockTraits::child_begin(entry)))
0628     return true;
0629 
0630   return false;
0631 }
0632 
0633 template <class Tr>
0634 typename Tr::RegionT *RegionInfoBase<Tr>::createRegion(BlockT *entry,
0635                                                        BlockT *exit) {
0636   assert(entry && exit && "entry and exit must not be null!");
0637 
0638   if (isTrivialRegion(entry, exit))
0639     return nullptr;
0640 
0641   RegionT *region =
0642       new RegionT(entry, exit, static_cast<RegionInfoT *>(this), DT);
0643   BBtoRegion.insert({entry, region});
0644 
0645   region->verifyRegion();
0646 
0647   updateStatistics(region);
0648   return region;
0649 }
0650 
0651 template <class Tr>
0652 void RegionInfoBase<Tr>::findRegionsWithEntry(BlockT *entry,
0653                                               BBtoBBMap *ShortCut) {
0654   assert(entry);
0655 
0656   DomTreeNodeT *N = PDT->getNode(entry);
0657   if (!N)
0658     return;
0659 
0660   RegionT *lastRegion = nullptr;
0661   BlockT *lastExit = entry;
0662 
0663   // As only a BasicBlock that postdominates entry can finish a region, walk the
0664   // post dominance tree upwards.
0665   while ((N = getNextPostDom(N, ShortCut))) {
0666     BlockT *exit = N->getBlock();
0667 
0668     if (!exit)
0669       break;
0670 
0671     if (isRegion(entry, exit)) {
0672       RegionT *newRegion = createRegion(entry, exit);
0673 
0674       if (lastRegion)
0675         newRegion->addSubRegion(lastRegion);
0676 
0677       lastRegion = newRegion;
0678       lastExit = exit;
0679     }
0680 
0681     // This can never be a region, so stop the search.
0682     if (!DT->dominates(entry, exit))
0683       break;
0684   }
0685 
0686   // Tried to create regions from entry to lastExit.  Next time take a
0687   // shortcut from entry to lastExit.
0688   if (lastExit != entry)
0689     insertShortCut(entry, lastExit, ShortCut);
0690 }
0691 
0692 template <class Tr>
0693 void RegionInfoBase<Tr>::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) {
0694   using FuncPtrT = std::add_pointer_t<FuncT>;
0695 
0696   BlockT *entry = GraphTraits<FuncPtrT>::getEntryNode(&F);
0697   DomTreeNodeT *N = DT->getNode(entry);
0698 
0699   // Iterate over the dominance tree in post order to start with the small
0700   // regions from the bottom of the dominance tree.  If the small regions are
0701   // detected first, detection of bigger regions is faster, as we can jump
0702   // over the small regions.
0703   for (auto DomNode : post_order(N))
0704     findRegionsWithEntry(DomNode->getBlock(), ShortCut);
0705 }
0706 
0707 template <class Tr>
0708 typename Tr::RegionT *RegionInfoBase<Tr>::getTopMostParent(RegionT *region) {
0709   while (region->getParent())
0710     region = region->getParent();
0711 
0712   return region;
0713 }
0714 
0715 template <class Tr>
0716 void RegionInfoBase<Tr>::buildRegionsTree(DomTreeNodeT *N, RegionT *region) {
0717   BlockT *BB = N->getBlock();
0718 
0719   // Passed region exit
0720   while (BB == region->getExit())
0721     region = region->getParent();
0722 
0723   typename BBtoRegionMap::iterator it = BBtoRegion.find(BB);
0724 
0725   // This basic block is a start block of a region. It is already in the
0726   // BBtoRegion relation. Only the child basic blocks have to be updated.
0727   if (it != BBtoRegion.end()) {
0728     RegionT *newRegion = it->second;
0729     region->addSubRegion(getTopMostParent(newRegion));
0730     region = newRegion;
0731   } else {
0732     BBtoRegion[BB] = region;
0733   }
0734 
0735   for (DomTreeNodeBase<BlockT> *C : *N) {
0736     buildRegionsTree(C, region);
0737   }
0738 }
0739 
0740 #ifdef EXPENSIVE_CHECKS
0741 template <class Tr>
0742 bool RegionInfoBase<Tr>::VerifyRegionInfo = true;
0743 #else
0744 template <class Tr>
0745 bool RegionInfoBase<Tr>::VerifyRegionInfo = false;
0746 #endif
0747 
0748 template <class Tr>
0749 typename Tr::RegionT::PrintStyle RegionInfoBase<Tr>::printStyle =
0750     RegionBase<Tr>::PrintNone;
0751 
0752 template <class Tr>
0753 void RegionInfoBase<Tr>::print(raw_ostream &OS) const {
0754   OS << "Region tree:\n";
0755   TopLevelRegion->print(OS, true, 0, printStyle);
0756   OS << "End region tree\n";
0757 }
0758 
0759 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0760 template <class Tr>
0761 void RegionInfoBase<Tr>::dump() const { print(dbgs()); }
0762 #endif
0763 
0764 template <class Tr> void RegionInfoBase<Tr>::releaseMemory() {
0765   BBtoRegion.clear();
0766   if (TopLevelRegion) {
0767     delete TopLevelRegion;
0768     TopLevelRegion = nullptr;
0769   }
0770 }
0771 
0772 template <class Tr>
0773 void RegionInfoBase<Tr>::verifyAnalysis() const {
0774   // Do only verify regions if explicitely activated using EXPENSIVE_CHECKS or
0775   // -verify-region-info
0776   if (!RegionInfoBase<Tr>::VerifyRegionInfo)
0777     return;
0778 
0779   TopLevelRegion->verifyRegionNest();
0780 
0781   verifyBBMap(TopLevelRegion);
0782 }
0783 
0784 // Region pass manager support.
0785 template <class Tr>
0786 typename Tr::RegionT *RegionInfoBase<Tr>::getRegionFor(BlockT *BB) const {
0787   return BBtoRegion.lookup(BB);
0788 }
0789 
0790 template <class Tr>
0791 void RegionInfoBase<Tr>::setRegionFor(BlockT *BB, RegionT *R) {
0792   BBtoRegion[BB] = R;
0793 }
0794 
0795 template <class Tr>
0796 typename Tr::RegionT *RegionInfoBase<Tr>::operator[](BlockT *BB) const {
0797   return getRegionFor(BB);
0798 }
0799 
0800 template <class Tr>
0801 typename RegionInfoBase<Tr>::BlockT *
0802 RegionInfoBase<Tr>::getMaxRegionExit(BlockT *BB) const {
0803   BlockT *Exit = nullptr;
0804 
0805   while (true) {
0806     // Get largest region that starts at BB.
0807     RegionT *R = getRegionFor(BB);
0808     while (R && R->getParent() && R->getParent()->getEntry() == BB)
0809       R = R->getParent();
0810 
0811     // Get the single exit of BB.
0812     if (R && R->getEntry() == BB)
0813       Exit = R->getExit();
0814     else if (std::next(BlockTraits::child_begin(BB)) ==
0815              BlockTraits::child_end(BB))
0816       Exit = *BlockTraits::child_begin(BB);
0817     else // No single exit exists.
0818       return Exit;
0819 
0820     // Get largest region that starts at Exit.
0821     RegionT *ExitR = getRegionFor(Exit);
0822     while (ExitR && ExitR->getParent() &&
0823            ExitR->getParent()->getEntry() == Exit)
0824       ExitR = ExitR->getParent();
0825 
0826     for (BlockT *Pred : llvm::inverse_children<BlockT *>(Exit)) {
0827       if (!R->contains(Pred) && !ExitR->contains(Pred))
0828         break;
0829     }
0830 
0831     // This stops infinite cycles.
0832     if (DT->dominates(Exit, BB))
0833       break;
0834 
0835     BB = Exit;
0836   }
0837 
0838   return Exit;
0839 }
0840 
0841 template <class Tr>
0842 typename Tr::RegionT *RegionInfoBase<Tr>::getCommonRegion(RegionT *A,
0843                                                           RegionT *B) const {
0844   assert(A && B && "One of the Regions is NULL");
0845 
0846   if (A->contains(B))
0847     return A;
0848 
0849   while (!B->contains(A))
0850     B = B->getParent();
0851 
0852   return B;
0853 }
0854 
0855 template <class Tr>
0856 typename Tr::RegionT *
0857 RegionInfoBase<Tr>::getCommonRegion(SmallVectorImpl<RegionT *> &Regions) const {
0858   RegionT *ret = Regions.pop_back_val();
0859 
0860   for (RegionT *R : Regions)
0861     ret = getCommonRegion(ret, R);
0862 
0863   return ret;
0864 }
0865 
0866 template <class Tr>
0867 typename Tr::RegionT *
0868 RegionInfoBase<Tr>::getCommonRegion(SmallVectorImpl<BlockT *> &BBs) const {
0869   RegionT *ret = getRegionFor(BBs.back());
0870   BBs.pop_back();
0871 
0872   for (BlockT *BB : BBs)
0873     ret = getCommonRegion(ret, getRegionFor(BB));
0874 
0875   return ret;
0876 }
0877 
0878 template <class Tr>
0879 void RegionInfoBase<Tr>::calculate(FuncT &F) {
0880   using FuncPtrT = std::add_pointer_t<FuncT>;
0881 
0882   // ShortCut a function where for every BB the exit of the largest region
0883   // starting with BB is stored. These regions can be threated as single BBS.
0884   // This improves performance on linear CFGs.
0885   BBtoBBMap ShortCut;
0886 
0887   scanForRegions(F, &ShortCut);
0888   BlockT *BB = GraphTraits<FuncPtrT>::getEntryNode(&F);
0889   buildRegionsTree(DT->getNode(BB), TopLevelRegion);
0890 }
0891 
0892 } // end namespace llvm
0893 
0894 #undef DEBUG_TYPE
0895 
0896 #endif // LLVM_ANALYSIS_REGIONINFOIMPL_H