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