151 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- DDGPrinter.cpp - DOT printer for the data dependence graph ----------==//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file defines the `-dot-ddg` analysis pass, which emits DDG in DOT format
 | 
						|
// in a file named `ddg.<graph-name>.dot` for each loop  in a function.
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "llvm/Analysis/DDGPrinter.h"
 | 
						|
#include "llvm/Support/CommandLine.h"
 | 
						|
#include "llvm/Support/GraphWriter.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
static cl::opt<bool> DotOnly("dot-ddg-only", cl::init(false), cl::Hidden,
 | 
						|
                             cl::ZeroOrMore, cl::desc("simple ddg dot graph"));
 | 
						|
static cl::opt<std::string> DDGDotFilenamePrefix(
 | 
						|
    "dot-ddg-filename-prefix", cl::init("ddg"), cl::Hidden,
 | 
						|
    cl::desc("The prefix used for the DDG dot file names."));
 | 
						|
 | 
						|
static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly = false);
 | 
						|
 | 
						|
//===--------------------------------------------------------------------===//
 | 
						|
// Implementation of DDG DOT Printer for a loop
 | 
						|
//===--------------------------------------------------------------------===//
 | 
						|
PreservedAnalyses DDGDotPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
 | 
						|
                                         LoopStandardAnalysisResults &AR,
 | 
						|
                                         LPMUpdater &U) {
 | 
						|
  writeDDGToDotFile(*AM.getResult<DDGAnalysis>(L, AR), DotOnly);
 | 
						|
  return PreservedAnalyses::all();
 | 
						|
}
 | 
						|
 | 
						|
static void writeDDGToDotFile(DataDependenceGraph &G, bool DOnly) {
 | 
						|
  std::string Filename =
 | 
						|
      Twine(DDGDotFilenamePrefix + "." + G.getName() + ".dot").str();
 | 
						|
  errs() << "Writing '" << Filename << "'...";
 | 
						|
 | 
						|
  std::error_code EC;
 | 
						|
  raw_fd_ostream File(Filename, EC, sys::fs::OF_Text);
 | 
						|
 | 
						|
  if (!EC)
 | 
						|
    // We only provide the constant verson of the DOTGraphTrait specialization,
 | 
						|
    // hence the conversion to const pointer
 | 
						|
    WriteGraph(File, (const DataDependenceGraph *)&G, DOnly);
 | 
						|
  else
 | 
						|
    errs() << "  error opening file for writing!";
 | 
						|
  errs() << "\n";
 | 
						|
}
 | 
						|
 | 
						|
//===--------------------------------------------------------------------===//
 | 
						|
// DDG DOT Printer Implementation
 | 
						|
//===--------------------------------------------------------------------===//
 | 
						|
std::string DDGDotGraphTraits::getNodeLabel(const DDGNode *Node,
 | 
						|
                                            const DataDependenceGraph *Graph) {
 | 
						|
  if (isSimple())
 | 
						|
    return getSimpleNodeLabel(Node, Graph);
 | 
						|
  else
 | 
						|
    return getVerboseNodeLabel(Node, Graph);
 | 
						|
}
 | 
						|
 | 
						|
std::string DDGDotGraphTraits::getEdgeAttributes(
 | 
						|
    const DDGNode *Node, GraphTraits<const DDGNode *>::ChildIteratorType I,
 | 
						|
    const DataDependenceGraph *G) {
 | 
						|
  const DDGEdge *E = static_cast<const DDGEdge *>(*I.getCurrent());
 | 
						|
  if (isSimple())
 | 
						|
    return getSimpleEdgeAttributes(Node, E, G);
 | 
						|
  else
 | 
						|
    return getVerboseEdgeAttributes(Node, E, G);
 | 
						|
}
 | 
						|
 | 
						|
