151 lines · cpp
1//===- DDGPrinter.cpp - DOT printer for the data dependence graph ----------==//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//===----------------------------------------------------------------------===//10//11// This file defines the `-dot-ddg` analysis pass, which emits DDG in DOT format12// in a file named `ddg.<graph-name>.dot` for each loop in a function.13//===----------------------------------------------------------------------===//14 15#include "llvm/Analysis/DDGPrinter.h"16#include "llvm/Support/CommandLine.h"17#include "llvm/Support/GraphWriter.h"18 19using namespace llvm;20 21static cl::opt<bool> DotOnly("dot-ddg-only", cl::Hidden,22 cl::desc("simple ddg dot graph"));23static cl::opt<std::string> DDGDotFilenamePrefix(24 "dot-ddg-filename-prefix", cl::init("ddg"), cl::Hidden,25 cl::desc("The prefix used for the DDG dot file names."));26 27static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly = false);28 29//===--------------------------------------------------------------------===//30// Implementation of DDG DOT Printer for a loop31//===--------------------------------------------------------------------===//32PreservedAnalyses DDGDotPrinterPass::run(Loop &L, LoopAnalysisManager &AM,33 LoopStandardAnalysisResults &AR,34 LPMUpdater &U) {35 writeDDGToDotFile(*AM.getResult<DDGAnalysis>(L, AR), DotOnly);36 return PreservedAnalyses::all();37}38 39static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly) {40 std::string Filename =41 Twine(DDGDotFilenamePrefix + "." + G.getName() + ".dot").str();42 errs() << "Writing '" << Filename << "'...";43 44 std::error_code EC;45 raw_fd_ostream File(Filename, EC, sys::fs::OF_Text);46 47 if (!EC)48 // We only provide the constant verson of the DOTGraphTrait specialization,49 // hence the conversion to const pointer50 WriteGraph(File, (const DataDependenceGraph *)&G, DOnly);51 else52 errs() << " error opening file for writing!";53 errs() << "\n";54}55 56//===--------------------------------------------------------------------===//57// DDG DOT Printer Implementation58//===--------------------------------------------------------------------===//59std::string DDGDotGraphTraits::getNodeLabel(const DDGNode *Node,60 const DataDependenceGraph *Graph) {61 if (isSimple())62 return getSimpleNodeLabel(Node, Graph);63 else64 return getVerboseNodeLabel(Node, Graph);65}66 67std::string DDGDotGraphTraits::getEdgeAttributes(68 const DDGNode *Node, GraphTraits<const DDGNode *>::ChildIteratorType I,69 const DataDependenceGraph *G) {70 const DDGEdge *E = static_cast<const DDGEdge *>(*I.getCurrent());71 if (isSimple())72 return getSimpleEdgeAttributes(Node, E, G);73 else74 return getVerboseEdgeAttributes(Node, E, G);75}76 77bool DDGDotGraphTraits::isNodeHidden(const DDGNode *Node,78 const DataDependenceGraph *Graph) {79 if (isSimple() && isa<RootDDGNode>(Node))80 return true;81 assert(Graph && "expected a valid graph pointer");82 return Graph->getPiBlock(*Node) != nullptr;83}84 85std::string86DDGDotGraphTraits::getSimpleNodeLabel(const DDGNode *Node,87 const DataDependenceGraph *G) {88 std::string Str;89 raw_string_ostream OS(Str);90 if (isa<SimpleDDGNode>(Node))91 for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())92 OS << *II << "\n";93 else if (isa<PiBlockDDGNode>(Node))94 OS << "pi-block\nwith\n"95 << cast<PiBlockDDGNode>(Node)->getNodes().size() << " nodes\n";96 else if (isa<RootDDGNode>(Node))97 OS << "root\n";98 else99 llvm_unreachable("Unimplemented type of node");100 return OS.str();101}102 103std::string104DDGDotGraphTraits::getVerboseNodeLabel(const DDGNode *Node,105 const DataDependenceGraph *G) {106 std::string Str;107 raw_string_ostream OS(Str);108 OS << "<kind:" << Node->getKind() << ">\n";109 if (isa<SimpleDDGNode>(Node))110 for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())111 OS << *II << "\n";112 else if (isa<PiBlockDDGNode>(Node)) {113 OS << "--- start of nodes in pi-block ---\n";114 unsigned Count = 0;115 const auto &PNodes = cast<PiBlockDDGNode>(Node)->getNodes();116 for (auto *PN : PNodes) {117 OS << getVerboseNodeLabel(PN, G);118 if (++Count != PNodes.size())119 OS << "\n";120 }121 OS << "--- end of nodes in pi-block ---\n";122 } else if (isa<RootDDGNode>(Node))123 OS << "root\n";124 else125 llvm_unreachable("Unimplemented type of node");126 return OS.str();127}128 129std::string DDGDotGraphTraits::getSimpleEdgeAttributes(130 const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) {131 std::string Str;132 raw_string_ostream OS(Str);133 DDGEdge::EdgeKind Kind = Edge->getKind();134 OS << "label=\"[" << Kind << "]\"";135 return OS.str();136}137 138std::string DDGDotGraphTraits::getVerboseEdgeAttributes(139 const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) {140 std::string Str;141 raw_string_ostream OS(Str);142 DDGEdge::EdgeKind Kind = Edge->getKind();143 OS << "label=\"[";144 if (Kind == DDGEdge::EdgeKind::MemoryDependence)145 OS << G->getDependenceString(*Src, Edge->getTargetNode());146 else147 OS << Kind;148 OS << "]\"";149 return OS.str();150}151