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