blob: d7f5109848817f9db132d4eb50226ffc5e878928 [file] [log] [blame]
Tobias Grosser336734a2010-07-22 07:46:31 +00001//===- 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
Chandler Carruthed0881b2012-12-03 16:50:05 +000012#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"
Tobias Grosser336734a2010-07-22 07:46:31 +000017#include "llvm/Analysis/RegionInfo.h"
18#include "llvm/Analysis/RegionIterator.h"
19#include "llvm/Analysis/RegionPrinter.h"
Tobias Grosser336734a2010-07-22 07:46:31 +000020#include "llvm/Support/CommandLine.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/Support/Debug.h"
Tobias Grosser336734a2010-07-22 07:46:31 +000022#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<>
Matt Arsenault1b8d8372014-07-19 18:29:29 +000059struct DOTGraphTraits<RegionInfoPass*> : public DOTGraphTraits<RegionNode*> {
Tobias Grosser336734a2010-07-22 07:46:31 +000060
Matt Arsenault1b8d8372014-07-19 18:29:29 +000061 DOTGraphTraits (bool isSimple = false)
Tobias Grosser336734a2010-07-22 07:46:31 +000062 : DOTGraphTraits<RegionNode*>(isSimple) {}
63
Matt Arsenault1b8d8372014-07-19 18:29:29 +000064 static std::string getGraphName(RegionInfoPass *DT) {
Tobias Grosser336734a2010-07-22 07:46:31 +000065 return "Region Graph";
66 }
67
Matt Arsenault1b8d8372014-07-19 18:29:29 +000068 std::string getNodeLabel(RegionNode *Node, RegionInfoPass *G) {
69 RegionInfo &RI = G->getRegionInfo();
Tobias Grosser336734a2010-07-22 07:46:31 +000070 return DOTGraphTraits<RegionNode*>::getNodeLabel(Node,
Matt Arsenault1b8d8372014-07-19 18:29:29 +000071 reinterpret_cast<RegionNode*>(RI.getTopLevelRegion()));
Tobias Grosser336734a2010-07-22 07:46:31 +000072 }
73
Tobias Grosser98eecaf2011-02-27 04:11:07 +000074 std::string getEdgeAttributes(RegionNode *srcNode,
Matt Arsenault1b8d8372014-07-19 18:29:29 +000075 GraphTraits<RegionInfo*>::ChildIteratorType CI, RegionInfoPass *G) {
76 RegionInfo &RI = G->getRegionInfo();
Tobias Grosser98eecaf2011-02-27 04:11:07 +000077 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
Matt Arsenault1b8d8372014-07-19 18:29:29 +000086 Region *R = RI.getRegionFor(destBB);
Tobias Grosser98eecaf2011-02-27 04:11:07 +000087
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
Tobias Grosser336734a2010-07-22 07:46:31 +0000100 // Print the cluster of the subregions. This groups the single basic blocks
101 // and adds a different background color for each group.
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000102 static void printRegionCluster(const Region &R,
103 GraphWriter<RegionInfoPass*> &GW,
Tobias Grosser336734a2010-07-22 07:46:31 +0000104 unsigned depth = 0) {
105 raw_ostream &O = GW.getOStream();
David Blaikieec649ac2014-04-15 18:32:43 +0000106 O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(&R)
Tobias Grosser336734a2010-07-22 07:46:31 +0000107 << " {\n";
108 O.indent(2 * (depth + 1)) << "label = \"\";\n";
109
David Blaikieec649ac2014-04-15 18:32:43 +0000110 if (!onlySimpleRegions || R.isSimple()) {
Tobias Grosser336734a2010-07-22 07:46:31 +0000111 O.indent(2 * (depth + 1)) << "style = filled;\n";
112 O.indent(2 * (depth + 1)) << "color = "
David Blaikieec649ac2014-04-15 18:32:43 +0000113 << ((R.getDepth() * 2 % 12) + 1) << "\n";
Tobias Grosser336734a2010-07-22 07:46:31 +0000114
115 } else {
116 O.indent(2 * (depth + 1)) << "style = solid;\n";
117 O.indent(2 * (depth + 1)) << "color = "
David Blaikieec649ac2014-04-15 18:32:43 +0000118 << ((R.getDepth() * 2 % 12) + 2) << "\n";
Tobias Grosser336734a2010-07-22 07:46:31 +0000119 }
120
David Blaikieec649ac2014-04-15 18:32:43 +0000121 for (Region::const_iterator RI = R.begin(), RE = R.end(); RI != RE; ++RI)
122 printRegionCluster(**RI, GW, depth + 1);
Tobias Grosser336734a2010-07-22 07:46:31 +0000123
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000124 const RegionInfo &RI = *static_cast<const RegionInfo*>(R.getRegionInfo());
Tobias Grosser336734a2010-07-22 07:46:31 +0000125
Richard Trieua2ee3012015-04-15 21:40:50 +0000126 for (auto *BB : R.blocks())
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000127 if (RI.getRegionFor(BB) == &R)
Tobias Grosser336734a2010-07-22 07:46:31 +0000128 O.indent(2 * (depth + 1)) << "Node"
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000129 << static_cast<const void*>(RI.getTopLevelRegion()->getBBNode(BB))
Tobias Grosser336734a2010-07-22 07:46:31 +0000130 << ";\n";
Tobias Grosser336734a2010-07-22 07:46:31 +0000131
132 O.indent(2 * depth) << "}\n";
133 }
134
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000135 static void addCustomGraphFeatures(const RegionInfoPass* RIP,
136 GraphWriter<RegionInfoPass*> &GW) {
137 const RegionInfo &RI = RIP->getRegionInfo();
Tobias Grosser336734a2010-07-22 07:46:31 +0000138 raw_ostream &O = GW.getOStream();
139 O << "\tcolorscheme = \"paired12\"\n";
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000140 printRegionCluster(*RI.getTopLevelRegion(), GW, 4);
Tobias Grosser336734a2010-07-22 07:46:31 +0000141 }
142};
143} //end namespace llvm
144
145namespace {
146
147struct RegionViewer
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000148 : public DOTGraphTraitsViewer<RegionInfoPass, false> {
Tobias Grosser336734a2010-07-22 07:46:31 +0000149 static char ID;
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000150 RegionViewer() : DOTGraphTraitsViewer<RegionInfoPass, false>("reg", ID){
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000151 initializeRegionViewerPass(*PassRegistry::getPassRegistry());
152 }
Tobias Grosser336734a2010-07-22 07:46:31 +0000153};
Tobias Grosser336734a2010-07-22 07:46:31 +0000154char RegionViewer::ID = 0;
Tobias Grosser336734a2010-07-22 07:46:31 +0000155
156struct RegionOnlyViewer
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000157 : public DOTGraphTraitsViewer<RegionInfoPass, true> {
Tobias Grosser336734a2010-07-22 07:46:31 +0000158 static char ID;
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000159 RegionOnlyViewer() : DOTGraphTraitsViewer<RegionInfoPass, true>("regonly", ID) {
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000160 initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry());
161 }
Tobias Grosser336734a2010-07-22 07:46:31 +0000162};
Tobias Grosser336734a2010-07-22 07:46:31 +0000163char RegionOnlyViewer::ID = 0;
Tobias Grosser336734a2010-07-22 07:46:31 +0000164
165struct RegionPrinter
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000166 : public DOTGraphTraitsPrinter<RegionInfoPass, false> {
Tobias Grosser336734a2010-07-22 07:46:31 +0000167 static char ID;
168 RegionPrinter() :
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000169 DOTGraphTraitsPrinter<RegionInfoPass, false>("reg", ID) {
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000170 initializeRegionPrinterPass(*PassRegistry::getPassRegistry());
171 }
Tobias Grosser336734a2010-07-22 07:46:31 +0000172};
Owen Anderson5e19bfc2010-10-07 04:13:08 +0000173char RegionPrinter::ID = 0;
Tobias Grosser336734a2010-07-22 07:46:31 +0000174} //end anonymous namespace
175
Tobias Grosser336734a2010-07-22 07:46:31 +0000176INITIALIZE_PASS(RegionPrinter, "dot-regions",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000177 "Print regions of function to 'dot' file", true, true)
Tobias Grosser336734a2010-07-22 07:46:31 +0000178
Owen Anderson5e19bfc2010-10-07 04:13:08 +0000179INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000180 true, true)
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000181
Owen Anderson5e19bfc2010-10-07 04:13:08 +0000182INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only",
183 "View regions of function (with no function bodies)",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000184 true, true)
Owen Anderson5e19bfc2010-10-07 04:13:08 +0000185
Dan Gohmanabfafad2010-08-02 18:50:06 +0000186namespace {
187
Tobias Grosser336734a2010-07-22 07:46:31 +0000188struct RegionOnlyPrinter
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000189 : public DOTGraphTraitsPrinter<RegionInfoPass, true> {
Tobias Grosser336734a2010-07-22 07:46:31 +0000190 static char ID;
191 RegionOnlyPrinter() :
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000192 DOTGraphTraitsPrinter<RegionInfoPass, true>("reg", ID) {
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000193 initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry());
194 }
Tobias Grosser336734a2010-07-22 07:46:31 +0000195};
196
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000197}
Dan Gohmanabfafad2010-08-02 18:50:06 +0000198
Tobias Grosser336734a2010-07-22 07:46:31 +0000199char RegionOnlyPrinter::ID = 0;
200INITIALIZE_PASS(RegionOnlyPrinter, "dot-regions-only",
201 "Print regions of function to 'dot' file "
202 "(with no function bodies)",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000203 true, true)
Tobias Grosser336734a2010-07-22 07:46:31 +0000204
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