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 |
|
---|
24 | using namespace llvm;
|
---|
25 |
|
---|
26 | //===----------------------------------------------------------------------===//
|
---|
27 | /// onlySimpleRegion - Show only the simple regions in the RegionViewer.
|
---|
28 | static cl::opt<bool>
|
---|
29 | onlySimpleRegions("only-simple-regions",
|
---|
30 | cl::desc("Show only simple regions in the graphviz viewer"),
|
---|
31 | cl::Hidden,
|
---|
32 | cl::init(false));
|
---|
33 |
|
---|
34 | namespace llvm {
|
---|
35 | template<>
|
---|
36 | struct 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 |
|
---|
58 | template<>
|
---|
59 | struct 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 |
|
---|
119 | namespace {
|
---|
120 |
|
---|
121 | struct RegionViewer
|
---|
122 | : public DOTGraphTraitsViewer<RegionInfo, false> {
|
---|
123 | static char ID;
|
---|
124 | RegionViewer() : DOTGraphTraitsViewer<RegionInfo, false>("reg", ID){}
|
---|
125 | };
|
---|
126 |
|
---|
127 | char RegionViewer::ID = 0;
|
---|
128 | INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function",
|
---|
129 | true, true);
|
---|
130 |
|
---|
131 | struct RegionOnlyViewer
|
---|
132 | : public DOTGraphTraitsViewer<RegionInfo, true> {
|
---|
133 | static char ID;
|
---|
134 | RegionOnlyViewer() : DOTGraphTraitsViewer<RegionInfo, true>("regonly", ID){}
|
---|
135 | };
|
---|
136 |
|
---|
137 | char RegionOnlyViewer::ID = 0;
|
---|
138 | INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only",
|
---|
139 | "View regions of function (with no function bodies)",
|
---|
140 | true, true);
|
---|
141 |
|
---|
142 | struct RegionPrinter
|
---|
143 | : public DOTGraphTraitsPrinter<RegionInfo, false> {
|
---|
144 | static char ID;
|
---|
145 | RegionPrinter() :
|
---|
146 | DOTGraphTraitsPrinter<RegionInfo, false>("reg", ID) {}
|
---|
147 | };
|
---|
148 | } //end anonymous namespace
|
---|
149 |
|
---|
150 | char RegionPrinter::ID = 0;
|
---|
151 | INITIALIZE_PASS(RegionPrinter, "dot-regions",
|
---|
152 | "Print regions of function to 'dot' file", true, true);
|
---|
153 |
|
---|
154 | namespace {
|
---|
155 |
|
---|
156 | struct RegionOnlyPrinter
|
---|
157 | : public DOTGraphTraitsPrinter<RegionInfo, true> {
|
---|
158 | static char ID;
|
---|
159 | RegionOnlyPrinter() :
|
---|
160 | DOTGraphTraitsPrinter<RegionInfo, true>("reg", ID) {}
|
---|
161 | };
|
---|
162 |
|
---|
163 | }
|
---|
164 |
|
---|
165 | char RegionOnlyPrinter::ID = 0;
|
---|
166 | INITIALIZE_PASS(RegionOnlyPrinter, "dot-regions-only",
|
---|
167 | "Print regions of function to 'dot' file "
|
---|
168 | "(with no function bodies)",
|
---|
169 | true, true);
|
---|
170 |
|
---|
171 | FunctionPass* llvm::createRegionViewerPass() {
|
---|
172 | return new RegionViewer();
|
---|
173 | }
|
---|
174 |
|
---|
175 | FunctionPass* llvm::createRegionOnlyViewerPass() {
|
---|
176 | return new RegionOnlyViewer();
|
---|
177 | }
|
---|
178 |
|
---|
179 | FunctionPass* llvm::createRegionPrinterPass() {
|
---|
180 | return new RegionPrinter();
|
---|
181 | }
|
---|
182 |
|
---|
183 | FunctionPass* llvm::createRegionOnlyPrinterPass() {
|
---|
184 | return new RegionOnlyPrinter();
|
---|
185 | }
|
---|
186 |
|
---|