blob: f41725244a5a34dd037024a345784c7ce2034602 [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
Michael Krusee838e722015-08-10 12:57:23 +000058template <>
59struct DOTGraphTraits<RegionInfo *> : 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
Michael Krusee838e722015-08-10 12:57:23 +000064 static std::string getGraphName(const RegionInfo *) { return "Region Graph"; }
Tobias Grosser336734a2010-07-22 07:46:31 +000065
Michael Krusee838e722015-08-10 12:57:23 +000066 std::string getNodeLabel(RegionNode *Node, RegionInfo *G) {
67 return DOTGraphTraits<RegionNode *>::getNodeLabel(
68 Node, reinterpret_cast<RegionNode *>(G->getTopLevelRegion()));
Tobias Grosser336734a2010-07-22 07:46:31 +000069 }
70
Tobias Grosser98eecaf2011-02-27 04:11:07 +000071 std::string getEdgeAttributes(RegionNode *srcNode,
Michael Krusee838e722015-08-10 12:57:23 +000072 GraphTraits<RegionInfo *>::ChildIteratorType CI,
73 RegionInfo *G) {
Tobias Grosser98eecaf2011-02-27 04:11:07 +000074 RegionNode *destNode = *CI;
75
76 if (srcNode->isSubRegion() || destNode->isSubRegion())
77 return "";
78
79 // In case of a backedge, do not use it to define the layout of the nodes.
80 BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>();
81 BasicBlock *destBB = destNode->getNodeAs<BasicBlock>();
82
Michael Krusee838e722015-08-10 12:57:23 +000083 Region *R = G->getRegionFor(destBB);
Tobias Grosser98eecaf2011-02-27 04:11:07 +000084
85 while (R && R->getParent())
86 if (R->getParent()->getEntry() == destBB)
87 R = R->getParent();
88 else
89 break;
90
Michael Krusee838e722015-08-10 12:57:23 +000091 if (R && R->getEntry() == destBB && R->contains(srcBB))
Tobias Grosser98eecaf2011-02-27 04:11:07 +000092 return "constraint=false";
93
94 return "";
95 }
96
Tobias Grosser336734a2010-07-22 07:46:31 +000097 // Print the cluster of the subregions. This groups the single basic blocks
98 // and adds a different background color for each group.
Michael Krusee838e722015-08-10 12:57:23 +000099 static void printRegionCluster(const Region &R, GraphWriter<RegionInfo *> &GW,
Tobias Grosser336734a2010-07-22 07:46:31 +0000100 unsigned depth = 0) {
101 raw_ostream &O = GW.getOStream();
David Blaikieec649ac2014-04-15 18:32:43 +0000102 O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(&R)
Tobias Grosser336734a2010-07-22 07:46:31 +0000103 << " {\n";
104 O.indent(2 * (depth + 1)) << "label = \"\";\n";
105
David Blaikieec649ac2014-04-15 18:32:43 +0000106 if (!onlySimpleRegions || R.isSimple()) {
Tobias Grosser336734a2010-07-22 07:46:31 +0000107 O.indent(2 * (depth + 1)) << "style = filled;\n";
108 O.indent(2 * (depth + 1)) << "color = "
David Blaikieec649ac2014-04-15 18:32:43 +0000109 << ((R.getDepth() * 2 % 12) + 1) << "\n";
Tobias Grosser336734a2010-07-22 07:46:31 +0000110
111 } else {
112 O.indent(2 * (depth + 1)) << "style = solid;\n";
113 O.indent(2 * (depth + 1)) << "color = "
David Blaikieec649ac2014-04-15 18:32:43 +0000114 << ((R.getDepth() * 2 % 12) + 2) << "\n";
Tobias Grosser336734a2010-07-22 07:46:31 +0000115 }
116
David Blaikieec649ac2014-04-15 18:32:43 +0000117 for (Region::const_iterator RI = R.begin(), RE = R.end(); RI != RE; ++RI)
118 printRegionCluster(**RI, GW, depth + 1);
Tobias Grosser336734a2010-07-22 07:46:31 +0000119
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000120 const RegionInfo &RI = *static_cast<const RegionInfo*>(R.getRegionInfo());
Tobias Grosser336734a2010-07-22 07:46:31 +0000121
Richard Trieua2ee3012015-04-15 21:40:50 +0000122 for (auto *BB : R.blocks())
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000123 if (RI.getRegionFor(BB) == &R)
Tobias Grosser336734a2010-07-22 07:46:31 +0000124 O.indent(2 * (depth + 1)) << "Node"
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000125 << static_cast<const void*>(RI.getTopLevelRegion()->getBBNode(BB))
Tobias Grosser336734a2010-07-22 07:46:31 +0000126 << ";\n";
Tobias Grosser336734a2010-07-22 07:46:31 +0000127
128 O.indent(2 * depth) << "}\n";
129 }
130
Michael Krusee838e722015-08-10 12:57:23 +0000131 static void addCustomGraphFeatures(const RegionInfo *G,
132 GraphWriter<RegionInfo *> &GW) {
Tobias Grosser336734a2010-07-22 07:46:31 +0000133 raw_ostream &O = GW.getOStream();
134 O << "\tcolorscheme = \"paired12\"\n";
Michael Krusee838e722015-08-10 12:57:23 +0000135 printRegionCluster(*G->getTopLevelRegion(), GW, 4);
Tobias Grosser336734a2010-07-22 07:46:31 +0000136 }
137};
138} //end namespace llvm
139
140namespace {
141
Michael Krusee838e722015-08-10 12:57:23 +0000142struct RegionInfoPassGraphTraits {
143 static RegionInfo *getGraph(RegionInfoPass *RIP) {
144 return &RIP->getRegionInfo();
145 }
146};
147
148struct RegionPrinter
149 : public DOTGraphTraitsPrinter<RegionInfoPass, false, RegionInfo *,
150 RegionInfoPassGraphTraits> {
Tobias Grosser336734a2010-07-22 07:46:31 +0000151 static char ID;
Michael Krusee838e722015-08-10 12:57:23 +0000152 RegionPrinter()
153 : DOTGraphTraitsPrinter<RegionInfoPass, false, RegionInfo *,
154 RegionInfoPassGraphTraits>("reg", ID) {
155 initializeRegionPrinterPass(*PassRegistry::getPassRegistry());
156 }
157};
158char RegionPrinter::ID = 0;
159
160struct RegionOnlyPrinter
161 : public DOTGraphTraitsPrinter<RegionInfoPass, true, RegionInfo *,
162 RegionInfoPassGraphTraits> {
163 static char ID;
164 RegionOnlyPrinter()
165 : DOTGraphTraitsPrinter<RegionInfoPass, true, RegionInfo *,
166 RegionInfoPassGraphTraits>("reg", ID) {
167 initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry());
168 }
169};
170char RegionOnlyPrinter::ID = 0;
171
172struct RegionViewer
173 : public DOTGraphTraitsViewer<RegionInfoPass, false, RegionInfo *,
174 RegionInfoPassGraphTraits> {
175 static char ID;
176 RegionViewer()
177 : DOTGraphTraitsViewer<RegionInfoPass, false, RegionInfo *,
178 RegionInfoPassGraphTraits>("reg", ID) {
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000179 initializeRegionViewerPass(*PassRegistry::getPassRegistry());
180 }
Tobias Grosser336734a2010-07-22 07:46:31 +0000181};
Tobias Grosser336734a2010-07-22 07:46:31 +0000182char RegionViewer::ID = 0;
Tobias Grosser336734a2010-07-22 07:46:31 +0000183
184struct RegionOnlyViewer
Michael Krusee838e722015-08-10 12:57:23 +0000185 : public DOTGraphTraitsViewer<RegionInfoPass, true, RegionInfo *,
186 RegionInfoPassGraphTraits> {
Tobias Grosser336734a2010-07-22 07:46:31 +0000187 static char ID;
Michael Krusee838e722015-08-10 12:57:23 +0000188 RegionOnlyViewer()
189 : DOTGraphTraitsViewer<RegionInfoPass, true, RegionInfo *,
190 RegionInfoPassGraphTraits>("regonly", ID) {
Owen Anderson6c18d1a2010-10-19 17:21:58 +0000191 initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry());
192 }
Tobias Grosser336734a2010-07-22 07:46:31 +0000193};
Tobias Grosser336734a2010-07-22 07:46:31 +0000194char RegionOnlyViewer::ID = 0;
Tobias Grosser336734a2010-07-22 07:46:31 +0000195
Tobias Grosser336734a2010-07-22 07:46:31 +0000196} //end anonymous namespace
197
Tobias Grosser336734a2010-07-22 07:46:31 +0000198INITIALIZE_PASS(RegionPrinter, "dot-regions",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000199 "Print regions of function to 'dot' file", true, true)
Tobias Grosser336734a2010-07-22 07:46:31 +0000200
Michael Krusee838e722015-08-10 12:57:23 +0000201INITIALIZE_PASS(
202 RegionOnlyPrinter, "dot-regions-only",
203 "Print regions of function to 'dot' file (with no function bodies)", true,
204 true)
205
Owen Anderson5e19bfc2010-10-07 04:13:08 +0000206INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000207 true, true)
Matt Arsenault1b8d8372014-07-19 18:29:29 +0000208
Owen Anderson5e19bfc2010-10-07 04:13:08 +0000209INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only",
210 "View regions of function (with no function bodies)",
Owen Andersondf7a4f22010-10-07 22:25:06 +0000211 true, true)
Owen Anderson5e19bfc2010-10-07 04:13:08 +0000212
Michael Krusee838e722015-08-10 12:57:23 +0000213FunctionPass *llvm::createRegionPrinterPass() { return new RegionPrinter(); }
Dan Gohmanabfafad2010-08-02 18:50:06 +0000214
Michael Krusee838e722015-08-10 12:57:23 +0000215FunctionPass *llvm::createRegionOnlyPrinterPass() {
216 return new RegionOnlyPrinter();
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000217}
Dan Gohmanabfafad2010-08-02 18:50:06 +0000218
Tobias Grosser336734a2010-07-22 07:46:31 +0000219FunctionPass* llvm::createRegionViewerPass() {
220 return new RegionViewer();
221}
222
223FunctionPass* llvm::createRegionOnlyViewerPass() {
224 return new RegionOnlyViewer();
225}
226