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(
74       std::unique(FeatureBitsets.begin(), FeatureBitsets.end()),
75       FeatureBitsets.end());
76   OS << "// Feature bitsets.\n"
77      << "enum {\n"
78      << "  GIFBS_Invalid,\n";
79   for (const auto &FeatureBitset : FeatureBitsets) {
80     if (FeatureBitset.first.empty() && FeatureBitset.second < 0)
81       continue;
82     OS << "  "
83        << getNameForFeatureBitset(FeatureBitset.first, FeatureBitset.second)
84        << ",\n";
85   }
86   OS << "};\n"
87      << "constexpr static PredicateBitset FeatureBitsets[] {\n"
88      << "  {}, // GIFBS_Invalid\n";
89   for (const auto &FeatureBitset : FeatureBitsets) {
90     if (FeatureBitset.first.empty() && FeatureBitset.second < 0)
91       continue;
92     OS << "  {";
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() << ", ";
97     }
98     // HwModeIdx
99     if (FeatureBitset.second >= 0) {
100       OS << "Feature_HwMode" << FeatureBitset.second << "Bit, ";
101     }
102     OS << "},\n";
103   }
104   OS << "};\n\n";
105 }
106 
emitComplexPredicates(raw_ostream & OS,ArrayRef<Record * > ComplexOperandMatchers)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"
111      << "enum {\n"
112      << "  GICP_Invalid,\n";
113   for (const auto &Record : ComplexOperandMatchers)
114     OS << "  GICP_" << Record->getName() << ",\n";
115   OS << "};\n"
116      << "// See constructor for table contents\n\n";
117 
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";
125   OS << "};\n\n";
126 }
127 
emitCustomOperandRenderers(raw_ostream & OS,ArrayRef<StringRef> CustomOperandRenderers)128 void GlobalISelMatchTableExecutorEmitter::emitCustomOperandRenderers(
129     raw_ostream &OS, ArrayRef<StringRef> CustomOperandRenderers) {
130   OS << "// Custom renderers.\n"
131      << "enum {\n"
132      << "  GICR_Invalid,\n";
133   for (const auto &Fn : CustomOperandRenderers)
134     OS << "  GICR_" << Fn << ",\n";
135   OS << "};\n";
136 
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";
142   OS << "};\n\n";
143 }
144 
emitTypeObjects(raw_ostream & OS,ArrayRef<LLTCodeGen> TypeObjects)145 void GlobalISelMatchTableExecutorEmitter::emitTypeObjects(
146     raw_ostream &OS, ArrayRef<LLTCodeGen> TypeObjects) {
147   OS << "// LLT Objects.\n"
148      << "enum {\n";
149   for (const auto &TypeObject : TypeObjects) {
150     OS << "  ";
151     TypeObject.emitCxxEnumValue(OS);
152     OS << ",\n";
153   }
154   OS << "};\n"
155      << "const static size_t NumTypeObjects = " << TypeObjects.size() << ";\n"
156      << "const static LLT TypeObjects[] = {\n";
157   for (const auto &TypeObject : TypeObjects) {
158     OS << "  ";
159     TypeObject.emitCxxConstructorCall(OS);
160     OS << ",\n";
161   }
162   OS << "};\n\n";
163 }
164 
emitMatchTable(raw_ostream & OS,const MatchTable & Table)165 void GlobalISelMatchTableExecutorEmitter::emitMatchTable(
166     raw_ostream &OS, const MatchTable &Table) {
167   emitEncodingMacrosDef(OS);
168   OS << "const uint8_t *" << getClassName() << "::getMatchTable() const {\n";
169   Table.emitDeclaration(OS);
170   OS << "  return ";
171   Table.emitUse(OS);
172   OS << ";\n}\n";
173   emitEncodingMacrosUndef(OS);
174   OS << "\n";
175 }
176 
emitExecutorImpl(raw_ostream & OS,const MatchTable & Table,ArrayRef<LLTCodeGen> TypeObjects,ArrayRef<RuleMatcher> Rules,ArrayRef<Record * > ComplexOperandMatchers,ArrayRef<StringRef> CustomOperandRenderers,StringRef IfDefName)177 void GlobalISelMatchTableExecutorEmitter::emitExecutorImpl(
178     raw_ostream &OS, const MatchTable &Table, ArrayRef<LLTCodeGen> TypeObjects,
179     ArrayRef<RuleMatcher> Rules, ArrayRef<Record *> ComplexOperandMatchers,
180     ArrayRef<StringRef> CustomOperandRenderers, StringRef IfDefName) {
181   OS << "#ifdef " << IfDefName << "\n";
182   emitTypeObjects(OS, TypeObjects);
183   emitSubtargetFeatureBitsetImpl(OS, Rules);
184   emitComplexPredicates(OS, ComplexOperandMatchers);
185   emitMIPredicateFns(OS);
186   emitI64ImmPredicateFns(OS);
187   emitAPFloatImmPredicateFns(OS);
188   emitAPIntImmPredicateFns(OS);
189   emitTestSimplePredicate(OS);
190   emitCustomOperandRenderers(OS, CustomOperandRenderers);
191   emitAdditionalImpl(OS);
192   emitRunCustomAction(OS);
193 
194   emitMatchTable(OS, Table);
195 
196   OS << "#endif // ifdef " << IfDefName << "\n\n";
197 }
198 
emitPredicateBitset(raw_ostream & OS,StringRef IfDefName)199 void GlobalISelMatchTableExecutorEmitter::emitPredicateBitset(
200     raw_ostream &OS, StringRef IfDefName) {
201   unsigned Size = SubtargetFeatures.size() + HwModes.size();
202   OS << "#ifdef " << IfDefName << "\n"
203      << "const unsigned MAX_SUBTARGET_PREDICATES = " << Size << ";\n"
204      << "using PredicateBitset = "
205         "llvm::Bitset<MAX_SUBTARGET_PREDICATES>;\n"
206      << "#endif // ifdef " << IfDefName << "\n\n";
207 }
208 
emitTemporariesDecl(raw_ostream & OS,StringRef IfDefName)209 void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl(
210     raw_ostream &OS, StringRef IfDefName) {
211   OS << "#ifdef " << IfDefName << "\n"
212      << "  mutable MatcherState State;\n"
213      << "  typedef "
214         "ComplexRendererFns("
215      << getClassName() << "::*ComplexMatcherMemFn)(MachineOperand &) const;\n"
216 
217      << "  typedef void(" << getClassName()
218      << "::*CustomRendererFn)(MachineInstrBuilder &, const "
219         "MachineInstr &, int) "
220         "const;\n"
221      << "  const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, "
222         "CustomRendererFn> "
223         "ExecInfo;\n"
224      << "  static " << getClassName()
225      << "::ComplexMatcherMemFn ComplexPredicateFns[];\n"
226      << "  static " << getClassName()
227      << "::CustomRendererFn CustomRenderers[];\n"
228      << "  bool testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const "
229         "override;\n"
230      << "  bool testImmPredicate_APInt(unsigned PredicateID, const APInt &Imm) "
231         "const override;\n"
232      << "  bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat "
233         "&Imm) const override;\n"
234      << "  const uint8_t *getMatchTable() const override;\n"
235      << "  bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI"
236         ", const MatcherState &State) "
237         "const override;\n"
238      << "  bool testSimplePredicate(unsigned PredicateID) const override;\n"
239      << "  void runCustomAction(unsigned FnID, const MatcherState &State, "
240         "NewMIVector &OutMIs) "
241         "const override;\n";
242   emitAdditionalTemporariesDecl(OS, "  ");
243   OS << "#endif // ifdef " << IfDefName << "\n\n";
244 }
245 
emitTemporariesInit(raw_ostream & OS,unsigned MaxTemporaries,StringRef IfDefName)246 void GlobalISelMatchTableExecutorEmitter::emitTemporariesInit(
247     raw_ostream &OS, unsigned MaxTemporaries, StringRef IfDefName) {
248   OS << "#ifdef " << IfDefName << "\n"
249      << ", State(" << MaxTemporaries << "),\n"
250      << "ExecInfo(TypeObjects, NumTypeObjects, FeatureBitsets"
251      << ", ComplexPredicateFns, CustomRenderers)\n"
252      << "#endif // ifdef " << IfDefName << "\n\n";
253 
254   emitAdditionalTemporariesInit(OS);
255 }
256 
emitPredicatesDecl(raw_ostream & OS,StringRef IfDefName)257 void GlobalISelMatchTableExecutorEmitter::emitPredicatesDecl(
258     raw_ostream &OS, StringRef IfDefName) {
259   OS << "#ifdef " << IfDefName << "\n"
260      << "PredicateBitset AvailableModuleFeatures;\n"
261      << "mutable PredicateBitset AvailableFunctionFeatures;\n"
262      << "PredicateBitset getAvailableFeatures() const {\n"
263      << "  return AvailableModuleFeatures | AvailableFunctionFeatures;\n"
264      << "}\n"
265      << "PredicateBitset\n"
266      << "computeAvailableModuleFeatures(const " << getTarget().getName()
267      << "Subtarget *Subtarget) const;\n"
268      << "PredicateBitset\n"
269      << "computeAvailableFunctionFeatures(const " << getTarget().getName()
270      << "Subtarget *Subtarget,\n"
271      << "                                 const MachineFunction *MF) const;\n"
272      << "void setupGeneratedPerFunctionState(MachineFunction &MF) override;\n"
273      << "#endif // ifdef " << IfDefName << "\n";
274 }
275 
emitPredicatesInit(raw_ostream & OS,StringRef IfDefName)276 void GlobalISelMatchTableExecutorEmitter::emitPredicatesInit(
277     raw_ostream &OS, StringRef IfDefName) {
278   OS << "#ifdef " << IfDefName << "\n"
279      << "AvailableModuleFeatures(computeAvailableModuleFeatures(&STI)),\n"
280      << "AvailableFunctionFeatures()\n"
281      << "#endif // ifdef " << IfDefName << "\n";
282 }
283