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 
15 void GlobalISelMatchTableExecutorEmitter::emitSubtargetFeatureBitsetImpl(
16     raw_ostream &OS, ArrayRef<RuleMatcher> Rules) {
17   SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,
18                                                            OS);
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);
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::vector<Record *>> FeatureBitsets;
53   FeatureBitsets.reserve(Rules.size());
54   for (auto &Rule : Rules)
55     FeatureBitsets.push_back(Rule.getRequiredFeatures());
56   llvm::sort(FeatureBitsets, [&](const std::vector<Record *> &A,
57                                  const std::vector<Record *> &B) {
58     if (A.size() < B.size())
59       return true;
60     if (A.size() > B.size())
61       return false;
62     for (auto [First, Second] : zip(A, B)) {
63       if (First->getName() < Second->getName())
64         return true;
65       if (First->getName() > Second->getName())
66         return false;
67     }
68     return false;
69   });
70   FeatureBitsets.erase(
71       std::unique(FeatureBitsets.begin(), FeatureBitsets.end()),
72       FeatureBitsets.end());
73   OS << "// Feature bitsets.\n"
74      << "enum {\n"
75      << "  GIFBS_Invalid,\n";
76   for (const auto &FeatureBitset : FeatureBitsets) {
77     if (FeatureBitset.empty())
78       continue;
79     OS << "  " << getNameForFeatureBitset(FeatureBitset) << ",\n";
80   }
81   OS << "};\n"
82      << "const static PredicateBitset FeatureBitsets[] {\n"
83      << "  {}, // GIFBS_Invalid\n";
84   for (const auto &FeatureBitset : FeatureBitsets) {
85     if (FeatureBitset.empty())
86       continue;
87     OS << "  {";
88     for (const auto &Feature : FeatureBitset) {
89       const auto &I = SubtargetFeatures.find(Feature);
90       assert(I != SubtargetFeatures.end() && "Didn't import predicate?");
91       OS << I->second.getEnumBitName() << ", ";
92     }
93     OS << "},\n";
94   }
95   OS << "};\n\n";
96 }
97 
98 void GlobalISelMatchTableExecutorEmitter::emitComplexPredicates(
99     raw_ostream &OS, ArrayRef<Record *> ComplexOperandMatchers) {
100   // Emit complex predicate table and an enum to reference them with.
101   OS << "// ComplexPattern predicates.\n"
102      << "enum {\n"
103      << "  GICP_Invalid,\n";
104   for (const auto &Record : ComplexOperandMatchers)
105     OS << "  GICP_" << Record->getName() << ",\n";
106   OS << "};\n"
107      << "// See constructor for table contents\n\n";
108 
109   OS << getClassName() << "::ComplexMatcherMemFn\n"
110      << getClassName() << "::ComplexPredicateFns[] = {\n"
111      << "  nullptr, // GICP_Invalid\n";
112   for (const auto &Record : ComplexOperandMatchers)
113     OS << "  &" << getClassName()
114        << "::" << Record->getValueAsString("MatcherFn") << ", // "
115        << Record->getName() << "\n";
116   OS << "};\n\n";
117 }
118 
119 void GlobalISelMatchTableExecutorEmitter::emitCustomOperandRenderers(
120     raw_ostream &OS, ArrayRef<StringRef> CustomOperandRenderers) {
121   OS << "// Custom renderers.\n"
122      << "enum {\n"
123      << "  GICR_Invalid,\n";
124   for (const auto &Fn : CustomOperandRenderers)
125     OS << "  GICR_" << Fn << ",\n";
126   OS << "};\n";
127 
128   OS << getClassName() << "::CustomRendererFn\n"
129      << getClassName() << "::CustomRenderers[] = {\n"
130      << "  nullptr, // GICR_Invalid\n";
131   for (const auto &Fn : CustomOperandRenderers)
132     OS << "  &" << getClassName() << "::" << Fn << ",\n";
133   OS << "};\n\n";
134 }
135 
136 void GlobalISelMatchTableExecutorEmitter::emitTypeObjects(
137     raw_ostream &OS, ArrayRef<LLTCodeGen> TypeObjects) {
138   OS << "// LLT Objects.\n"
139      << "enum {\n";
140   for (const auto &TypeObject : TypeObjects) {
141     OS << "  ";
142     TypeObject.emitCxxEnumValue(OS);
143     OS << ",\n";
144   }
145   OS << "};\n"
146      << "const static size_t NumTypeObjects = " << TypeObjects.size() << ";\n"
147      << "const static LLT TypeObjects[] = {\n";
148   for (const auto &TypeObject : TypeObjects) {
149     OS << "  ";
150     TypeObject.emitCxxConstructorCall(OS);
151     OS << ",\n";
152   }
153   OS << "};\n\n";
154 }
155 
156 void GlobalISelMatchTableExecutorEmitter::emitMatchTable(
157     raw_ostream &OS, const MatchTable &Table) {
158   OS << "const int64_t *" << getClassName() << "::getMatchTable() const {\n";
159   Table.emitDeclaration(OS);
160   OS << "  return ";
161   Table.emitUse(OS);
162   OS << ";\n}\n";
163 }
164 
165 void GlobalISelMatchTableExecutorEmitter::emitExecutorImpl(
166     raw_ostream &OS, const MatchTable &Table, ArrayRef<LLTCodeGen> TypeObjects,
167     ArrayRef<RuleMatcher> Rules, ArrayRef<Record *> ComplexOperandMatchers,
168     ArrayRef<StringRef> CustomOperandRenderers, StringRef IfDefName) {
169   OS << "#ifdef " << IfDefName << "\n";
170   emitTypeObjects(OS, TypeObjects);
171   emitSubtargetFeatureBitsetImpl(OS, Rules);
172   emitComplexPredicates(OS, ComplexOperandMatchers);
173   emitMIPredicateFns(OS);
174   emitI64ImmPredicateFns(OS);
175   emitAPFloatImmPredicateFns(OS);
176   emitAPIntImmPredicateFns(OS);
177   emitTestSimplePredicate(OS);
178   emitCustomOperandRenderers(OS, CustomOperandRenderers);
179   emitAdditionalImpl(OS);
180   emitRunCustomAction(OS);
181   emitMatchTable(OS, Table);
182   OS << "#endif // ifdef " << IfDefName << "\n\n";
183 }
184 
185 void GlobalISelMatchTableExecutorEmitter::emitPredicateBitset(
186     raw_ostream &OS, StringRef IfDefName) {
187   OS << "#ifdef " << IfDefName << "\n"
188      << "const unsigned MAX_SUBTARGET_PREDICATES = " << SubtargetFeatures.size()
189      << ";\n"
190      << "using PredicateBitset = "
191         "llvm::PredicateBitsetImpl<MAX_SUBTARGET_PREDICATES>;\n"
192      << "#endif // ifdef " << IfDefName << "\n\n";
193 }
194 
195 void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl(
196     raw_ostream &OS, StringRef IfDefName) {
197   OS << "#ifdef " << IfDefName << "\n"
198      << "  mutable MatcherState State;\n"
199      << "  typedef "
200         "ComplexRendererFns("
201      << getClassName() << "::*ComplexMatcherMemFn)(MachineOperand &) const;\n"
202 
203      << "  typedef void(" << getClassName()
204      << "::*CustomRendererFn)(MachineInstrBuilder &, const "
205         "MachineInstr &, int) "
206         "const;\n"
207      << "  const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, "
208         "CustomRendererFn> "
209         "ExecInfo;\n"
210      << "  static " << getClassName()
211      << "::ComplexMatcherMemFn ComplexPredicateFns[];\n"
212      << "  static " << getClassName()
213      << "::CustomRendererFn CustomRenderers[];\n"
214      << "  bool testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const "
215         "override;\n"
216      << "  bool testImmPredicate_APInt(unsigned PredicateID, const APInt &Imm) "
217         "const override;\n"
218      << "  bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat "
219         "&Imm) const override;\n"
220      << "  const int64_t *getMatchTable() const override;\n"
221      << "  bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI"
222         ", const MatcherState &State) "
223         "const override;\n"
224      << "  bool testSimplePredicate(unsigned PredicateID) const override;\n"
225      << "  void runCustomAction(unsigned FnID, const MatcherState &State) "
226         "const override;\n";
227   emitAdditionalTemporariesDecl(OS, "  ");
228   OS << "#endif // ifdef " << IfDefName << "\n\n";
229 }
230 
231 void GlobalISelMatchTableExecutorEmitter::emitTemporariesInit(
232     raw_ostream &OS, unsigned MaxTemporaries, StringRef IfDefName) {
233   OS << "#ifdef " << IfDefName << "\n"
234      << ", State(" << MaxTemporaries << "),\n"
235      << "ExecInfo(TypeObjects, NumTypeObjects, FeatureBitsets"
236      << ", ComplexPredicateFns, CustomRenderers)\n"
237      << "#endif // ifdef " << IfDefName << "\n\n";
238 
239   emitAdditionalTemporariesInit(OS);
240 }
241 
242 void GlobalISelMatchTableExecutorEmitter::emitPredicatesDecl(
243     raw_ostream &OS, StringRef IfDefName) {
244   OS << "#ifdef " << IfDefName << "\n"
245      << "PredicateBitset AvailableModuleFeatures;\n"
246      << "mutable PredicateBitset AvailableFunctionFeatures;\n"
247      << "PredicateBitset getAvailableFeatures() const {\n"
248      << "  return AvailableModuleFeatures | AvailableFunctionFeatures;\n"
249      << "}\n"
250      << "PredicateBitset\n"
251      << "computeAvailableModuleFeatures(const " << getTarget().getName()
252      << "Subtarget *Subtarget) const;\n"
253      << "PredicateBitset\n"
254      << "computeAvailableFunctionFeatures(const " << getTarget().getName()
255      << "Subtarget *Subtarget,\n"
256      << "                                 const MachineFunction *MF) const;\n"
257      << "void setupGeneratedPerFunctionState(MachineFunction &MF) override;\n"
258      << "#endif // ifdef " << IfDefName << "\n";
259 }
260 
261 void GlobalISelMatchTableExecutorEmitter::emitPredicatesInit(
262     raw_ostream &OS, StringRef IfDefName) {
263   OS << "#ifdef " << IfDefName << "\n"
264      << "AvailableModuleFeatures(computeAvailableModuleFeatures(&STI)),\n"
265      << "AvailableFunctionFeatures()\n"
266      << "#endif // ifdef " << IfDefName << "\n";
267 }
268