1 //===- RegionPrinter.cpp - Print regions tree pass ------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
9 // Print out the region tree of a function using dotty/graphviz.
10 //===----------------------------------------------------------------------===//
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"
26 //===----------------------------------------------------------------------===//
27 /// onlySimpleRegion - Show only the simple regions in the RegionViewer.
29 onlySimpleRegions("only-simple-regions",
30 cl::desc("Show only simple regions in the graphviz viewer"),
36 struct DOTGraphTraits
<RegionNode
*> : public DefaultDOTGraphTraits
{
38 DOTGraphTraits (bool isSimple
=false)
39 : DefaultDOTGraphTraits(isSimple
) {}
41 std::string
getNodeLabel(RegionNode
*Node
, RegionNode
*Graph
) {
43 if (!Node
->isSubRegion()) {
44 BasicBlock
*BB
= Node
->getNodeAs
<BasicBlock
>();
47 return DOTGraphTraits
<const Function
*>
48 ::getSimpleNodeLabel(BB
, BB
->getParent());
50 return DOTGraphTraits
<const Function
*>
51 ::getCompleteNodeLabel(BB
, BB
->getParent());
54 return "Not implemented";
59 struct DOTGraphTraits
<RegionInfo
*> : public DOTGraphTraits
<RegionNode
*> {
61 DOTGraphTraits (bool isSimple
=false)
62 : DOTGraphTraits
<RegionNode
*>(isSimple
) {}
64 static std::string
getGraphName(RegionInfo
*DT
) {
65 return "Region Graph";
68 std::string
getNodeLabel(RegionNode
*Node
, RegionInfo
*G
) {
69 return DOTGraphTraits
<RegionNode
*>::getNodeLabel(Node
,
70 G
->getTopLevelRegion());
73 std::string
getEdgeAttributes(RegionNode
*srcNode
,
74 GraphTraits
<RegionInfo
*>::ChildIteratorType CI
, RegionInfo
*RI
) {
76 RegionNode
*destNode
= *CI
;
78 if (srcNode
->isSubRegion() || destNode
->isSubRegion())
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
>();
85 Region
*R
= RI
->getRegionFor(destBB
);
87 while (R
&& R
->getParent())
88 if (R
->getParent()->getEntry() == destBB
)
93 if (R
->getEntry() == destBB
&& R
->contains(srcBB
))
94 return "constraint=false";
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
)
106 O
.indent(2 * (depth
+ 1)) << "label = \"\";\n";
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";
114 O
.indent(2 * (depth
+ 1)) << "style = solid;\n";
115 O
.indent(2 * (depth
+ 1)) << "color = "
116 << ((R
->getDepth() * 2 % 12) + 2) << "\n";
119 for (Region::const_iterator RI
= R
->begin(), RE
= R
->end(); RI
!= RE
; ++RI
)
120 printRegionCluster(*RI
, GW
, depth
+ 1);
122 RegionInfo
*RI
= R
->getRegionInfo();
124 for (Region::const_block_iterator BI
= R
->block_begin(),
125 BE
= R
->block_end(); BI
!= BE
; ++BI
) {
126 BasicBlock
*BB
= (*BI
)->getNodeAs
<BasicBlock
>();
127 if (RI
->getRegionFor(BB
) == R
)
128 O
.indent(2 * (depth
+ 1)) << "Node"
129 << static_cast<const void*>(RI
->getTopLevelRegion()->getBBNode(BB
))
133 O
.indent(2 * depth
) << "}\n";
136 static void addCustomGraphFeatures(const RegionInfo
* RI
,
137 GraphWriter
<RegionInfo
*> &GW
) {
138 raw_ostream
&O
= GW
.getOStream();
139 O
<< "\tcolorscheme = \"paired12\"\n";
140 printRegionCluster(RI
->getTopLevelRegion(), GW
, 4);
143 } //end namespace llvm
148 : public DOTGraphTraitsViewer
<RegionInfo
, false> {
150 RegionViewer() : DOTGraphTraitsViewer
<RegionInfo
, false>("reg", ID
){
151 initializeRegionViewerPass(*PassRegistry::getPassRegistry());
154 char RegionViewer::ID
= 0;
156 struct RegionOnlyViewer
157 : public DOTGraphTraitsViewer
<RegionInfo
, true> {
159 RegionOnlyViewer() : DOTGraphTraitsViewer
<RegionInfo
, true>("regonly", ID
) {
160 initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry());
163 char RegionOnlyViewer::ID
= 0;
166 : public DOTGraphTraitsPrinter
<RegionInfo
, false> {
169 DOTGraphTraitsPrinter
<RegionInfo
, false>("reg", ID
) {
170 initializeRegionPrinterPass(*PassRegistry::getPassRegistry());
173 char RegionPrinter::ID
= 0;
174 } //end anonymous namespace
176 INITIALIZE_PASS(RegionPrinter
, "dot-regions",
177 "Print regions of function to 'dot' file", true, true)
179 INITIALIZE_PASS(RegionViewer
, "view-regions", "View regions of function",
182 INITIALIZE_PASS(RegionOnlyViewer
, "view-regions-only",
183 "View regions of function (with no function bodies)",
188 struct RegionOnlyPrinter
189 : public DOTGraphTraitsPrinter
<RegionInfo
, true> {
191 RegionOnlyPrinter() :
192 DOTGraphTraitsPrinter
<RegionInfo
, true>("reg", ID
) {
193 initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry());
199 char RegionOnlyPrinter::ID
= 0;
200 INITIALIZE_PASS(RegionOnlyPrinter
, "dot-regions-only",
201 "Print regions of function to 'dot' file "
202 "(with no function bodies)",
205 FunctionPass
* llvm::createRegionViewerPass() {
206 return new RegionViewer();
209 FunctionPass
* llvm::createRegionOnlyViewerPass() {
210 return new RegionOnlyViewer();
213 FunctionPass
* llvm::createRegionPrinterPass() {
214 return new RegionPrinter();
217 FunctionPass
* llvm::createRegionOnlyPrinterPass() {
218 return new RegionOnlyPrinter();