1//===- GIMatchDag.cpp - A DAG representation of a pattern to be matched ---===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "GIMatchDag.h"
10
11#include "llvm/Support/Format.h"
12#include "llvm/TableGen/Record.h"
13#include "../CodeGenInstruction.h"
14
15using namespace llvm;
16
17void GIMatchDag::writeDOTGraph(raw_ostream &OS, StringRef ID) const {
18  const auto writePorts = [&](StringRef Prefix,
19                              const GIMatchDagOperandList &Operands) {
20    StringRef Separator = "";
21    OS << "{";
22    for (const auto &Op : enumerate(Operands)) {
23      OS << Separator << "<" << Prefix << format("%d", Op.index()) << ">"
24         << "#" << Op.index() << " $" << Op.value().getName();
25      Separator = "|";
26    }
27    OS << "}";
28  };
29
30  OS << "digraph \"" << ID << "\" {\n"
31     << "  rankdir=\"BT\"\n";
32  for (const auto &N : InstrNodes) {
33    OS << "  " << format("Node%p", &*N) << " [shape=record,label=\"{";
34    writePorts("s", N->getOperandInfo());
35    OS << "|" << N->getName();
36    if (N->getOpcodeAnnotation())
37      OS << "|" << N->getOpcodeAnnotation()->TheDef->getName();
38    if (N->isMatchRoot())
39      OS << "|Match starts here";
40    OS << "|";
41    SmallVector<std::pair<unsigned, StringRef>, 8> ToPrint;
42    for (const auto &Assignment : N->user_assigned_operand_names())
43      ToPrint.emplace_back(Assignment.first, Assignment.second);
44    llvm::sort(ToPrint.begin(), ToPrint.end());
45    StringRef Separator = "";
46    for (const auto &Assignment : ToPrint) {
47      OS << Separator << "$" << Assignment.second << "=getOperand("
48         << Assignment.first << ")";
49      Separator = ", ";
50    }
51    OS << format("|%p|", &N);
52    writePorts("d", N->getOperandInfo());
53    OS << "}\"";
54    if (N->isMatchRoot())
55      OS << ",color=red";
56    OS << "]\n";
57  }
58
59  for (const auto &E : Edges) {
60    const char *FromFmt = "Node%p:s%d:n";
61    const char *ToFmt = "Node%p:d%d:s";
62    if (E->getFromMO()->isDef() && !E->getToMO()->isDef())
63      std::swap(FromFmt, ToFmt);
64    auto From = format(FromFmt, E->getFromMI(), E->getFromMO()->getIdx());
65    auto To = format(ToFmt, E->getToMI(), E->getToMO()->getIdx());
66    if (E->getFromMO()->isDef() && !E->getToMO()->isDef())
67      std::swap(From, To);
68
69    OS << "  " << From << " -> " << To << " [label=\"$" << E->getName();
70    if (E->getFromMO()->isDef() == E->getToMO()->isDef())
71      OS << " INVALID EDGE!";
72    OS << "\"";
73    if (E->getFromMO()->isDef() == E->getToMO()->isDef())
74      OS << ",color=red";
75    else if (E->getFromMO()->isDef() && !E->getToMO()->isDef())
76      OS << ",dir=back,arrowtail=crow";
77    OS << "]\n";
78  }
79
80  for (const auto &N : PredicateNodes) {
81    OS << "  " << format("Pred%p", &*N) << " [shape=record,label=\"{";
82    writePorts("s", N->getOperandInfo());
83    OS << "|" << N->getName() << "|";
84    N->printDescription(OS);
85    OS << format("|%p|", &N);
86    writePorts("d", N->getOperandInfo());
87    OS << "}\",style=dotted]\n";
88  }
89
90  for (const auto &E : PredicateDependencies) {
91    const char *FromMIFmt = "Node%p:e";
92    const char *FromMOFmt = "Node%p:s%d:n";
93    const char *ToFmt = "Pred%p:d%d:s";
94    auto To = format(ToFmt, E->getPredicate(), E->getPredicateOp()->getIdx());
95    auto Style = "[style=dotted]";
96    if (E->getRequiredMO()) {
97      auto From =
98          format(FromMOFmt, E->getRequiredMI(), E->getRequiredMO()->getIdx());
99      OS << "  " << From << " -> " << To << " " << Style << "\n";
100      continue;
101    }
102    auto From = format(FromMIFmt, E->getRequiredMI());
103    OS << "  " << From << " -> " << To << " " << Style << "\n";
104  }
105
106  OS << "}\n";
107}
108
109LLVM_DUMP_METHOD void GIMatchDag::print(raw_ostream &OS) const {
110  OS << "matchdag {\n";
111  for (const auto &N : InstrNodes) {
112    OS << "  ";
113    N->print(OS);
114    OS << "\n";
115  }
116  for (const auto &E : Edges) {
117    OS << "  ";
118    E->print(OS);
119    OS << "\n";
120  }
121
122  for (const auto &P : PredicateNodes) {
123    OS << "  ";
124    P->print(OS);
125    OS << "\n";
126  }
127  for (const auto &D : PredicateDependencies) {
128    OS << "  ";
129    D->print(OS);
130    OS << "\n";
131  }
132  OS << "}\n";
133}
134
135raw_ostream &llvm::operator<<(raw_ostream &OS, const GIMatchDag &G) {
136  G.print(OS);
137  return OS;
138}
139