| 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: &HwModes); |
| 19 | |
| 20 | // Separate subtarget features by how often they must be recomputed. |
| 21 | SubtargetFeatureInfoMap ModuleFeatures; |
| 22 | llvm::copy_if(Range&: SubtargetFeatures, |
| 23 | Out: std::inserter(x&: ModuleFeatures, i: ModuleFeatures.end()), |
| 24 | P: [](const SubtargetFeatureInfoMap::value_type &X) { |
| 25 | return !X.second.mustRecomputePerFunction(); |
| 26 | }); |
| 27 | SubtargetFeatureInfoMap FunctionFeatures; |
| 28 | llvm::copy_if(Range&: SubtargetFeatures, |
| 29 | Out: std::inserter(x&: FunctionFeatures, i: FunctionFeatures.end()), |
| 30 | P: [](const SubtargetFeatureInfoMap::value_type &X) { |
| 31 | return X.second.mustRecomputePerFunction(); |
| 32 | }); |
| 33 | |
| 34 | SubtargetFeatureInfo::emitComputeAvailableFeatures( |
| 35 | TargetName: getTarget().getName(), ClassName: getClassName(), FuncName: "computeAvailableModuleFeatures" , |
| 36 | SubtargetFeatures: ModuleFeatures, OS, ExtraParams: "" , HwModes: &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 | TargetName: getTarget().getName(), ClassName: getClassName(), FuncName: "computeAvailableFunctionFeatures" , |
| 48 | SubtargetFeatures: FunctionFeatures, OS, ExtraParams: "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<const Record *>, int>> FeatureBitsets; |
| 53 | FeatureBitsets.reserve(n: Rules.size()); |
| 54 | for (auto &Rule : Rules) |
| 55 | FeatureBitsets.emplace_back(args: Rule.getRequiredFeatures(), |
| 56 | args: Rule.getHwModeIdx()); |
| 57 | llvm::sort(C&: FeatureBitsets, |
| 58 | Comp: [&](const std::pair<std::vector<const Record *>, int> &A, |
| 59 | const std::pair<std::vector<const 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(t: A.first, u: 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(first: llvm::unique(R&: FeatureBitsets), last: 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: FeatureBitset.first, HwModeIdx: 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(x: 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<const 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(FieldName: "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, |
| 178 | ArrayRef<const Record *> ComplexOperandMatchers, |
| 179 | ArrayRef<StringRef> CustomOperandRenderers, StringRef IfDefName) { |
| 180 | OS << "#ifdef " << IfDefName << "\n" ; |
| 181 | emitTypeObjects(OS, TypeObjects); |
| 182 | emitSubtargetFeatureBitsetImpl(OS, Rules); |
| 183 | emitComplexPredicates(OS, ComplexOperandMatchers); |
| 184 | emitMIPredicateFns(OS); |
| 185 | emitLeafPredicateFns(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 | |
| 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 | |
| 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 testMOPredicate_MO(unsigned PredicateID, const MachineOperand " |
| 239 | "&MO, const MatcherState &State) " |
| 240 | "const override;\n" |
| 241 | << " bool testSimplePredicate(unsigned PredicateID) const override;\n" |
| 242 | << " bool runCustomAction(unsigned FnID, const MatcherState &State, " |
| 243 | "NewMIVector &OutMIs) " |
| 244 | "const override;\n" |
| 245 | << "#endif // ifdef " << IfDefName << "\n\n" ; |
| 246 | } |
| 247 | |
| 248 | void GlobalISelMatchTableExecutorEmitter::emitTemporariesInit( |
| 249 | raw_ostream &OS, unsigned MaxTemporaries, StringRef IfDefName) { |
| 250 | OS << "#ifdef " << IfDefName << "\n" |
| 251 | << ", State(" << MaxTemporaries << "),\n" |
| 252 | << "ExecInfo(TypeObjects, NumTypeObjects, FeatureBitsets" |
| 253 | << ", ComplexPredicateFns, CustomRenderers)\n" |
| 254 | << "#endif // ifdef " << IfDefName << "\n\n" ; |
| 255 | |
| 256 | emitAdditionalTemporariesInit(OS); |
| 257 | } |
| 258 | |
| 259 | void GlobalISelMatchTableExecutorEmitter::emitPredicatesDecl( |
| 260 | raw_ostream &OS, StringRef IfDefName) { |
| 261 | OS << "#ifdef " << IfDefName << "\n" |
| 262 | << "PredicateBitset AvailableModuleFeatures;\n" |
| 263 | << "mutable PredicateBitset AvailableFunctionFeatures;\n" |
| 264 | << "PredicateBitset getAvailableFeatures() const {\n" |
| 265 | << " return AvailableModuleFeatures | AvailableFunctionFeatures;\n" |
| 266 | << "}\n" |
| 267 | << "PredicateBitset\n" |
| 268 | << "computeAvailableModuleFeatures(const " << getTarget().getName() |
| 269 | << "Subtarget *Subtarget) const;\n" |
| 270 | << "PredicateBitset\n" |
| 271 | << "computeAvailableFunctionFeatures(const " << getTarget().getName() |
| 272 | << "Subtarget *Subtarget,\n" |
| 273 | << " const MachineFunction *MF) const;\n" |
| 274 | << "void setupGeneratedPerFunctionState(MachineFunction &MF) override;\n" |
| 275 | << "#endif // ifdef " << IfDefName << "\n" ; |
| 276 | } |
| 277 | |
| 278 | void GlobalISelMatchTableExecutorEmitter::emitPredicatesInit( |
| 279 | raw_ostream &OS, StringRef IfDefName) { |
| 280 | OS << "#ifdef " << IfDefName << "\n" |
| 281 | << "AvailableModuleFeatures(computeAvailableModuleFeatures(&STI)),\n" |
| 282 | << "AvailableFunctionFeatures()\n" |
| 283 | << "#endif // ifdef " << IfDefName << "\n" ; |
| 284 | } |
| 285 | |