1 //===- GlobalISelMatchTableExecutorEmitter.h ------------------------------===//
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 /// \file
10 /// This file contains common code related to emitting
11 /// GIMatchTableExecutor-derived classes.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLEEXECUTOREMITTER_H
16 #define LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLEEXECUTOREMITTER_H
17 
18 #include "Common/SubtargetFeatureInfo.h"
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/Twine.h"
22 #include <functional>
23 
24 namespace llvm {
25 class CodeGenTarget;
26 
27 namespace gi {
28 class RuleMatcher;
29 class LLTCodeGen;
30 class MatchTable;
31 } // namespace gi
32 
33 /// Abstract base class for TableGen backends that emit a
34 /// `GIMatchTableExecutor`-derived class.
35 class GlobalISelMatchTableExecutorEmitter {
36   /// Emits logic to check features required by \p Rules using the
37 
38   /// SubtargetFeatures map.
39   void emitSubtargetFeatureBitsetImpl(raw_ostream &OS,
40                                       ArrayRef<gi::RuleMatcher> Rules);
41 
42   /// Emits an enum + an array that stores references to
43   /// \p ComplexOperandMatchers.
44   void emitComplexPredicates(raw_ostream &OS,
45                              ArrayRef<Record *> ComplexOperandMatchers);
46 
47   /// Emits an enum + an array that stores references to
48   /// \p CustomOperandRenderers.
49   void emitCustomOperandRenderers(raw_ostream &OS,
50                                   ArrayRef<StringRef> CustomOperandRenderers);
51 
52   /// Emits an enum + an array to reference \p TypeObjects (LLTs) in the match
53   /// table.
54   void emitTypeObjects(raw_ostream &OS, ArrayRef<gi::LLTCodeGen> TypeObjects);
55 
56   /// Emits the getMatchTable function which contains all of the match table's
57   /// opcodes.
58   void emitMatchTable(raw_ostream &OS, const gi::MatchTable &Table);
59 
60   /// Helper function to emit `test` functions for the executor. This emits both
61   /// an enum to reference predicates in the MatchTable, and a function to
62   /// switch over the enum & execute the predicate's C++ code.
63   ///
64   /// \tparam PredicateObject An object representing a predicate to emit.
65   /// \param OS Output stream
66   /// \param TypeIdentifier Identifier used for the type of the predicate,
67   ///        e.g. `MI` for MachineInstrs.
68   /// \param ArgType Full type of the argument, e.g. `const MachineInstr &`
69   /// \param ArgName Name of the argument, e.g. `MI` for MachineInstrs.
70   /// \param AdditionalArgs Optional additional argument declarations.
71   /// \param AdditionalDeclarations Optional declarations to write at the start
72   ///        of the function, before switching over the predicates enum.
73   /// \param Predicates Predicates to emit.
74   /// \param GetPredEnumName Returns an enum name for a given predicate.
75   /// \param GetPredCode Returns the C++ code of a given predicate.
76   /// \param Comment Optional comment for the enum declaration.
77   template <typename PredicateObject>
emitCxxPredicateFns(raw_ostream & OS,StringRef TypeIdentifier,StringRef ArgType,StringRef ArgName,StringRef AdditionalArgs,StringRef AdditionalDeclarations,ArrayRef<PredicateObject> Predicates,std::function<StringRef (PredicateObject)> GetPredEnumName,std::function<StringRef (PredicateObject)> GetPredCode,StringRef Comment)78   void emitCxxPredicateFns(
79       raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType,
80       StringRef ArgName, StringRef AdditionalArgs,
81       StringRef AdditionalDeclarations, ArrayRef<PredicateObject> Predicates,
82       std::function<StringRef(PredicateObject)> GetPredEnumName,
83       std::function<StringRef(PredicateObject)> GetPredCode,
84       StringRef Comment) {
85     if (!Comment.empty())
86       OS << "// " << Comment << "\n";
87     if (!Predicates.empty()) {
88       OS << "enum {\n";
89       StringRef EnumeratorSeparator = " = GICXXPred_Invalid + 1,\n";
90       for (const auto &Pred : Predicates) {
91         OS << "  GICXXPred_" << TypeIdentifier << "_Predicate_"
92            << GetPredEnumName(Pred) << EnumeratorSeparator;
93         EnumeratorSeparator = ",\n";
94       }
95       OS << "};\n";
96     }
97 
98     OS << "bool " << getClassName() << "::test" << ArgName << "Predicate_"
99        << TypeIdentifier << "(unsigned PredicateID, " << ArgType << " "
100        << ArgName << AdditionalArgs << ") const {\n"
101        << AdditionalDeclarations;
102     if (!AdditionalDeclarations.empty())
103       OS << "\n";
104     if (!Predicates.empty()) {
105       OS << "  switch (PredicateID) {\n";
106       for (const auto &Pred : Predicates) {
107         // Ensure all code is indented.
108         const auto Code = join(split(GetPredCode(Pred).str(), "\n"), "\n    ");
109         OS << "  case GICXXPred_" << TypeIdentifier << "_Predicate_"
110            << GetPredEnumName(Pred) << ": {\n"
111            << "    " << Code << "\n";
112         if (!StringRef(Code).ltrim().starts_with("return")) {
113           OS << "    llvm_unreachable(\"" << GetPredEnumName(Pred)
114              << " should have returned\");\n";
115         }
116         OS << "  }\n";
117       }
118       OS << "  }\n";
119     }
120     OS << "  llvm_unreachable(\"Unknown predicate\");\n"
121        << "  return false;\n"
122        << "}\n";
123   }
124 
125 protected:
126   /// Emits `testMIPredicate_MI`.
127   /// \tparam PredicateObject An object representing a predicate to emit.
128   /// \param OS Output stream
129   /// \param AdditionalDecls Additional C++ variable declarations.
130   /// \param Predicates Predicates to emit.
131   /// \param GetPredEnumName Returns an enum name for a given predicate.
132   /// \param GetPredCode Returns the C++ code of a given predicate.
133   /// \param Comment Optional comment for the enum declaration.
134   template <typename PredicateObject>
135   void emitMIPredicateFnsImpl(
136       raw_ostream &OS, StringRef AdditionalDecls,
137       ArrayRef<PredicateObject> Predicates,
138       std::function<StringRef(PredicateObject)> GetPredEnumName,
139       std::function<StringRef(PredicateObject)> GetPredCode,
140       StringRef Comment = "") {
141     return emitCxxPredicateFns(
142         OS, "MI", "const MachineInstr &", "MI", ", const MatcherState &State",
143         AdditionalDecls, Predicates, GetPredEnumName, GetPredCode, Comment);
144   }
145 
146   /// Helper function to emit the following executor functions:
147   ///   * testImmPredicate_I64      (TypeIdentifier=I64)
148   ///   * testImmPredicate_APInt    (TypeIdentifier=APInt)
149   ///   * testImmPredicate_APFloat  (TypeIdentifier=APFloat)
150   ///
151   /// \tparam PredicateObject An object representing a predicate to emit.
152   /// \param OS Output stream
153   /// \param TypeIdentifier Identifier used for the type of the predicate
154   /// \param ArgType Full type of the argument
155   /// \param Predicates Predicates to emit.
156   /// \param GetPredEnumName Returns an enum name for a given predicate.
157   /// \param GetPredCode Returns the C++ code of a given predicate.
158   /// \param Comment Optional comment for the enum declaration.
159   template <typename PredicateObject>
160   void emitImmPredicateFnsImpl(
161       raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType,
162       ArrayRef<PredicateObject> Predicates,
163       std::function<StringRef(PredicateObject)> GetPredEnumName,
164       std::function<StringRef(PredicateObject)> GetPredCode,
165       StringRef Comment = "") {
166     return emitCxxPredicateFns(OS, TypeIdentifier, ArgType, "Imm", "", "",
167                                Predicates, GetPredEnumName, GetPredCode,
168                                Comment);
169   }
170 
171   GlobalISelMatchTableExecutorEmitter() = default;
172 
173 public:
174   virtual ~GlobalISelMatchTableExecutorEmitter() = default;
175 
176   virtual const CodeGenTarget &getTarget() const = 0;
177 
178   /// \returns the name of the class being emitted including any prefixes, e.g.
179   /// `AMDGPUInstructionSelector`.
180   virtual StringRef getClassName() const = 0;
181 
182   /// Emit additional content in emitExecutorImpl
emitAdditionalImpl(raw_ostream & OS)183   virtual void emitAdditionalImpl(raw_ostream &OS) {}
184 
185   /// Emit additional content in emitTemporariesInit.
emitAdditionalTemporariesInit(raw_ostream & OS)186   virtual void emitAdditionalTemporariesInit(raw_ostream &OS) {}
187 
188   /// Emit the `testMIPredicate_MI` function.
189   /// Note: `emitMIPredicateFnsImpl` can be used to do most of the work.
190   virtual void emitMIPredicateFns(raw_ostream &OS) = 0;
191 
192   /// Emit the `testImmPredicate_I64` function.
193   /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
194   virtual void emitI64ImmPredicateFns(raw_ostream &OS) = 0;
195 
196   /// Emit the `testImmPredicate_APFloat` function.
197   /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
198   virtual void emitAPFloatImmPredicateFns(raw_ostream &OS) = 0;
199 
200   /// Emit the `testImmPredicate_APInt` function.
201   /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
202   virtual void emitAPIntImmPredicateFns(raw_ostream &OS) = 0;
203   virtual void emitTestSimplePredicate(raw_ostream &OS) = 0;
204   virtual void emitRunCustomAction(raw_ostream &OS) = 0;
205 
206   void emitExecutorImpl(raw_ostream &OS, const gi::MatchTable &Table,
207                         ArrayRef<gi::LLTCodeGen> TypeObjects,
208                         ArrayRef<gi::RuleMatcher> Rules,
209                         ArrayRef<Record *> ComplexOperandMatchers,
210                         ArrayRef<StringRef> CustomOperandRenderers,
211                         StringRef IfDefName);
212   void emitPredicateBitset(raw_ostream &OS, StringRef IfDefName);
213   void emitTemporariesDecl(raw_ostream &OS, StringRef IfDefName);
214   void emitTemporariesInit(raw_ostream &OS, unsigned MaxTemporaries,
215                            StringRef IfDefName);
216   void emitPredicatesDecl(raw_ostream &OS, StringRef IfDefName);
217   void emitPredicatesInit(raw_ostream &OS, StringRef IfDefName);
218 
219   // Map of predicates to their subtarget features.
220   SubtargetFeatureInfoMap SubtargetFeatures;
221 
222   std::map<std::string, unsigned> HwModes;
223 };
224 } // namespace llvm
225 
226 #endif
227