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