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