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); 19 20 // Separate subtarget features by how often they must be recomputed. 21 SubtargetFeatureInfoMap ModuleFeatures; 22 std::copy_if(SubtargetFeatures.begin(), SubtargetFeatures.end(), 23 std::inserter(ModuleFeatures, ModuleFeatures.end()), 24 [](const SubtargetFeatureInfoMap::value_type &X) { 25 return !X.second.mustRecomputePerFunction(); 26 }); 27 SubtargetFeatureInfoMap FunctionFeatures; 28 std::copy_if(SubtargetFeatures.begin(), SubtargetFeatures.end(), 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); 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 matcher 51 // and an enum for the matcher to reference them with. 52 std::vector<std::vector<Record *>> FeatureBitsets; 53 FeatureBitsets.reserve(Rules.size()); 54 for (auto &Rule : Rules) 55 FeatureBitsets.push_back(Rule.getRequiredFeatures()); 56 llvm::sort(FeatureBitsets, [&](const std::vector<Record *> &A, 57 const std::vector<Record *> &B) { 58 if (A.size() < B.size()) 59 return true; 60 if (A.size() > B.size()) 61 return false; 62 for (auto [First, Second] : zip(A, B)) { 63 if (First->getName() < Second->getName()) 64 return true; 65 if (First->getName() > Second->getName()) 66 return false; 67 } 68 return false; 69 }); 70 FeatureBitsets.erase( 71 std::unique(FeatureBitsets.begin(), FeatureBitsets.end()), 72 FeatureBitsets.end()); 73 OS << "// Feature bitsets.\n" 74 << "enum {\n" 75 << " GIFBS_Invalid,\n"; 76 for (const auto &FeatureBitset : FeatureBitsets) { 77 if (FeatureBitset.empty()) 78 continue; 79 OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n"; 80 } 81 OS << "};\n" 82 << "const static PredicateBitset FeatureBitsets[] {\n" 83 << " {}, // GIFBS_Invalid\n"; 84 for (const auto &FeatureBitset : FeatureBitsets) { 85 if (FeatureBitset.empty()) 86 continue; 87 OS << " {"; 88 for (const auto &Feature : FeatureBitset) { 89 const auto &I = SubtargetFeatures.find(Feature); 90 assert(I != SubtargetFeatures.end() && "Didn't import predicate?"); 91 OS << I->second.getEnumBitName() << ", "; 92 } 93 OS << "},\n"; 94 } 95 OS << "};\n\n"; 96 } 97 98 void GlobalISelMatchTableExecutorEmitter::emitComplexPredicates( 99 raw_ostream &OS, ArrayRef<Record *> ComplexOperandMatchers) { 100 // Emit complex predicate table and an enum to reference them with. 101 OS << "// ComplexPattern predicates.\n" 102 << "enum {\n" 103 << " GICP_Invalid,\n"; 104 for (const auto &Record : ComplexOperandMatchers) 105 OS << " GICP_" << Record->getName() << ",\n"; 106 OS << "};\n" 107 << "// See constructor for table contents\n\n"; 108 109 OS << getClassName() << "::ComplexMatcherMemFn\n" 110 << getClassName() << "::ComplexPredicateFns[] = {\n" 111 << " nullptr, // GICP_Invalid\n"; 112 for (const auto &Record : ComplexOperandMatchers) 113 OS << " &" << getClassName() 114 << "::" << Record->getValueAsString("MatcherFn") << ", // " 115 << Record->getName() << "\n"; 116 OS << "};\n\n"; 117 } 118 119 void GlobalISelMatchTableExecutorEmitter::emitCustomOperandRenderers( 120 raw_ostream &OS, ArrayRef<StringRef> CustomOperandRenderers) { 121 OS << "// Custom renderers.\n" 122 << "enum {\n" 123 << " GICR_Invalid,\n"; 124 for (const auto &Fn : CustomOperandRenderers) 125 OS << " GICR_" << Fn << ",\n"; 126 OS << "};\n"; 127 128 OS << getClassName() << "::CustomRendererFn\n" 129 << getClassName() << "::CustomRenderers[] = {\n" 130 << " nullptr, // GICR_Invalid\n"; 131 for (const auto &Fn : CustomOperandRenderers) 132 OS << " &" << getClassName() << "::" << Fn << ",\n"; 133 OS << "};\n\n"; 134 } 135 136 void GlobalISelMatchTableExecutorEmitter::emitTypeObjects( 137 raw_ostream &OS, ArrayRef<LLTCodeGen> TypeObjects) { 138 OS << "// LLT Objects.\n" 139 << "enum {\n"; 140 for (const auto &TypeObject : TypeObjects) { 141 OS << " "; 142 TypeObject.emitCxxEnumValue(OS); 143 OS << ",\n"; 144 } 145 OS << "};\n" 146 << "const static size_t NumTypeObjects = " << TypeObjects.size() << ";\n" 147 << "const static LLT TypeObjects[] = {\n"; 148 for (const auto &TypeObject : TypeObjects) { 149 OS << " "; 150 TypeObject.emitCxxConstructorCall(OS); 151 OS << ",\n"; 152 } 153 OS << "};\n\n"; 154 } 155 156 void GlobalISelMatchTableExecutorEmitter::emitMatchTable( 157 raw_ostream &OS, const MatchTable &Table) { 158 OS << "const int64_t *" << getClassName() << "::getMatchTable() const {\n"; 159 Table.emitDeclaration(OS); 160 OS << " return "; 161 Table.emitUse(OS); 162 OS << ";\n}\n"; 163 } 164 165 void GlobalISelMatchTableExecutorEmitter::emitExecutorImpl( 166 raw_ostream &OS, const MatchTable &Table, ArrayRef<LLTCodeGen> TypeObjects, 167 ArrayRef<RuleMatcher> Rules, ArrayRef<Record *> ComplexOperandMatchers, 168 ArrayRef<StringRef> CustomOperandRenderers, StringRef IfDefName) { 169 OS << "#ifdef " << IfDefName << "\n"; 170 emitTypeObjects(OS, TypeObjects); 171 emitSubtargetFeatureBitsetImpl(OS, Rules); 172 emitComplexPredicates(OS, ComplexOperandMatchers); 173 emitMIPredicateFns(OS); 174 emitI64ImmPredicateFns(OS); 175 emitAPFloatImmPredicateFns(OS); 176 emitAPIntImmPredicateFns(OS); 177 emitTestSimplePredicate(OS); 178 emitCustomOperandRenderers(OS, CustomOperandRenderers); 179 emitAdditionalImpl(OS); 180 emitRunCustomAction(OS); 181 emitMatchTable(OS, Table); 182 OS << "#endif // ifdef " << IfDefName << "\n\n"; 183 } 184 185 void GlobalISelMatchTableExecutorEmitter::emitPredicateBitset( 186 raw_ostream &OS, StringRef IfDefName) { 187 OS << "#ifdef " << IfDefName << "\n" 188 << "const unsigned MAX_SUBTARGET_PREDICATES = " << SubtargetFeatures.size() 189 << ";\n" 190 << "using PredicateBitset = " 191 "llvm::PredicateBitsetImpl<MAX_SUBTARGET_PREDICATES>;\n" 192 << "#endif // ifdef " << IfDefName << "\n\n"; 193 } 194 195 void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl( 196 raw_ostream &OS, StringRef IfDefName) { 197 OS << "#ifdef " << IfDefName << "\n" 198 << " mutable MatcherState State;\n" 199 << " typedef " 200 "ComplexRendererFns(" 201 << getClassName() << "::*ComplexMatcherMemFn)(MachineOperand &) const;\n" 202 203 << " typedef void(" << getClassName() 204 << "::*CustomRendererFn)(MachineInstrBuilder &, const " 205 "MachineInstr &, int) " 206 "const;\n" 207 << " const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, " 208 "CustomRendererFn> " 209 "ExecInfo;\n" 210 << " static " << getClassName() 211 << "::ComplexMatcherMemFn ComplexPredicateFns[];\n" 212 << " static " << getClassName() 213 << "::CustomRendererFn CustomRenderers[];\n" 214 << " bool testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const " 215 "override;\n" 216 << " bool testImmPredicate_APInt(unsigned PredicateID, const APInt &Imm) " 217 "const override;\n" 218 << " bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat " 219 "&Imm) const override;\n" 220 << " const int64_t *getMatchTable() const override;\n" 221 << " bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI" 222 ", const MatcherState &State) " 223 "const override;\n" 224 << " bool testSimplePredicate(unsigned PredicateID) const override;\n" 225 << " void runCustomAction(unsigned FnID, const MatcherState &State) " 226 "const override;\n"; 227 emitAdditionalTemporariesDecl(OS, " "); 228 OS << "#endif // ifdef " << IfDefName << "\n\n"; 229 } 230 231 void GlobalISelMatchTableExecutorEmitter::emitTemporariesInit( 232 raw_ostream &OS, unsigned MaxTemporaries, StringRef IfDefName) { 233 OS << "#ifdef " << IfDefName << "\n" 234 << ", State(" << MaxTemporaries << "),\n" 235 << "ExecInfo(TypeObjects, NumTypeObjects, FeatureBitsets" 236 << ", ComplexPredicateFns, CustomRenderers)\n" 237 << "#endif // ifdef " << IfDefName << "\n\n"; 238 239 emitAdditionalTemporariesInit(OS); 240 } 241 242 void GlobalISelMatchTableExecutorEmitter::emitPredicatesDecl( 243 raw_ostream &OS, StringRef IfDefName) { 244 OS << "#ifdef " << IfDefName << "\n" 245 << "PredicateBitset AvailableModuleFeatures;\n" 246 << "mutable PredicateBitset AvailableFunctionFeatures;\n" 247 << "PredicateBitset getAvailableFeatures() const {\n" 248 << " return AvailableModuleFeatures | AvailableFunctionFeatures;\n" 249 << "}\n" 250 << "PredicateBitset\n" 251 << "computeAvailableModuleFeatures(const " << getTarget().getName() 252 << "Subtarget *Subtarget) const;\n" 253 << "PredicateBitset\n" 254 << "computeAvailableFunctionFeatures(const " << getTarget().getName() 255 << "Subtarget *Subtarget,\n" 256 << " const MachineFunction *MF) const;\n" 257 << "void setupGeneratedPerFunctionState(MachineFunction &MF) override;\n" 258 << "#endif // ifdef " << IfDefName << "\n"; 259 } 260 261 void GlobalISelMatchTableExecutorEmitter::emitPredicatesInit( 262 raw_ostream &OS, StringRef IfDefName) { 263 OS << "#ifdef " << IfDefName << "\n" 264 << "AvailableModuleFeatures(computeAvailableModuleFeatures(&STI)),\n" 265 << "AvailableFunctionFeatures()\n" 266 << "#endif // ifdef " << IfDefName << "\n"; 267 } 268