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