| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 1 | //===- RegionInfo.cpp - SESE region detection analysis --------------------===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // Detects single entry single exit regions in the control flow graph. | 
|  | 10 | //===----------------------------------------------------------------------===// | 
|  | 11 |  | 
|  | 12 | #include "llvm/Analysis/RegionInfo.h" | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 13 | #include "llvm/ADT/PostOrderIterator.h" | 
|  | 14 | #include "llvm/ADT/Statistic.h" | 
| Chandler Carruth | ed0881b | 2012-12-03 16:50:05 +0000 | [diff] [blame] | 15 | #include "llvm/Analysis/LoopInfo.h" | 
| Chandler Carruth | d990388 | 2015-01-14 11:23:27 +0000 | [diff] [blame] | 16 | #include "llvm/Analysis/RegionInfoImpl.h" | 
| Chandler Carruth | ed0881b | 2012-12-03 16:50:05 +0000 | [diff] [blame] | 17 | #include "llvm/Analysis/RegionIterator.h" | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 18 | #include "llvm/Support/CommandLine.h" | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 19 | #include "llvm/Support/Debug.h" | 
| Chandler Carruth | 8a8cd2b | 2014-01-07 11:48:04 +0000 | [diff] [blame] | 20 | #include "llvm/Support/ErrorHandling.h" | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 21 | #include <algorithm> | 
| David Blaikie | ec649ac | 2014-04-15 18:32:43 +0000 | [diff] [blame] | 22 | #include <iterator> | 
| Bill Wendling | 570d302 | 2013-08-21 21:14:19 +0000 | [diff] [blame] | 23 | #include <set> | 
| Michael Kruse | 20dcc9f | 2015-08-10 13:21:59 +0000 | [diff] [blame] | 24 | #ifndef NDEBUG | 
|  | 25 | #include "llvm/Analysis/RegionPrinter.h" | 
|  | 26 | #endif | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 27 |  | 
|  | 28 | using namespace llvm; | 
|  | 29 |  | 
| Chandler Carruth | f1221bd | 2014-04-22 02:48:03 +0000 | [diff] [blame] | 30 | #define DEBUG_TYPE "region" | 
|  | 31 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 32 | namespace llvm { | 
|  | 33 | template class RegionBase<RegionTraits<Function>>; | 
|  | 34 | template class RegionNodeBase<RegionTraits<Function>>; | 
|  | 35 | template class RegionInfoBase<RegionTraits<Function>>; | 
|  | 36 | } | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 37 |  | 
|  | 38 | STATISTIC(numRegions,       "The # of regions"); | 
|  | 39 | STATISTIC(numSimpleRegions, "The # of simple regions"); | 
|  | 40 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 41 | // Always verify if expensive checking is enabled. | 
|  | 42 |  | 
|  | 43 | static cl::opt<bool,true> | 
|  | 44 | VerifyRegionInfoX( | 
|  | 45 | "verify-region-info", | 
|  | 46 | cl::location(RegionInfoBase<RegionTraits<Function>>::VerifyRegionInfo), | 
|  | 47 | cl::desc("Verify region info (time consuming)")); | 
|  | 48 |  | 
|  | 49 |  | 
|  | 50 | static cl::opt<Region::PrintStyle, true> printStyleX("print-region-style", | 
|  | 51 | cl::location(RegionInfo::printStyle), | 
| Tobias Grosser | 8b304ff | 2011-04-04 07:19:18 +0000 | [diff] [blame] | 52 | cl::Hidden, | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 53 | cl::desc("style of printing regions"), | 
|  | 54 | cl::values( | 
| Tobias Grosser | 8b304ff | 2011-04-04 07:19:18 +0000 | [diff] [blame] | 55 | clEnumValN(Region::PrintNone, "none",  "print no details"), | 
|  | 56 | clEnumValN(Region::PrintBB, "bb", | 
| Hongbin Zheng | 14c05c4 | 2012-08-27 13:49:24 +0000 | [diff] [blame] | 57 | "print regions in detail with block_iterator"), | 
| Tobias Grosser | 8b304ff | 2011-04-04 07:19:18 +0000 | [diff] [blame] | 58 | clEnumValN(Region::PrintRN, "rn", | 
|  | 59 | "print regions in detail with element_iterator"), | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 60 | clEnumValEnd)); | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 61 |  | 
|  | 62 |  | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 63 | //===----------------------------------------------------------------------===// | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 64 | // Region implementation | 
|  | 65 | // | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 66 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 67 | Region::Region(BasicBlock *Entry, BasicBlock *Exit, | 
|  | 68 | RegionInfo* RI, | 
|  | 69 | DominatorTree *DT, Region *Parent) : | 
|  | 70 | RegionBase<RegionTraits<Function>>(Entry, Exit, RI, DT, Parent) { | 
| Daniel Dunbar | 18e39ce | 2010-07-28 20:28:50 +0000 | [diff] [blame] | 71 |  | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 72 | } | 
|  | 73 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 74 | Region::~Region() { } | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 75 |  | 
|  | 76 | //===----------------------------------------------------------------------===// | 
|  | 77 | // RegionInfo implementation | 
|  | 78 | // | 
|  | 79 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 80 | RegionInfo::RegionInfo() : | 
|  | 81 | RegionInfoBase<RegionTraits<Function>>() { | 
|  | 82 |  | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 83 | } | 
|  | 84 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 85 | RegionInfo::~RegionInfo() { | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 86 |  | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 87 | } | 
|  | 88 |  | 
|  | 89 | void RegionInfo::updateStatistics(Region *R) { | 
|  | 90 | ++numRegions; | 
|  | 91 |  | 
|  | 92 | // TODO: Slow. Should only be enabled if -stats is used. | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 93 | if (R->isSimple()) | 
|  | 94 | ++numSimpleRegions; | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 95 | } | 
|  | 96 |  | 
| NAKAMURA Takumi | 8eb82fc | 2014-07-20 03:57:51 +0000 | [diff] [blame] | 97 | void RegionInfo::recalculate(Function &F, DominatorTree *DT_, | 
|  | 98 | PostDominatorTree *PDT_, DominanceFrontier *DF_) { | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 99 | DT = DT_; | 
|  | 100 | PDT = PDT_; | 
|  | 101 | DF = DF_; | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 102 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 103 | TopLevelRegion = new Region(&F.getEntryBlock(), nullptr, | 
|  | 104 | this, DT, nullptr); | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 105 | updateStatistics(TopLevelRegion); | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 106 | calculate(F); | 
|  | 107 | } | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 108 |  | 
| Michael Kruse | 20dcc9f | 2015-08-10 13:21:59 +0000 | [diff] [blame] | 109 | #ifndef NDEBUG | 
|  | 110 | void RegionInfo::view() { viewRegion(this); } | 
|  | 111 |  | 
|  | 112 | void RegionInfo::viewOnly() { viewRegionOnly(this); } | 
|  | 113 | #endif | 
|  | 114 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 115 | //===----------------------------------------------------------------------===// | 
|  | 116 | // RegionInfoPass implementation | 
|  | 117 | // | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 118 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 119 | RegionInfoPass::RegionInfoPass() : FunctionPass(ID) { | 
|  | 120 | initializeRegionInfoPassPass(*PassRegistry::getPassRegistry()); | 
|  | 121 | } | 
|  | 122 |  | 
|  | 123 | RegionInfoPass::~RegionInfoPass() { | 
|  | 124 |  | 
|  | 125 | } | 
|  | 126 |  | 
|  | 127 | bool RegionInfoPass::runOnFunction(Function &F) { | 
|  | 128 | releaseMemory(); | 
|  | 129 |  | 
|  | 130 | auto DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); | 
|  | 131 | auto PDT = &getAnalysis<PostDominatorTree>(); | 
|  | 132 | auto DF = &getAnalysis<DominanceFrontier>(); | 
|  | 133 |  | 
|  | 134 | RI.recalculate(F, DT, PDT, DF); | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 135 | return false; | 
|  | 136 | } | 
|  | 137 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 138 | void RegionInfoPass::releaseMemory() { | 
|  | 139 | RI.releaseMemory(); | 
|  | 140 | } | 
|  | 141 |  | 
|  | 142 | void RegionInfoPass::verifyAnalysis() const { | 
|  | 143 | RI.verifyAnalysis(); | 
|  | 144 | } | 
|  | 145 |  | 
|  | 146 | void RegionInfoPass::getAnalysisUsage(AnalysisUsage &AU) const { | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 147 | AU.setPreservesAll(); | 
| Chandler Carruth | 7352302 | 2014-01-13 13:07:17 +0000 | [diff] [blame] | 148 | AU.addRequiredTransitive<DominatorTreeWrapperPass>(); | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 149 | AU.addRequired<PostDominatorTree>(); | 
|  | 150 | AU.addRequired<DominanceFrontier>(); | 
|  | 151 | } | 
|  | 152 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 153 | void RegionInfoPass::print(raw_ostream &OS, const Module *) const { | 
|  | 154 | RI.print(OS); | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 155 | } | 
|  | 156 |  | 
| NAKAMURA Takumi | 118b0c7 | 2014-07-20 00:00:42 +0000 | [diff] [blame] | 157 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 158 | void RegionInfoPass::dump() const { | 
|  | 159 | RI.dump(); | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 160 | } | 
| NAKAMURA Takumi | 118b0c7 | 2014-07-20 00:00:42 +0000 | [diff] [blame] | 161 | #endif | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 162 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 163 | char RegionInfoPass::ID = 0; | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 164 |  | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 165 | INITIALIZE_PASS_BEGIN(RegionInfoPass, "regions", | 
| Owen Anderson | 8ac477f | 2010-10-12 19:48:12 +0000 | [diff] [blame] | 166 | "Detect single entry single exit regions", true, true) | 
| Chandler Carruth | 7352302 | 2014-01-13 13:07:17 +0000 | [diff] [blame] | 167 | INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) | 
| Owen Anderson | 8ac477f | 2010-10-12 19:48:12 +0000 | [diff] [blame] | 168 | INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) | 
|  | 169 | INITIALIZE_PASS_DEPENDENCY(DominanceFrontier) | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 170 | INITIALIZE_PASS_END(RegionInfoPass, "regions", | 
| Owen Anderson | df7a4f2 | 2010-10-07 22:25:06 +0000 | [diff] [blame] | 171 | "Detect single entry single exit regions", true, true) | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 172 |  | 
|  | 173 | // Create methods available outside of this file, to use them | 
|  | 174 | // "include/llvm/LinkAllPasses.h". Otherwise the pass would be deleted by | 
|  | 175 | // the link time optimization. | 
|  | 176 |  | 
|  | 177 | namespace llvm { | 
|  | 178 | FunctionPass *createRegionInfoPass() { | 
| Matt Arsenault | 1b8d837 | 2014-07-19 18:29:29 +0000 | [diff] [blame] | 179 | return new RegionInfoPass(); | 
| Tobias Grosser | 336734a | 2010-07-22 07:46:31 +0000 | [diff] [blame] | 180 | } | 
|  | 181 | } | 
|  | 182 |  |