Line data Source code
1 : //===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//
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 : // This implements the SelectionDAG::viewGraph method.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "ScheduleDAGSDNodes.h"
15 : #include "llvm/ADT/DenseSet.h"
16 : #include "llvm/ADT/StringExtras.h"
17 : #include "llvm/CodeGen/MachineConstantPool.h"
18 : #include "llvm/CodeGen/MachineFunction.h"
19 : #include "llvm/CodeGen/SelectionDAG.h"
20 : #include "llvm/CodeGen/TargetRegisterInfo.h"
21 : #include "llvm/IR/Constants.h"
22 : #include "llvm/Support/Debug.h"
23 : #include "llvm/Support/GraphWriter.h"
24 : #include "llvm/Support/raw_ostream.h"
25 : #include "llvm/Target/TargetMachine.h"
26 : using namespace llvm;
27 :
28 : #define DEBUG_TYPE "dag-printer"
29 :
30 : namespace llvm {
31 : template<>
32 : struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
33 :
34 : explicit DOTGraphTraits(bool isSimple=false) :
35 : DefaultDOTGraphTraits(isSimple) {}
36 :
37 : static bool hasEdgeDestLabels() {
38 : return true;
39 : }
40 :
41 : static unsigned numEdgeDestLabels(const void *Node) {
42 : return ((const SDNode *) Node)->getNumValues();
43 : }
44 :
45 : static std::string getEdgeDestLabel(const void *Node, unsigned i) {
46 : return ((const SDNode *) Node)->getValueType(i).getEVTString();
47 : }
48 :
49 : template<typename EdgeIter>
50 : static std::string getEdgeSourceLabel(const void *Node, EdgeIter I) {
51 : return itostr(I - SDNodeIterator::begin((const SDNode *) Node));
52 : }
53 :
54 : /// edgeTargetsEdgeSource - This method returns true if this outgoing edge
55 : /// should actually target another edge source, not a node. If this method
56 : /// is implemented, getEdgeTarget should be implemented.
57 : template<typename EdgeIter>
58 : static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) {
59 : return true;
60 : }
61 :
62 : /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is
63 : /// called to determine which outgoing edge of Node is the target of this
64 : /// edge.
65 : template<typename EdgeIter>
66 : static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) {
67 : SDNode *TargetNode = *I;
68 : SDNodeIterator NI = SDNodeIterator::begin(TargetNode);
69 : std::advance(NI, I.getNode()->getOperand(I.getOperand()).getResNo());
70 : return NI;
71 : }
72 :
73 : static std::string getGraphName(const SelectionDAG *G) {
74 : return G->getMachineFunction().getName();
75 : }
76 :
77 : static bool renderGraphFromBottomUp() {
78 : return true;
79 : }
80 :
81 : static std::string getNodeIdentifierLabel(const SDNode *Node,
82 : const SelectionDAG *Graph) {
83 : std::string R;
84 : raw_string_ostream OS(R);
85 : #ifndef NDEBUG
86 : OS << 't' << Node->PersistentId;
87 : #else
88 : OS << static_cast<const void *>(Node);
89 : #endif
90 : return R;
91 : }
92 :
93 : /// If you want to override the dot attributes printed for a particular
94 : /// edge, override this method.
95 : template<typename EdgeIter>
96 : static std::string getEdgeAttributes(const void *Node, EdgeIter EI,
97 : const SelectionDAG *Graph) {
98 : SDValue Op = EI.getNode()->getOperand(EI.getOperand());
99 : EVT VT = Op.getValueType();
100 : if (VT == MVT::Glue)
101 : return "color=red,style=bold";
102 : else if (VT == MVT::Other)
103 : return "color=blue,style=dashed";
104 : return "";
105 : }
106 :
107 :
108 0 : static std::string getSimpleNodeLabel(const SDNode *Node,
109 : const SelectionDAG *G) {
110 0 : std::string Result = Node->getOperationName(G);
111 : {
112 0 : raw_string_ostream OS(Result);
113 0 : Node->print_details(OS, G);
114 : }
115 0 : return Result;
116 : }
117 : std::string getNodeLabel(const SDNode *Node, const SelectionDAG *Graph);
118 : static std::string getNodeAttributes(const SDNode *N,
119 : const SelectionDAG *Graph) {
120 : #ifndef NDEBUG
121 : const std::string &Attrs = Graph->getGraphAttrs(N);
122 : if (!Attrs.empty()) {
123 : if (Attrs.find("shape=") == std::string::npos)
124 : return std::string("shape=Mrecord,") + Attrs;
125 : else
126 : return Attrs;
127 : }
128 : #endif
129 : return "shape=Mrecord";
130 : }
131 :
132 : static void addCustomGraphFeatures(SelectionDAG *G,
133 : GraphWriter<SelectionDAG*> &GW) {
134 : GW.emitSimpleNode(nullptr, "plaintext=circle", "GraphRoot");
135 : if (G->getRoot().getNode())
136 : GW.emitEdge(nullptr, -1, G->getRoot().getNode(), G->getRoot().getResNo(),
137 : "color=blue,style=dashed");
138 : }
139 : };
140 : }
141 :
142 0 : std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
143 : const SelectionDAG *G) {
144 0 : return DOTGraphTraits<SelectionDAG*>::getSimpleNodeLabel(Node, G);
145 : }
146 :
147 :
148 : /// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
149 : /// rendered using 'dot'.
150 : ///
151 0 : void SelectionDAG::viewGraph(const std::string &Title) {
152 : // This code is only for debugging!
153 : #ifndef NDEBUG
154 : ViewGraph(this, "dag." + getMachineFunction().getName(),
155 : false, Title);
156 : #else
157 0 : errs() << "SelectionDAG::viewGraph is only available in debug builds on "
158 0 : << "systems with Graphviz or gv!\n";
159 : #endif // NDEBUG
160 0 : }
161 :
162 : // This overload is defined out-of-line here instead of just using a
163 : // default parameter because this is easiest for gdb to call.
164 0 : void SelectionDAG::viewGraph() {
165 0 : viewGraph("");
166 0 : }
167 :
168 : /// clearGraphAttrs - Clear all previously defined node graph attributes.
169 : /// Intended to be used from a debugging tool (eg. gdb).
170 0 : void SelectionDAG::clearGraphAttrs() {
171 : #ifndef NDEBUG
172 : NodeGraphAttrs.clear();
173 : #else
174 0 : errs() << "SelectionDAG::clearGraphAttrs is only available in debug builds"
175 0 : << " on systems with Graphviz or gv!\n";
176 : #endif
177 0 : }
178 :
179 :
180 : /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".)
181 : ///
182 0 : void SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) {
183 : #ifndef NDEBUG
184 : NodeGraphAttrs[N] = Attrs;
185 : #else
186 0 : errs() << "SelectionDAG::setGraphAttrs is only available in debug builds"
187 0 : << " on systems with Graphviz or gv!\n";
188 : #endif
189 0 : }
190 :
191 :
192 : /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".)
193 : /// Used from getNodeAttributes.
194 0 : const std::string SelectionDAG::getGraphAttrs(const SDNode *N) const {
195 : #ifndef NDEBUG
196 : std::map<const SDNode *, std::string>::const_iterator I =
197 : NodeGraphAttrs.find(N);
198 :
199 : if (I != NodeGraphAttrs.end())
200 : return I->second;
201 : else
202 : return "";
203 : #else
204 0 : errs() << "SelectionDAG::getGraphAttrs is only available in debug builds"
205 0 : << " on systems with Graphviz or gv!\n";
206 0 : return std::string();
207 : #endif
208 : }
209 :
210 : /// setGraphColor - Convenience for setting node color attribute.
211 : ///
212 0 : void SelectionDAG::setGraphColor(const SDNode *N, const char *Color) {
213 : #ifndef NDEBUG
214 : NodeGraphAttrs[N] = std::string("color=") + Color;
215 : #else
216 0 : errs() << "SelectionDAG::setGraphColor is only available in debug builds"
217 0 : << " on systems with Graphviz or gv!\n";
218 : #endif
219 0 : }
220 :
221 : /// setSubgraphColorHelper - Implement setSubgraphColor. Return
222 : /// whether we truncated the search.
223 : ///
224 0 : bool SelectionDAG::setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited,
225 : int level, bool &printed) {
226 : bool hit_limit = false;
227 :
228 : #ifndef NDEBUG
229 : if (level >= 20) {
230 : if (!printed) {
231 : printed = true;
232 : LLVM_DEBUG(dbgs() << "setSubgraphColor hit max level\n");
233 : }
234 : return true;
235 : }
236 :
237 : unsigned oldSize = visited.size();
238 : visited.insert(N);
239 : if (visited.size() != oldSize) {
240 : setGraphColor(N, Color);
241 : for(SDNodeIterator i = SDNodeIterator::begin(N), iend = SDNodeIterator::end(N);
242 : i != iend;
243 : ++i) {
244 : hit_limit = setSubgraphColorHelper(*i, Color, visited, level+1, printed) || hit_limit;
245 : }
246 : }
247 : #else
248 0 : errs() << "SelectionDAG::setSubgraphColor is only available in debug builds"
249 0 : << " on systems with Graphviz or gv!\n";
250 : #endif
251 0 : return hit_limit;
252 : }
253 :
254 : /// setSubgraphColor - Convenience for setting subgraph color attribute.
255 : ///
256 0 : void SelectionDAG::setSubgraphColor(SDNode *N, const char *Color) {
257 : #ifndef NDEBUG
258 : DenseSet<SDNode *> visited;
259 : bool printed = false;
260 : if (setSubgraphColorHelper(N, Color, visited, 0, printed)) {
261 : // Visually mark that we hit the limit
262 : if (strcmp(Color, "red") == 0) {
263 : setSubgraphColorHelper(N, "blue", visited, 0, printed);
264 : } else if (strcmp(Color, "yellow") == 0) {
265 : setSubgraphColorHelper(N, "green", visited, 0, printed);
266 : }
267 : }
268 :
269 : #else
270 0 : errs() << "SelectionDAG::setSubgraphColor is only available in debug builds"
271 0 : << " on systems with Graphviz or gv!\n";
272 : #endif
273 0 : }
274 :
275 0 : std::string ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit *SU) const {
276 : std::string s;
277 0 : raw_string_ostream O(s);
278 0 : O << "SU(" << SU->NodeNum << "): ";
279 0 : if (SU->getNode()) {
280 : SmallVector<SDNode *, 4> GluedNodes;
281 0 : for (SDNode *N = SU->getNode(); N; N = N->getGluedNode())
282 0 : GluedNodes.push_back(N);
283 0 : while (!GluedNodes.empty()) {
284 : O << DOTGraphTraits<SelectionDAG*>
285 0 : ::getSimpleNodeLabel(GluedNodes.back(), DAG);
286 : GluedNodes.pop_back();
287 0 : if (!GluedNodes.empty())
288 0 : O << "\n ";
289 : }
290 : } else {
291 0 : O << "CROSS RC COPY";
292 : }
293 0 : return O.str();
294 : }
295 :
296 0 : void ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter<ScheduleDAG*> &GW) const {
297 0 : if (DAG) {
298 : // Draw a special "GraphRoot" node to indicate the root of the graph.
299 0 : GW.emitSimpleNode(nullptr, "plaintext=circle", "GraphRoot");
300 0 : const SDNode *N = DAG->getRoot().getNode();
301 0 : if (N && N->getNodeId() != -1)
302 0 : GW.emitEdge(nullptr, -1, &SUnits[N->getNodeId()], -1,
303 : "color=blue,style=dashed");
304 : }
305 0 : }
|