bool DDGDotGraphTraits::isNodeHidden(const DDGNode *Node,
 | 
						|
                                     const DataDependenceGraph *Graph) {
 | 
						|
  if (isSimple() && isa<RootDDGNode>(Node))
 | 
						|
    return true;
 | 
						|
  assert(Graph && "expected a valid graph pointer");
 | 
						|
  return Graph->getPiBlock(*Node) != nullptr;
 | 
						|
}
 | 
						|
 | 
						|
std::string
 | 
						|
DDGDotGraphTraits::getSimpleNodeLabel(const DDGNode *Node,
 | 
						|
                                      const DataDependenceGraph *G) {
 | 
						|
  std::string Str;
 | 
						|
  raw_string_ostream OS(Str);
 | 
						|
  if (isa<SimpleDDGNode>(Node))
 | 
						|
    for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())
 | 
						|
      OS << *II << "\n";
 | 
						|
  else if (isa<PiBlockDDGNode>(Node))
 | 
						|
    OS << "pi-block\nwith\n"
 | 
						|
       << cast<PiBlockDDGNode>(Node)->getNodes().size() << " nodes\n";
 | 
						|
  else if (isa<RootDDGNode>(Node))
 | 
						|
    OS << "root\n";
 | 
						|
  else
 | 
						|
    llvm_unreachable("Unimplemented type of node");
 | 
						|
  return OS.str();
 | 
						|
}
 | 
						|
 | 
						|
std::string
 | 
						|
DDGDotGraphTraits::getVerboseNodeLabel(const DDGNode *Node,
 | 
						|
                                       const DataDependenceGraph *G) {
 | 
						|
  std::string Str;
 | 
						|
  raw_string_ostream OS(Str);
 | 
						|
  OS << "<kind:" << Node->getKind() << ">\n";
 | 
						|
  if (isa<SimpleDDGNode>(Node))
 | 
						|
    for (auto *II : static_cast<const SimpleDDGNode *>(Node)->getInstructions())
 | 
						|
      OS << *II << "\n";
 | 
						|
  else if (isa<PiBlockDDGNode>(Node)) {
 | 
						|
    OS << "--- start of nodes in pi-block ---\n";
 | 
						|
    unsigned Count = 0;
 | 
						|
    const auto &PNodes = cast<PiBlockDDGNode>(Node)->getNodes();
 | 
						|
    for (auto *PN : PNodes) {
 | 
						|
      OS << getVerboseNodeLabel(PN, G);
 | 
						|
      if (++Count != PNodes.size())
 | 
						|
        OS << "\n";
 | 
						|
    }
 | 
						|
    OS << "--- end of nodes in pi-block ---\n";
 | 
						|
  } else if (isa<RootDDGNode>(Node))
 | 
						|
    OS << "root\n";
 | 
						|
  else
 | 
						|
    llvm_unreachable("Unimplemented type of node");
 | 
						|
  return OS.str();
 | 
						|
}
 | 
						|
 | 
						|
std::string DDGDotGraphTraits::getSimpleEdgeAttributes(
 | 
						|
    const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) {
 | 
						|
  std::string Str;
 | 
						|
  raw_string_ostream OS(Str);
 | 
						|
  DDGEdge::EdgeKind Kind = Edge->getKind();
 | 
						|
  OS << "label=\"[" << Kind << "]\"";
 | 
						|
  return OS.str();
 | 
						|
}
 | 
						|
 | 
						|
std::string DDGDotGraphTraits::getVerboseEdgeAttributes(
 | 
						|
    const DDGNode *Src, const DDGEdge *Edge, const DataDependenceGraph *G) {
 | 
						|
  std::string Str;
 | 
						|
  raw_string_ostream OS(Str);
 | 
						|
  DDGEdge::EdgeKind Kind = Edge->getKind();
 | 
						|
  OS << "label=\"[";
 | 
						|
  if (Kind == DDGEdge::EdgeKind::MemoryDependence)
 | 
						|
    OS << G->getDependenceString(*Src, Edge->getTargetNode());
 | 
						|
  else
 | 
						|
    OS << Kind;
 | 
						|
  OS << "]\"";
 | 
						|
  return OS.str();
 | 
						|
}
 |