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, &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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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