SelectionDAGPrinter.cpp revision 221345
1193323Sed//===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This implements the SelectionDAG::viewGraph method.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed#include "ScheduleDAGSDNodes.h"
15193323Sed#include "llvm/Constants.h"
16193323Sed#include "llvm/Function.h"
17193323Sed#include "llvm/Assembly/Writer.h"
18193323Sed#include "llvm/CodeGen/SelectionDAG.h"
19193323Sed#include "llvm/CodeGen/MachineConstantPool.h"
20193323Sed#include "llvm/CodeGen/MachineFunction.h"
21193323Sed#include "llvm/CodeGen/MachineModuleInfo.h"
22193323Sed#include "llvm/CodeGen/PseudoSourceValue.h"
23193323Sed#include "llvm/Analysis/DebugInfo.h"
24193323Sed#include "llvm/Target/TargetRegisterInfo.h"
25193323Sed#include "llvm/Target/TargetMachine.h"
26193323Sed#include "llvm/Support/Debug.h"
27193323Sed#include "llvm/Support/GraphWriter.h"
28193323Sed#include "llvm/Support/raw_ostream.h"
29193323Sed#include "llvm/ADT/DenseSet.h"
30193323Sed#include "llvm/ADT/StringExtras.h"
31193323Sed#include "llvm/Config/config.h"
32193323Sedusing namespace llvm;
33193323Sed
34193323Sednamespace llvm {
35193323Sed  template<>
36193323Sed  struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
37199989Srdivacky
38200581Srdivacky    explicit DOTGraphTraits(bool isSimple=false) :
39200581Srdivacky      DefaultDOTGraphTraits(isSimple) {}
40199989Srdivacky
41193323Sed    static bool hasEdgeDestLabels() {
42193323Sed      return true;
43193323Sed    }
44193323Sed
45193323Sed    static unsigned numEdgeDestLabels(const void *Node) {
46193323Sed      return ((const SDNode *) Node)->getNumValues();
47193323Sed    }
48193323Sed
49193323Sed    static std::string getEdgeDestLabel(const void *Node, unsigned i) {
50198090Srdivacky      return ((const SDNode *) Node)->getValueType(i).getEVTString();
51193323Sed    }
52193323Sed
53200581Srdivacky    template<typename EdgeIter>
54200581Srdivacky    static std::string getEdgeSourceLabel(const void *Node, EdgeIter I) {
55200581Srdivacky      return itostr(I - SDNodeIterator::begin((SDNode *) Node));
56200581Srdivacky    }
57200581Srdivacky
58193323Sed    /// edgeTargetsEdgeSource - This method returns true if this outgoing edge
59199989Srdivacky    /// should actually target another edge source, not a node.  If this method
60199989Srdivacky    /// is implemented, getEdgeTarget should be implemented.
61193323Sed    template<typename EdgeIter>
62193323Sed    static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) {
63193323Sed      return true;
64193323Sed    }
65193323Sed
66193323Sed    /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is
67193323Sed    /// called to determine which outgoing edge of Node is the target of this
68193323Sed    /// edge.
69193323Sed    template<typename EdgeIter>
70193323Sed    static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) {
71193323Sed      SDNode *TargetNode = *I;
72193323Sed      SDNodeIterator NI = SDNodeIterator::begin(TargetNode);
73193323Sed      std::advance(NI, I.getNode()->getOperand(I.getOperand()).getResNo());
74193323Sed      return NI;
75193323Sed    }
76193323Sed
77193323Sed    static std::string getGraphName(const SelectionDAG *G) {
78193323Sed      return G->getMachineFunction().getFunction()->getName();
79193323Sed    }
80193323Sed
81193323Sed    static bool renderGraphFromBottomUp() {
82193323Sed      return true;
83193323Sed    }
84200581Srdivacky
85193323Sed    static bool hasNodeAddressLabel(const SDNode *Node,
86193323Sed                                    const SelectionDAG *Graph) {
87193323Sed      return true;
88193323Sed    }
89200581Srdivacky
90193323Sed    /// If you want to override the dot attributes printed for a particular
91193323Sed    /// edge, override this method.
92193323Sed    template<typename EdgeIter>
93221345Sdim    static std::string getEdgeAttributes(const void *Node, EdgeIter EI,
94221345Sdim                                         const SelectionDAG *Graph) {
95193323Sed      SDValue Op = EI.getNode()->getOperand(EI.getOperand());
96198090Srdivacky      EVT VT = Op.getValueType();
97218893Sdim      if (VT == MVT::Glue)
98193323Sed        return "color=red,style=bold";
99193323Sed      else if (VT == MVT::Other)
100193323Sed        return "color=blue,style=dashed";
101193323Sed      return "";
102193323Sed    }
103193323Sed
104200581Srdivacky
105199989Srdivacky    static std::string getSimpleNodeLabel(const SDNode *Node,
106199989Srdivacky                                          const SelectionDAG *G) {
107199989Srdivacky      std::string Result = Node->getOperationName(G);
108199989Srdivacky      {
109199989Srdivacky        raw_string_ostream OS(Result);
110199989Srdivacky        Node->print_details(OS, G);
111199989Srdivacky      }
112199989Srdivacky      return Result;
113199989Srdivacky    }
114199989Srdivacky    std::string getNodeLabel(const SDNode *Node, const SelectionDAG *Graph);
115193323Sed    static std::string getNodeAttributes(const SDNode *N,
116193323Sed                                         const SelectionDAG *Graph) {
117193323Sed#ifndef NDEBUG
118193323Sed      const std::string &Attrs = Graph->getGraphAttrs(N);
119193323Sed      if (!Attrs.empty()) {
120193323Sed        if (Attrs.find("shape=") == std::string::npos)
121193323Sed          return std::string("shape=Mrecord,") + Attrs;
122193323Sed        else
123193323Sed          return Attrs;
124193323Sed      }
125193323Sed#endif
126193323Sed      return "shape=Mrecord";
127193323Sed    }
128193323Sed
129193323Sed    static void addCustomGraphFeatures(SelectionDAG *G,
130193323Sed                                       GraphWriter<SelectionDAG*> &GW) {
131193323Sed      GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
132193323Sed      if (G->getRoot().getNode())
133193323Sed        GW.emitEdge(0, -1, G->getRoot().getNode(), G->getRoot().getResNo(),
134193323Sed                    "color=blue,style=dashed");
135193323Sed    }
136193323Sed  };
137193323Sed}
138193323Sed
139193323Sedstd::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
140199989Srdivacky                                                        const SelectionDAG *G) {
141200581Srdivacky  return DOTGraphTraits<SelectionDAG*>::getSimpleNodeLabel(Node, G);
142193323Sed}
143193323Sed
144193323Sed
145193323Sed/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
146193323Sed/// rendered using 'dot'.
147193323Sed///
148193323Sedvoid SelectionDAG::viewGraph(const std::string &Title) {
149193323Sed// This code is only for debugging!
150193323Sed#ifndef NDEBUG
151200581Srdivacky  ViewGraph(this, "dag." + getMachineFunction().getFunction()->getNameStr(),
152198090Srdivacky            false, Title);
153193323Sed#else
154198090Srdivacky  errs() << "SelectionDAG::viewGraph is only available in debug builds on "
155198090Srdivacky         << "systems with Graphviz or gv!\n";
156193323Sed#endif  // NDEBUG
157193323Sed}
158193323Sed
159193323Sed// This overload is defined out-of-line here instead of just using a
160193323Sed// default parameter because this is easiest for gdb to call.
161193323Sedvoid SelectionDAG::viewGraph() {
162193323Sed  viewGraph("");
163193323Sed}
164193323Sed
165193323Sed/// clearGraphAttrs - Clear all previously defined node graph attributes.
166193323Sed/// Intended to be used from a debugging tool (eg. gdb).
167193323Sedvoid SelectionDAG::clearGraphAttrs() {
168193323Sed#ifndef NDEBUG
169193323Sed  NodeGraphAttrs.clear();
170193323Sed#else
171198090Srdivacky  errs() << "SelectionDAG::clearGraphAttrs is only available in debug builds"
172198090Srdivacky         << " on systems with Graphviz or gv!\n";
173193323Sed#endif
174193323Sed}
175193323Sed
176193323Sed
177193323Sed/// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".)
178193323Sed///
179193323Sedvoid SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) {
180193323Sed#ifndef NDEBUG
181193323Sed  NodeGraphAttrs[N] = Attrs;
182193323Sed#else
183198090Srdivacky  errs() << "SelectionDAG::setGraphAttrs is only available in debug builds"
184198090Srdivacky         << " on systems with Graphviz or gv!\n";
185193323Sed#endif
186193323Sed}
187193323Sed
188193323Sed
189193323Sed/// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".)
190193323Sed/// Used from getNodeAttributes.
191193323Sedconst std::string SelectionDAG::getGraphAttrs(const SDNode *N) const {
192193323Sed#ifndef NDEBUG
193193323Sed  std::map<const SDNode *, std::string>::const_iterator I =
194193323Sed    NodeGraphAttrs.find(N);
195200581Srdivacky
196193323Sed  if (I != NodeGraphAttrs.end())
197193323Sed    return I->second;
198193323Sed  else
199193323Sed    return "";
200193323Sed#else
201198090Srdivacky  errs() << "SelectionDAG::getGraphAttrs is only available in debug builds"
202198090Srdivacky         << " on systems with Graphviz or gv!\n";
203212904Sdim  return std::string();
204193323Sed#endif
205193323Sed}
206193323Sed
207193323Sed/// setGraphColor - Convenience for setting node color attribute.
208193323Sed///
209193323Sedvoid SelectionDAG::setGraphColor(const SDNode *N, const char *Color) {
210193323Sed#ifndef NDEBUG
211193323Sed  NodeGraphAttrs[N] = std::string("color=") + Color;
212193323Sed#else
213198090Srdivacky  errs() << "SelectionDAG::setGraphColor is only available in debug builds"
214198090Srdivacky         << " on systems with Graphviz or gv!\n";
215193323Sed#endif
216193323Sed}
217193323Sed
218193323Sed/// setSubgraphColorHelper - Implement setSubgraphColor.  Return
219193323Sed/// whether we truncated the search.
220193323Sed///
221193323Sedbool SelectionDAG::setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited,
222193323Sed                                          int level, bool &printed) {
223193323Sed  bool hit_limit = false;
224193323Sed
225193323Sed#ifndef NDEBUG
226193323Sed  if (level >= 20) {
227193323Sed    if (!printed) {
228193323Sed      printed = true;
229202375Srdivacky      DEBUG(dbgs() << "setSubgraphColor hit max level\n");
230193323Sed    }
231193323Sed    return true;
232193323Sed  }
233193323Sed
234193323Sed  unsigned oldSize = visited.size();
235193323Sed  visited.insert(N);
236193323Sed  if (visited.size() != oldSize) {
237193323Sed    setGraphColor(N, Color);
238193323Sed    for(SDNodeIterator i = SDNodeIterator::begin(N), iend = SDNodeIterator::end(N);
239193323Sed        i != iend;
240193323Sed        ++i) {
241193323Sed      hit_limit = setSubgraphColorHelper(*i, Color, visited, level+1, printed) || hit_limit;
242193323Sed    }
243193323Sed  }
244193323Sed#else
245198090Srdivacky  errs() << "SelectionDAG::setSubgraphColor is only available in debug builds"
246198090Srdivacky         << " on systems with Graphviz or gv!\n";
247193323Sed#endif
248193323Sed  return hit_limit;
249193323Sed}
250193323Sed
251193323Sed/// setSubgraphColor - Convenience for setting subgraph color attribute.
252193323Sed///
253193323Sedvoid SelectionDAG::setSubgraphColor(SDNode *N, const char *Color) {
254193323Sed#ifndef NDEBUG
255193323Sed  DenseSet<SDNode *> visited;
256193323Sed  bool printed = false;
257193323Sed  if (setSubgraphColorHelper(N, Color, visited, 0, printed)) {
258193323Sed    // Visually mark that we hit the limit
259193323Sed    if (strcmp(Color, "red") == 0) {
260193323Sed      setSubgraphColorHelper(N, "blue", visited, 0, printed);
261200581Srdivacky    } else if (strcmp(Color, "yellow") == 0) {
262193323Sed      setSubgraphColorHelper(N, "green", visited, 0, printed);
263193323Sed    }
264193323Sed  }
265193323Sed
266193323Sed#else
267198090Srdivacky  errs() << "SelectionDAG::setSubgraphColor is only available in debug builds"
268198090Srdivacky         << " on systems with Graphviz or gv!\n";
269193323Sed#endif
270193323Sed}
271193323Sed
272193323Sedstd::string ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit *SU) const {
273193323Sed  std::string s;
274193323Sed  raw_string_ostream O(s);
275193323Sed  O << "SU(" << SU->NodeNum << "): ";
276193323Sed  if (SU->getNode()) {
277218893Sdim    SmallVector<SDNode *, 4> GluedNodes;
278218893Sdim    for (SDNode *N = SU->getNode(); N; N = N->getGluedNode())
279218893Sdim      GluedNodes.push_back(N);
280218893Sdim    while (!GluedNodes.empty()) {
281199989Srdivacky      O << DOTGraphTraits<SelectionDAG*>
282218893Sdim        ::getSimpleNodeLabel(GluedNodes.back(), DAG);
283218893Sdim      GluedNodes.pop_back();
284218893Sdim      if (!GluedNodes.empty())
285193323Sed        O << "\n    ";
286193323Sed    }
287193323Sed  } else {
288193323Sed    O << "CROSS RC COPY";
289193323Sed  }
290193323Sed  return O.str();
291193323Sed}
292193323Sed
293193323Sedvoid ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter<ScheduleDAG*> &GW) const {
294193323Sed  if (DAG) {
295193323Sed    // Draw a special "GraphRoot" node to indicate the root of the graph.
296193323Sed    GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
297193323Sed    const SDNode *N = DAG->getRoot().getNode();
298193323Sed    if (N && N->getNodeId() != -1)
299193323Sed      GW.emitEdge(0, -1, &SUnits[N->getNodeId()], -1,
300193323Sed                  "color=blue,style=dashed");
301193323Sed  }
302193323Sed}
303