Coverage Report

Created: 2017-08-21 19:50

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