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
15 using namespace llvm;
16
writeDOTGraph(raw_ostream & OS,StringRef ID) const17 void 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
print(raw_ostream & OS) const109 LLVM_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
operator <<(raw_ostream & OS,const GIMatchDag & G)135 raw_ostream &llvm::operator<<(raw_ostream &OS, const GIMatchDag &G) {
136 G.print(OS);
137 return OS;
138 }
139