1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | #include "polly/LinkAllPasses.h" |
18 | #include "polly/ScopDetection.h" |
19 | #include "llvm/Analysis/DOTGraphTraitsPass.h" |
20 | #include "llvm/Analysis/RegionInfo.h" |
21 | #include "llvm/Analysis/RegionIterator.h" |
22 | |
23 | using namespace polly; |
24 | using namespace llvm; |
25 | |
26 | namespace llvm { |
27 | template <> |
28 | struct GraphTraits<ScopDetection *> : public GraphTraits<RegionInfo *> { |
29 | static NodeType *getEntryNode(ScopDetection *SD) { |
30 | return GraphTraits<RegionInfo *>::getEntryNode(SD->getRI()); |
31 | } |
32 | static nodes_iterator nodes_begin(ScopDetection *SD) { |
33 | return nodes_iterator::begin(getEntryNode(SD)); |
34 | } |
35 | static nodes_iterator nodes_end(ScopDetection *SD) { |
36 | return nodes_iterator::end(getEntryNode(SD)); |
37 | } |
38 | }; |
39 | |
40 | template <> struct DOTGraphTraits<RegionNode *> : public DefaultDOTGraphTraits { |
41 | DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {} |
42 | |
43 | std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) { |
44 | if (!Node->isSubRegion()) { |
45 | BasicBlock *BB = Node->getNodeAs<BasicBlock>(); |
46 | |
47 | if (isSimple()) |
48 | return DOTGraphTraits<const Function *>::getSimpleNodeLabel( |
49 | BB, BB->getParent()); |
50 | else |
51 | return DOTGraphTraits<const Function *>::getCompleteNodeLabel( |
52 | BB, BB->getParent()); |
53 | } |
54 | |
55 | return "Not implemented"; |
56 | } |
57 | }; |
58 | |
59 | template <> |
60 | struct DOTGraphTraits<ScopDetection *> : public DOTGraphTraits<RegionNode *> { |
61 | DOTGraphTraits(bool isSimple = false) |
62 | : DOTGraphTraits<RegionNode *>(isSimple) {} |
63 | static std::string getGraphName(ScopDetection *SD) { return "Scop Graph"; } |
64 | |
65 | std::string getEdgeAttributes(RegionNode *srcNode, |
66 | GraphTraits<RegionInfo *>::ChildIteratorType CI, |
67 | ScopDetection *SD) { |
68 | RegionNode *destNode = *CI; |
69 | |
70 | if (srcNode->isSubRegion() || destNode->isSubRegion()) |
| |
71 | return ""; |
72 | |
73 | |
74 | BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>(); |
75 | BasicBlock *destBB = destNode->getNodeAs<BasicBlock>(); |
76 | |
77 | RegionInfo *RI = SD->getRI(); |
78 | Region *R = RI->getRegionFor(destBB); |
| |
79 | |
80 | while (R && R->getParent()) |
| 3 | | Assuming pointer value is null | |
|
81 | if (R->getParent()->getEntry() == destBB) |
82 | R = R->getParent(); |
83 | else |
84 | break; |
85 | |
86 | if (R->getEntry() == destBB && R->contains(srcBB)) |
| 4 | | Called C++ object pointer is null |
|
87 | return "constraint=false"; |
88 | |
89 | return ""; |
90 | } |
91 | |
92 | std::string getNodeLabel(RegionNode *Node, ScopDetection *SD) { |
93 | return DOTGraphTraits<RegionNode *>::getNodeLabel( |
94 | Node, reinterpret_cast<RegionNode *>(SD->getRI()->getTopLevelRegion())); |
95 | } |
96 | |
97 | static std::string escapeString(std::string String) { |
98 | std::string Escaped; |
99 | |
100 | for (const auto &C : String) { |
101 | if (C == '"') |
102 | Escaped += '\\'; |
103 | |
104 | Escaped += C; |
105 | } |
106 | return Escaped; |
107 | } |
108 | |
109 | |
110 | |
111 | static void printRegionCluster(const ScopDetection *SD, const Region *R, |
112 | raw_ostream &O, unsigned depth = 0) { |
113 | O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R) |
114 | << " {\n"; |
115 | std::string ErrorMessage = SD->regionIsInvalidBecause(R); |
116 | ErrorMessage = escapeString(ErrorMessage); |
117 | O.indent(2 * (depth + 1)) << "label = \"" << ErrorMessage << "\";\n"; |
118 | |
119 | if (SD->isMaxRegionInScop(*R)) { |
120 | O.indent(2 * (depth + 1)) << "style = filled;\n"; |
121 | |
122 | |
123 | O.indent(2 * (depth + 1)) << "color = 3"; |
124 | } else { |
125 | O.indent(2 * (depth + 1)) << "style = solid;\n"; |
126 | |
127 | int color = (R->getDepth() * 2 % 12) + 1; |
128 | |
129 | |
130 | if (color == 3) |
131 | color = 6; |
132 | |
133 | O.indent(2 * (depth + 1)) << "color = " << color << "\n"; |
134 | } |
135 | |
136 | for (const auto &SubRegion : *R) |
137 | printRegionCluster(SD, SubRegion.get(), O, depth + 1); |
138 | |
139 | RegionInfo *RI = R->getRegionInfo(); |
140 | |
141 | for (const auto &BB : R->blocks()) |
142 | if (RI->getRegionFor(BB) == R) |
143 | O.indent(2 * (depth + 1)) |
144 | << "Node" |
145 | << static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB)) |
146 | << ";\n"; |
147 | |
148 | O.indent(2 * depth) << "}\n"; |
149 | } |
150 | static void addCustomGraphFeatures(const ScopDetection *SD, |
151 | GraphWriter<ScopDetection *> &GW) { |
152 | raw_ostream &O = GW.getOStream(); |
153 | O << "\tcolorscheme = \"paired12\"\n"; |
154 | printRegionCluster(SD, SD->getRI()->getTopLevelRegion(), O, 4); |
155 | } |
156 | }; |
157 | |
158 | } |
159 | |
160 | struct ScopViewer : public DOTGraphTraitsViewer<ScopDetection, false> { |
161 | static char ID; |
162 | ScopViewer() : DOTGraphTraitsViewer<ScopDetection, false>("scops", ID) {} |
163 | }; |
164 | char ScopViewer::ID = 0; |
165 | |
166 | struct ScopOnlyViewer : public DOTGraphTraitsViewer<ScopDetection, true> { |
167 | static char ID; |
168 | ScopOnlyViewer() |
169 | : DOTGraphTraitsViewer<ScopDetection, true>("scopsonly", ID) {} |
170 | }; |
171 | char ScopOnlyViewer::ID = 0; |
172 | |
173 | struct ScopPrinter : public DOTGraphTraitsPrinter<ScopDetection, false> { |
174 | static char ID; |
175 | ScopPrinter() : DOTGraphTraitsPrinter<ScopDetection, false>("scops", ID) {} |
176 | }; |
177 | char ScopPrinter::ID = 0; |
178 | |
179 | struct ScopOnlyPrinter : public DOTGraphTraitsPrinter<ScopDetection, true> { |
180 | static char ID; |
181 | ScopOnlyPrinter() |
182 | : DOTGraphTraitsPrinter<ScopDetection, true>("scopsonly", ID) {} |
183 | }; |
184 | char ScopOnlyPrinter::ID = 0; |
185 | |
186 | static RegisterPass<ScopViewer> X("view-scops", |
187 | "Polly - View Scops of function"); |
188 | |
189 | static RegisterPass<ScopOnlyViewer> |
190 | Y("view-scops-only", |
191 | "Polly - View Scops of function (with no function bodies)"); |
192 | |
193 | static RegisterPass<ScopPrinter> M("dot-scops", |
194 | "Polly - Print Scops of function"); |
195 | |
196 | static RegisterPass<ScopOnlyPrinter> |
197 | N("dot-scops-only", |
198 | "Polly - Print Scops of function (with no function bodies)"); |
199 | |
200 | Pass *polly::createDOTViewerPass() { return new ScopViewer(); } |
201 | |
202 | Pass *polly::createDOTOnlyViewerPass() { return new ScopOnlyViewer(); } |
203 | |
204 | Pass *polly::createDOTPrinterPass() { return new ScopPrinter(); } |
205 | |
206 | Pass *polly::createDOTOnlyPrinterPass() { return new ScopOnlyPrinter(); } |