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<RegionInfo*> : public DOTGraphTraits<RegionNode*> { 00060 00061 DOTGraphTraits (bool isSimple=false) 00062 : DOTGraphTraits<RegionNode*>(isSimple) {} 00063 00064 static std::string getGraphName(RegionInfo *DT) { 00065 return "Region Graph"; 00066 } 00067 00068 std::string getNodeLabel(RegionNode *Node, RegionInfo *G) { 00069 return DOTGraphTraits<RegionNode*>::getNodeLabel(Node, 00070 G->getTopLevelRegion()); 00071 } 00072 00073 std::string getEdgeAttributes(RegionNode *srcNode, 00074 GraphTraits<RegionInfo*>::ChildIteratorType CI, RegionInfo *RI) { 00075 00076 RegionNode *destNode = *CI; 00077 00078 if (srcNode->isSubRegion() || destNode->isSubRegion()) 00079 return ""; 00080 00081 // In case of a backedge, do not use it to define the layout of the nodes. 00082 BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>(); 00083 BasicBlock *destBB = destNode->getNodeAs<BasicBlock>(); 00084 00085 Region *R = RI->getRegionFor(destBB); 00086 00087 while (R && R->getParent()) 00088 if (R->getParent()->getEntry() == destBB) 00089 R = R->getParent(); 00090 else 00091 break; 00092 00093 if (R->getEntry() == destBB && R->contains(srcBB)) 00094 return "constraint=false"; 00095 00096 return ""; 00097 } 00098 00099 // Print the cluster of the subregions. This groups the single basic blocks 00100 // and adds a different background color for each group. 00101 static void printRegionCluster(const Region *R, GraphWriter<RegionInfo*> &GW, 00102 unsigned depth = 0) { 00103 raw_ostream &O = GW.getOStream(); 00104 O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(R) 00105 << " {\n"; 00106 O.indent(2 * (depth + 1)) << "label = \"\";\n"; 00107 00108 if (!onlySimpleRegions || R->isSimple()) { 00109 O.indent(2 * (depth + 1)) << "style = filled;\n"; 00110 O.indent(2 * (depth + 1)) << "color = " 00111 << ((R->getDepth() * 2 % 12) + 1) << "\n"; 00112 00113 } else { 00114 O.indent(2 * (depth + 1)) << "style = solid;\n"; 00115 O.indent(2 * (depth + 1)) << "color = " 00116 << ((R->getDepth() * 2 % 12) + 2) << "\n"; 00117 } 00118 00119 for (Region::const_iterator RI = R->begin(), RE = R->end(); RI != RE; ++RI) 00120 printRegionCluster(*RI, GW, depth + 1); 00121 00122 RegionInfo *RI = R->getRegionInfo(); 00123 00124 for (Region::const_block_iterator BI = R->block_begin(), 00125 BE = R->block_end(); BI != BE; ++BI) 00126 if (RI->getRegionFor(*BI) == R) 00127 O.indent(2 * (depth + 1)) << "Node" 00128 << static_cast<const void*>(RI->getTopLevelRegion()->getBBNode(*BI)) 00129 << ";\n"; 00130 00131 O.indent(2 * depth) << "}\n"; 00132 } 00133 00134 static void addCustomGraphFeatures(const RegionInfo* RI, 00135 GraphWriter<RegionInfo*> &GW) { 00136 raw_ostream &O = GW.getOStream(); 00137 O << "\tcolorscheme = \"paired12\"\n"; 00138 printRegionCluster(RI->getTopLevelRegion(), GW, 4); 00139 } 00140 }; 00141 } //end namespace llvm 00142 00143 namespace { 00144 00145 struct RegionViewer 00146 : public DOTGraphTraitsViewer<RegionInfo, false> { 00147 static char ID; 00148 RegionViewer() : DOTGraphTraitsViewer<RegionInfo, false>("reg", ID){ 00149 initializeRegionViewerPass(*PassRegistry::getPassRegistry()); 00150 } 00151 }; 00152 char RegionViewer::ID = 0; 00153 00154 struct RegionOnlyViewer 00155 : public DOTGraphTraitsViewer<RegionInfo, true> { 00156 static char ID; 00157 RegionOnlyViewer() : DOTGraphTraitsViewer<RegionInfo, true>("regonly", ID) { 00158 initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry()); 00159 } 00160 }; 00161 char RegionOnlyViewer::ID = 0; 00162 00163 struct RegionPrinter 00164 : public DOTGraphTraitsPrinter<RegionInfo, false> { 00165 static char ID; 00166 RegionPrinter() : 00167 DOTGraphTraitsPrinter<RegionInfo, false>("reg", ID) { 00168 initializeRegionPrinterPass(*PassRegistry::getPassRegistry()); 00169 } 00170 }; 00171 char RegionPrinter::ID = 0; 00172 } //end anonymous namespace 00173 00174 INITIALIZE_PASS(RegionPrinter, "dot-regions", 00175 "Print regions of function to 'dot' file", true, true) 00176 00177 INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function", 00178 true, true) 00179 00180 INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only", 00181 "View regions of function (with no function bodies)", 00182 true, true) 00183 00184 namespace { 00185 00186 struct RegionOnlyPrinter 00187 : public DOTGraphTraitsPrinter<RegionInfo, true> { 00188 static char ID; 00189 RegionOnlyPrinter() : 00190 DOTGraphTraitsPrinter<RegionInfo, true>("reg", ID) { 00191 initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry()); 00192 } 00193 }; 00194 00195 } 00196 00197 char RegionOnlyPrinter::ID = 0; 00198 INITIALIZE_PASS(RegionOnlyPrinter, "dot-regions-only", 00199 "Print regions of function to 'dot' file " 00200 "(with no function bodies)", 00201 true, true) 00202 00203 FunctionPass* llvm::createRegionViewerPass() { 00204 return new RegionViewer(); 00205 } 00206 00207 FunctionPass* llvm::createRegionOnlyViewerPass() { 00208 return new RegionOnlyViewer(); 00209 } 00210 00211 FunctionPass* llvm::createRegionPrinterPass() { 00212 return new RegionPrinter(); 00213 } 00214 00215 FunctionPass* llvm::createRegionOnlyPrinterPass() { 00216 return new RegionOnlyPrinter(); 00217 } 00218