LLVM API Documentation
00001 //===- RegionPrinter.cpp - Print regions tree pass ------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // Print out the region tree of a function using dotty/graphviz. 00010 //===----------------------------------------------------------------------===// 00011 00012 #include "llvm/Analysis/Passes.h" 00013 #include "llvm/ADT/DepthFirstIterator.h" 00014 #include "llvm/ADT/PostOrderIterator.h" 00015 #include "llvm/ADT/Statistic.h" 00016 #include "llvm/Analysis/DOTGraphTraitsPass.h" 00017 #include "llvm/Analysis/RegionInfo.h" 00018 #include "llvm/Analysis/RegionIterator.h" 00019 #include "llvm/Analysis/RegionPrinter.h" 00020 #include "llvm/Support/CommandLine.h" 00021 #include "llvm/Support/Debug.h" 00022 #include "llvm/Support/raw_ostream.h" 00023 00024 using namespace llvm; 00025 00026 //===----------------------------------------------------------------------===// 00027 /// onlySimpleRegion - Show only the simple regions in the RegionViewer. 00028 static cl::opt<bool> 00029 onlySimpleRegions("only-simple-regions", 00030 cl::desc("Show only simple regions in the graphviz viewer"), 00031 cl::Hidden, 00032 cl::init(false)); 00033 00034 namespace llvm { 00035 template<> 00036 struct DOTGraphTraits<RegionNode*> : public DefaultDOTGraphTraits { 00037 00038 DOTGraphTraits (bool isSimple=false) 00039 : DefaultDOTGraphTraits(isSimple) {} 00040 00041 std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) { 00042 00043 if (!Node->isSubRegion()) { 00044 BasicBlock *BB = Node->getNodeAs<BasicBlock>(); 00045 00046 if (isSimple()) 00047 return DOTGraphTraits<const Function*> 00048 ::getSimpleNodeLabel(BB, BB->getParent()); 00049 else 00050 return DOTGraphTraits<const Function*> 00051 ::getCompleteNodeLabel(BB, BB->getParent()); 00052 } 00053 00054 return "Not implemented"; 00055 } 00056 }; 00057 00058 template<> 00059 struct DOTGraphTraits<RegionInfoPass*> : public DOTGraphTraits<RegionNode*> { 00060 00061 DOTGraphTraits (bool isSimple = false) 00062 : DOTGraphTraits<RegionNode*>(isSimple) {} 00063 00064 static std::string getGraphName(RegionInfoPass *DT) { 00065 return "Region Graph"; 00066 } 00067 00068 std::string getNodeLabel(RegionNode *Node, RegionInfoPass *G) { 00069 RegionInfo &RI = G->getRegionInfo(); 00070 return DOTGraphTraits<RegionNode*>::getNodeLabel(Node, 00071 reinterpret_cast<RegionNode*>(RI.getTopLevelRegion())); 00072 } 00073 00074 std::string getEdgeAttributes(RegionNode *srcNode, 00075 GraphTraits<RegionInfo*>::ChildIteratorType CI, RegionInfoPass *G) { 00076 RegionInfo &RI = G->getRegionInfo(); 00077 RegionNode *destNode = *CI; 00078 00079 if (srcNode->isSubRegion() || destNode->isSubRegion()) 00080 return ""; 00081 00082 // In case of a backedge, do not use it to define the layout of the nodes. 00083 BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>(); 00084 BasicBlock *destBB = destNode->getNodeAs<BasicBlock>(); 00085 00086 Region *R = RI.getRegionFor(destBB); 00087 00088 while (R && R->getParent()) 00089 if (R->getParent()->getEntry() == destBB) 00090 R = R->getParent(); 00091 else 00092 break; 00093 00094 if (R->getEntry() == destBB && R->contains(srcBB)) 00095 return "constraint=false"; 00096 00097 return ""; 00098 } 00099 00100 // Print the cluster of the subregions. This groups the single basic blocks 00101 // and adds a different background color for each group. 00102 static void printRegionCluster(const Region &R, 00103 GraphWriter<RegionInfoPass*> &GW, 00104 unsigned depth = 0) { 00105 raw_ostream &O = GW.getOStream(); 00106 O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(&R) 00107 << " {\n"; 00108 O.indent(2 * (depth + 1)) << "label = \"\";\n"; 00109 00110 if (!onlySimpleRegions || R.isSimple()) { 00111 O.indent(2 * (depth + 1)) << "style = filled;\n"; 00112 O.indent(2 * (depth + 1)) << "color = " 00113 << ((R.getDepth() * 2 % 12) + 1) << "\n"; 00114 00115 } else { 00116 O.indent(2 * (depth + 1)) << "style = solid;\n"; 00117 O.indent(2 * (depth + 1)) << "color = " 00118 << ((R.getDepth() * 2 % 12) + 2) << "\n"; 00119 } 00120 00121 for (Region::const_iterator RI = R.begin(), RE = R.end(); RI != RE; ++RI) 00122 printRegionCluster(**RI, GW, depth + 1); 00123 00124 const RegionInfo &RI = *static_cast<const RegionInfo*>(R.getRegionInfo()); 00125 00126 for (const auto &BB : R.blocks()) 00127 if (RI.getRegionFor(BB) == &R) 00128 O.indent(2 * (depth + 1)) << "Node" 00129 << static_cast<const void*>(RI.getTopLevelRegion()->getBBNode(BB)) 00130 << ";\n"; 00131 00132 O.indent(2 * depth) << "}\n"; 00133 } 00134 00135 static void addCustomGraphFeatures(const RegionInfoPass* RIP, 00136 GraphWriter<RegionInfoPass*> &GW) { 00137 const RegionInfo &RI = RIP->getRegionInfo(); 00138 raw_ostream &O = GW.getOStream(); 00139 O << "\tcolorscheme = \"paired12\"\n"; 00140 printRegionCluster(*RI.getTopLevelRegion(), GW, 4); 00141 } 00142 }; 00143 } //end namespace llvm 00144 00145 namespace { 00146 00147 struct RegionViewer 00148 : public DOTGraphTraitsViewer<RegionInfoPass, false> { 00149 static char ID; 00150 RegionViewer() : DOTGraphTraitsViewer<RegionInfoPass, false>("reg", ID){ 00151 initializeRegionViewerPass(*PassRegistry::getPassRegistry()); 00152 } 00153 }; 00154 char RegionViewer::ID = 0; 00155 00156 struct RegionOnlyViewer 00157 : public DOTGraphTraitsViewer<RegionInfoPass, true> { 00158 static char ID; 00159 RegionOnlyViewer() : DOTGraphTraitsViewer<RegionInfoPass, true>("regonly", ID) { 00160 initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry()); 00161 } 00162 }; 00163 char RegionOnlyViewer::ID = 0; 00164 00165 struct RegionPrinter 00166 : public DOTGraphTraitsPrinter<RegionInfoPass, false> { 00167 static char ID; 00168 RegionPrinter() : 00169 DOTGraphTraitsPrinter<RegionInfoPass, false>("reg", ID) { 00170 initializeRegionPrinterPass(*PassRegistry::getPassRegistry()); 00171 } 00172 }; 00173 char RegionPrinter::ID = 0; 00174 } //end anonymous namespace 00175 00176 INITIALIZE_PASS(RegionPrinter, "dot-regions", 00177 "Print regions of function to 'dot' file", true, true) 00178 00179 INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function", 00180 true, true) 00181 00182 INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only", 00183 "View regions of function (with no function bodies)", 00184 true, true) 00185 00186 namespace { 00187 00188 struct RegionOnlyPrinter 00189 : public DOTGraphTraitsPrinter<RegionInfoPass, true> { 00190 static char ID; 00191 RegionOnlyPrinter() : 00192 DOTGraphTraitsPrinter<RegionInfoPass, true>("reg", ID) { 00193 initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry()); 00194 } 00195 }; 00196 00197 } 00198 00199 char RegionOnlyPrinter::ID = 0; 00200 INITIALIZE_PASS(RegionOnlyPrinter, "dot-regions-only", 00201 "Print regions of function to 'dot' file " 00202 "(with no function bodies)", 00203 true, true) 00204 00205 FunctionPass* llvm::createRegionViewerPass() { 00206 return new RegionViewer(); 00207 } 00208 00209 FunctionPass* llvm::createRegionOnlyViewerPass() { 00210 return new RegionOnlyViewer(); 00211 } 00212 00213 FunctionPass* llvm::createRegionPrinterPass() { 00214 return new RegionPrinter(); 00215 } 00216 00217 FunctionPass* llvm::createRegionOnlyPrinterPass() { 00218 return new RegionOnlyPrinter(); 00219 } 00220