1*0fca6ea1SDimitry Andric //===- GlobalISelMatchTableExecutorEmitter.cpp ----------------------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric 9*0fca6ea1SDimitry Andric #include "GlobalISelMatchTableExecutorEmitter.h" 10*0fca6ea1SDimitry Andric #include "GlobalISelMatchTable.h" 11*0fca6ea1SDimitry Andric 12*0fca6ea1SDimitry Andric using namespace llvm; 13*0fca6ea1SDimitry Andric using namespace llvm::gi; 14*0fca6ea1SDimitry Andric 15*0fca6ea1SDimitry Andric void GlobalISelMatchTableExecutorEmitter::emitSubtargetFeatureBitsetImpl( 16*0fca6ea1SDimitry Andric raw_ostream &OS, ArrayRef<RuleMatcher> Rules) { 17*0fca6ea1SDimitry Andric SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures, 18*0fca6ea1SDimitry Andric OS, &HwModes); 19*0fca6ea1SDimitry Andric 20*0fca6ea1SDimitry Andric // Separate subtarget features by how often they must be recomputed. 21*0fca6ea1SDimitry Andric SubtargetFeatureInfoMap ModuleFeatures; 22*0fca6ea1SDimitry Andric std::copy_if(SubtargetFeatures.begin(), SubtargetFeatures.end(), 23*0fca6ea1SDimitry Andric std::inserter(ModuleFeatures, ModuleFeatures.end()), 24*0fca6ea1SDimitry Andric [](const SubtargetFeatureInfoMap::value_type &X) { 25*0fca6ea1SDimitry Andric return !X.second.mustRecomputePerFunction(); 26*0fca6ea1SDimitry Andric }); 27*0fca6ea1SDimitry Andric SubtargetFeatureInfoMap FunctionFeatures; 28*0fca6ea1SDimitry Andric std::copy_if(SubtargetFeatures.begin(), SubtargetFeatures.end(), 29*0fca6ea1SDimitry Andric std::inserter(FunctionFeatures, FunctionFeatures.end()), 30*0fca6ea1SDimitry Andric [](const SubtargetFeatureInfoMap::value_type &X) { 31*0fca6ea1SDimitry Andric return X.second.mustRecomputePerFunction(); 32*0fca6ea1SDimitry Andric }); 33*0fca6ea1SDimitry Andric 34*0fca6ea1SDimitry Andric SubtargetFeatureInfo::emitComputeAvailableFeatures( 35*0fca6ea1SDimitry Andric getTarget().getName(), getClassName(), "computeAvailableModuleFeatures", 36*0fca6ea1SDimitry Andric ModuleFeatures, OS, "", &HwModes); 37*0fca6ea1SDimitry Andric 38*0fca6ea1SDimitry Andric OS << "void " << getClassName() 39*0fca6ea1SDimitry Andric << "::setupGeneratedPerFunctionState(MachineFunction &MF) {\n" 40*0fca6ea1SDimitry Andric " AvailableFunctionFeatures = computeAvailableFunctionFeatures(" 41*0fca6ea1SDimitry Andric "(const " 42*0fca6ea1SDimitry Andric << getTarget().getName() 43*0fca6ea1SDimitry Andric << "Subtarget *)&MF.getSubtarget(), &MF);\n" 44*0fca6ea1SDimitry Andric "}\n"; 45*0fca6ea1SDimitry Andric 46*0fca6ea1SDimitry Andric SubtargetFeatureInfo::emitComputeAvailableFeatures( 47*0fca6ea1SDimitry Andric getTarget().getName(), getClassName(), "computeAvailableFunctionFeatures", 48*0fca6ea1SDimitry Andric FunctionFeatures, OS, "const MachineFunction *MF"); 49*0fca6ea1SDimitry Andric 50*0fca6ea1SDimitry Andric // Emit a table containing the PredicateBitsets objects needed by the matcher 51*0fca6ea1SDimitry Andric // and an enum for the matcher to reference them with. 52*0fca6ea1SDimitry Andric std::vector<std::pair<std::vector<Record *>, int>> FeatureBitsets; 53*0fca6ea1SDimitry Andric FeatureBitsets.reserve(Rules.size()); 54*0fca6ea1SDimitry Andric for (auto &Rule : Rules) 55*0fca6ea1SDimitry Andric FeatureBitsets.emplace_back(Rule.getRequiredFeatures(), 56*0fca6ea1SDimitry Andric Rule.getHwModeIdx()); 57*0fca6ea1SDimitry Andric llvm::sort(FeatureBitsets, 58*0fca6ea1SDimitry Andric [&](const std::pair<std::vector<Record *>, int> &A, 59*0fca6ea1SDimitry Andric const std::pair<std::vector<Record *>, int> &B) { 60*0fca6ea1SDimitry Andric if (A.first.size() < B.first.size()) 61*0fca6ea1SDimitry Andric return true; 62*0fca6ea1SDimitry Andric if (A.first.size() > B.first.size()) 63*0fca6ea1SDimitry Andric return false; 64*0fca6ea1SDimitry Andric for (auto [First, Second] : zip(A.first, B.first)) { 65*0fca6ea1SDimitry Andric if (First->getName() < Second->getName()) 66*0fca6ea1SDimitry Andric return true; 67*0fca6ea1SDimitry Andric if (First->getName() > Second->getName()) 68*0fca6ea1SDimitry Andric return false; 69*0fca6ea1SDimitry Andric } 70*0fca6ea1SDimitry Andric 71*0fca6ea1SDimitry Andric return (A.second < B.second); 72*0fca6ea1SDimitry Andric }); 73*0fca6ea1SDimitry Andric FeatureBitsets.erase(llvm::unique(FeatureBitsets), FeatureBitsets.end()); 74*0fca6ea1SDimitry Andric OS << "// Feature bitsets.\n" 75*0fca6ea1SDimitry Andric << "enum {\n" 76*0fca6ea1SDimitry Andric << " GIFBS_Invalid,\n"; 77*0fca6ea1SDimitry Andric for (const auto &FeatureBitset : FeatureBitsets) { 78*0fca6ea1SDimitry Andric if (FeatureBitset.first.empty() && FeatureBitset.second < 0) 79*0fca6ea1SDimitry Andric continue; 80*0fca6ea1SDimitry Andric OS << " " 81*0fca6ea1SDimitry Andric << getNameForFeatureBitset(FeatureBitset.first, FeatureBitset.second) 82*0fca6ea1SDimitry Andric << ",\n"; 83*0fca6ea1SDimitry Andric } 84*0fca6ea1SDimitry Andric OS << "};\n" 85*0fca6ea1SDimitry Andric << "constexpr static PredicateBitset FeatureBitsets[] {\n" 86*0fca6ea1SDimitry Andric << " {}, // GIFBS_Invalid\n"; 87*0fca6ea1SDimitry Andric for (const auto &FeatureBitset : FeatureBitsets) { 88*0fca6ea1SDimitry Andric if (FeatureBitset.first.empty() && FeatureBitset.second < 0) 89*0fca6ea1SDimitry Andric continue; 90*0fca6ea1SDimitry Andric OS << " {"; 91*0fca6ea1SDimitry Andric for (const auto &Feature : FeatureBitset.first) { 92*0fca6ea1SDimitry Andric const auto &I = SubtargetFeatures.find(Feature); 93*0fca6ea1SDimitry Andric assert(I != SubtargetFeatures.end() && "Didn't import predicate?"); 94*0fca6ea1SDimitry Andric OS << I->second.getEnumBitName() << ", "; 95*0fca6ea1SDimitry Andric } 96*0fca6ea1SDimitry Andric // HwModeIdx 97*0fca6ea1SDimitry Andric if (FeatureBitset.second >= 0) { 98*0fca6ea1SDimitry Andric OS << "Feature_HwMode" << FeatureBitset.second << "Bit, "; 99*0fca6ea1SDimitry Andric } 100*0fca6ea1SDimitry Andric OS << "},\n"; 101*0fca6ea1SDimitry Andric } 102*0fca6ea1SDimitry Andric OS << "};\n\n"; 103*0fca6ea1SDimitry Andric } 104*0fca6ea1SDimitry Andric 105*0fca6ea1SDimitry Andric void GlobalISelMatchTableExecutorEmitter::emitComplexPredicates( 106*0fca6ea1SDimitry Andric raw_ostream &OS, ArrayRef<Record *> ComplexOperandMatchers) { 107*0fca6ea1SDimitry Andric // Emit complex predicate table and an enum to reference them with. 108*0fca6ea1SDimitry Andric OS << "// ComplexPattern predicates.\n" 109*0fca6ea1SDimitry Andric << "enum {\n" 110*0fca6ea1SDimitry Andric << " GICP_Invalid,\n"; 111*0fca6ea1SDimitry Andric for (const auto &Record : ComplexOperandMatchers) 112*0fca6ea1SDimitry Andric OS << " GICP_" << Record->getName() << ",\n"; 113*0fca6ea1SDimitry Andric OS << "};\n" 114*0fca6ea1SDimitry Andric << "// See constructor for table contents\n\n"; 115*0fca6ea1SDimitry Andric 116*0fca6ea1SDimitry Andric OS << getClassName() << "::ComplexMatcherMemFn\n" 117*0fca6ea1SDimitry Andric << getClassName() << "::ComplexPredicateFns[] = {\n" 118*0fca6ea1SDimitry Andric << " nullptr, // GICP_Invalid\n"; 119*0fca6ea1SDimitry Andric for (const auto &Record : ComplexOperandMatchers) 120*0fca6ea1SDimitry Andric OS << " &" << getClassName() 121*0fca6ea1SDimitry Andric << "::" << Record->getValueAsString("MatcherFn") << ", // " 122*0fca6ea1SDimitry Andric << Record->getName() << "\n"; 123*0fca6ea1SDimitry Andric OS << "};\n\n"; 124*0fca6ea1SDimitry Andric } 125*0fca6ea1SDimitry Andric 126*0fca6ea1SDimitry Andric void GlobalISelMatchTableExecutorEmitter::emitCustomOperandRenderers( 127*0fca6ea1SDimitry Andric raw_ostream &OS, ArrayRef<StringRef> CustomOperandRenderers) { 128*0fca6ea1SDimitry Andric OS << "// Custom renderers.\n" 129*0fca6ea1SDimitry Andric << "enum {\n" 130*0fca6ea1SDimitry Andric << " GICR_Invalid,\n"; 131*0fca6ea1SDimitry Andric for (const auto &Fn : CustomOperandRenderers) 132*0fca6ea1SDimitry Andric OS << " GICR_" << Fn << ",\n"; 133*0fca6ea1SDimitry Andric OS << "};\n"; 134*0fca6ea1SDimitry Andric 135*0fca6ea1SDimitry Andric OS << getClassName() << "::CustomRendererFn\n" 136*0fca6ea1SDimitry Andric << getClassName() << "::CustomRenderers[] = {\n" 137*0fca6ea1SDimitry Andric << " nullptr, // GICR_Invalid\n"; 138*0fca6ea1SDimitry Andric for (const auto &Fn : CustomOperandRenderers) 139*0fca6ea1SDimitry Andric OS << " &" << getClassName() << "::" << Fn << ",\n"; 140*0fca6ea1SDimitry Andric OS << "};\n\n"; 141*0fca6ea1SDimitry Andric } 142*0fca6ea1SDimitry Andric 143*0fca6ea1SDimitry Andric void GlobalISelMatchTableExecutorEmitter::emitTypeObjects( 144*0fca6ea1SDimitry Andric raw_ostream &OS, ArrayRef<LLTCodeGen> TypeObjects) { 145*0fca6ea1SDimitry Andric OS << "// LLT Objects.\n" 146*0fca6ea1SDimitry Andric << "enum {\n"; 147*0fca6ea1SDimitry Andric for (const auto &TypeObject : TypeObjects) { 148*0fca6ea1SDimitry Andric OS << " "; 149*0fca6ea1SDimitry Andric TypeObject.emitCxxEnumValue(OS); 150*0fca6ea1SDimitry Andric OS << ",\n"; 151*0fca6ea1SDimitry Andric } 152*0fca6ea1SDimitry Andric OS << "};\n" 153*0fca6ea1SDimitry Andric << "const static size_t NumTypeObjects = " << TypeObjects.size() << ";\n" 154*0fca6ea1SDimitry Andric << "const static LLT TypeObjects[] = {\n"; 155*0fca6ea1SDimitry Andric for (const auto &TypeObject : TypeObjects) { 156*0fca6ea1SDimitry Andric OS << " "; 157*0fca6ea1SDimitry Andric TypeObject.emitCxxConstructorCall(OS); 158*0fca6ea1SDimitry Andric OS << ",\n"; 159*0fca6ea1SDimitry Andric } 160*0fca6ea1SDimitry Andric OS << "};\n\n"; 161*0fca6ea1SDimitry Andric } 162*0fca6ea1SDimitry Andric 163*0fca6ea1SDimitry Andric void GlobalISelMatchTableExecutorEmitter::emitMatchTable( 164*0fca6ea1SDimitry Andric raw_ostream &OS, const MatchTable &Table) { 165*0fca6ea1SDimitry Andric emitEncodingMacrosDef(OS); 166*0fca6ea1SDimitry Andric OS << "const uint8_t *" << getClassName() << "::getMatchTable() const {\n"; 167*0fca6ea1SDimitry Andric Table.emitDeclaration(OS); 168*0fca6ea1SDimitry Andric OS << " return "; 169*0fca6ea1SDimitry Andric Table.emitUse(OS); 170*0fca6ea1SDimitry Andric OS << ";\n}\n"; 171*0fca6ea1SDimitry Andric emitEncodingMacrosUndef(OS); 172*0fca6ea1SDimitry Andric OS << "\n"; 173*0fca6ea1SDimitry Andric } 174*0fca6ea1SDimitry Andric 175*0fca6ea1SDimitry Andric void GlobalISelMatchTableExecutorEmitter::emitExecutorImpl( 176*0fca6ea1SDimitry Andric raw_ostream &OS, const MatchTable &Table, ArrayRef<LLTCodeGen> TypeObjects, 177*0fca6ea1SDimitry Andric ArrayRef<RuleMatcher> Rules, ArrayRef<Record *> ComplexOperandMatchers, 178*0fca6ea1SDimitry Andric ArrayRef<StringRef> CustomOperandRenderers, StringRef IfDefName) { 179*0fca6ea1SDimitry Andric OS << "#ifdef " << IfDefName << "\n"; 180*0fca6ea1SDimitry Andric emitTypeObjects(OS, TypeObjects); 181*0fca6ea1SDimitry Andric emitSubtargetFeatureBitsetImpl(OS, Rules); 182*0fca6ea1SDimitry Andric emitComplexPredicates(OS, ComplexOperandMatchers); 183*0fca6ea1SDimitry Andric emitMIPredicateFns(OS); 184*0fca6ea1SDimitry Andric emitI64ImmPredicateFns(OS); 185*0fca6ea1SDimitry Andric emitAPFloatImmPredicateFns(OS); 186*0fca6ea1SDimitry Andric emitAPIntImmPredicateFns(OS); 187*0fca6ea1SDimitry Andric emitTestSimplePredicate(OS); 188*0fca6ea1SDimitry Andric emitCustomOperandRenderers(OS, CustomOperandRenderers); 189*0fca6ea1SDimitry Andric emitAdditionalImpl(OS); 190*0fca6ea1SDimitry Andric emitRunCustomAction(OS); 191*0fca6ea1SDimitry Andric 192*0fca6ea1SDimitry Andric emitMatchTable(OS, Table); 193*0fca6ea1SDimitry Andric 194*0fca6ea1SDimitry Andric OS << "#endif // ifdef " << IfDefName << "\n\n"; 195*0fca6ea1SDimitry Andric } 196*0fca6ea1SDimitry Andric 197*0fca6ea1SDimitry Andric void GlobalISelMatchTableExecutorEmitter::emitPredicateBitset( 198*0fca6ea1SDimitry Andric raw_ostream &OS, StringRef IfDefName) { 199*0fca6ea1SDimitry Andric unsigned Size = SubtargetFeatures.size() + HwModes.size(); 200*0fca6ea1SDimitry Andric OS << "#ifdef " << IfDefName << "\n" 201*0fca6ea1SDimitry Andric << "const unsigned MAX_SUBTARGET_PREDICATES = " << Size << ";\n" 202*0fca6ea1SDimitry Andric << "using PredicateBitset = " 203*0fca6ea1SDimitry Andric "llvm::Bitset<MAX_SUBTARGET_PREDICATES>;\n" 204*0fca6ea1SDimitry Andric << "#endif // ifdef " << IfDefName << "\n\n"; 205*0fca6ea1SDimitry Andric } 206*0fca6ea1SDimitry Andric 207*0fca6ea1SDimitry Andric void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl( 208*0fca6ea1SDimitry Andric raw_ostream &OS, StringRef IfDefName) { 209*0fca6ea1SDimitry Andric OS << "#ifdef " << IfDefName << "\n" 210*0fca6ea1SDimitry Andric << " mutable MatcherState State;\n" 211*0fca6ea1SDimitry Andric << " typedef " 212*0fca6ea1SDimitry Andric "ComplexRendererFns(" 213*0fca6ea1SDimitry Andric << getClassName() << "::*ComplexMatcherMemFn)(MachineOperand &) const;\n" 214*0fca6ea1SDimitry Andric 215*0fca6ea1SDimitry Andric << " typedef void(" << getClassName() 216*0fca6ea1SDimitry Andric << "::*CustomRendererFn)(MachineInstrBuilder &, const " 217*0fca6ea1SDimitry Andric "MachineInstr &, int) " 218*0fca6ea1SDimitry Andric "const;\n" 219*0fca6ea1SDimitry Andric << " const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, " 220*0fca6ea1SDimitry Andric "CustomRendererFn> " 221*0fca6ea1SDimitry Andric "ExecInfo;\n" 222*0fca6ea1SDimitry Andric << " static " << getClassName() 223*0fca6ea1SDimitry Andric << "::ComplexMatcherMemFn ComplexPredicateFns[];\n" 224*0fca6ea1SDimitry Andric << " static " << getClassName() 225*0fca6ea1SDimitry Andric << "::CustomRendererFn CustomRenderers[];\n" 226*0fca6ea1SDimitry Andric << " bool testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const " 227*0fca6ea1SDimitry Andric "override;\n" 228*0fca6ea1SDimitry Andric << " bool testImmPredicate_APInt(unsigned PredicateID, const APInt &Imm) " 229*0fca6ea1SDimitry Andric "const override;\n" 230*0fca6ea1SDimitry Andric << " bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat " 231*0fca6ea1SDimitry Andric "&Imm) const override;\n" 232*0fca6ea1SDimitry Andric << " const uint8_t *getMatchTable() const override;\n" 233*0fca6ea1SDimitry Andric << " bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI" 234*0fca6ea1SDimitry Andric ", const MatcherState &State) " 235*0fca6ea1SDimitry Andric "const override;\n" 236*0fca6ea1SDimitry Andric << " bool testSimplePredicate(unsigned PredicateID) const override;\n" 237*0fca6ea1SDimitry Andric << " bool runCustomAction(unsigned FnID, const MatcherState &State, " 238*0fca6ea1SDimitry Andric "NewMIVector &OutMIs) " 239*0fca6ea1SDimitry Andric "const override;\n" 240*0fca6ea1SDimitry Andric << "#endif // ifdef " << IfDefName << "\n\n"; 241*0fca6ea1SDimitry Andric } 242*0fca6ea1SDimitry Andric 243*0fca6ea1SDimitry Andric void GlobalISelMatchTableExecutorEmitter::emitTemporariesInit( 244*0fca6ea1SDimitry Andric raw_ostream &OS, unsigned MaxTemporaries, StringRef IfDefName) { 245*0fca6ea1SDimitry Andric OS << "#ifdef " << IfDefName << "\n" 246*0fca6ea1SDimitry Andric << ", State(" << MaxTemporaries << "),\n" 247*0fca6ea1SDimitry Andric << "ExecInfo(TypeObjects, NumTypeObjects, FeatureBitsets" 248*0fca6ea1SDimitry Andric << ", ComplexPredicateFns, CustomRenderers)\n" 249*0fca6ea1SDimitry Andric << "#endif // ifdef " << IfDefName << "\n\n"; 250*0fca6ea1SDimitry Andric 251*0fca6ea1SDimitry Andric emitAdditionalTemporariesInit(OS); 252*0fca6ea1SDimitry Andric } 253*0fca6ea1SDimitry Andric 254*0fca6ea1SDimitry Andric void GlobalISelMatchTableExecutorEmitter::emitPredicatesDecl( 255*0fca6ea1SDimitry Andric raw_ostream &OS, StringRef IfDefName) { 256*0fca6ea1SDimitry Andric OS << "#ifdef " << IfDefName << "\n" 257*0fca6ea1SDimitry Andric << "PredicateBitset AvailableModuleFeatures;\n" 258*0fca6ea1SDimitry Andric << "mutable PredicateBitset AvailableFunctionFeatures;\n" 259*0fca6ea1SDimitry Andric << "PredicateBitset getAvailableFeatures() const {\n" 260*0fca6ea1SDimitry Andric << " return AvailableModuleFeatures | AvailableFunctionFeatures;\n" 261*0fca6ea1SDimitry Andric << "}\n" 262*0fca6ea1SDimitry Andric << "PredicateBitset\n" 263*0fca6ea1SDimitry Andric << "computeAvailableModuleFeatures(const " << getTarget().getName() 264*0fca6ea1SDimitry Andric << "Subtarget *Subtarget) const;\n" 265*0fca6ea1SDimitry Andric << "PredicateBitset\n" 266*0fca6ea1SDimitry Andric << "computeAvailableFunctionFeatures(const " << getTarget().getName() 267*0fca6ea1SDimitry Andric << "Subtarget *Subtarget,\n" 268*0fca6ea1SDimitry Andric << " const MachineFunction *MF) const;\n" 269*0fca6ea1SDimitry Andric << "void setupGeneratedPerFunctionState(MachineFunction &MF) override;\n" 270*0fca6ea1SDimitry Andric << "#endif // ifdef " << IfDefName << "\n"; 271*0fca6ea1SDimitry Andric } 272*0fca6ea1SDimitry Andric 273*0fca6ea1SDimitry Andric void GlobalISelMatchTableExecutorEmitter::emitPredicatesInit( 274*0fca6ea1SDimitry Andric raw_ostream &OS, StringRef IfDefName) { 275*0fca6ea1SDimitry Andric OS << "#ifdef " << IfDefName << "\n" 276*0fca6ea1SDimitry Andric << "AvailableModuleFeatures(computeAvailableModuleFeatures(&STI)),\n" 277*0fca6ea1SDimitry Andric << "AvailableFunctionFeatures()\n" 278*0fca6ea1SDimitry Andric << "#endif // ifdef " << IfDefName << "\n"; 279*0fca6ea1SDimitry Andric } 280