Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/Analysis/ScopGraphPrinter.cpp
Line
Count
Source (jump to first uncovered line)
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
16
#include "polly/LinkAllPasses.h"
17
#include "polly/ScopDetection.h"
18
#include "polly/Support/ScopLocation.h"
19
#include "llvm/Analysis/DOTGraphTraitsPass.h"
20
#include "llvm/Analysis/RegionInfo.h"
21
#include "llvm/Analysis/RegionIterator.h"
22
#include "llvm/Support/CommandLine.h"
23
24
using namespace polly;
25
using namespace llvm;
26
static cl::opt<std::string>
27
    ViewFilter("polly-view-only",
28
               cl::desc("Only view functions that match this pattern"),
29
               cl::Hidden, cl::init(""), cl::ZeroOrMore);
30
31
static cl::opt<bool> ViewAll("polly-view-all",
32
                             cl::desc("Also show functions without any scops"),
33
                             cl::Hidden, cl::init(false), cl::ZeroOrMore);
34
35
namespace llvm {
36
template <>
37
struct GraphTraits<ScopDetection *> : public GraphTraits<RegionInfo *> {
38
2
  static NodeRef getEntryNode(ScopDetection *SD) {
39
2
    return GraphTraits<RegionInfo *>::getEntryNode(SD->getRI());
40
2
  }
41
0
  static nodes_iterator nodes_begin(ScopDetection *SD) {
42
0
    return nodes_iterator::begin(getEntryNode(SD));
43
0
  }
44
0
  static nodes_iterator nodes_end(ScopDetection *SD) {
45
0
    return nodes_iterator::end(getEntryNode(SD));
46
0
  }
47
};
48
49
template <>
50
struct GraphTraits<ScopDetectionWrapperPass *>
51
    : public GraphTraits<ScopDetection *> {
52
2
  static NodeRef getEntryNode(ScopDetectionWrapperPass *P) {
53
2
    return GraphTraits<ScopDetection *>::getEntryNode(&P->getSD());
54
2
  }
55
1
  static nodes_iterator nodes_begin(ScopDetectionWrapperPass *P) {
56
1
    return nodes_iterator::begin(getEntryNode(P));
57
1
  }
58
1
  static nodes_iterator nodes_end(ScopDetectionWrapperPass *P) {
59
1
    return nodes_iterator::end(getEntryNode(P));
60
1
  }
61
};
62
63
template <> struct DOTGraphTraits<RegionNode *> : public DefaultDOTGraphTraits {
64
  DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
65
66
  std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) {
67
    if (!Node->isSubRegion()) {
68
      BasicBlock *BB = Node->getNodeAs<BasicBlock>();
69
70
      if (isSimple())
71
        return DOTGraphTraits<const Function *>::getSimpleNodeLabel(
72
            BB, BB->getParent());
73
      else
74
        return DOTGraphTraits<const Function *>::getCompleteNodeLabel(
75
            BB, BB->getParent());
76
    }
77
78
    return "Not implemented";
79
  }
80
};
81
82
template <>
83
struct DOTGraphTraits<ScopDetectionWrapperPass *>
84
    : public DOTGraphTraits<RegionNode *> {
85
  DOTGraphTraits(bool isSimple = false)
86
2
      : DOTGraphTraits<RegionNode *>(isSimple) {}
87
2
  static std::string getGraphName(ScopDetectionWrapperPass *SD) {
88
2
    return "Scop Graph";
89
2
  }
90
91
  std::string getEdgeAttributes(RegionNode *srcNode,
92
                                GraphTraits<RegionInfo *>::ChildIteratorType CI,
93
10
                                ScopDetectionWrapperPass *P) {
94
10
    RegionNode *destNode = *CI;
95
10
    auto *SD = &P->getSD();
96
10
97
10
    if (srcNode->isSubRegion() || destNode->isSubRegion())
98
0
      return "";
99
10
100
10
    // In case of a backedge, do not use it to define the layout of the nodes.
101
10
    BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>();
102
10
    BasicBlock *destBB = destNode->getNodeAs<BasicBlock>();
103
10
104
10
    RegionInfo *RI = SD->getRI();
105
10
    Region *R = RI->getRegionFor(destBB);
106
10
107
12
    while (R && R->getParent())
108
11
      if (R->getParent()->getEntry() == destBB)
109
2
        R = R->getParent();
110
9
      else
111
9
        break;
112
10
113
10
    if (R && R->getEntry() == destBB && 
R->contains(srcBB)4
)
114
2
      return "constraint=false";
115
8
116
8
    return "";
117
8
  }
118
119
9
  std::string getNodeLabel(RegionNode *Node, ScopDetectionWrapperPass *P) {
120
9
    return DOTGraphTraits<RegionNode *>::getNodeLabel(
121
9
        Node, reinterpret_cast<RegionNode *>(
122
9
                  P->getSD().getRI()->getTopLevelRegion()));
123
9
  }
124
125
4
  static std::string escapeString(std::string String) {
126
4
    std::string Escaped;
127
4
128
4
    for (const auto &C : String) {
129
0
      if (C == '"')
130
0
        Escaped += '\\';
131
0
132
0
      Escaped += C;
133
0
    }
134
4
    return Escaped;
135
4
  }
136
137
  // Print the cluster of the subregions. This groups the single basic blocks
138
  // and adds a different background color for each group.
139
  static void printRegionCluster(const ScopDetection *SD, const Region *R,
140
4
                                 raw_ostream &O, unsigned depth = 0) {
141
4
    O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R)
142
4
                        << " {\n";
143
4
    unsigned LineBegin, LineEnd;
144
4
    std::string FileName;
145
4
146
4
    getDebugLocation(R, LineBegin, LineEnd, FileName);
147
4
148
4
    std::string Location;
149
4
    if (LineBegin != (unsigned)-1) {
150
0
      Location = escapeString(FileName + ":" + std::to_string(LineBegin) + "-" +
151
0
                              std::to_string(LineEnd) + "\n");
152
0
    }
153
4
154
4
    std::string ErrorMessage = SD->regionIsInvalidBecause(R);
155
4
    ErrorMessage = escapeString(ErrorMessage);
156
4
    O.indent(2 * (depth + 1))
157
4
        << "label = \"" << Location << ErrorMessage << "\";\n";
158
4
159
4
    if (SD->isMaxRegionInScop(*R)) {
160
1
      O.indent(2 * (depth + 1)) << "style = filled;\n";
161
1
162
1
      // Set color to green.
163
1
      O.indent(2 * (depth + 1)) << "color = 3";
164
3
    } else {
165
3
      O.indent(2 * (depth + 1)) << "style = solid;\n";
166
3
167
3
      int color = (R->getDepth() * 2 % 12) + 1;
168
3
169
3
      // We do not want green again.
170
3
      if (color == 3)
171
0
        color = 6;
172
3
173
3
      O.indent(2 * (depth + 1)) << "color = " << color << "\n";
174
3
    }
175
4
176
4
    for (const auto &SubRegion : *R)
177
3
      printRegionCluster(SD, SubRegion.get(), O, depth + 1);
178
4
179
4
    RegionInfo *RI = R->getRegionInfo();
180
4
181
4
    for (const auto &BB : R->blocks())
182
25
      if (RI->getRegionFor(BB) == R)
183
9
        O.indent(2 * (depth + 1))
184
9
            << "Node"
185
9
            << static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB))
