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<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 // 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("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 emitI64ImmPredicateFns(OS); 186 emitAPFloatImmPredicateFns(OS); 187 emitAPIntImmPredicateFns(OS); 188 emitTestSimplePredicate(OS); 189 emitCustomOperandRenderers(OS, CustomOperandRenderers); 190 emitAdditionalImpl(OS); 191 emitRunCustomAction(OS); 192 193 emitMatchTable(OS, Table); 194 195 OS << "#endif // ifdef " << IfDefName << "\n\n"; 196 } 197 198 void GlobalISelMatchTableExecutorEmitter::emitPredicateBitset( 199 raw_ostream &OS, StringRef IfDefName) { 200 unsigned Size = SubtargetFeatures.size() + HwModes.size(); 201 OS << "#ifdef " << IfDefName << "\n" 202 << "const unsigned MAX_SUBTARGET_PREDICATES = " << Size << ";\n" 203 << "using PredicateBitset = " 204 "llvm::Bitset<MAX_SUBTARGET_PREDICATES>;\n" 205 << "#endif // ifdef " << IfDefName << "\n\n"; 206 } 207 208 void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl( 209 raw_ostream &OS, StringRef IfDefName) { 210 OS << "#ifdef " << IfDefName << "\n" 211 << " mutable MatcherState State;\n" 212 << " typedef " 213 "ComplexRendererFns(" 214 << getClassName() << "::*ComplexMatcherMemFn)(MachineOperand &) const;\n" 215 216 << " typedef void(" << getClassName() 217 << "::*CustomRendererFn)(MachineInstrBuilder &, const " 218 "MachineInstr &, int) " 219 "const;\n" 220 << " const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, " 221 "CustomRendererFn> " 222 "ExecInfo;\n" 223 << " static " << getClassName() 224 << "::ComplexMatcherMemFn ComplexPredicateFns[];\n" 225 << " static " << getClassName() 226 << "::CustomRendererFn CustomRenderers[];\n" 227 << " bool testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const " 228 "override;\n" 229 << " bool testImmPredicate_APInt(unsigned PredicateID, const APInt &Imm) " 230 "const override;\n" 231 << " bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat " 232 "&Imm) const override;\n" 233 << " const uint8_t *getMatchTable() const override;\n" 234 << " bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI" 235 ", const MatcherState &State) " 236 "const override;\n" 237 << " bool testSimplePredicate(unsigned PredicateID) const override;\n" 238 << " bool runCustomAction(unsigned FnID, const MatcherState &State, " 239 "NewMIVector &OutMIs) " 240 "const override;\n" 241 << "#endif // ifdef " << IfDefName << "\n\n"; 242 } 243 244 void GlobalISelMatchTableExecutorEmitter::emitTemporariesInit( 245 raw_ostream &OS, unsigned MaxTemporaries, StringRef IfDefName) { 246 OS << "#ifdef " << IfDefName << "\n" 247 << ", State(" << MaxTemporaries << "),\n" 248 << "ExecInfo(TypeObjects, NumTypeObjects, FeatureBitsets" 249 << ", ComplexPredicateFns, CustomRenderers)\n" 250 << "#endif // ifdef " << IfDefName << "\n\n"; 251 252 emitAdditionalTemporariesInit(OS); 253 } 254 255 void GlobalISelMatchTableExecutorEmitter::emitPredicatesDecl( 256 raw_ostream &OS, StringRef IfDefName) { 257 OS << "#ifdef " << IfDefName << "\n" 258 << "PredicateBitset AvailableModuleFeatures;\n" 259 << "mutable PredicateBitset AvailableFunctionFeatures;\n" 260 << "PredicateBitset getAvailableFeatures() const {\n" 261 << " return AvailableModuleFeatures | AvailableFunctionFeatures;\n" 262 << "}\n" 263 << "PredicateBitset\n" 264 << "computeAvailableModuleFeatures(const " << getTarget().getName() 265 << "Subtarget *Subtarget) const;\n" 266 << "PredicateBitset\n" 267 << "computeAvailableFunctionFeatures(const " << getTarget().getName() 268 << "Subtarget *Subtarget,\n" 269 << " const MachineFunction *MF) const;\n" 270 << "void setupGeneratedPerFunctionState(MachineFunction &MF) override;\n" 271 << "#endif // ifdef " << IfDefName << "\n"; 272 } 273 274 void GlobalISelMatchTableExecutorEmitter::emitPredicatesInit( 275 raw_ostream &OS, StringRef IfDefName) { 276 OS << "#ifdef " << IfDefName << "\n" 277 << "AvailableModuleFeatures(computeAvailableModuleFeatures(&STI)),\n" 278 << "AvailableFunctionFeatures()\n" 279 << "#endif // ifdef " << IfDefName << "\n"; 280 } 281