1 //===------ MacroFusionPredicatorEmitter.cpp - Generator for Fusion ------===//
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
7 //===---------------------------------------------------------------------===//
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
22 // The generated predicator will be like:
25 // bool isNAME(const TargetInstrInfo &TII,
26 // const TargetSubtargetInfo &STI,
27 // const MachineInstr *FirstMI,
28 // const MachineInstr &SecondMI) {
29 // auto &MRI = SecondMI.getMF()->getRegInfo();
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"
53 #define DEBUG_TYPE "macro-fusion-predicator"
56 class MacroFusionPredicatorEmitter
{
57 RecordKeeper
&Records
;
60 void emitMacroFusionDecl(std::vector
<Record
*> Fusions
, PredicateExpander
&PE
,
62 void emitMacroFusionImpl(std::vector
<Record
*> Fusions
, PredicateExpander
&PE
,
64 void emitPredicates(std::vector
<Record
*> &FirstPredicate
,
65 PredicateExpander
&PE
, raw_ostream
&OS
);
66 void emitFirstPredicate(Record
*SecondPredicate
, PredicateExpander
&PE
,
68 void emitSecondPredicate(Record
*SecondPredicate
, PredicateExpander
&PE
,
70 void emitBothPredicate(Record
*Predicates
, PredicateExpander
&PE
,
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";
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";
120 OS
<< "} // end namespace llvm\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
);
135 PrintFatalError(Target
->getLoc(),
136 "Unsupported 'FusionTarget': " + Target
->getName());
140 void MacroFusionPredicatorEmitter::emitFirstPredicate(Record
*Predicate
,
141 PredicateExpander
&PE
,
143 if (Predicate
->isSubClassOf("WildcardPred")) {
144 OS
.indent(2) << "if (!FirstMI)\n";
145 OS
.indent(2) << " return "
146 << (Predicate
->getValueAsBit("ReturnValue") ? "true" : "false")
148 } else if (Predicate
->isSubClassOf("OneUsePred")) {
149 OS
.indent(2) << "{\n";
150 OS
.indent(4) << "Register FirstDest = FirstMI->getOperand(0).getReg();\n";
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"));
163 OS
.indent(4) << " return false;\n";
164 OS
.indent(2) << "}\n";
166 PrintFatalError(Predicate
->getLoc(),
167 "Unsupported predicate for first instruction: " +
168 Predicate
->getType()->getAsString());
172 void MacroFusionPredicatorEmitter::emitSecondPredicate(Record
*Predicate
,
173 PredicateExpander
&PE
,
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"));
183 OS
.indent(4) << " return false;\n";
184 OS
.indent(2) << "}\n";
186 PrintFatalError(Predicate
->getLoc(),
187 "Unsupported predicate for second instruction: " +
188 Predicate
->getType()->getAsString());
192 void MacroFusionPredicatorEmitter::emitBothPredicate(Record
*Predicate
,
193 PredicateExpander
&PE
,
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
205 OS
.indent(2) << " SecondMI.getOperand(" << SecondOpIdx
207 OS
.indent(2) << " FirstMI->getOperand(" << FirstOpIdx
208 << ").getReg() == SecondMI.getOperand(" << SecondOpIdx
210 OS
.indent(2) << " return false;\n";
212 PrintFatalError(Predicate
->getLoc(),
213 "Unsupported predicate for both instruction: " +
214 Predicate
->getType()->getAsString());
217 void MacroFusionPredicatorEmitter::run(raw_ostream
&OS
) {
219 emitSourceFileHeader("Macro Fusion Predicators", OS
);
221 PredicateExpander
PE(Target
.getName());
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
);
230 emitMacroFusionImpl(Fusions
, PE
, OS
);
233 static TableGen::Emitter::OptClass
<MacroFusionPredicatorEmitter
>
234 X("gen-macro-fusion-pred", "Generate macro fusion predicators.");