285 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "GlobalISelMatchTableExecutorEmitter.h"10#include "GlobalISelMatchTable.h"11 12using namespace llvm;13using namespace llvm::gi;14 15void 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 llvm::copy_if(SubtargetFeatures,23 std::inserter(ModuleFeatures, ModuleFeatures.end()),24 [](const SubtargetFeatureInfoMap::value_type &X) {25 return !X.second.mustRecomputePerFunction();26 });27 SubtargetFeatureInfoMap FunctionFeatures;28 llvm::copy_if(SubtargetFeatures,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 matcher51 // and an enum for the matcher to reference them with.52 std::vector<std::pair<std::vector<const 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<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(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(llvm::unique(FeatureBitsets), 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.first, 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(Feature);93 assert(I != SubtargetFeatures.end() && "Didn't import predicate?");94 OS << I->second.getEnumBitName() << ", ";95 }96 // HwModeIdx97 if (FeatureBitset.second >= 0) {98 OS << "Feature_HwMode" << FeatureBitset.second << "Bit, ";99 }100 OS << "},\n";101 }102 OS << "};\n\n";103}104 105void 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("MatcherFn") << ", // "122 << Record->getName() << "\n";123 OS << "};\n\n";124}125 126void 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 143void 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 163void 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 175void 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 199void 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 209void 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 248void 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 259void 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 278void 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