1 //===- GraphPrinter.cpp - Create a DOT output describing the Scop. --------===//
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 //===----------------------------------------------------------------------===//
10 // Create a DOT output describing the Scop.
12 // For each function a dot file is created that shows the control flow graph of
13 // the function and highlights the detected Scops.
15 //===----------------------------------------------------------------------===//
17 #include "polly/LinkAllPasses.h"
18 #include "polly/ScopDetection.h"
19 #include "polly/Support/ScopLocation.h"
20 #include "llvm/Analysis/DOTGraphTraitsPass.h"
21 #include "llvm/Analysis/RegionInfo.h"
22 #include "llvm/Analysis/RegionIterator.h"
23 #include "llvm/Support/CommandLine.h"
25 using namespace polly
;
27 static cl::opt
<std::string
>
28 ViewFilter("polly-view-only",
29 cl::desc("Only view functions that match this pattern"),
30 cl::Hidden
, cl::init(""), cl::ZeroOrMore
);
32 static cl::opt
<bool> ViewAll("polly-view-all",
33 cl::desc("Also show functions without any scops"),
34 cl::Hidden
, cl::init(false), cl::ZeroOrMore
);
38 struct GraphTraits
<ScopDetection
*> : public GraphTraits
<RegionInfo
*> {
39 static NodeRef
getEntryNode(ScopDetection
*SD
) {
40 return GraphTraits
<RegionInfo
*>::getEntryNode(SD
->getRI());
42 static nodes_iterator
nodes_begin(ScopDetection
*SD
) {
43 return nodes_iterator::begin(getEntryNode(SD
));
45 static nodes_iterator
nodes_end(ScopDetection
*SD
) {
46 return nodes_iterator::end(getEntryNode(SD
));
51 struct GraphTraits
<ScopDetectionWrapperPass
*>
52 : public GraphTraits
<ScopDetection
*> {
53 static NodeRef
getEntryNode(ScopDetectionWrapperPass
*P
) {
54 return GraphTraits
<ScopDetection
*>::getEntryNode(&P
->getSD());
56 static nodes_iterator
nodes_begin(ScopDetectionWrapperPass
*P
) {
57 return nodes_iterator::begin(getEntryNode(P
));
59 static nodes_iterator
nodes_end(ScopDetectionWrapperPass
*P
) {
60 return nodes_iterator::end(getEntryNode(P
));
64 template <> struct DOTGraphTraits
<RegionNode
*> : public DefaultDOTGraphTraits
{
65 DOTGraphTraits(bool isSimple
= false) : DefaultDOTGraphTraits(isSimple
) {}
67 std::string
getNodeLabel(RegionNode
*Node
, RegionNode
*Graph
) {
68 if (!Node
->isSubRegion()) {
69 BasicBlock
*BB
= Node
->getNodeAs
<BasicBlock
>();
72 return DOTGraphTraits
<const Function
*>::getSimpleNodeLabel(
75 return DOTGraphTraits
<const Function
*>::getCompleteNodeLabel(
79 return "Not implemented";
84 struct DOTGraphTraits
<ScopDetectionWrapperPass
*>
85 : public DOTGraphTraits
<RegionNode
*> {
86 DOTGraphTraits(bool isSimple
= false)
87 : DOTGraphTraits
<RegionNode
*>(isSimple
) {}
88 static std::string
getGraphName(ScopDetectionWrapperPass
*SD
) {
92 std::string
getEdgeAttributes(RegionNode
*srcNode
,
93 GraphTraits
<RegionInfo
*>::ChildIteratorType CI
,
94 ScopDetectionWrapperPass
*P
) {
95 RegionNode
*destNode
= *CI
;
96 auto *SD
= &P
->getSD();
98 if (srcNode
->isSubRegion() || destNode
->isSubRegion())
101 // In case of a backedge, do not use it to define the layout of the nodes.
102 BasicBlock
*srcBB
= srcNode
->getNodeAs
<BasicBlock
>();
103 BasicBlock
*destBB
= destNode
->getNodeAs
<BasicBlock
>();
105 RegionInfo
*RI
= SD
->getRI();
106 Region
*R
= RI
->getRegionFor(destBB
);
108 while (R
&& R
->getParent())
109 if (R
->getParent()->getEntry() == destBB
)
114 if (R
&& R
->getEntry() == destBB
&& R
->contains(srcBB
))
115 return "constraint=false";
120 std::string
getNodeLabel(RegionNode
*Node
, ScopDetectionWrapperPass
*P
) {
121 return DOTGraphTraits
<RegionNode
*>::getNodeLabel(
122 Node
, reinterpret_cast<RegionNode
*>(
123 P
->getSD().getRI()->getTopLevelRegion()));
126 static std::string
escapeString(std::string String
) {
129 for (const auto &C
: String
) {
138 // Print the cluster of the subregions. This groups the single basic blocks
139 // and adds a different background color for each group.
140 static void printRegionCluster(const ScopDetection
*SD
, const Region
*R
,
141 raw_ostream
&O
, unsigned depth
= 0) {
142 O
.indent(2 * depth
) << "subgraph cluster_" << static_cast<const void *>(R
)
144 unsigned LineBegin
, LineEnd
;
145 std::string FileName
;
147 getDebugLocation(R
, LineBegin
, LineEnd
, FileName
);
149 std::string Location
;
150 if (LineBegin
!= (unsigned)-1) {
151 Location
= escapeString(FileName
+ ":" + std::to_string(LineBegin
) + "-" +
152 std::to_string(LineEnd
) + "\n");
155 std::string ErrorMessage
= SD
->regionIsInvalidBecause(R
);
156 ErrorMessage
= escapeString(ErrorMessage
);
157 O
.indent(2 * (depth
+ 1))
158 << "label = \"" << Location
<< ErrorMessage
<< "\";\n";
160 if (SD
->isMaxRegionInScop(*R
)) {
161 O
.indent(2 * (depth
+ 1)) << "style = filled;\n";
163 // Set color to green.
164 O
.indent(2 * (depth
+ 1)) << "color = 3";
166 O
.indent(2 * (depth
+ 1)) << "style = solid;\n";
168 int color
= (R
->getDepth() * 2 % 12) + 1;
170 // We do not want green again.
174 O
.indent(2 * (depth
+ 1)) << "color = " << color
<< "\n";
177 for (const auto &SubRegion
: *R
)
178 printRegionCluster(SD
, SubRegion
.get(), O
, depth
+ 1);
180 RegionInfo
*RI
= R
->getRegionInfo();
182 for (const auto &BB
: R
->blocks())
183 if (RI
->getRegionFor(BB
) == R
)
184 O
.indent(2 * (depth
+ 1))
186 << static_cast<void *>(RI
->getTopLevelRegion()->getBBNode(BB
))
189 O
.indent(2 * depth
) << "}\n";
192 addCustomGraphFeatures(const ScopDetectionWrapperPass
*SD
,
193 GraphWriter
<ScopDetectionWrapperPass
*> &GW
) {
194 raw_ostream
&O
= GW
.getOStream();
195 O
<< "\tcolorscheme = \"paired12\"\n";
196 printRegionCluster(&SD
->getSD(), SD
->getSD().getRI()->getTopLevelRegion(),
201 } // end namespace llvm
204 : public DOTGraphTraitsViewer
<ScopDetectionWrapperPass
, false> {
207 : DOTGraphTraitsViewer
<ScopDetectionWrapperPass
, false>("scops", ID
) {}
208 bool processFunction(Function
&F
, ScopDetectionWrapperPass
&SD
) override
{
209 if (ViewFilter
!= "" && !F
.getName().count(ViewFilter
))
215 // Check that at least one scop was detected.
216 return std::distance(SD
.getSD().begin(), SD
.getSD().end()) > 0;
219 char ScopViewer::ID
= 0;
221 struct ScopOnlyViewer
222 : public DOTGraphTraitsViewer
<ScopDetectionWrapperPass
, true> {
225 : DOTGraphTraitsViewer
<ScopDetectionWrapperPass
, true>("scopsonly", ID
) {}
227 char ScopOnlyViewer::ID
= 0;
230 : public DOTGraphTraitsPrinter
<ScopDetectionWrapperPass
, false> {
233 : DOTGraphTraitsPrinter
<ScopDetectionWrapperPass
, false>("scops", ID
) {}
235 char ScopPrinter::ID
= 0;
237 struct ScopOnlyPrinter
238 : public DOTGraphTraitsPrinter
<ScopDetectionWrapperPass
, true> {
241 : DOTGraphTraitsPrinter
<ScopDetectionWrapperPass
, true>("scopsonly", ID
) {
244 char ScopOnlyPrinter::ID
= 0;
246 static RegisterPass
<ScopViewer
> X("view-scops",
247 "Polly - View Scops of function");
249 static RegisterPass
<ScopOnlyViewer
>
251 "Polly - View Scops of function (with no function bodies)");
253 static RegisterPass
<ScopPrinter
> M("dot-scops",
254 "Polly - Print Scops of function");
256 static RegisterPass
<ScopOnlyPrinter
>
258 "Polly - Print Scops of function (with no function bodies)");
260 Pass
*polly::createDOTViewerPass() { return new ScopViewer(); }
262 Pass
*polly::createDOTOnlyViewerPass() { return new ScopOnlyViewer(); }
264 Pass
*polly::createDOTPrinterPass() { return new ScopPrinter(); }
266 Pass
*polly::createDOTOnlyPrinterPass() { return new ScopOnlyPrinter(); }