1//===- GlobalISelMatchTableExecutorEmitter.cpp ----------------------------===//
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 "GlobalISelMatchTableExecutorEmitter.h"
10#include "GlobalISelMatchTable.h"
11#include "llvm/TableGen/CodeGenHelpers.h"
12
13using namespace llvm;
14using namespace llvm::gi;
15
16void GlobalISelMatchTableExecutorEmitter::emitSubtargetFeatureBitsetImpl(
17 raw_ostream &OS, ArrayRef<RuleMatcher> Rules) {
18 SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,
19 OS, HwModes: &HwModes);
20
21 // Separate subtarget features by how often they must be recomputed.
22 SubtargetFeatureInfoMap ModuleFeatures;
23 llvm::copy_if(Range&: SubtargetFeatures,
24 Out: std::inserter(x&: ModuleFeatures, i: ModuleFeatures.end()),
25 P: [](const SubtargetFeatureInfoMap::value_type &X) {
26 return !X.second.mustRecomputePerFunction();
27 });
28 SubtargetFeatureInfoMap FunctionFeatures;
29 llvm::copy_if(Range&: SubtargetFeatures,
30 Out: std::inserter(x&: FunctionFeatures, i: FunctionFeatures.end()),
31 P: [](const SubtargetFeatureInfoMap::value_type &X) {
32 return X.second.mustRecomputePerFunction();
33 });
34
35 SubtargetFeatureInfo::emitComputeAvailableFeatures(
36 TargetName: getTarget().getName(), ClassName: getClassName(), FuncName: "computeAvailableModuleFeatures",
37 SubtargetFeatures: ModuleFeatures, OS, ExtraParams: "", HwModes: &HwModes);
38
39 OS << "void " << getClassName()
40 << "::setupGeneratedPerFunctionState(MachineFunction &MF) {\n"
41 " AvailableFunctionFeatures = computeAvailableFunctionFeatures("
42 "(const "
43 << getTarget().getName()
44 << "Subtarget *)&MF.getSubtarget(), &MF);\n"
45 "}\n";
46
47 SubtargetFeatureInfo::emitComputeAvailableFeatures(
48 TargetName: getTarget().getName(), ClassName: getClassName(), FuncName: "computeAvailableFunctionFeatures",
49 SubtargetFeatures: FunctionFeatures, OS, ExtraParams: "const MachineFunction *MF");
50
51 // Emit a table containing the PredicateBitsets objects needed by the matcher
52 // and an enum for the matcher to reference them with.
53 std::vector<std::pair<std::vector<const Record *>, int>> FeatureBitsets;
54 FeatureBitsets.reserve(n: Rules.size());
55 for (auto &Rule : Rules)
56 FeatureBitsets.emplace_back(args: Rule.getRequiredFeatures(),
57 args: Rule.getHwModeIdx());
58 llvm::sort(C&: FeatureBitsets,
59 Comp: [&](const std::pair<std::vector<const Record *>, int> &A,
60 const std::pair<std::vector<const Record *>, int> &B) {
61 if (A.first.size() < B.first.size())
62 return true;
63 if (A.first.size() > B.first.size())
64 return false;
65 for (auto [First, Second] : zip(t: A.first, u: B.first)) {
66 if (First->getName() < Second->getName())
67 return true;
68 if (First->getName() > Second->getName())
69 return false;
70 }
71
72 return (A.second < B.second);
73 });
74 FeatureBitsets.erase(first: llvm::unique(R&: FeatureBitsets), last: FeatureBitsets.end());
75 OS << "// Feature bitsets.\n"
76 << "enum {\n"
77 << " GIFBS_Invalid,\n";
78 for (const auto &FeatureBitset : FeatureBitsets) {
79 if (FeatureBitset.first.empty() && FeatureBitset.second < 0)
80 continue;
81 OS << " "
82 << getNameForFeatureBitset(FeatureBitset: FeatureBitset.first, HwModeIdx: FeatureBitset.second)
83 << ",\n";
84 }
85 OS << "};\n"
86 << "constexpr static PredicateBitset FeatureBitsets[] {\n"
87 << " {}, // GIFBS_Invalid\n";
88 for (const auto &FeatureBitset : FeatureBitsets) {
89 if (FeatureBitset.first.empty() && FeatureBitset.second < 0)
90 continue;
91 OS << " {";
92 for (const auto &Feature : FeatureBitset.first) {
93 const auto &I = SubtargetFeatures.find(x: Feature);
94 assert(I != SubtargetFeatures.end() && "Didn't import predicate?");
95 OS << I->second.getEnumBitName() << ", ";
96 }
97 // HwModeIdx
98 if (FeatureBitset.second >= 0) {
99 OS << "Feature_HwMode" << FeatureBitset.second << "Bit, ";
100 }
101 OS << "},\n";
102 }
103 OS << "};\n\n";
104}
105
106void GlobalISelMatchTableExecutorEmitter::emitComplexPredicates(
107 raw_ostream &OS, ArrayRef<const Record *> ComplexOperandMatchers) {
108 // Emit complex predicate table and an enum to reference them with.
109 OS << "// ComplexPattern predicates.\n"
110 << "enum {\n"
111 << " GICP_Invalid,\n";
112 for (const auto &Record : ComplexOperandMatchers)
113 OS << " GICP_" << Record->getName() << ",\n";
114 OS << "};\n"
115 << "// See constructor for table contents\n\n";
116
117 OS << getClassName() << "::ComplexMatcherMemFn\n"
118 << getClassName() << "::ComplexPredicateFns[] = {\n"
119 << " nullptr, // GICP_Invalid\n";
120 for (const auto &Record : ComplexOperandMatchers)
121 OS << " &" << getClassName()
122 << "::" << Record->getValueAsString(FieldName: "MatcherFn") << ", // "
123 << Record->getName() << "\n";
124 OS << "};\n\n";
125}
126
127void GlobalISelMatchTableExecutorEmitter::emitCustomOperandRenderers(
128 raw_ostream &OS, ArrayRef<StringRef> CustomOperandRenderers) {
129 OS << "// Custom renderers.\n"
130 << "enum {\n"
131 << " GICR_Invalid,\n";
132 for (const auto &Fn : CustomOperandRenderers)
133 OS << " GICR_" << Fn << ",\n";
134 OS << "};\n";
135
136 OS << getClassName() << "::CustomRendererFn\n"
137 << getClassName() << "::CustomRenderers[] = {\n"
138 << " nullptr, // GICR_Invalid\n";
139 for (const auto &Fn : CustomOperandRenderers)
140 OS << " &" << getClassName() << "::" << Fn << ",\n";
141 OS << "};\n\n";
142}
143
144void GlobalISelMatchTableExecutorEmitter::emitTypeObjects(
145 raw_ostream &OS, ArrayRef<LLTCodeGen> TypeObjects) {
146 OS << "// LLT Objects.\n"
147 << "enum {\n";
148 for (const auto &TypeObject : TypeObjects) {
149 OS << " ";
150 TypeObject.emitCxxEnumValue(OS);
151 OS << ",\n";
152 }
153 OS << "};\n"
154 << "const static size_t NumTypeObjects = " << TypeObjects.size() << ";\n"
155 << "const static LLT TypeObjects[] = {\n";
156 for (const auto &TypeObject : TypeObjects) {
157 OS << " ";
158 TypeObject.emitCxxConstructorCall(OS);
159 OS << ",\n";
160 }
161 OS << "};\n\n";
162}
163
164void GlobalISelMatchTableExecutorEmitter::emitMatchTable(
165 raw_ostream &OS, const MatchTable &Table) {
166 emitEncodingMacrosDef(OS);
167 OS << "const uint8_t *" << getClassName() << "::getMatchTable() const {\n";
168 Table.emitDeclaration(OS);
169 OS << " return ";
170 Table.emitUse(OS);
171 OS << ";\n}\n";
172 emitEncodingMacrosUndef(OS);
173 OS << "\n";
174}
175
176void GlobalISelMatchTableExecutorEmitter::emitExecutorImpl(
177 raw_ostream &OS, const MatchTable &Table, ArrayRef<LLTCodeGen> TypeObjects,
178 ArrayRef<RuleMatcher> Rules,
179 ArrayRef<const Record *> ComplexOperandMatchers,
180 ArrayRef<StringRef> CustomOperandRenderers, StringRef IfDefName) {
181 IfDefGuardEmitter If(OS, IfDefName);
182 emitTypeObjects(OS, TypeObjects);
183 emitSubtargetFeatureBitsetImpl(OS, Rules);
184 emitComplexPredicates(OS, ComplexOperandMatchers);
185 emitMIPredicateFns(OS);
186 emitLeafPredicateFns(OS);
187 emitI64ImmPredicateFns(OS);
188 emitAPFloatImmPredicateFns(OS);
189 emitAPIntImmPredicateFns(OS);
190 emitTestSimplePredicate(OS);
191 emitCustomOperandRenderers(OS, CustomOperandRenderers);
192 emitAdditionalImpl(OS);
193 emitRunCustomAction(OS);
194
195 emitMatchTable(OS, Table);
196}
197
198void GlobalISelMatchTableExecutorEmitter::emitPredicateBitset(
199 raw_ostream &OS, StringRef IfDefName) {
200 unsigned Size = SubtargetFeatures.size() + HwModes.size();
201 IfDefGuardEmitter IfDef(OS, IfDefName);
202 OS << "const unsigned MAX_SUBTARGET_PREDICATES = " << Size << ";\n"
203 << "using PredicateBitset = "
204 "llvm::Bitset<MAX_SUBTARGET_PREDICATES>;\n";
205}
206
207void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl(
208 raw_ostream &OS, StringRef IfDefName) {
209 IfDefGuardEmitter If(OS, IfDefName);
210 OS << " mutable MatcherState State;\n"
211 << " typedef "
212 "ComplexRendererFns("
213 << getClassName() << "::*ComplexMatcherMemFn)(MachineOperand &) const;\n"
214
215 << " typedef void(" << getClassName()
216 << "::*CustomRendererFn)(MachineInstrBuilder &, const "
217 "MachineInstr &, int) "
218 "const;\n"
219 << " const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, "
220 "CustomRendererFn> "
221 "ExecInfo;\n"
222 << " static " << getClassName()
223 << "::ComplexMatcherMemFn ComplexPredicateFns[];\n"
224 << " static " << getClassName()
225 << "::CustomRendererFn CustomRenderers[];\n"
226 << " bool testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const "
227 "override;\n"
228 << " bool testImmPredicate_APInt(unsigned PredicateID, const APInt &Imm) "
229 "const override;\n"
230 << " bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat "
231 "&Imm) const override;\n"
232 << " const uint8_t *getMatchTable() const override;\n"
233 << " bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI"
234 ", const MatcherState &State) "
235 "const override;\n"
236 << " bool testMOPredicate_MO(unsigned PredicateID, const MachineOperand "
237 "&MO, const MatcherState &State) "
238 "const override;\n"
239 << " bool testSimplePredicate(unsigned PredicateID) const override;\n"
240 << " bool runCustomAction(unsigned FnID, const MatcherState &State, "
241 "NewMIVector &OutMIs) "
242 "const override;\n";
243}
244
245void GlobalISelMatchTableExecutorEmitter::emitTemporariesInit(
246 raw_ostream &OS, unsigned MaxTemporaries, StringRef IfDefName) {
247 {
248 IfDefGuardEmitter If(OS, IfDefName);
249 OS << ", State(" << MaxTemporaries << "),\n"
250 << "ExecInfo(TypeObjects, NumTypeObjects, FeatureBitsets"
251 << ", ComplexPredicateFns, CustomRenderers)\n";
252 }
253 emitAdditionalTemporariesInit(OS);
254}
255
256void GlobalISelMatchTableExecutorEmitter::emitPredicatesDecl(
257 raw_ostream &OS, StringRef IfDefName) {
258 IfDefGuardEmitter If(OS, IfDefName);
259 OS << "PredicateBitset AvailableModuleFeatures;\n"
260 << "mutable PredicateBitset AvailableFunctionFeatures;\n"
261 << "PredicateBitset getAvailableFeatures() const {\n"
262 << " return AvailableModuleFeatures | AvailableFunctionFeatures;\n"
263 << "}\n"
264 << "PredicateBitset\n"
265 << "computeAvailableModuleFeatures(const " << getTarget().getName()
266 << "Subtarget *Subtarget) const;\n"
267 << "PredicateBitset\n"
268 << "computeAvailableFunctionFeatures(const " << getTarget().getName()
269 << "Subtarget *Subtarget,\n"
270 << " const MachineFunction *MF) const;\n"
271 << "void setupGeneratedPerFunctionState(MachineFunction &MF) override;\n";
272}
273
274void GlobalISelMatchTableExecutorEmitter::emitPredicatesInit(
275 raw_ostream &OS, StringRef IfDefName) {
276 IfDefGuardEmitter If(OS, IfDefName);
277 OS << "AvailableModuleFeatures(computeAvailableModuleFeatures(&STI)),\n"
278 << "AvailableFunctionFeatures()\n";
279}
280