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
14249423Sdim#include "llvm/CodeGen/SelectionDAG.h"
15193323Sed#include "ScheduleDAGSDNodes.h"
16249423Sdim#include "llvm/ADT/DenseSet.h"
17249423Sdim#include "llvm/ADT/StringExtras.h"
18193323Sed#include "llvm/Assembly/Writer.h"
19193323Sed#include "llvm/CodeGen/MachineConstantPool.h"
20193323Sed#include "llvm/CodeGen/MachineFunction.h"
21193323Sed#include "llvm/CodeGen/MachineModuleInfo.h"
22249423Sdim#include "llvm/DebugInfo.h"
23249423Sdim#include "llvm/IR/Constants.h"
24193323Sed#include "llvm/Support/Debug.h"
25193323Sed#include "llvm/Support/GraphWriter.h"
26193323Sed#include "llvm/Support/raw_ostream.h"
27249423Sdim#include "llvm/Target/TargetMachine.h"
28249423Sdim#include "llvm/Target/TargetRegisterInfo.h"
29193323Sedusing namespace llvm;
30193323Sed
31193323Sednamespace llvm {
32193323Sed  template<>
33193323Sed  struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {
34199989Srdivacky
35200581Srdivacky    explicit DOTGraphTraits(bool isSimple=false) :
36200581Srdivacky      DefaultDOTGraphTraits(isSimple) {}
37199989Srdivacky
38193323Sed    static bool hasEdgeDestLabels() {
39193323Sed      return true;
40193323Sed    }
41193323Sed
42193323Sed    static unsigned numEdgeDestLabels(const void *Node) {
43193323Sed      return ((const SDNode *) Node)->getNumValues();
44193323Sed    }
45193323Sed
46193323Sed    static std::string getEdgeDestLabel(const void *Node, unsigned i) {
47198090Srdivacky      return ((const SDNode *) Node)->getValueType(i).getEVTString();
48193323Sed    }
49193323Sed
50200581Srdivacky    template<typename EdgeIter>
51200581Srdivacky    static std::string getEdgeSourceLabel(const void *Node, EdgeIter I) {
52243830Sdim      return itostr(I - SDNodeIterator::begin((const SDNode *) Node));
53200581Srdivacky    }
54200581Srdivacky
55193323Sed    /// edgeTargetsEdgeSource - This method returns true if this outgoing edge
56199989Srdivacky    /// should actually target another edge source, not a node.  If this method
57199989Srdivacky    /// is implemented, getEdgeTarget should be implemented.
58193323Sed    template<typename EdgeIter>
59193323Sed    static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) {
60193323Sed      return true;
61193323Sed    }
62193323Sed
63193323Sed    /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is
64193323Sed    /// called to determine which outgoing edge of Node is the target of this
65193323Sed    /// edge.
66193323Sed    template<typename EdgeIter>
67193323Sed    static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) {
68193323Sed      SDNode *TargetNode = *I;
69193323Sed      SDNodeIterator NI = SDNodeIterator::begin(TargetNode);
70193323Sed      std::advance(NI, I.getNode()->getOperand(I.getOperand()).getResNo());
71193323Sed      return NI;
72193323Sed    }
73193323Sed
74193323Sed    static std::string getGraphName(const SelectionDAG *G) {
75243830Sdim      return G->getMachineFunction().getName();
76193323Sed    }
77193323Sed
78193323Sed    static bool renderGraphFromBottomUp() {
79193323Sed      return true;
80193323Sed    }
81200581Srdivacky
82193323Sed    static bool hasNodeAddressLabel(const SDNode *Node,
83193323Sed                                    const SelectionDAG *Graph) {
84193323Sed      return true;
85193323Sed    }
86200581Srdivacky
87193323Sed    /// If you want to override the dot attributes printed for a particular
88193323Sed    /// edge, override this method.
89193323Sed    template<typename EdgeIter>
90221345Sdim    static std::string getEdgeAttributes(const void *Node, EdgeIter EI,
91221345Sdim                                         const SelectionDAG *Graph) {
92193323Sed      SDValue Op = EI.getNode()->getOperand(EI.getOperand());
93198090Srdivacky      EVT VT = Op.getValueType();
94218893Sdim      if (VT == MVT::Glue)
95193323Sed        return "color=red,style=bold";
96193323Sed      else if (VT == MVT::Other)
97193323Sed        return "color=blue,style=dashed";
98193323Sed      return "";
99193323Sed    }
100193323Sed
101200581Srdivacky
102199989Srdivacky    static std::string getSimpleNodeLabel(const SDNode *Node,
103199989Srdivacky                                          const SelectionDAG *G) {
104199989Srdivacky      std::string Result = Node->getOperationName(G);
105199989Srdivacky      {
106199989Srdivacky        raw_string_ostream OS(Result);
107199989Srdivacky        Node->print_details(OS, G);
108199989Srdivacky      }
109199989Srdivacky      return Result;
110199989Srdivacky    }
111199989Srdivacky    std::string getNodeLabel(const SDNode *Node, const SelectionDAG *Graph);
112193323Sed    static std::string getNodeAttributes(const SDNode *N,
113193323Sed                                         const SelectionDAG *Graph) {
114193323Sed#ifndef NDEBUG
115193323Sed      const std::string &Attrs = Graph->getGraphAttrs(N);
116193323Sed      if (!Attrs.empty()) {
117193323Sed        if (Attrs.find("shape=") == std::string::npos)
118193323Sed          return std::string("shape=Mrecord,") + Attrs;
119193323Sed        else
120193323Sed          return Attrs;
121193323Sed      }
122193323Sed#endif
123193323Sed      return "shape=Mrecord";
124193323Sed    }
125193323Sed
126193323Sed    static void addCustomGraphFeatures(SelectionDAG *G,
127193323Sed                                       GraphWriter<SelectionDAG*> &GW) {
128193323Sed      GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
129193323Sed      if (G->getRoot().getNode())
130193323Sed        GW.emitEdge(0, -1, G->getRoot().getNode(), G->getRoot().getResNo(),
131193323Sed                    "color=blue,style=dashed");
132193323Sed    }
133193323Sed  };
134193323Sed}
135193323Sed
136193323Sedstd::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
137199989Srdivacky                                                        const SelectionDAG *G) {
138200581Srdivacky  return DOTGraphTraits<SelectionDAG*>::getSimpleNodeLabel(Node, G);
139193323Sed}
140193323Sed
141193323Sed
142193323Sed/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
143193323Sed/// rendered using 'dot'.
144193323Sed///
145193323Sedvoid SelectionDAG::viewGraph(const std::string &Title) {
146193323Sed// This code is only for debugging!
147193323Sed#ifndef NDEBUG
148243830Sdim  ViewGraph(this, "dag." + getMachineFunction().getName(),
149198090Srdivacky            false, Title);
150193323Sed#else
151198090Srdivacky  errs() << "SelectionDAG::viewGraph is only available in debug builds on "
152198090Srdivacky         << "systems with Graphviz or gv!\n";
153193323Sed#endif  // NDEBUG
154193323Sed}
155193323Sed
156193323Sed// This overload is defined out-of-line here instead of just using a
157193323Sed// default parameter because this is easiest for gdb to call.
158193323Sedvoid SelectionDAG::viewGraph() {
159193323Sed  viewGraph("");
160193323Sed}
161193323Sed
162193323Sed/// clearGraphAttrs - Clear all previously defined node graph attributes.
163193323Sed/// Intended to be used from a debugging tool (eg. gdb).
164193323Sedvoid SelectionDAG::clearGraphAttrs() {
165193323Sed#ifndef NDEBUG
166193323Sed  NodeGraphAttrs.clear();
167193323Sed#else
168198090Srdivacky  errs() << "SelectionDAG::clearGraphAttrs is only available in debug builds"
169198090Srdivacky         << " on systems with Graphviz or gv!\n";
170193323Sed#endif
171193323Sed}
172193323Sed
173193323Sed
174193323Sed/// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".)
175193323Sed///
176193323Sedvoid SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) {
177193323Sed#ifndef NDEBUG
178193323Sed  NodeGraphAttrs[N] = Attrs;
179193323Sed#else
180198090Srdivacky  errs() << "SelectionDAG::setGraphAttrs is only available in debug builds"
181198090Srdivacky         << " on systems with Graphviz or gv!\n";
182193323Sed#endif
183193323Sed}
184193323Sed
185193323Sed
186193323Sed/// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".)
187193323Sed/// Used from getNodeAttributes.
188193323Sedconst std::string SelectionDAG::getGraphAttrs(const SDNode *N) const {
189193323Sed#ifndef NDEBUG
190193323Sed  std::map<const SDNode *, std::string>::const_iterator I =
191193323Sed    NodeGraphAttrs.find(N);
192200581Srdivacky
193193323Sed  if (I != NodeGraphAttrs.end())
194193323Sed    return I->second;
195193323Sed  else
196193323Sed    return "";
197193323Sed#else
198198090Srdivacky  errs() << "SelectionDAG::getGraphAttrs is only available in debug builds"
199198090Srdivacky         << " on systems with Graphviz or gv!\n";
200212904Sdim  return std::string();
201193323Sed#endif
202193323Sed}
203193323Sed
204193323Sed/// setGraphColor - Convenience for setting node color attribute.
205193323Sed///
206193323Sedvoid SelectionDAG::setGraphColor(const SDNode *N, const char *Color) {
207193323Sed#ifndef NDEBUG
208193323Sed  NodeGraphAttrs[N] = std::string("color=") + Color;
209193323Sed#else
210198090Srdivacky  errs() << "SelectionDAG::setGraphColor is only available in debug builds"
211198090Srdivacky         << " on systems with Graphviz or gv!\n";
212193323Sed#endif
213193323Sed}
214193323Sed
215193323Sed/// setSubgraphColorHelper - Implement setSubgraphColor.  Return
216193323Sed/// whether we truncated the search.
217193323Sed///
218193323Sedbool SelectionDAG::setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited,
219193323Sed                                          int level, bool &printed) {
220193323Sed  bool hit_limit = false;
221193323Sed
222193323Sed#ifndef NDEBUG
223193323Sed  if (level >= 20) {
224193323Sed    if (!printed) {
225193323Sed      printed = true;
226202375Srdivacky      DEBUG(dbgs() << "setSubgraphColor hit max level\n");
227193323Sed    }
228193323Sed    return true;
229193323Sed  }
230193323Sed
231193323Sed  unsigned oldSize = visited.size();
232193323Sed  visited.insert(N);
233193323Sed  if (visited.size() != oldSize) {
234193323Sed    setGraphColor(N, Color);
235193323Sed    for(SDNodeIterator i = SDNodeIterator::begin(N), iend = SDNodeIterator::end(N);
236193323Sed        i != iend;
237193323Sed        ++i) {
238193323Sed      hit_limit = setSubgraphColorHelper(*i, Color, visited, level+1, printed) || hit_limit;
239193323Sed    }
240193323Sed  }
241193323Sed#else
242198090Srdivacky  errs() << "SelectionDAG::setSubgraphColor is only available in debug builds"
243198090Srdivacky         << " on systems with Graphviz or gv!\n";
244193323Sed#endif
245193323Sed  return hit_limit;
246193323Sed}
247193323Sed
248193323Sed/// setSubgraphColor - Convenience for setting subgraph color attribute.
249193323Sed///
250193323Sedvoid SelectionDAG::setSubgraphColor(SDNode *N, const char *Color) {
251193323Sed#ifndef NDEBUG
252193323Sed  DenseSet<SDNode *> visited;
253193323Sed  bool printed = false;
254193323Sed  if (setSubgraphColorHelper(N, Color, visited, 0, printed)) {
255193323Sed    // Visually mark that we hit the limit
256193323Sed    if (strcmp(Color, "red") == 0) {
257193323Sed      setSubgraphColorHelper(N, "blue", visited, 0, printed);
258200581Srdivacky    } else if (strcmp(Color, "yellow") == 0) {
259193323Sed      setSubgraphColorHelper(N, "green", visited, 0, printed);
260193323Sed    }
261193323Sed  }
262193323Sed
263193323Sed#else
264198090Srdivacky  errs() << "SelectionDAG::setSubgraphColor is only available in debug builds"
265198090Srdivacky         << " on systems with Graphviz or gv!\n";
266193323Sed#endif
267193323Sed}
268193323Sed
269193323Sedstd::string ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit *SU) const {
270193323Sed  std::string s;
271193323Sed  raw_string_ostream O(s);
272193323Sed  O << "SU(" << SU->NodeNum << "): ";
273193323Sed  if (SU->getNode()) {
274218893Sdim    SmallVector<SDNode *, 4> GluedNodes;
275218893Sdim    for (SDNode *N = SU->getNode(); N; N = N->getGluedNode())
276218893Sdim      GluedNodes.push_back(N);
277218893Sdim    while (!GluedNodes.empty()) {
278199989Srdivacky      O << DOTGraphTraits<SelectionDAG*>
279218893Sdim        ::getSimpleNodeLabel(GluedNodes.back(), DAG);
280218893Sdim      GluedNodes.pop_back();
281218893Sdim      if (!GluedNodes.empty())
282193323Sed        O << "\n    ";
283193323Sed    }
284193323Sed  } else {
285193323Sed    O << "CROSS RC COPY";
286193323Sed  }
287193323Sed  return O.str();
288193323Sed}
289193323Sed
290193323Sedvoid ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter<ScheduleDAG*> &GW) const {
291193323Sed  if (DAG) {
292193323Sed    // Draw a special "GraphRoot" node to indicate the root of the graph.
293193323Sed    GW.emitSimpleNode(0, "plaintext=circle", "GraphRoot");
294193323Sed    const SDNode *N = DAG->getRoot().getNode();
295193323Sed    if (N && N->getNodeId() != -1)
296193323Sed      GW.emitEdge(0, -1, &SUnits[N->getNodeId()], -1,
297193323Sed                  "color=blue,style=dashed");
298193323Sed  }
299193323Sed}
300