RegionPrinter.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
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/Passes.h" 13#include "llvm/ADT/DepthFirstIterator.h" 14#include "llvm/ADT/PostOrderIterator.h" 15#include "llvm/ADT/Statistic.h" 16#include "llvm/Analysis/DOTGraphTraitsPass.h" 17#include "llvm/Analysis/RegionInfo.h" 18#include "llvm/Analysis/RegionIterator.h" 19#include "llvm/Analysis/RegionPrinter.h" 20#include "llvm/Support/CommandLine.h" 21#include "llvm/Support/Debug.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 std::string getEdgeAttributes(RegionNode *srcNode, 74 GraphTraits<RegionInfo*>::ChildIteratorType CI, RegionInfo *RI) { 75 76 RegionNode *destNode = *CI; 77 78 if (srcNode->isSubRegion() || destNode->isSubRegion()) 79 return ""; 80 81 // In case of a backedge, do not use it to define the layout of the nodes. 82 BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>(); 83 BasicBlock *destBB = destNode->getNodeAs<BasicBlock>(); 84 85 Region *R = RI->getRegionFor(destBB); 86 87 while (R && R->getParent()) 88 if (R->getParent()->getEntry() == destBB) 89 R = R->getParent(); 90 else 91 break; 92 93 if (R->getEntry() == destBB && R->contains(srcBB)) 94 return "constraint=false"; 95 96 return ""; 97 } 98 99 // Print the cluster of the subregions. This groups the single basic blocks 100 // and adds a different background color for each group. 101 static void printRegionCluster(const Region &R, GraphWriter<RegionInfo*> &GW, 102 unsigned depth = 0) { 103 raw_ostream &O = GW.getOStream(); 104 O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(&R) 105 << " {\n"; 106 O.indent(2 * (depth + 1)) << "label = \"\";\n"; 107 108 if (!onlySimpleRegions || R.isSimple()) { 109 O.indent(2 * (depth + 1)) << "style = filled;\n"; 110 O.indent(2 * (depth + 1)) << "color = " 111 << ((R.getDepth() * 2 % 12) + 1) << "\n"; 112 113 } else { 114 O.indent(2 * (depth + 1)) << "style = solid;\n"; 115 O.indent(2 * (depth + 1)) << "color = " 116 << ((R.getDepth() * 2 % 12) + 2) << "\n"; 117 } 118 119 for (Region::const_iterator RI = R.begin(), RE = R.end(); RI != RE; ++RI) 120 printRegionCluster(**RI, GW, depth + 1); 121 122 RegionInfo *RI = R.getRegionInfo(); 123 124 for (const auto &BB : R.blocks()) 125 if (RI->getRegionFor(BB) == &R) 126 O.indent(2 * (depth + 1)) << "Node" 127 << static_cast<const void*>(RI->getTopLevelRegion()->getBBNode(BB)) 128 << ";\n"; 129 130 O.indent(2 * depth) << "}\n"; 131 } 132 133 static void addCustomGraphFeatures(const RegionInfo* RI, 134 GraphWriter<RegionInfo*> &GW) { 135 raw_ostream &O = GW.getOStream(); 136 O << "\tcolorscheme = \"paired12\"\n"; 137 printRegionCluster(*RI->getTopLevelRegion(), GW, 4); 138 } 139}; 140} //end namespace llvm 141 142namespace { 143 144struct RegionViewer 145 : public DOTGraphTraitsViewer<RegionInfo, false> { 146 static char ID; 147 RegionViewer() : DOTGraphTraitsViewer<RegionInfo, false>("reg", ID){ 148 initializeRegionViewerPass(*PassRegistry::getPassRegistry()); 149 } 150}; 151char RegionViewer::ID = 0; 152 153struct RegionOnlyViewer 154 : public DOTGraphTraitsViewer<RegionInfo, true> { 155 static char ID; 156 RegionOnlyViewer() : DOTGraphTraitsViewer<RegionInfo, true>("regonly", ID) { 157 initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry()); 158 } 159}; 160char RegionOnlyViewer::ID = 0; 161 162struct RegionPrinter 163 : public DOTGraphTraitsPrinter<RegionInfo, false> { 164 static char ID; 165 RegionPrinter() : 166 DOTGraphTraitsPrinter<RegionInfo, false>("reg", ID) { 167 initializeRegionPrinterPass(*PassRegistry::getPassRegistry()); 168 } 169}; 170char RegionPrinter::ID = 0; 171} //end anonymous namespace 172 173INITIALIZE_PASS(RegionPrinter, "dot-regions", 174 "Print regions of function to 'dot' file", true, true) 175 176INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function", 177 true, true) 178 179INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only", 180 "View regions of function (with no function bodies)", 181 true, true) 182 183namespace { 184 185struct RegionOnlyPrinter 186 : public DOTGraphTraitsPrinter<RegionInfo, true> { 187 static char ID; 188 RegionOnlyPrinter() : 189 DOTGraphTraitsPrinter<RegionInfo, true>("reg", ID) { 190 initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry()); 191 } 192}; 193 194} 195 196char RegionOnlyPrinter::ID = 0; 197INITIALIZE_PASS(RegionOnlyPrinter, "dot-regions-only", 198 "Print regions of function to 'dot' file " 199 "(with no function bodies)", 200 true, true) 201 202FunctionPass* llvm::createRegionViewerPass() { 203 return new RegionViewer(); 204} 205 206FunctionPass* llvm::createRegionOnlyViewerPass() { 207 return new RegionOnlyViewer(); 208} 209 210FunctionPass* llvm::createRegionPrinterPass() { 211 return new RegionPrinter(); 212} 213 214FunctionPass* llvm::createRegionOnlyPrinterPass() { 215 return new RegionOnlyPrinter(); 216} 217 218