Home | History | Annotate | Line # | Download | only in TableGen
      1 //===- SubtargetFeatureInfo.cpp - Helpers for subtarget features ----------===//
      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 "SubtargetFeatureInfo.h"
     10 #include "Types.h"
     11 #include "llvm/Config/llvm-config.h"
     12 #include "llvm/TableGen/Error.h"
     13 #include "llvm/TableGen/Record.h"
     14 #include <map>
     15 
     16 using namespace llvm;
     17 
     18 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
     19 LLVM_DUMP_METHOD void SubtargetFeatureInfo::dump() const {
     20   errs() << getEnumName() << " " << Index << "\n" << *TheDef;
     21 }
     22 #endif
     23 
     24 std::vector<std::pair<Record *, SubtargetFeatureInfo>>
     25 SubtargetFeatureInfo::getAll(const RecordKeeper &Records) {
     26   std::vector<std::pair<Record *, SubtargetFeatureInfo>> SubtargetFeatures;
     27   std::vector<Record *> AllPredicates =
     28       Records.getAllDerivedDefinitions("Predicate");
     29   for (Record *Pred : AllPredicates) {
     30     // Ignore predicates that are not intended for the assembler.
     31     //
     32     // The "AssemblerMatcherPredicate" string should be promoted to an argument
     33     // if we re-use the machinery for non-assembler purposes in future.
     34     if (!Pred->getValueAsBit("AssemblerMatcherPredicate"))
     35       continue;
     36 
     37     if (Pred->getName().empty())
     38       PrintFatalError(Pred->getLoc(), "Predicate has no name!");
     39 
     40     // Ignore always true predicates.
     41     if (Pred->getValueAsString("CondString").empty())
     42       continue;
     43 
     44     SubtargetFeatures.emplace_back(
     45         Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size()));
     46   }
     47   return SubtargetFeatures;
     48 }
     49 
     50 void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(
     51     SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) {
     52   OS << "// Bits for subtarget features that participate in "
     53      << "instruction matching.\n";
     54   OS << "enum SubtargetFeatureBits : "
     55      << getMinimalTypeForRange(SubtargetFeatures.size()) << " {\n";
     56   for (const auto &SF : SubtargetFeatures) {
     57     const SubtargetFeatureInfo &SFI = SF.second;
     58     OS << "  " << SFI.getEnumBitName() << " = " << SFI.Index << ",\n";
     59   }
     60   OS << "};\n\n";
     61 }
     62 
     63 void SubtargetFeatureInfo::emitNameTable(
     64     SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) {
     65   // Need to sort the name table so that lookup by the log of the enum value
     66   // gives the proper name. More specifically, for a feature of value 1<<n,
     67   // SubtargetFeatureNames[n] should be the name of the feature.
     68   uint64_t IndexUB = 0;
     69   for (const auto &SF : SubtargetFeatures)
     70     if (IndexUB <= SF.second.Index)
     71       IndexUB = SF.second.Index+1;
     72 
     73   std::vector<std::string> Names;
     74   if (IndexUB > 0)
     75     Names.resize(IndexUB);
     76   for (const auto &SF : SubtargetFeatures)
     77     Names[SF.second.Index] = SF.second.getEnumName();
     78 
     79   OS << "static const char *SubtargetFeatureNames[] = {\n";
     80   for (uint64_t I = 0; I < IndexUB; ++I)
     81     OS << "  \"" << Names[I] << "\",\n";
     82 
     83   // A small number of targets have no predicates. Null terminate the array to
     84   // avoid a zero-length array.
     85   OS << "  nullptr\n"
     86      << "};\n\n";
     87 }
     88 
     89 void SubtargetFeatureInfo::emitComputeAvailableFeatures(
     90     StringRef TargetName, StringRef ClassName, StringRef FuncName,
     91     SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS,
     92     StringRef ExtraParams) {
     93   OS << "PredicateBitset " << TargetName << ClassName << "::\n"
     94      << FuncName << "(const " << TargetName << "Subtarget *Subtarget";
     95   if (!ExtraParams.empty())
     96     OS << ", " << ExtraParams;
     97   OS << ") const {\n";
     98   OS << "  PredicateBitset Features;\n";
     99   for (const auto &SF : SubtargetFeatures) {
    100     const SubtargetFeatureInfo &SFI = SF.second;
    101     StringRef CondStr = SFI.TheDef->getValueAsString("CondString");
    102     assert(!CondStr.empty() && "true predicate should have been filtered");
    103 
    104     OS << "  if (" << CondStr << ")\n";
    105     OS << "    Features.set(" << SFI.getEnumBitName() << ");\n";
    106   }
    107   OS << "  return Features;\n";
    108   OS << "}\n\n";
    109 }
    110 
    111 void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures(
    112     StringRef TargetName, StringRef ClassName, StringRef FuncName,
    113     SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) {
    114   OS << "FeatureBitset " << TargetName << ClassName << "::\n"
    115      << FuncName << "(const FeatureBitset &FB) const {\n";
    116   OS << "  FeatureBitset Features;\n";
    117   for (const auto &SF : SubtargetFeatures) {
    118     const SubtargetFeatureInfo &SFI = SF.second;
    119 
    120     OS << "  if (";
    121 
    122     const DagInit *D = SFI.TheDef->getValueAsDag("AssemblerCondDag");
    123     std::string CombineType = D->getOperator()->getAsString();
    124     if (CombineType != "any_of" && CombineType != "all_of")
    125       PrintFatalError(SFI.TheDef->getLoc(), "Invalid AssemblerCondDag!");
    126     if (D->getNumArgs() == 0)
    127       PrintFatalError(SFI.TheDef->getLoc(), "Invalid AssemblerCondDag!");
    128     bool IsOr = CombineType == "any_of";
    129 
    130     if (IsOr)
    131       OS << "(";
    132 
    133     ListSeparator LS(IsOr ? " || " : " && ");
    134     for (auto *Arg : D->getArgs()) {
    135       OS << LS;
    136       if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
    137         if (NotArg->getOperator()->getAsString() != "not" ||
    138             NotArg->getNumArgs() != 1)
    139           PrintFatalError(SFI.TheDef->getLoc(), "Invalid AssemblerCondDag!");
    140         Arg = NotArg->getArg(0);
    141         OS << "!";
    142       }
    143       if (!isa<DefInit>(Arg) ||
    144           !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature"))
    145         PrintFatalError(SFI.TheDef->getLoc(), "Invalid AssemblerCondDag!");
    146       OS << "FB[" << TargetName << "::" << Arg->getAsString() << "]";
    147     }
    148 
    149     if (IsOr)
    150       OS << ")";
    151 
    152     OS << ")\n";
    153     OS << "    Features.set(" << SFI.getEnumBitName() << ");\n";
    154   }
    155   OS << "  return Features;\n";
    156   OS << "}\n\n";
    157 }
    158