1 //===- GlobalISelMatchTableExecutorEmitter.cpp ----------------------------===//
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 #include "GlobalISelMatchTableExecutorEmitter.h"
10 #include "GlobalISelMatchTable.h"
13 using namespace llvm::gi
;
15 void GlobalISelMatchTableExecutorEmitter::emitSubtargetFeatureBitsetImpl(
16 raw_ostream
&OS
, ArrayRef
<RuleMatcher
> Rules
) {
17 SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures
,
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();
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();
34 SubtargetFeatureInfo::emitComputeAvailableFeatures(
35 getTarget().getName(), getClassName(), "computeAvailableModuleFeatures",
36 ModuleFeatures
, OS
, "", &HwModes
);
38 OS
<< "void " << getClassName()
39 << "::setupGeneratedPerFunctionState(MachineFunction &MF) {\n"
40 " AvailableFunctionFeatures = computeAvailableFunctionFeatures("
42 << getTarget().getName()
43 << "Subtarget *)&MF.getSubtarget(), &MF);\n"
46 SubtargetFeatureInfo::emitComputeAvailableFeatures(
47 getTarget().getName(), getClassName(), "computeAvailableFunctionFeatures",
48 FunctionFeatures
, OS
, "const MachineFunction *MF");
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(),
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())
62 if (A
.first
.size() > B
.first
.size())
64 for (auto [First
, Second
] : zip(A
.first
, B
.first
)) {
65 if (First
->getName() < Second
->getName())
67 if (First
->getName() > Second
->getName())
71 return (A
.second
< B
.second
);
74 std::unique(FeatureBitsets
.begin(), FeatureBitsets
.end()),
75 FeatureBitsets
.end());
76 OS
<< "// Feature bitsets.\n"
78 << " GIFBS_Invalid,\n";
79 for (const auto &FeatureBitset
: FeatureBitsets
) {
80 if (FeatureBitset
.first
.empty() && FeatureBitset
.second
< 0)
83 << getNameForFeatureBitset(FeatureBitset
.first
, FeatureBitset
.second
)
87 << "constexpr static PredicateBitset FeatureBitsets[] {\n"
88 << " {}, // GIFBS_Invalid\n";
89 for (const auto &FeatureBitset
: FeatureBitsets
) {
90 if (FeatureBitset
.first
.empty() && FeatureBitset
.second
< 0)
93 for (const auto &Feature
: FeatureBitset
.first
) {
94 const auto &I
= SubtargetFeatures
.find(Feature
);
95 assert(I
!= SubtargetFeatures
.end() && "Didn't import predicate?");
96 OS
<< I
->second
.getEnumBitName() << ", ";
99 if (FeatureBitset
.second
>= 0) {
100 OS
<< "Feature_HwMode" << FeatureBitset
.second
<< "Bit, ";
107 void GlobalISelMatchTableExecutorEmitter::emitComplexPredicates(
108 raw_ostream
&OS
, ArrayRef
<Record
*> ComplexOperandMatchers
) {
109 // Emit complex predicate table and an enum to reference them with.
110 OS
<< "// ComplexPattern predicates.\n"
112 << " GICP_Invalid,\n";
113 for (const auto &Record
: ComplexOperandMatchers
)
114 OS
<< " GICP_" << Record
->getName() << ",\n";
116 << "// See constructor for table contents\n\n";
118 OS
<< getClassName() << "::ComplexMatcherMemFn\n"
119 << getClassName() << "::ComplexPredicateFns[] = {\n"
120 << " nullptr, // GICP_Invalid\n";
121 for (const auto &Record
: ComplexOperandMatchers
)
122 OS
<< " &" << getClassName()
123 << "::" << Record
->getValueAsString("MatcherFn") << ", // "
124 << Record
->getName() << "\n";
128 void GlobalISelMatchTableExecutorEmitter::emitCustomOperandRenderers(
129 raw_ostream
&OS
, ArrayRef
<StringRef
> CustomOperandRenderers
) {
130 OS
<< "// Custom renderers.\n"
132 << " GICR_Invalid,\n";
133 for (const auto &Fn
: CustomOperandRenderers
)
134 OS
<< " GICR_" << Fn
<< ",\n";
137 OS
<< getClassName() << "::CustomRendererFn\n"
138 << getClassName() << "::CustomRenderers[] = {\n"
139 << " nullptr, // GICR_Invalid\n";
140 for (const auto &Fn
: CustomOperandRenderers
)
141 OS
<< " &" << getClassName() << "::" << Fn
<< ",\n";
145 void GlobalISelMatchTableExecutorEmitter::emitTypeObjects(
146 raw_ostream
&OS
, ArrayRef
<LLTCodeGen
> TypeObjects
) {
147 OS
<< "// LLT Objects.\n"
149 for (const auto &TypeObject
: TypeObjects
) {
151 TypeObject
.emitCxxEnumValue(OS
);
155 << "const static size_t NumTypeObjects = " << TypeObjects
.size() << ";\n"
156 << "const static LLT TypeObjects[] = {\n";
157 for (const auto &TypeObject
: TypeObjects
) {
159 TypeObject
.emitCxxConstructorCall(OS
);
165 void GlobalISelMatchTableExecutorEmitter::emitMatchTable(
166 raw_ostream
&OS
, const MatchTable
&Table
) {
167 OS
<< "const int64_t *" << getClassName() << "::getMatchTable() const {\n";
168 Table
.emitDeclaration(OS
);
174 void GlobalISelMatchTableExecutorEmitter::emitExecutorImpl(
175 raw_ostream
&OS
, const MatchTable
&Table
, ArrayRef
<LLTCodeGen
> TypeObjects
,
176 ArrayRef
<RuleMatcher
> Rules
, ArrayRef
<Record
*> ComplexOperandMatchers
,
177 ArrayRef
<StringRef
> CustomOperandRenderers
, StringRef IfDefName
) {
178 OS
<< "#ifdef " << IfDefName
<< "\n";
179 emitTypeObjects(OS
, TypeObjects
);
180 emitSubtargetFeatureBitsetImpl(OS
, Rules
);
181 emitComplexPredicates(OS
, ComplexOperandMatchers
);
182 emitMIPredicateFns(OS
);
183 emitI64ImmPredicateFns(OS
);
184 emitAPFloatImmPredicateFns(OS
);
185 emitAPIntImmPredicateFns(OS
);
186 emitTestSimplePredicate(OS
);
187 emitCustomOperandRenderers(OS
, CustomOperandRenderers
);
188 emitAdditionalImpl(OS
);
189 emitRunCustomAction(OS
);
190 emitMatchTable(OS
, Table
);
191 OS
<< "#endif // ifdef " << IfDefName
<< "\n\n";
194 void GlobalISelMatchTableExecutorEmitter::emitPredicateBitset(
195 raw_ostream
&OS
, StringRef IfDefName
) {
196 unsigned Size
= SubtargetFeatures
.size() + HwModes
.size();
197 OS
<< "#ifdef " << IfDefName
<< "\n"
198 << "const unsigned MAX_SUBTARGET_PREDICATES = " << Size
<< ";\n"
199 << "using PredicateBitset = "
200 "llvm::Bitset<MAX_SUBTARGET_PREDICATES>;\n"
201 << "#endif // ifdef " << IfDefName
<< "\n\n";
204 void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl(
205 raw_ostream
&OS
, StringRef IfDefName
) {
206 OS
<< "#ifdef " << IfDefName
<< "\n"
207 << " mutable MatcherState State;\n"
209 "ComplexRendererFns("
210 << getClassName() << "::*ComplexMatcherMemFn)(MachineOperand &) const;\n"
212 << " typedef void(" << getClassName()
213 << "::*CustomRendererFn)(MachineInstrBuilder &, const "
214 "MachineInstr &, int) "
216 << " const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, "
219 << " static " << getClassName()
220 << "::ComplexMatcherMemFn ComplexPredicateFns[];\n"
221 << " static " << getClassName()
222 << "::CustomRendererFn CustomRenderers[];\n"
223 << " bool testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const "
225 << " bool testImmPredicate_APInt(unsigned PredicateID, const APInt &Imm) "
227 << " bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat "
228 "&Imm) const override;\n"
229 << " const int64_t *getMatchTable() const override;\n"
230 << " bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI"
231 ", const MatcherState &State) "
233 << " bool testSimplePredicate(unsigned PredicateID) const override;\n"
234 << " void runCustomAction(unsigned FnID, const MatcherState &State, "
235 "NewMIVector &OutMIs) "
237 emitAdditionalTemporariesDecl(OS
, " ");
238 OS
<< "#endif // ifdef " << IfDefName
<< "\n\n";
241 void GlobalISelMatchTableExecutorEmitter::emitTemporariesInit(
242 raw_ostream
&OS
, unsigned MaxTemporaries
, StringRef IfDefName
) {
243 OS
<< "#ifdef " << IfDefName
<< "\n"
244 << ", State(" << MaxTemporaries
<< "),\n"
245 << "ExecInfo(TypeObjects, NumTypeObjects, FeatureBitsets"
246 << ", ComplexPredicateFns, CustomRenderers)\n"
247 << "#endif // ifdef " << IfDefName
<< "\n\n";
249 emitAdditionalTemporariesInit(OS
);
252 void GlobalISelMatchTableExecutorEmitter::emitPredicatesDecl(
253 raw_ostream
&OS
, StringRef IfDefName
) {
254 OS
<< "#ifdef " << IfDefName
<< "\n"
255 << "PredicateBitset AvailableModuleFeatures;\n"
256 << "mutable PredicateBitset AvailableFunctionFeatures;\n"
257 << "PredicateBitset getAvailableFeatures() const {\n"
258 << " return AvailableModuleFeatures | AvailableFunctionFeatures;\n"
260 << "PredicateBitset\n"
261 << "computeAvailableModuleFeatures(const " << getTarget().getName()
262 << "Subtarget *Subtarget) const;\n"
263 << "PredicateBitset\n"
264 << "computeAvailableFunctionFeatures(const " << getTarget().getName()
265 << "Subtarget *Subtarget,\n"
266 << " const MachineFunction *MF) const;\n"
267 << "void setupGeneratedPerFunctionState(MachineFunction &MF) override;\n"
268 << "#endif // ifdef " << IfDefName
<< "\n";
271 void GlobalISelMatchTableExecutorEmitter::emitPredicatesInit(
272 raw_ostream
&OS
, StringRef IfDefName
) {
273 OS
<< "#ifdef " << IfDefName
<< "\n"
274 << "AvailableModuleFeatures(computeAvailableModuleFeatures(&STI)),\n"
275 << "AvailableFunctionFeatures()\n"
276 << "#endif // ifdef " << IfDefName
<< "\n";