[RISCV][VLOPT] Add vector narrowing integer right shift instructions to isSupportedIn...
[llvm-project.git] / llvm / utils / TableGen / MacroFusionPredicatorEmitter.cpp
blobce509c7ef1aba2ed2075f8ce68c699244a58d146
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 "Common/CodeGenTarget.h"
42 #include "Common/PredicateExpander.h"
43 #include "llvm/Support/Debug.h"
44 #include "llvm/TableGen/Error.h"
45 #include "llvm/TableGen/Record.h"
46 #include "llvm/TableGen/TableGenBackend.h"
47 #include <vector>
49 using namespace llvm;
51 #define DEBUG_TYPE "macro-fusion-predicator"
53 namespace {
54 class MacroFusionPredicatorEmitter {
55 const RecordKeeper &Records;
56 const CodeGenTarget Target;
58 void emitMacroFusionDecl(ArrayRef<const Record *> Fusions,
59 PredicateExpander &PE, raw_ostream &OS);
60 void emitMacroFusionImpl(ArrayRef<const Record *> Fusions,
61 PredicateExpander &PE, raw_ostream &OS);
62 void emitPredicates(ArrayRef<const Record *> FirstPredicate,
63 bool IsCommutable, PredicateExpander &PE,
64 raw_ostream &OS);
65 void emitFirstPredicate(const Record *SecondPredicate, bool IsCommutable,
66 PredicateExpander &PE, raw_ostream &OS);
67 void emitSecondPredicate(const Record *SecondPredicate, bool IsCommutable,
68 PredicateExpander &PE, raw_ostream &OS);
69 void emitBothPredicate(const Record *Predicates, bool IsCommutable,
70 PredicateExpander &PE, raw_ostream &OS);
72 public:
73 MacroFusionPredicatorEmitter(const RecordKeeper &R) : Records(R), Target(R) {}
75 void run(raw_ostream &OS);
77 } // End anonymous namespace.
79 void MacroFusionPredicatorEmitter::emitMacroFusionDecl(
80 ArrayRef<const Record *> Fusions, PredicateExpander &PE, raw_ostream &OS) {
81 OS << "#ifdef GET_" << Target.getName() << "_MACRO_FUSION_PRED_DECL\n";
82 OS << "#undef GET_" << Target.getName() << "_MACRO_FUSION_PRED_DECL\n\n";
83 OS << "namespace llvm {\n";
85 for (const Record *Fusion : Fusions) {
86 OS << "bool is" << Fusion->getName() << "(const TargetInstrInfo &, "
87 << "const TargetSubtargetInfo &, "
88 << "const MachineInstr *, "
89 << "const MachineInstr &);\n";
92 OS << "} // end namespace llvm\n";
93 OS << "\n#endif\n";
96 void MacroFusionPredicatorEmitter::emitMacroFusionImpl(
97 ArrayRef<const Record *> Fusions, PredicateExpander &PE, raw_ostream &OS) {
98 OS << "#ifdef GET_" << Target.getName() << "_MACRO_FUSION_PRED_IMPL\n";
99 OS << "#undef GET_" << Target.getName() << "_MACRO_FUSION_PRED_IMPL\n\n";
100 OS << "namespace llvm {\n";
102 for (const Record *Fusion : Fusions) {
103 std::vector<const Record *> Predicates =
104 Fusion->getValueAsListOfDefs("Predicates");
105 bool IsCommutable = Fusion->getValueAsBit("IsCommutable");
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)
113 << "[[maybe_unused]] auto &MRI = SecondMI.getMF()->getRegInfo();\n";
115 emitPredicates(Predicates, IsCommutable, PE, OS);
117 OS.indent(2) << "return true;\n";
118 OS << "}\n";
121 OS << "} // end namespace llvm\n";
122 OS << "\n#endif\n";
125 void MacroFusionPredicatorEmitter::emitPredicates(
126 ArrayRef<const Record *> Predicates, bool IsCommutable,
127 PredicateExpander &PE, raw_ostream &OS) {
128 for (const Record *Predicate : Predicates) {
129 const Record *Target = Predicate->getValueAsDef("Target");
130 if (Target->getName() == "first_fusion_target")
131 emitFirstPredicate(Predicate, IsCommutable, PE, OS);
132 else if (Target->getName() == "second_fusion_target")
133 emitSecondPredicate(Predicate, IsCommutable, PE, OS);
134 else if (Target->getName() == "both_fusion_target")
135 emitBothPredicate(Predicate, IsCommutable, PE, OS);
136 else
137 PrintFatalError(Target->getLoc(),
138 "Unsupported 'FusionTarget': " + Target->getName());
142 void MacroFusionPredicatorEmitter::emitFirstPredicate(const Record *Predicate,
143 bool IsCommutable,
144 PredicateExpander &PE,
145 raw_ostream &OS) {
146 if (Predicate->isSubClassOf("WildcardPred")) {
147 OS.indent(2) << "if (!FirstMI)\n";
148 OS.indent(2) << " return "
149 << (Predicate->getValueAsBit("ReturnValue") ? "true" : "false")
150 << ";\n";
151 } else if (Predicate->isSubClassOf("OneUsePred")) {
152 OS.indent(2) << "{\n";
153 OS.indent(4) << "Register FirstDest = FirstMI->getOperand(0).getReg();\n";
154 OS.indent(4)
155 << "if (FirstDest.isVirtual() && !MRI.hasOneNonDBGUse(FirstDest))\n";
156 OS.indent(4) << " return false;\n";
157 OS.indent(2) << "}\n";
158 } else if (Predicate->isSubClassOf("FusionPredicateWithMCInstPredicate")) {
159 OS.indent(2) << "{\n";
160 OS.indent(4) << "const MachineInstr *MI = FirstMI;\n";
161 OS.indent(4) << "if (";
162 PE.setNegatePredicate(true);
163 PE.getIndent() = 3;
164 PE.expandPredicate(OS, Predicate->getValueAsDef("Predicate"));
165 OS << ")\n";
166 OS.indent(4) << " return false;\n";
167 OS.indent(2) << "}\n";
168 } else {
169 PrintFatalError(Predicate->getLoc(),
170 "Unsupported predicate for first instruction: " +
171 Predicate->getType()->getAsString());
175 void MacroFusionPredicatorEmitter::emitSecondPredicate(const Record *Predicate,
176 bool IsCommutable,
177 PredicateExpander &PE,
178 raw_ostream &OS) {
179 if (Predicate->isSubClassOf("FusionPredicateWithMCInstPredicate")) {
180 OS.indent(2) << "{\n";
181 OS.indent(4) << "const MachineInstr *MI = &SecondMI;\n";
182 OS.indent(4) << "if (";
183 PE.setNegatePredicate(true);
184 PE.getIndent() = 3;
185 PE.expandPredicate(OS, Predicate->getValueAsDef("Predicate"));
186 OS << ")\n";
187 OS.indent(4) << " return false;\n";
188 OS.indent(2) << "}\n";
189 } else if (Predicate->isSubClassOf("SameReg")) {
190 int FirstOpIdx = Predicate->getValueAsInt("FirstOpIdx");
191 int SecondOpIdx = Predicate->getValueAsInt("SecondOpIdx");
193 OS.indent(2) << "if (!SecondMI.getOperand(" << FirstOpIdx
194 << ").getReg().isVirtual()) {\n";
195 OS.indent(4) << "if (SecondMI.getOperand(" << FirstOpIdx
196 << ").getReg() != SecondMI.getOperand(" << SecondOpIdx
197 << ").getReg())";
199 if (IsCommutable) {
200 OS << " {\n";
201 OS.indent(6) << "if (!SecondMI.getDesc().isCommutable())\n";
202 OS.indent(6) << " return false;\n";
204 OS.indent(6)
205 << "unsigned SrcOpIdx1 = " << SecondOpIdx
206 << ", SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;\n";
207 OS.indent(6)
208 << "if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2))\n";
209 OS.indent(6)
210 << " if (SecondMI.getOperand(" << FirstOpIdx
211 << ").getReg() != SecondMI.getOperand(SrcOpIdx2).getReg())\n";
212 OS.indent(6) << " return false;\n";
213 OS.indent(4) << "}\n";
214 } else {
215 OS << "\n";
216 OS.indent(4) << " return false;\n";
218 OS.indent(2) << "}\n";
219 } else {
220 PrintFatalError(Predicate->getLoc(),
221 "Unsupported predicate for second instruction: " +
222 Predicate->getType()->getAsString());
226 void MacroFusionPredicatorEmitter::emitBothPredicate(const Record *Predicate,
227 bool IsCommutable,
228 PredicateExpander &PE,
229 raw_ostream &OS) {
230 if (Predicate->isSubClassOf("FusionPredicateWithCode"))
231 OS << Predicate->getValueAsString("Predicate");
232 else if (Predicate->isSubClassOf("BothFusionPredicateWithMCInstPredicate")) {
233 emitFirstPredicate(Predicate, IsCommutable, PE, OS);
234 emitSecondPredicate(Predicate, IsCommutable, PE, OS);
235 } else if (Predicate->isSubClassOf("TieReg")) {
236 int FirstOpIdx = Predicate->getValueAsInt("FirstOpIdx");
237 int SecondOpIdx = Predicate->getValueAsInt("SecondOpIdx");
238 OS.indent(2) << "if (!(FirstMI->getOperand(" << FirstOpIdx
239 << ").isReg() &&\n";
240 OS.indent(2) << " SecondMI.getOperand(" << SecondOpIdx
241 << ").isReg() &&\n";
242 OS.indent(2) << " FirstMI->getOperand(" << FirstOpIdx
243 << ").getReg() == SecondMI.getOperand(" << SecondOpIdx
244 << ").getReg()))";
246 if (IsCommutable) {
247 OS << " {\n";
248 OS.indent(4) << "if (!SecondMI.getDesc().isCommutable())\n";
249 OS.indent(4) << " return false;\n";
251 OS.indent(4)
252 << "unsigned SrcOpIdx1 = " << SecondOpIdx
253 << ", SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;\n";
254 OS.indent(4)
255 << "if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2))\n";
256 OS.indent(4)
257 << " if (FirstMI->getOperand(" << FirstOpIdx
258 << ").getReg() != SecondMI.getOperand(SrcOpIdx2).getReg())\n";
259 OS.indent(4) << " return false;\n";
260 OS.indent(2) << "}";
261 } else {
262 OS << "\n";
263 OS.indent(2) << " return false;";
265 OS << "\n";
266 } else
267 PrintFatalError(Predicate->getLoc(),
268 "Unsupported predicate for both instruction: " +
269 Predicate->getType()->getAsString());
272 void MacroFusionPredicatorEmitter::run(raw_ostream &OS) {
273 // Emit file header.
274 emitSourceFileHeader("Macro Fusion Predicators", OS);
276 PredicateExpander PE(Target.getName());
277 PE.setByRef(false);
278 PE.setExpandForMC(false);
280 ArrayRef<const Record *> Fusions = Records.getAllDerivedDefinitions("Fusion");
281 emitMacroFusionDecl(Fusions, PE, OS);
282 OS << "\n";
283 emitMacroFusionImpl(Fusions, PE, OS);
286 static TableGen::Emitter::OptClass<MacroFusionPredicatorEmitter>
287 X("gen-macro-fusion-pred", "Generate macro fusion predicators.");