brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.3 KiB · ac28f62 Raw
315 lines · cpp
1//===-- SelectionDAGPrinter.cpp - Implement SelectionDAG::viewGraph() -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This implements the SelectionDAG::viewGraph method.10//11//===----------------------------------------------------------------------===//12 13#include "ScheduleDAGSDNodes.h"14#include "llvm/ADT/DenseSet.h"15#include "llvm/ADT/StringExtras.h"16#include "llvm/CodeGen/MachineFunction.h"17#include "llvm/CodeGen/SelectionDAG.h"18#include "llvm/Support/Debug.h"19#include "llvm/Support/GraphWriter.h"20#include "llvm/Support/raw_ostream.h"21using namespace llvm;22 23#define DEBUG_TYPE "dag-printer"24 25namespace llvm {26  template<>27  struct DOTGraphTraits<SelectionDAG*> : public DefaultDOTGraphTraits {28 29    explicit DOTGraphTraits(bool isSimple=false) :30      DefaultDOTGraphTraits(isSimple) {}31 32    static bool hasEdgeDestLabels() {33      return true;34    }35 36    static unsigned numEdgeDestLabels(const void *Node) {37      return ((const SDNode *) Node)->getNumValues();38    }39 40    static std::string getEdgeDestLabel(const void *Node, unsigned i) {41      return ((const SDNode *) Node)->getValueType(i).getEVTString();42    }43 44    template<typename EdgeIter>45    static std::string getEdgeSourceLabel(const void *Node, EdgeIter I) {46      return itostr(I - SDNodeIterator::begin((const SDNode *) Node));47    }48 49    /// edgeTargetsEdgeSource - This method returns true if this outgoing edge50    /// should actually target another edge source, not a node.  If this method51    /// is implemented, getEdgeTarget should be implemented.52    template<typename EdgeIter>53    static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) {54      return true;55    }56 57    /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is58    /// called to determine which outgoing edge of Node is the target of this59    /// edge.60    template<typename EdgeIter>61    static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) {62      SDNode *TargetNode = *I;63      SDNodeIterator NI = SDNodeIterator::begin(TargetNode);64      std::advance(NI, I.getNode()->getOperand(I.getOperand()).getResNo());65      return NI;66    }67 68    static std::string getGraphName(const SelectionDAG *G) {69      return std::string(G->getMachineFunction().getName());70    }71 72    static bool renderGraphFromBottomUp() {73      return true;74    }75 76    static std::string getNodeIdentifierLabel(const SDNode *Node,77                                              const SelectionDAG *Graph) {78      std::string R;79      raw_string_ostream OS(R);80#ifndef NDEBUG81      OS << 't' << Node->PersistentId;82#else83      OS << static_cast<const void *>(Node);84#endif85      return R;86    }87 88    /// If you want to override the dot attributes printed for a particular89    /// edge, override this method.90    template<typename EdgeIter>91    static std::string getEdgeAttributes(const void *Node, EdgeIter EI,92                                         const SelectionDAG *Graph) {93      SDValue Op = EI.getNode()->getOperand(EI.getOperand());94      EVT VT = Op.getValueType();95      if (VT == MVT::Glue)96        return "color=red,style=bold";97      else if (VT == MVT::Other)98        return "color=blue,style=dashed";99      return "";100    }101 102 103    static std::string getSimpleNodeLabel(const SDNode *Node,104                                          const SelectionDAG *G) {105      std::string Result = Node->getOperationName(G);106      {107        raw_string_ostream OS(Result);108        Node->print_details(OS, G);109      }110      return Result;111    }112    std::string getNodeLabel(const SDNode *Node, const SelectionDAG *Graph);113    static std::string getNodeAttributes(const SDNode *N,114                                         const SelectionDAG *Graph) {115#ifndef NDEBUG116      const std::string &Attrs = Graph->getGraphAttrs(N);117      if (!Attrs.empty()) {118        if (Attrs.find("shape=") == std::string::npos)119          return std::string("shape=Mrecord,") + Attrs;120        else121          return Attrs;122      }123#endif124      return "shape=Mrecord";125    }126 127    static void addCustomGraphFeatures(SelectionDAG *G,128                                       GraphWriter<SelectionDAG*> &GW) {129      GW.emitSimpleNode(nullptr, "plaintext=circle", "GraphRoot");130      if (G->getRoot().getNode())131        GW.emitEdge(nullptr, -1, G->getRoot().getNode(), G->getRoot().getResNo(),132                    "color=blue,style=dashed");133    }134  };135}136 137std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,138                                                        const SelectionDAG *G) {139  return DOTGraphTraits<SelectionDAG*>::getSimpleNodeLabel(Node, G);140}141 142 143/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG144/// rendered using 'dot'.145///146void SelectionDAG::viewGraph(const std::string &Title) {147// This code is only for debugging!148#ifndef NDEBUG149  ViewGraph(this, "dag." + getMachineFunction().getName(),150            false, Title);151#else152  errs() << "SelectionDAG::viewGraph is only available in debug builds on "153         << "systems with Graphviz or gv!\n";154#endif  // NDEBUG155}156 157// This overload is defined out-of-line here instead of just using a158// default parameter because this is easiest for gdb to call.159void SelectionDAG::viewGraph() {160  viewGraph("");161}162 163/// Just dump dot graph to a user-provided path and title.164/// This doesn't open the dot viewer program and165/// helps visualization when outside debugging session.166/// FileName expects absolute path. If provided167/// without any path separators then the file168/// will be created in the current directory.169/// Error will be emitted if the path is insane.170#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)171LLVM_DUMP_METHOD void SelectionDAG::dumpDotGraph(const Twine &FileName,172                                                 const Twine &Title) {173  dumpDotGraphToFile(this, FileName, Title);174}175#endif176 177/// clearGraphAttrs - Clear all previously defined node graph attributes.178/// Intended to be used from a debugging tool (eg. gdb).179void SelectionDAG::clearGraphAttrs() {180#if LLVM_ENABLE_ABI_BREAKING_CHECKS181  NodeGraphAttrs.clear();182#else183  errs() << "SelectionDAG::clearGraphAttrs is only available in builds with "184         << "ABI breaking checks enabled on systems with Graphviz or gv!\n";185#endif186}187 188 189/// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".)190///191void SelectionDAG::setGraphAttrs(const SDNode *N, const char *Attrs) {192#if LLVM_ENABLE_ABI_BREAKING_CHECKS193  NodeGraphAttrs[N] = Attrs;194#else195  errs() << "SelectionDAG::setGraphAttrs is only available in builds with "196         << "ABI breaking checks enabled on systems with Graphviz or gv!\n";197#endif198}199 200 201/// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".)202/// Used from getNodeAttributes.203std::string SelectionDAG::getGraphAttrs(const SDNode *N) const {204#if LLVM_ENABLE_ABI_BREAKING_CHECKS205  std::map<const SDNode *, std::string>::const_iterator I =206    NodeGraphAttrs.find(N);207 208  if (I != NodeGraphAttrs.end())209    return I->second;210  else211    return "";212#else213  errs() << "SelectionDAG::getGraphAttrs is only available in builds with "214         << "ABI breaking checks enabled on systems with Graphviz or gv!\n";215  return std::string();216#endif217}218 219/// setGraphColor - Convenience for setting node color attribute.220///221void SelectionDAG::setGraphColor(const SDNode *N, const char *Color) {222#if LLVM_ENABLE_ABI_BREAKING_CHECKS223  NodeGraphAttrs[N] = std::string("color=") + Color;224#else225  errs() << "SelectionDAG::setGraphColor is only available in builds with "226         << "ABI breaking checks enabled on systems with Graphviz or gv!\n";227#endif228}229 230/// setSubgraphColorHelper - Implement setSubgraphColor.  Return231/// whether we truncated the search.232///233bool SelectionDAG::setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited,234                                          int level, bool &printed) {235  bool hit_limit = false;236 237#ifndef NDEBUG238  if (level >= 20) {239    if (!printed) {240      printed = true;241      LLVM_DEBUG(dbgs() << "setSubgraphColor hit max level\n");242    }243    return true;244  }245 246  unsigned oldSize = visited.size();247  visited.insert(N);248  if (visited.size() != oldSize) {249    setGraphColor(N, Color);250    for(SDNodeIterator i = SDNodeIterator::begin(N), iend = SDNodeIterator::end(N);251        i != iend;252        ++i) {253      hit_limit = setSubgraphColorHelper(*i, Color, visited, level+1, printed) || hit_limit;254    }255  }256#else257  errs() << "SelectionDAG::setSubgraphColor is only available in debug builds"258         << " on systems with Graphviz or gv!\n";259#endif260  return hit_limit;261}262 263/// setSubgraphColor - Convenience for setting subgraph color attribute.264///265void SelectionDAG::setSubgraphColor(SDNode *N, const char *Color) {266#ifndef NDEBUG267  DenseSet<SDNode *> visited;268  bool printed = false;269  if (setSubgraphColorHelper(N, Color, visited, 0, printed)) {270    // Visually mark that we hit the limit271    if (strcmp(Color, "red") == 0) {272      setSubgraphColorHelper(N, "blue", visited, 0, printed);273    } else if (strcmp(Color, "yellow") == 0) {274      setSubgraphColorHelper(N, "green", visited, 0, printed);275    }276  }277 278#else279  errs() << "SelectionDAG::setSubgraphColor is only available in debug builds"280         << " on systems with Graphviz or gv!\n";281#endif282}283 284std::string ScheduleDAGSDNodes::getGraphNodeLabel(const SUnit *SU) const {285  std::string s;286  raw_string_ostream O(s);287  O << "SU(" << SU->NodeNum << "): ";288  if (SU->getNode()) {289    SmallVector<SDNode *, 4> GluedNodes;290    for (SDNode *N = SU->getNode(); N; N = N->getGluedNode())291      GluedNodes.push_back(N);292    while (!GluedNodes.empty()) {293      O << DOTGraphTraits<SelectionDAG*>294        ::getSimpleNodeLabel(GluedNodes.back(), DAG);295      GluedNodes.pop_back();296      if (!GluedNodes.empty())297        O << "\n    ";298    }299  } else {300    O << "CROSS RC COPY";301  }302  return s;303}304 305void ScheduleDAGSDNodes::getCustomGraphFeatures(GraphWriter<ScheduleDAG*> &GW) const {306  if (DAG) {307    // Draw a special "GraphRoot" node to indicate the root of the graph.308    GW.emitSimpleNode(nullptr, "plaintext=circle", "GraphRoot");309    const SDNode *N = DAG->getRoot().getNode();310    if (N && N->getNodeId() != -1)311      GW.emitEdge(nullptr, -1, &SUnits[N->getNodeId()], -1,312                  "color=blue,style=dashed");313  }314}315