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); 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, "", &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 matcher 51 // and an enum for the matcher to reference them with. 52 std::vector<std::pair<std::vector<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<Record *>, int> &A, 59 const std::pair<std::vector<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( 74 std::unique(FeatureBitsets.begin(), FeatureBitsets.end()), 75 FeatureBitsets.end()); 76 OS << "// Feature bitsets.\n" 77 << "enum {\n" 78 << " GIFBS_Invalid,\n"; 79 for (const auto &FeatureBitset : FeatureBitsets) { 80 if (FeatureBitset.first.empty() && FeatureBitset.second < 0) 81 continue; 82 OS << " " 83 << getNameForFeatureBitset(FeatureBitset.first, FeatureBitset.second) 84 << ",\n"; 85 } 86 OS << "};\n" 87 << "constexpr static PredicateBitset FeatureBitsets[] {\n" 88 << " {}, // GIFBS_Invalid\n"; 89 for (const auto &FeatureBitset : FeatureBitsets) { 90 if (FeatureBitset.first.empty() && FeatureBitset.second < 0) 91 continue; 92 OS << " {"; 93 for (const auto &Feature : FeatureBitset.first) { 94 const auto &I = SubtargetFeatures.find(Feature); 95 assert(I != SubtargetFeatures.end() && "Didn't import predicate?"); 96 OS << I->second.getEnumBitName() << ", "; 97 } 98 // HwModeIdx 99 if (FeatureBitset.second >= 0) { 100 OS << "Feature_HwMode" << FeatureBitset.second << "Bit, "; 101 } 102 OS << "},\n"; 103 } 104 OS << "};\n\n"; 105 } 106 107 void GlobalISelMatchTableExecutorEmitter::emitComplexPredicates( 108 raw_ostream &OS, ArrayRef<Record *> ComplexOperandMatchers) { 109 // Emit complex predicate table and an enum to reference them with. 110 OS << "// ComplexPattern predicates.\n" 111 << "enum {\n" 112 << " GICP_Invalid,\n"; 113 for (const auto &Record : ComplexOperandMatchers) 114 OS << " GICP_" << Record->getName() << ",\n"; 115 OS << "};\n" 116 << "// See constructor for table contents\n\n"; 117 118 OS << getClassName() << "::ComplexMatcherMemFn\n" 119 << getClassName() << "::ComplexPredicateFns[] = {\n" 120 << " nullptr, // GICP_Invalid\n"; 121 for (const auto &Record : ComplexOperandMatchers) 122 OS << " &" << getClassName() 123 << "::" << Record->getValueAsString("MatcherFn") << ", // " 124 << Record->getName() << "\n"; 125 OS << "};\n\n"; 126 } 127 128 void GlobalISelMatchTableExecutorEmitter::emitCustomOperandRenderers( 129 raw_ostream &OS, ArrayRef<StringRef> CustomOperandRenderers) { 130 OS << "// Custom renderers.\n" 131 << "enum {\n" 132 << " GICR_Invalid,\n"; 133 for (const auto &Fn : CustomOperandRenderers) 134 OS << " GICR_" << Fn << ",\n"; 135 OS << "};\n"; 136 137 OS << getClassName() << "::CustomRendererFn\n" 138 << getClassName() << "::CustomRenderers[] = {\n" 139 << " nullptr, // GICR_Invalid\n"; 140 for (const auto &Fn : CustomOperandRenderers) 141 OS << " &" << getClassName() << "::" << Fn << ",\n"; 142 OS << "};\n\n"; 143 } 144 145 void GlobalISelMatchTableExecutorEmitter::emitTypeObjects( 146 raw_ostream &OS, ArrayRef<LLTCodeGen> TypeObjects) { 147 OS << "// LLT Objects.\n" 148 << "enum {\n"; 149 for (const auto &TypeObject : TypeObjects) { 150 OS << " "; 151 TypeObject.emitCxxEnumValue(OS); 152 OS << ",\n"; 153 } 154 OS << "};\n" 155 << "const static size_t NumTypeObjects = " << TypeObjects.size() << ";\n" 156 << "const static LLT TypeObjects[] = {\n"; 157 for (const auto &TypeObject : TypeObjects) { 158 OS << " "; 159 TypeObject.emitCxxConstructorCall(OS); 160 OS << ",\n"; 161 } 162 OS << "};\n\n"; 163 } 164 165 void GlobalISelMatchTableExecutorEmitter::emitMatchTable( 166 raw_ostream &OS, const MatchTable &Table) { 167 emitEncodingMacrosDef(OS); 168 OS << "const uint8_t *" << getClassName() << "::getMatchTable() const {\n"; 169 Table.emitDeclaration(OS); 170 OS << " return "; 171 Table.emitUse(OS); 172 OS << ";\n}\n"; 173 emitEncodingMacrosUndef(OS); 174 OS << "\n"; 175 } 176 177 void GlobalISelMatchTableExecutorEmitter::emitExecutorImpl( 178 raw_ostream &OS, const MatchTable &Table, ArrayRef<LLTCodeGen> TypeObjects, 179 ArrayRef<RuleMatcher> Rules, ArrayRef<Record *> ComplexOperandMatchers, 180 ArrayRef<StringRef> CustomOperandRenderers, StringRef IfDefName) { 181 OS << "#ifdef " << IfDefName << "\n"; 182 emitTypeObjects(OS, TypeObjects); 183 emitSubtargetFeatureBitsetImpl(OS, Rules); 184 emitComplexPredicates(OS, ComplexOperandMatchers); 185 emitMIPredicateFns(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 testSimplePredicate(unsigned PredicateID) const override;\n" 239 << " void runCustomAction(unsigned FnID, const MatcherState &State, " 240 "NewMIVector &OutMIs) " 241 "const override;\n"; 242 emitAdditionalTemporariesDecl(OS, " "); 243 OS << "#endif // ifdef " << IfDefName << "\n\n"; 244 } 245 246 void GlobalISelMatchTableExecutorEmitter::emitTemporariesInit( 247 raw_ostream &OS, unsigned MaxTemporaries, StringRef IfDefName) { 248 OS << "#ifdef " << IfDefName << "\n" 249 << ", State(" << MaxTemporaries << "),\n" 250 << "ExecInfo(TypeObjects, NumTypeObjects, FeatureBitsets" 251 << ", ComplexPredicateFns, CustomRenderers)\n" 252 << "#endif // ifdef " << IfDefName << "\n\n"; 253 254 emitAdditionalTemporariesInit(OS); 255 } 256 257 void GlobalISelMatchTableExecutorEmitter::emitPredicatesDecl( 258 raw_ostream &OS, StringRef IfDefName) { 259 OS << "#ifdef " << IfDefName << "\n" 260 << "PredicateBitset AvailableModuleFeatures;\n" 261 << "mutable PredicateBitset AvailableFunctionFeatures;\n" 262 << "PredicateBitset getAvailableFeatures() const {\n" 263 << " return AvailableModuleFeatures | AvailableFunctionFeatures;\n" 264 << "}\n" 265 << "PredicateBitset\n" 266 << "computeAvailableModuleFeatures(const " << getTarget().getName() 267 << "Subtarget *Subtarget) const;\n" 268 << "PredicateBitset\n" 269 << "computeAvailableFunctionFeatures(const " << getTarget().getName() 270 << "Subtarget *Subtarget,\n" 271 << " const MachineFunction *MF) const;\n" 272 << "void setupGeneratedPerFunctionState(MachineFunction &MF) override;\n" 273 << "#endif // ifdef " << IfDefName << "\n"; 274 } 275 276 void GlobalISelMatchTableExecutorEmitter::emitPredicatesInit( 277 raw_ostream &OS, StringRef IfDefName) { 278 OS << "#ifdef " << IfDefName << "\n" 279 << "AvailableModuleFeatures(computeAvailableModuleFeatures(&STI)),\n" 280 << "AvailableFunctionFeatures()\n" 281 << "#endif // ifdef " << IfDefName << "\n"; 282 } 283