[llvm-shlib] Fix the version naming style of libLLVM for Windows (#85710)
[llvm-project.git] / llvm / utils / TableGen / MacroFusionPredicatorEmitter.cpp
blob7f494e532b1f441fab34432ea99b58dd9bd325de
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.
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.
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.
22 // The generated predicator will be like:
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 // ```
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.
39 //===---------------------------------------------------------------------===//
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>
51 using namespace llvm;
53 #define DEBUG_TYPE "macro-fusion-predicator"
55 namespace {
56 class MacroFusionPredicatorEmitter {
57 RecordKeeper &Records;
58 CodeGenTarget Target;
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);
73 public:
74 MacroFusionPredicatorEmitter(RecordKeeper &R) : Records(R), Target(R) {}
76 void run(raw_ostream &OS);
78 } // End anonymous namespace.
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";
86 for (Record *Fusion : Fusions) {
87 OS << "bool is" << Fusion->getName() << "(const TargetInstrInfo &, "
88 << "const TargetSubtargetInfo &, "
89 << "const MachineInstr *, "
90 << "const MachineInstr &);\n";
93 OS << "} // end namespace llvm\n";
94 OS << "\n#endif\n";
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";
103 for (Record *Fusion : Fusions) {
104 std::vector<Record *> Predicates =
105 Fusion->getValueAsListOfDefs("Predicates");
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";
114 emitPredicates(Predicates, PE, OS);
116 OS.indent(2) << "return true;\n";
117 OS << "}\n";
120 OS << "} // end namespace llvm\n";
121 OS << "\n#endif\n";
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());
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("FusionPredicateWithMCInstPredicate")) {
156 OS.indent(2) << "{\n";
157 OS.indent(4) << "const MachineInstr *MI = FirstMI;\n";
158 OS.indent(4) << "if (";
159 PE.setNegatePredicate(true);
160 PE.setIndentLevel(3);
161 PE.expandPredicate(OS, Predicate->getValueAsDef("Predicate"));
162 OS << ")\n";
163 OS.indent(4) << " return false;\n";
164 OS.indent(2) << "}\n";
165 } else {
166 PrintFatalError(Predicate->getLoc(),
167 "Unsupported predicate for first instruction: " +
168 Predicate->getType()->getAsString());
172 void MacroFusionPredicatorEmitter::emitSecondPredicate(Record *Predicate,
173 PredicateExpander &PE,
174 raw_ostream &OS) {
175 if (Predicate->isSubClassOf("FusionPredicateWithMCInstPredicate")) {
176 OS.indent(2) << "{\n";
177 OS.indent(4) << "const MachineInstr *MI = &SecondMI;\n";
178 OS.indent(4) << "if (";
179 PE.setNegatePredicate(true);
180 PE.setIndentLevel(3);
181 PE.expandPredicate(OS, Predicate->getValueAsDef("Predicate"));
182 OS << ")\n";
183 OS.indent(4) << " return false;\n";
184 OS.indent(2) << "}\n";
185 } else {
186 PrintFatalError(Predicate->getLoc(),
187 "Unsupported predicate for second instruction: " +
188 Predicate->getType()->getAsString());
192 void MacroFusionPredicatorEmitter::emitBothPredicate(Record *Predicate,
193 PredicateExpander &PE,
194 raw_ostream &OS) {
195 if (Predicate->isSubClassOf("FusionPredicateWithCode"))
196 OS << Predicate->getValueAsString("Predicate");
197 else if (Predicate->isSubClassOf("BothFusionPredicateWithMCInstPredicate")) {
198 emitFirstPredicate(Predicate, PE, OS);
199 emitSecondPredicate(Predicate, PE, OS);
200 } else if (Predicate->isSubClassOf("TieReg")) {
201 int FirstOpIdx = Predicate->getValueAsInt("FirstOpIdx");
202 int SecondOpIdx = Predicate->getValueAsInt("SecondOpIdx");
203 OS.indent(2) << "if (!(FirstMI->getOperand(" << FirstOpIdx
204 << ").isReg() &&\n";
205 OS.indent(2) << " SecondMI.getOperand(" << SecondOpIdx
206 << ").isReg() &&\n";
207 OS.indent(2) << " FirstMI->getOperand(" << FirstOpIdx
208 << ").getReg() == SecondMI.getOperand(" << SecondOpIdx
209 << ").getReg()))\n";
210 OS.indent(2) << " return false;\n";
211 } else
212 PrintFatalError(Predicate->getLoc(),
213 "Unsupported predicate for both instruction: " +
214 Predicate->getType()->getAsString());
217 void MacroFusionPredicatorEmitter::run(raw_ostream &OS) {
218 // Emit file header.
219 emitSourceFileHeader("Macro Fusion Predicators", OS);
221 PredicateExpander PE(Target.getName());
222 PE.setByRef(false);
223 PE.setExpandForMC(false);
225 std::vector<Record *> Fusions = Records.getAllDerivedDefinitions("Fusion");
226 // Sort macro fusions by name.
227 sort(Fusions, LessRecord());
228 emitMacroFusionDecl(Fusions, PE, OS);
229 OS << "\n";
230 emitMacroFusionImpl(Fusions, PE, OS);
233 static TableGen::Emitter::OptClass<MacroFusionPredicatorEmitter>
234 X("gen-macro-fusion-pred", "Generate macro fusion predicators.");