Polly 20.0.0git
ScopGraphPrinter.cpp
Go to the documentation of this file.
1//===- GraphPrinter.cpp - Create a DOT output describing the Scop. --------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// Create a DOT output describing the Scop.
10//
11// For each function a dot file is created that shows the control flow graph of
12// the function and highlights the detected Scops.
13//
14//===----------------------------------------------------------------------===//
15
17#include "polly/LinkAllPasses.h"
18#include "polly/ScopDetection.h"
19#include "llvm/Support/CommandLine.h"
20
21using namespace polly;
22using namespace llvm;
23static cl::opt<std::string>
24 ViewFilter("polly-view-only",
25 cl::desc("Only view functions that match this pattern"),
26 cl::Hidden, cl::init(""));
27
28static cl::opt<bool> ViewAll("polly-view-all",
29 cl::desc("Also show functions without any scops"),
30 cl::Hidden, cl::init(false));
31
32namespace llvm {
33
36 ScopDetection *SD) {
37 RegionNode *destNode = *CI;
38
39 if (srcNode->isSubRegion() || destNode->isSubRegion())
40 return "";
41
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>();
45
46 RegionInfo *RI = SD->getRI();
47 Region *R = RI->getRegionFor(destBB);
48
49 while (R && R->getParent())
50 if (R->getParent()->getEntry() == destBB)
51 R = R->getParent();
52 else
53 break;
54
55 if (R && R->getEntry() == destBB && R->contains(srcBB))
56 return "constraint=false";
57
58 return "";
59}
60
61std::string
63 std::string Escaped;
64
65 for (const auto &C : String) {
66 if (C == '"')
67 Escaped += '\\';
68
69 Escaped += C;
70 }
71 return Escaped;
72}
73
75 const Region *R,
76 raw_ostream &O,
77 unsigned depth) {
78 O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R)
79 << " {\n";
80 unsigned LineBegin, LineEnd;
81 std::string FileName;
82
83 getDebugLocation(R, LineBegin, LineEnd, FileName);
84
85 std::string Location;
86 if (LineBegin != (unsigned)-1) {
87 Location = escapeString(FileName + ":" + std::to_string(LineBegin) + "-" +
88 std::to_string(LineEnd) + "\n");
89 }
90
91 std::string ErrorMessage = SD->regionIsInvalidBecause(R);
92 ErrorMessage = escapeString(ErrorMessage);
93 O.indent(2 * (depth + 1))
94 << "label = \"" << Location << ErrorMessage << "\";\n";
95
96 if (SD->isMaxRegionInScop(*R)) {
97 O.indent(2 * (depth + 1)) << "style = filled;\n";
98
99 // Set color to green.
100 O.indent(2 * (depth + 1)) << "color = 3";
101 } else {
102 O.indent(2 * (depth + 1)) << "style = solid;\n";
103
104 int color = (R->getDepth() * 2 % 12) + 1;
105
106 // We do not want green again.
107 if (color == 3)
108 color = 6;
109
110 O.indent(2 * (depth + 1)) << "color = " << color << "\n";
111 }
112
113 for (const auto &SubRegion : *R)
114 printRegionCluster(SD, SubRegion.get(), O, depth + 1);
115
116 RegionInfo *RI = R->getRegionInfo();
117
118 for (BasicBlock *BB : R->blocks())
119 if (RI->getRegionFor(BB) == R)
120 O.indent(2 * (depth + 1))
121 << "Node"
122 << static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB))
123 << ";\n";
124
125 O.indent(2 * depth) << "}\n";
126}
127
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);
133}
134
135} // namespace llvm
136
139 return &Analysis->getSD();
140 }
141};
142
144 : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
145 ScopDetection *,
146 ScopDetectionAnalysisGraphTraits> {
147 static char ID;
152 "scops", ID) {}
153 bool processFunction(Function &F, ScopDetectionWrapperPass &SD) override {
154 if (ViewFilter != "" && !F.getName().count(ViewFilter))
155 return false;
156
157 if (ViewAll)
158 return true;
159
160 // Check that at least one scop was detected.
161 return std::distance(SD.getSD().begin(), SD.getSD().end()) > 0;
162 }
163};
165
167 : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
168 ScopDetection *,
169 ScopDetectionAnalysisGraphTraits> {
170 static char ID;
175 "scopsonly", ID) {}
176};
178
180 : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false,
181 ScopDetection *,
182 ScopDetectionAnalysisGraphTraits> {
183 static char ID;
188 "scops", ID) {}
189};
191
193 : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, true,
194 ScopDetection *,
195 ScopDetectionAnalysisGraphTraits> {
196 static char ID;
201 "scopsonly", ID) {}
202};
204
205static RegisterPass<ScopViewerWrapperPass> X("view-scops",
206 "Polly - View Scops of function");
207
208static RegisterPass<ScopOnlyViewerWrapperPass>
209 Y("view-scops-only",
210 "Polly - View Scops of function (with no function bodies)");
211
212static RegisterPass<ScopPrinterWrapperPass>
213 M("dot-scops", "Polly - Print Scops of function");
214
215static RegisterPass<ScopOnlyPrinterWrapperPass>
216 N("dot-scops-only",
217 "Polly - Print Scops of function (with no function bodies)");
218
220 return new ScopViewerWrapperPass();
221}
222
224 return new ScopOnlyViewerWrapperPass();
225}
226
228 return new ScopPrinterWrapperPass();
229}
230
232 return new ScopOnlyPrinterWrapperPass();
233}
234
235bool ScopViewer::processFunction(Function &F, const ScopDetection &SD) {
236 if (ViewFilter != "" && !F.getName().count(ViewFilter))
237 return false;
238
239 if (ViewAll)
240 return true;
241
242 // Check that at least one scop was detected.
243 return std::distance(SD.begin(), SD.end()) > 0;
244}
static cl::opt< bool > ViewAll("polly-view-all", cl::desc("Also show functions without any scops"), cl::Hidden, cl::init(false))
static RegisterPass< ScopViewerWrapperPass > X("view-scops", "Polly - View Scops of function")
static RegisterPass< ScopOnlyPrinterWrapperPass > N("dot-scops-only", "Polly - Print Scops of function (with no function bodies)")
static cl::opt< std::string > ViewFilter("polly-view-only", cl::desc("Only view functions that match this pattern"), cl::Hidden, cl::init(""))
static RegisterPass< ScopOnlyViewerWrapperPass > Y("view-scops-only", "Polly - View Scops of function (with no function bodies)")
static RegisterPass< ScopPrinterWrapperPass > M("dot-scops", "Polly - Print Scops of function")
ScopDetection & getSD() const
Pass to detect the maximal static control parts (Scops) of a function.
RegionInfo * getRI() const
Get the RegionInfo stored in this pass.
std::string regionIsInvalidBecause(const Region *R) const
Get a message why a region is invalid.
bool isMaxRegionInScop(const Region &R, bool Verify=true)
Is the region is the maximum region of a Scop?
#define C(FN,...)
Definition: isl_test2.cc:197
This file contains the declaration of the PolyhedralInfo class, which will provide an interface to ex...
llvm::Pass * createDOTViewerWrapperPass()
llvm::Pass * createDOTOnlyViewerWrapperPass()
void getDebugLocation(const llvm::Region *R, unsigned &LineBegin, unsigned &LineEnd, std::string &FileName)
Get the location of a region from the debug info.
llvm::Pass * createDOTPrinterWrapperPass()
llvm::Pass * createDOTOnlyPrinterWrapperPass()
static ScopDetection * getGraph(ScopDetectionWrapperPass *Analysis)
bool processFunction(Function &F, ScopDetectionWrapperPass &SD) override
bool processFunction(Function &F, const ScopDetection &SD) override