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_COMMON_GLOBALISEL_GLOBALISELMATCHTABLEEXECUTOREMITTER_H
16#define LLVM_UTILS_TABLEGEN_COMMON_GLOBALISEL_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
24namespace llvm {
25class CodeGenTarget;
26
27namespace gi {
28class RuleMatcher;
29class LLTCodeGen;
30class MatchTable;
31} // namespace gi
32
33/// Abstract base class for TableGen backends that emit a
34/// `GIMatchTableExecutor`-derived class.
35class 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<const 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>
78 void emitCxxPredicateFns(
79 raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType,
80 StringRef ArgName, StringRef AdditionalArgs,
81 StringRef AdditionalDeclarations, ArrayRef<PredicateObject> Predicates,
82 llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName,
83 llvm::function_ref<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(Prefix: "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
125protected:
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 llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName,
139 llvm::function_ref<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 /// Emits `testMOPredicate_MO`.
147 /// \tparam PredicateObject An object representing a predicate to emit.
148 /// \param OS Output stream.
149 /// \param AdditionalDecls Additional C++ variable declarations.
150 /// \param Predicates Predicates to emit.
151 /// \param GetPredEnumName Returns an enum name for a given predicate.
152 /// \param GetPredCode Returns the C++ code of a given predicate.
153 /// \param Comment Optional comment for the enum declaration.
154 template <typename PredicateObject>
155 void emitLeafPredicateFnsImpl(
156 raw_ostream &OS, StringRef AdditionalDecls,
157 ArrayRef<PredicateObject> Predicates,
158 llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName,
159 llvm::function_ref<StringRef(PredicateObject)> GetPredCode,
160 StringRef Comment = "") {
161 return emitCxxPredicateFns(
162 OS, "MO", "const MachineOperand &", "MO", ", const MatcherState &State",
163 AdditionalDecls, Predicates, GetPredEnumName, GetPredCode, Comment);
164 }
165
166 /// Helper function to emit the following executor functions:
167 /// * testImmPredicate_I64 (TypeIdentifier=I64)
168 /// * testImmPredicate_APInt (TypeIdentifier=APInt)
169 /// * testImmPredicate_APFloat (TypeIdentifier=APFloat)
170 ///
171 /// \tparam PredicateObject An object representing a predicate to emit.
172 /// \param OS Output stream
173 /// \param TypeIdentifier Identifier used for the type of the predicate
174 /// \param ArgType Full type of the argument
175 /// \param Predicates Predicates to emit.
176 /// \param GetPredEnumName Returns an enum name for a given predicate.
177 /// \param GetPredCode Returns the C++ code of a given predicate.
178 /// \param Comment Optional comment for the enum declaration.
179 template <typename PredicateObject>
180 void emitImmPredicateFnsImpl(
181 raw_ostream &OS, StringRef TypeIdentifier, StringRef ArgType,
182 ArrayRef<PredicateObject> Predicates,
183 llvm::function_ref<StringRef(PredicateObject)> GetPredEnumName,
184 llvm::function_ref<StringRef(PredicateObject)> GetPredCode,
185 StringRef Comment = "") {
186 return emitCxxPredicateFns(OS, TypeIdentifier, ArgType, "Imm", "", "",
187 Predicates, GetPredEnumName, GetPredCode,
188 Comment);
189 }
190
191 GlobalISelMatchTableExecutorEmitter() = default;
192
193public:
194 virtual ~GlobalISelMatchTableExecutorEmitter() = default;
195
196 virtual const CodeGenTarget &getTarget() const = 0;
197
198 /// \returns the name of the class being emitted including any prefixes, e.g.
199 /// `AMDGPUInstructionSelector`.
200 virtual StringRef getClassName() const = 0;
201
202 /// Emit additional content in emitExecutorImpl
203 virtual void emitAdditionalImpl(raw_ostream &OS) {}
204
205 /// Emit additional content in emitTemporariesInit.
206 virtual void emitAdditionalTemporariesInit(raw_ostream &OS) {}
207
208 /// Emit the `testMIPredicate_MI` function.
209 /// Note: `emitMIPredicateFnsImpl` can be used to do most of the work.
210 virtual void emitMIPredicateFns(raw_ostream &OS) = 0;
211
212 /// Emit the `testLeafPredicate` function
213 /// Note `emitLeafPredicateFnsImpl` can be used to do most of the work.
214 virtual void emitLeafPredicateFns(raw_ostream &OS) = 0;
215
216 /// Emit the `testImmPredicate_I64` function.
217 /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
218 virtual void emitI64ImmPredicateFns(raw_ostream &OS) = 0;
219
220 /// Emit the `testImmPredicate_APFloat` function.
221 /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
222 virtual void emitAPFloatImmPredicateFns(raw_ostream &OS) = 0;
223
224 /// Emit the `testImmPredicate_APInt` function.
225 /// Note: `emitImmPredicateFnsImpl` can be used to do most of the work.
226 virtual void emitAPIntImmPredicateFns(raw_ostream &OS) = 0;
227 virtual void emitTestSimplePredicate(raw_ostream &OS) = 0;
228 virtual void emitRunCustomAction(raw_ostream &OS) = 0;
229
230 void emitExecutorImpl(raw_ostream &OS, const gi::MatchTable &Table,
231 ArrayRef<gi::LLTCodeGen> TypeObjects,
232 ArrayRef<gi::RuleMatcher> Rules,
233 ArrayRef<const Record *> ComplexOperandMatchers,
234 ArrayRef<StringRef> CustomOperandRenderers,
235 StringRef IfDefName);
236 void emitPredicateBitset(raw_ostream &OS, StringRef IfDefName);
237 void emitTemporariesDecl(raw_ostream &OS, StringRef IfDefName);
238 void emitTemporariesInit(raw_ostream &OS, unsigned MaxTemporaries,
239 StringRef IfDefName);
240 void emitPredicatesDecl(raw_ostream &OS, StringRef IfDefName);
241 void emitPredicatesInit(raw_ostream &OS, StringRef IfDefName);
242
243 // Map of predicates to their subtarget features.
244 SubtargetFeatureInfoMap SubtargetFeatures;
245
246 std::map<std::string, unsigned> HwModes;
247};
248} // namespace llvm
249
250#endif // LLVM_UTILS_TABLEGEN_COMMON_GLOBALISEL_GLOBALISELMATCHTABLEEXECUTOREMITTER_H
251