xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
1 //===------ MacroFusionPredicatorEmitter.cpp - Generator for Fusion ------===//
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 // MacroFusionPredicatorEmitter implements a TableGen-driven predicators
10 // generator for macro-op fusions.
11 //
12 // This TableGen backend processes `Fusion` definitions and generates
13 // predicators for checking if input instructions can be fused. These
14 // predicators can used in `MacroFusion` DAG mutation.
15 //
16 // The generated header file contains two parts: one for predicator
17 // declarations and one for predicator implementations. The user can get them
18 // by defining macro `GET_<TargetName>_MACRO_FUSION_PRED_DECL` or
19 // `GET_<TargetName>_MACRO_FUSION_PRED_IMPL` and then including the generated
20 // header file.
21 //
22 // The generated predicator will be like:
23 //
24 // ```
25 // bool isNAME(const TargetInstrInfo &TII,
26 //             const TargetSubtargetInfo &STI,
27 //             const MachineInstr *FirstMI,
28 //             const MachineInstr &SecondMI) {
29 //   auto &MRI = SecondMI.getMF()->getRegInfo();
30 //   /* Predicates */
31 //   return true;
32 // }
33 // ```
34 //
35 // The `Predicates` part is generated from a list of `FusionPredicate`, which
36 // can be predefined predicates, a raw code string or `MCInstPredicate` defined
37 // in TargetInstrPredicate.td.
38 //
39 //===---------------------------------------------------------------------===//
40 
41 #include "CodeGenTarget.h"
42 #include "PredicateExpander.h"
43 #include "llvm/ADT/SmallVector.h"
44 #include "llvm/Support/Debug.h"
45 #include "llvm/TableGen/Error.h"
46 #include "llvm/TableGen/Record.h"
47 #include "llvm/TableGen/TableGenBackend.h"
48 #include <set>
49 #include <vector>
50 
51 using namespace llvm;
52 
53 #define DEBUG_TYPE "macro-fusion-predicator"
54 
55 namespace {
56 class MacroFusionPredicatorEmitter {
57   RecordKeeper &Records;
58   CodeGenTarget Target;
59 
60   void emitMacroFusionDecl(std::vector<Record *> Fusions, PredicateExpander &PE,
61                            raw_ostream &OS);
62   void emitMacroFusionImpl(std::vector<Record *> Fusions, PredicateExpander &PE,
63                            raw_ostream &OS);
64   void emitPredicates(std::vector<Record *> &FirstPredicate,
65                       PredicateExpander &PE, raw_ostream &OS);
66   void emitFirstPredicate(Record *SecondPredicate, PredicateExpander &PE,
67                           raw_ostream &OS);
68   void emitSecondPredicate(Record *SecondPredicate, PredicateExpander &PE,
69                            raw_ostream &OS);
70   void emitBothPredicate(Record *Predicates, PredicateExpander &PE,
71                          raw_ostream &OS);
72 
73 public:
74   MacroFusionPredicatorEmitter(RecordKeeper &R) : Records(R), Target(R) {}
75 
76   void run(raw_ostream &OS);
77 };
78 } // End anonymous namespace.
79 
80 void MacroFusionPredicatorEmitter::emitMacroFusionDecl(
81     std::vector<Record *> Fusions, PredicateExpander &PE, raw_ostream &OS) {
82   OS << "#ifdef GET_" << Target.getName() << "_MACRO_FUSION_PRED_DECL\n";
83   OS << "#undef GET_" << Target.getName() << "_MACRO_FUSION_PRED_DECL\n\n";
84   OS << "namespace llvm {\n";
85 
86   for (Record *Fusion : Fusions) {
87     OS << "bool is" << Fusion->getName() << "(const TargetInstrInfo &, "
88        << "const TargetSubtargetInfo &, "
89        << "const MachineInstr *, "
90        << "const MachineInstr &);\n";
91   }
92 
93   OS << "} // end namespace llvm\n";
94   OS << "\n#endif\n";
95 }
96 
97 void MacroFusionPredicatorEmitter::emitMacroFusionImpl(
98     std::vector<Record *> Fusions, PredicateExpander &PE, raw_ostream &OS) {
99   OS << "#ifdef GET_" << Target.getName() << "_MACRO_FUSION_PRED_IMPL\n";
100   OS << "#undef GET_" << Target.getName() << "_MACRO_FUSION_PRED_IMPL\n\n";
101   OS << "namespace llvm {\n";
102 
103   for (Record *Fusion : Fusions) {
104     std::vector<Record *> Predicates =
105         Fusion->getValueAsListOfDefs("Predicates");
106 
107     OS << "bool is" << Fusion->getName() << "(\n";
108     OS.indent(4) << "const TargetInstrInfo &TII,\n";
109     OS.indent(4) << "const TargetSubtargetInfo &STI,\n";
110     OS.indent(4) << "const MachineInstr *FirstMI,\n";
111     OS.indent(4) << "const MachineInstr &SecondMI) {\n";
112     OS.indent(2) << "auto &MRI = SecondMI.getMF()->getRegInfo();\n";
113 
114     emitPredicates(Predicates, PE, OS);
115 
116     OS.indent(2) << "return true;\n";
117     OS << "}\n";
118   }
119 
120   OS << "} // end namespace llvm\n";
121   OS << "\n#endif\n";
122 }
123 
124 void MacroFusionPredicatorEmitter::emitPredicates(
125     std::vector<Record *> &Predicates, PredicateExpander &PE, raw_ostream &OS) {
126   for (Record *Predicate : Predicates) {
127     Record *Target = Predicate->getValueAsDef("Target");
128     if (Target->getName() == "first_fusion_target")
129       emitFirstPredicate(Predicate, PE, OS);
130     else if (Target->getName() == "second_fusion_target")
131       emitSecondPredicate(Predicate, PE, OS);
132     else if (Target->getName() == "both_fusion_target")
133       emitBothPredicate(Predicate, PE, OS);
134     else
135       PrintFatalError(Target->getLoc(),
136                       "Unsupported 'FusionTarget': " + Target->getName());
137   }
138 }
139 
140 void MacroFusionPredicatorEmitter::emitFirstPredicate(Record *Predicate,
141                                                       PredicateExpander &PE,
142                                                       raw_ostream &OS) {
143   if (Predicate->isSubClassOf("WildcardPred")) {
144     OS.indent(2) << "if (!FirstMI)\n";
145     OS.indent(2) << "  return "
146                  << (Predicate->getValueAsBit("ReturnValue") ? "true" : "false")
147                  << ";\n";
148   } else if (Predicate->isSubClassOf("OneUsePred")) {
149     OS.indent(2) << "{\n";
150     OS.indent(4) << "Register FirstDest = FirstMI->getOperand(0).getReg();\n";
151     OS.indent(4)
152         << "if (FirstDest.isVirtual() && !MRI.hasOneNonDBGUse(FirstDest))\n";
153     OS.indent(4) << "  return false;\n";
154     OS.indent(2) << "}\n";
155   } else if (Predicate->isSubClassOf(
156                  "FirstFusionPredicateWithMCInstPredicate")) {
157     OS.indent(2) << "{\n";
158     OS.indent(4) << "const MachineInstr *MI = FirstMI;\n";
159     OS.indent(4) << "if (";
160     PE.setNegatePredicate(true);
161     PE.setIndentLevel(3);
162     PE.expandPredicate(OS, Predicate->getValueAsDef("Predicate"));
163     OS << ")\n";
164     OS.indent(4) << "  return false;\n";
165     OS.indent(2) << "}\n";
166   } else {
167     PrintFatalError(Predicate->getLoc(),
168                     "Unsupported predicate for first instruction: " +
169                         Predicate->getType()->getAsString());
170   }
171 }
172 
173 void MacroFusionPredicatorEmitter::emitSecondPredicate(Record *Predicate,
174                                                        PredicateExpander &PE,
175                                                        raw_ostream &OS) {
176   if (Predicate->isSubClassOf("SecondFusionPredicateWithMCInstPredicate")) {
177     OS.indent(2) << "{\n";
178     OS.indent(4) << "const MachineInstr *MI = &SecondMI;\n";
179     OS.indent(4) << "if (";
180     PE.setNegatePredicate(true);
181     PE.setIndentLevel(3);
182     PE.expandPredicate(OS, Predicate->getValueAsDef("Predicate"));
183     OS << ")\n";
184     OS.indent(4) << "  return false;\n";
185     OS.indent(2) << "}\n";
186   } else {
187     PrintFatalError(Predicate->getLoc(),
188                     "Unsupported predicate for first instruction: " +
189                         Predicate->getType()->getAsString());
190   }
191 }
192 
193 void MacroFusionPredicatorEmitter::emitBothPredicate(Record *Predicate,
194                                                      PredicateExpander &PE,
195                                                      raw_ostream &OS) {
196   if (Predicate->isSubClassOf("FusionPredicateWithCode"))
197     OS << Predicate->getValueAsString("Predicate");
198   else if (Predicate->isSubClassOf("BothFusionPredicateWithMCInstPredicate")) {
199     Record *MCPred = Predicate->getValueAsDef("Predicate");
200     emitFirstPredicate(MCPred, PE, OS);
201     emitSecondPredicate(MCPred, PE, OS);
202   } else if (Predicate->isSubClassOf("TieReg")) {
203     int FirstOpIdx = Predicate->getValueAsInt("FirstOpIdx");
204     int SecondOpIdx = Predicate->getValueAsInt("SecondOpIdx");
205     OS.indent(2) << "if (!(FirstMI->getOperand(" << FirstOpIdx
206                  << ").isReg() &&\n";
207     OS.indent(2) << "      SecondMI.getOperand(" << SecondOpIdx
208                  << ").isReg() &&\n";
209     OS.indent(2) << "      FirstMI->getOperand(" << FirstOpIdx
210                  << ").getReg() == SecondMI.getOperand(" << SecondOpIdx
211                  << ").getReg()))\n";
212     OS.indent(2) << "  return false;\n";
213   } else
214     PrintFatalError(Predicate->getLoc(),
215                     "Unsupported predicate for both instruction: " +
216                         Predicate->getType()->getAsString());
217 }
218 
219 void MacroFusionPredicatorEmitter::run(raw_ostream &OS) {
220   // Emit file header.
221   emitSourceFileHeader("Macro Fusion Predicators", OS);
222 
223   PredicateExpander PE(Target.getName());
224   PE.setByRef(false);
225   PE.setExpandForMC(false);
226 
227   std::vector<Record *> Fusions = Records.getAllDerivedDefinitions("Fusion");
228   // Sort macro fusions by name.
229   sort(Fusions, LessRecord());
230   emitMacroFusionDecl(Fusions, PE, OS);
231   OS << "\n";
232   emitMacroFusionImpl(Fusions, PE, OS);
233 }
234 
235 static TableGen::Emitter::OptClass<MacroFusionPredicatorEmitter>
236     X("gen-macro-fusion-pred", "Generate macro fusion predicators.");
237