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