186
9
            << ";\n";
187
4
188
4
    O.indent(2 * depth) << "}\n";
189
4
  }
190
  static void
191
  addCustomGraphFeatures(const ScopDetectionWrapperPass *SD,
192
1
                         GraphWriter<ScopDetectionWrapperPass *> &GW) {
193
1
    raw_ostream &O = GW.getOStream();
194
1
    O << "\tcolorscheme = \"paired12\"\n";
195
1
    printRegionCluster(&SD->getSD(), SD->getSD().getRI()->getTopLevelRegion(),
196
1
                       O, 4);
197
1
  }
198
};
199
} // end namespace llvm
200
201
struct ScopViewer
202
    : public DOTGraphTraitsViewer<ScopDetectionWrapperPass, false> {
203
  static char ID;
204
  ScopViewer()
205
0
      : DOTGraphTraitsViewer<ScopDetectionWrapperPass, false>("scops", ID) {}
206
0
  bool processFunction(Function &F, ScopDetectionWrapperPass &SD) override {
207
0
    if (ViewFilter != "" && !F.getName().count(ViewFilter))
208
0
      return false;
209
0
210
0
    if (ViewAll)
211
0
      return true;
212
0
213
0
    // Check that at least one scop was detected.
214
0
    return std::distance(SD.getSD().begin(), SD.getSD().end()) > 0;
215
0
  }
216
};
217
char ScopViewer::ID = 0;
218
219
struct ScopOnlyViewer
220
    : public DOTGraphTraitsViewer<ScopDetectionWrapperPass, true> {
221
  static char ID;
222
  ScopOnlyViewer()
223
0
      : DOTGraphTraitsViewer<ScopDetectionWrapperPass, true>("scopsonly", ID) {}
224
};
225
char ScopOnlyViewer::ID = 0;
226
227
struct ScopPrinter
228
    : public DOTGraphTraitsPrinter<ScopDetectionWrapperPass, false> {
229
  static char ID;
230
  ScopPrinter()
231
1
      : DOTGraphTraitsPrinter<ScopDetectionWrapperPass, false>("scops", ID) {}
232
};
233
char ScopPrinter::ID = 0;
234
235
struct ScopOnlyPrinter
236
    : public DOTGraphTraitsPrinter<ScopDetectionWrapperPass, true> {
237
  static char ID;
238
  ScopOnlyPrinter()
239
0
      : DOTGraphTraitsPrinter<ScopDetectionWrapperPass, true>("scopsonly", ID) {
240
0
  }
241
};
242
char ScopOnlyPrinter::ID = 0;
243
244
static RegisterPass<ScopViewer> X("view-scops",
245
                                  "Polly - View Scops of function");
246
247
static RegisterPass<ScopOnlyViewer>
248
    Y("view-scops-only",
249
      "Polly - View Scops of function (with no function bodies)");
250
251
static RegisterPass<ScopPrinter> M("dot-scops",
252
                                   "Polly - Print Scops of function");
253
254
static RegisterPass<ScopOnlyPrinter>
255
    N("dot-scops-only",
256
      "Polly - Print Scops of function (with no function bodies)");
257
258
0
Pass *polly::createDOTViewerPass() { return new ScopViewer(); }
259
260
0
Pass *polly::createDOTOnlyViewerPass() { return new ScopOnlyViewer(); }
261
262
0
Pass *polly::createDOTPrinterPass() { return new ScopPrinter(); }
263
264
0
Pass *polly::createDOTOnlyPrinterPass() { return new ScopOnlyPrinter(); }