RegionPrinter.cpp revision 212904
1//===- RegionPrinter.cpp - Print regions tree pass ------------------------===// 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// Print out the region tree of a function using dotty/graphviz. 10//===----------------------------------------------------------------------===// 11 12#include "llvm/Analysis/RegionInfo.h" 13#include "llvm/Analysis/RegionIterator.h" 14#include "llvm/Analysis/RegionPrinter.h" 15#include "llvm/Analysis/Passes.h" 16#include "llvm/Analysis/DOTGraphTraitsPass.h" 17#include "llvm/ADT/Statistic.h" 18#include "llvm/ADT/PostOrderIterator.h" 19#include "llvm/ADT/DepthFirstIterator.h" 20#include "llvm/Support/Debug.h" 21#include "llvm/Support/CommandLine.h" 22#include "llvm/Support/raw_ostream.h" 23 24using namespace llvm; 25 26//===----------------------------------------------------------------------===// 27/// onlySimpleRegion - Show only the simple regions in the RegionViewer. 28static cl::opt<bool> 29onlySimpleRegions("only-simple-regions", 30 cl::desc("Show only simple regions in the graphviz viewer"), 31 cl::Hidden, 32 cl::init(false)); 33 34namespace llvm { 35template<> 36struct DOTGraphTraits<RegionNode*> : public DefaultDOTGraphTraits { 37 38 DOTGraphTraits (bool isSimple=false) 39 : DefaultDOTGraphTraits(isSimple) {} 40 41 std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) { 42 43 if (!Node->isSubRegion()) { 44 BasicBlock *BB = Node->getNodeAs<BasicBlock>(); 45 46 if (isSimple()) 47 return DOTGraphTraits<const Function*> 48 ::getSimpleNodeLabel(BB, BB->getParent()); 49 else 50 return DOTGraphTraits<const Function*> 51 ::getCompleteNodeLabel(BB, BB->getParent()); 52 } 53 54 return "Not implemented"; 55 } 56}; 57 58template<> 59struct DOTGraphTraits<RegionInfo*> : public DOTGraphTraits<RegionNode*> { 60 61 DOTGraphTraits (bool isSimple=false) 62 : DOTGraphTraits<RegionNode*>(isSimple) {} 63 64 static std::string getGraphName(RegionInfo *DT) { 65 return "Region Graph"; 66 } 67 68 std::string getNodeLabel(RegionNode *Node, RegionInfo *G) { 69 return DOTGraphTraits<RegionNode*>::getNodeLabel(Node, 70 G->getTopLevelRegion()); 71 } 72 73 // Print the cluster of the subregions. This groups the single basic blocks 74 // and adds a different background color for each group. 75 static void printRegionCluster(const Region *R, GraphWriter<RegionInfo*> &GW, 76 unsigned depth = 0) { 77 raw_ostream &O = GW.getOStream(); 78 O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(R) 79 << " {\n"; 80 O.indent(2 * (depth + 1)) << "label = \"\";\n"; 81 82 if (!onlySimpleRegions || R->isSimple()) { 83 O.indent(2 * (depth + 1)) << "style = filled;\n"; 84 O.indent(2 * (depth + 1)) << "color = " 85 << ((R->getDepth() * 2 % 12) + 1) << "\n"; 86 87 } else { 88 O.indent(2 * (depth + 1)) << "style = solid;\n"; 89 O.indent(2 * (depth + 1)) << "color = " 90 << ((R->getDepth() * 2 % 12) + 2) << "\n"; 91 } 92 93 for (Region::const_iterator RI = R->begin(), RE = R->end(); RI != RE; ++RI) 94 printRegionCluster(*RI, GW, depth + 1); 95 96 RegionInfo *RI = R->getRegionInfo(); 97 98 for (Region::const_block_iterator BI = R->block_begin(), 99 BE = R->block_end(); BI != BE; ++BI) { 100 BasicBlock *BB = (*BI)->getNodeAs<BasicBlock>(); 101 if (RI->getRegionFor(BB) == R) 102 O.indent(2 * (depth + 1)) << "Node" 103 << static_cast<const void*>(RI->getTopLevelRegion()->getBBNode(BB)) 104 << ";\n"; 105 } 106 107 O.indent(2 * depth) << "}\n"; 108 } 109 110 static void addCustomGraphFeatures(const RegionInfo* RI, 111 GraphWriter<RegionInfo*> &GW) { 112 raw_ostream &O = GW.getOStream(); 113 O << "\tcolorscheme = \"paired12\"\n"; 114 printRegionCluster(RI->getTopLevelRegion(), GW, 4); 115 } 116}; 117} //end namespace llvm 118 119namespace { 120 121struct RegionViewer 122 : public DOTGraphTraitsViewer<RegionInfo, false> { 123 static char ID; 124 RegionViewer() : DOTGraphTraitsViewer<RegionInfo, false>("reg", ID){} 125}; 126 127char RegionViewer::ID = 0; 128INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function", 129 true, true); 130 131struct RegionOnlyViewer 132 : public DOTGraphTraitsViewer<RegionInfo, true> { 133 static char ID; 134 RegionOnlyViewer() : DOTGraphTraitsViewer<RegionInfo, true>("regonly", ID){} 135}; 136 137char RegionOnlyViewer::ID = 0; 138INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only", 139 "View regions of function (with no function bodies)", 140 true, true); 141 142struct RegionPrinter 143 : public DOTGraphTraitsPrinter<RegionInfo, false> { 144 static char ID; 145 RegionPrinter() : 146 DOTGraphTraitsPrinter<RegionInfo, false>("reg", ID) {} 147}; 148} //end anonymous namespace 149 150char RegionPrinter::ID = 0; 151INITIALIZE_PASS(RegionPrinter, "dot-regions", 152 "Print regions of function to 'dot' file", true, true); 153 154namespace { 155 156struct RegionOnlyPrinter 157 : public DOTGraphTraitsPrinter<RegionInfo, true> { 158 static char ID; 159 RegionOnlyPrinter() : 160 DOTGraphTraitsPrinter<RegionInfo, true>("reg", ID) {} 161}; 162 163} 164 165char RegionOnlyPrinter::ID = 0; 166INITIALIZE_PASS(RegionOnlyPrinter, "dot-regions-only", 167 "Print regions of function to 'dot' file " 168 "(with no function bodies)", 169 true, true); 170 171FunctionPass* llvm::createRegionViewerPass() { 172 return new RegionViewer(); 173} 174 175FunctionPass* llvm::createRegionOnlyViewerPass() { 176 return new RegionOnlyViewer(); 177} 178 179FunctionPass* llvm::createRegionPrinterPass() { 180 return new RegionPrinter(); 181} 182 183FunctionPass* llvm::createRegionOnlyPrinterPass() { 184 return new RegionOnlyPrinter(); 185} 186 187