1 //===- GraphPrinter.cpp - Create a DOT output describing the Scop. --------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Create a DOT output describing the Scop.
11 // For each function a dot file is created that shows the control flow graph of
12 // the function and highlights the detected Scops.
14 //===----------------------------------------------------------------------===//
16 #include "polly/ScopGraphPrinter.h"
17 #include "polly/LinkAllPasses.h"
18 #include "polly/ScopDetection.h"
19 #include "llvm/Support/CommandLine.h"
21 using namespace polly
;
23 static cl::opt
<std::string
>
24 ViewFilter("polly-view-only",
25 cl::desc("Only view functions that match this pattern"),
26 cl::Hidden
, cl::init(""));
28 static cl::opt
<bool> ViewAll("polly-view-all",
29 cl::desc("Also show functions without any scops"),
30 cl::Hidden
, cl::init(false));
34 std::string DOTGraphTraits
<ScopDetection
*>::getEdgeAttributes(
35 RegionNode
*srcNode
, GraphTraits
<RegionInfo
*>::ChildIteratorType CI
,
37 RegionNode
*destNode
= *CI
;
39 if (srcNode
->isSubRegion() || destNode
->isSubRegion())
42 // In case of a backedge, do not use it to define the layout of the nodes.
43 BasicBlock
*srcBB
= srcNode
->getNodeAs
<BasicBlock
>();
44 BasicBlock
*destBB
= destNode
->getNodeAs
<BasicBlock
>();
46 RegionInfo
*RI
= SD
->getRI();
47 Region
*R
= RI
->getRegionFor(destBB
);
49 while (R
&& R
->getParent())
50 if (R
->getParent()->getEntry() == destBB
)
55 if (R
&& R
->getEntry() == destBB
&& R
->contains(srcBB
))
56 return "constraint=false";
62 DOTGraphTraits
<ScopDetection
*>::escapeString(llvm::StringRef String
) {
65 for (const auto &C
: String
) {
74 void DOTGraphTraits
<ScopDetection
*>::printRegionCluster(ScopDetection
*SD
,
78 O
.indent(2 * depth
) << "subgraph cluster_" << static_cast<const void *>(R
)
80 unsigned LineBegin
, LineEnd
;
83 getDebugLocation(R
, LineBegin
, LineEnd
, FileName
);
86 if (LineBegin
!= (unsigned)-1) {
87 Location
= escapeString(FileName
+ ":" + std::to_string(LineBegin
) + "-" +
88 std::to_string(LineEnd
) + "\n");
91 std::string ErrorMessage
= SD
->regionIsInvalidBecause(R
);
92 ErrorMessage
= escapeString(ErrorMessage
);
93 O
.indent(2 * (depth
+ 1))
94 << "label = \"" << Location
<< ErrorMessage
<< "\";\n";
96 if (SD
->isMaxRegionInScop(*R
)) {
97 O
.indent(2 * (depth
+ 1)) << "style = filled;\n";
99 // Set color to green.
100 O
.indent(2 * (depth
+ 1)) << "color = 3";
102 O
.indent(2 * (depth
+ 1)) << "style = solid;\n";
104 int color
= (R
->getDepth() * 2 % 12) + 1;
106 // We do not want green again.
110 O
.indent(2 * (depth
+ 1)) << "color = " << color
<< "\n";
113 for (const auto &SubRegion
: *R
)
114 printRegionCluster(SD
, SubRegion
.get(), O
, depth
+ 1);
116 RegionInfo
*RI
= R
->getRegionInfo();
118 for (BasicBlock
*BB
: R
->blocks())
119 if (RI
->getRegionFor(BB
) == R
)
120 O
.indent(2 * (depth
+ 1))
122 << static_cast<void *>(RI
->getTopLevelRegion()->getBBNode(BB
))
125 O
.indent(2 * depth
) << "}\n";
128 void DOTGraphTraits
<ScopDetection
*>::addCustomGraphFeatures(
129 ScopDetection
*SD
, GraphWriter
<ScopDetection
*> &GW
) {
130 raw_ostream
&O
= GW
.getOStream();
131 O
<< "\tcolorscheme = \"paired12\"\n";
132 printRegionCluster(SD
, SD
->getRI()->getTopLevelRegion(), O
, 4);
137 struct ScopDetectionAnalysisGraphTraits
{
138 static ScopDetection
*getGraph(ScopDetectionWrapperPass
*Analysis
) {
139 return &Analysis
->getSD();
143 struct ScopViewerWrapperPass
144 : DOTGraphTraitsViewerWrapperPass
<ScopDetectionWrapperPass
, false,
146 ScopDetectionAnalysisGraphTraits
> {
148 ScopViewerWrapperPass()
149 : DOTGraphTraitsViewerWrapperPass
<ScopDetectionWrapperPass
, false,
151 ScopDetectionAnalysisGraphTraits
>(
153 bool processFunction(Function
&F
, ScopDetectionWrapperPass
&SD
) override
{
154 if (ViewFilter
!= "" && !F
.getName().count(ViewFilter
))
160 // Check that at least one scop was detected.
161 return std::distance(SD
.getSD().begin(), SD
.getSD().end()) > 0;
164 char ScopViewerWrapperPass::ID
= 0;
166 struct ScopOnlyViewerWrapperPass
167 : DOTGraphTraitsViewerWrapperPass
<ScopDetectionWrapperPass
, false,
169 ScopDetectionAnalysisGraphTraits
> {
171 ScopOnlyViewerWrapperPass()
172 : DOTGraphTraitsViewerWrapperPass
<ScopDetectionWrapperPass
, false,
174 ScopDetectionAnalysisGraphTraits
>(
177 char ScopOnlyViewerWrapperPass::ID
= 0;
179 struct ScopPrinterWrapperPass
180 : DOTGraphTraitsPrinterWrapperPass
<ScopDetectionWrapperPass
, false,
182 ScopDetectionAnalysisGraphTraits
> {
184 ScopPrinterWrapperPass()
185 : DOTGraphTraitsPrinterWrapperPass
<ScopDetectionWrapperPass
, false,
187 ScopDetectionAnalysisGraphTraits
>(
190 char ScopPrinterWrapperPass::ID
= 0;
192 struct ScopOnlyPrinterWrapperPass
193 : DOTGraphTraitsPrinterWrapperPass
<ScopDetectionWrapperPass
, true,
195 ScopDetectionAnalysisGraphTraits
> {
197 ScopOnlyPrinterWrapperPass()
198 : DOTGraphTraitsPrinterWrapperPass
<ScopDetectionWrapperPass
, true,
200 ScopDetectionAnalysisGraphTraits
>(
203 char ScopOnlyPrinterWrapperPass::ID
= 0;
205 static RegisterPass
<ScopViewerWrapperPass
> X("view-scops",
206 "Polly - View Scops of function");
208 static RegisterPass
<ScopOnlyViewerWrapperPass
>
210 "Polly - View Scops of function (with no function bodies)");
212 static RegisterPass
<ScopPrinterWrapperPass
>
213 M("dot-scops", "Polly - Print Scops of function");
215 static RegisterPass
<ScopOnlyPrinterWrapperPass
>
217 "Polly - Print Scops of function (with no function bodies)");
219 Pass
*polly::createDOTViewerWrapperPass() {
220 return new ScopViewerWrapperPass();
223 Pass
*polly::createDOTOnlyViewerWrapperPass() {
224 return new ScopOnlyViewerWrapperPass();
227 Pass
*polly::createDOTPrinterWrapperPass() {
228 return new ScopPrinterWrapperPass();
231 Pass
*polly::createDOTOnlyPrinterWrapperPass() {
232 return new ScopOnlyPrinterWrapperPass();
235 bool ScopViewer::processFunction(Function
&F
, const ScopDetection
&SD
) {
236 if (ViewFilter
!= "" && !F
.getName().count(ViewFilter
))
242 // Check that at least one scop was detected.
243 return std::distance(SD
.begin(), SD
.end()) > 0;