brintos

brintos / llvm-project-archived public Read only

0
0
Text · 28.5 KiB · d7f21f1 Raw
843 lines · cpp
1///===- FastISelEmitter.cpp - Generate an instruction selector ------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This tablegen backend emits code for use by the "fast" instruction10// selection algorithm. See the comments at the top of11// lib/CodeGen/SelectionDAG/FastISel.cpp for background.12//13// This file scans through the target's tablegen instruction-info files14// and extracts instructions with obvious-looking patterns, and it emits15// code to look up these instructions by type and operator.16//17//===----------------------------------------------------------------------===//18 19#include "Common/CodeGenDAGPatterns.h"20#include "Common/CodeGenInstruction.h"21#include "Common/CodeGenRegisters.h"22#include "Common/CodeGenTarget.h"23#include "Common/InfoByHwMode.h"24#include "llvm/ADT/StringSwitch.h"25#include "llvm/Support/ErrorHandling.h"26#include "llvm/TableGen/Error.h"27#include "llvm/TableGen/Record.h"28#include "llvm/TableGen/TableGenBackend.h"29#include <set>30#include <utility>31using namespace llvm;32 33/// InstructionMemo - This class holds additional information about an34/// instruction needed to emit code for it.35///36namespace {37struct InstructionMemo {38  StringRef Name;39  const CodeGenRegisterClass *RC;40  std::string SubRegNo;41  std::vector<std::string> PhysRegs;42  std::string PredicateCheck;43 44  InstructionMemo(StringRef Name, const CodeGenRegisterClass *RC,45                  std::string SubRegNo, std::vector<std::string> PhysRegs,46                  std::string PredicateCheck)47      : Name(Name), RC(RC), SubRegNo(std::move(SubRegNo)),48        PhysRegs(std::move(PhysRegs)),49        PredicateCheck(std::move(PredicateCheck)) {}50 51  // Make sure we do not copy InstructionMemo.52  InstructionMemo(const InstructionMemo &Other) = delete;53  InstructionMemo(InstructionMemo &&Other) = default;54};55 56/// ImmPredicateSet - This uniques predicates (represented as a string) and57/// gives them unique (small) integer ID's that start at 0.58class ImmPredicateSet {59  DenseMap<TreePattern *, unsigned> ImmIDs;60  std::vector<TreePredicateFn> PredsByName;61 62public:63  unsigned getIDFor(TreePredicateFn Pred) {64    unsigned &Entry = ImmIDs[Pred.getOrigPatFragRecord()];65    if (Entry == 0) {66      PredsByName.push_back(Pred);67      Entry = PredsByName.size();68    }69    return Entry - 1;70  }71 72  const TreePredicateFn &getPredicate(unsigned Idx) { return PredsByName[Idx]; }73 74  using iterator = std::vector<TreePredicateFn>::const_iterator;75  iterator begin() const { return PredsByName.begin(); }76  iterator end() const { return PredsByName.end(); }77};78 79/// OperandsSignature - This class holds a description of a list of operand80/// types. It has utility methods for emitting text based on the operands.81///82struct OperandsSignature {83  class OpKind {84    enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 };85    char Repr = OK_Invalid;86 87  public:88    OpKind() = default;89 90    bool operator<(OpKind RHS) const { return Repr < RHS.Repr; }91    bool operator==(OpKind RHS) const { return Repr == RHS.Repr; }92 93    static OpKind getReg() {94      OpKind K;95      K.Repr = OK_Reg;96      return K;97    }98    static OpKind getFP() {99      OpKind K;100      K.Repr = OK_FP;101      return K;102    }103    static OpKind getImm(unsigned V) {104      assert((unsigned)OK_Imm + V < 128 &&105             "Too many integer predicates for the 'Repr' char");106      OpKind K;107      K.Repr = OK_Imm + V;108      return K;109    }110 111    bool isReg() const { return Repr == OK_Reg; }112    bool isFP() const { return Repr == OK_FP; }113    bool isImm() const { return Repr >= OK_Imm; }114 115    unsigned getImmCode() const {116      assert(isImm());117      return Repr - OK_Imm;118    }119 120    void printManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,121                             bool StripImmCodes) const {122      if (isReg())123        OS << 'r';124      else if (isFP())125        OS << 'f';126      else {127        OS << 'i';128        if (!StripImmCodes)129          if (unsigned Code = getImmCode())130            OS << "_" << ImmPredicates.getPredicate(Code - 1).getFnName();131      }132    }133  };134 135  SmallVector<OpKind, 3> Operands;136 137  bool operator<(const OperandsSignature &O) const {138    return Operands < O.Operands;139  }140  bool operator==(const OperandsSignature &O) const {141    return Operands == O.Operands;142  }143 144  bool empty() const { return Operands.empty(); }145 146  bool hasAnyImmediateCodes() const {147    return llvm::any_of(Operands, [](OpKind Kind) {148      return Kind.isImm() && Kind.getImmCode() != 0;149    });150  }151 152  /// getWithoutImmCodes - Return a copy of this with any immediate codes forced153  /// to zero.154  OperandsSignature getWithoutImmCodes() const {155    OperandsSignature Result;156    Result.Operands.resize(Operands.size());157    llvm::transform(Operands, Result.Operands.begin(), [](OpKind Kind) {158      return Kind.isImm() ? OpKind::getImm(0) : Kind;159    });160    return Result;161  }162 163  void emitImmediatePredicate(raw_ostream &OS,164                              ImmPredicateSet &ImmPredicates) const {165    ListSeparator LS(" &&\n        ");166    for (auto [Idx, Opnd] : enumerate(Operands)) {167      if (!Opnd.isImm())168        continue;169 170      unsigned Code = Opnd.getImmCode();171      if (Code == 0)172        continue;173 174      TreePredicateFn PredFn = ImmPredicates.getPredicate(Code - 1);175 176      // Emit the type check.177      TreePattern *TP = PredFn.getOrigPatFragRecord();178      ValueTypeByHwMode VVT = TP->getTree(0)->getType(0);179      assert(VVT.isSimple() &&180             "Cannot use variable value types with fast isel");181      OS << LS << "VT == " << getEnumName(VVT.getSimple().SimpleTy) << " && ";182 183      OS << PredFn.getFnName() << "(imm" << Idx << ')';184    }185  }186 187  /// initialize - Examine the given pattern and initialize the contents188  /// of the Operands array accordingly. Return true if all the operands189  /// are supported, false otherwise.190  ///191  bool initialize(TreePatternNode &InstPatNode, const CodeGenTarget &Target,192                  MVT VT, ImmPredicateSet &ImmediatePredicates,193                  const CodeGenRegisterClass *OrigDstRC) {194    if (InstPatNode.isLeaf())195      return false;196 197    if (InstPatNode.getOperator()->getName() == "imm") {198      Operands.push_back(OpKind::getImm(0));199      return true;200    }201 202    if (InstPatNode.getOperator()->getName() == "fpimm") {203      Operands.push_back(OpKind::getFP());204      return true;205    }206 207    const CodeGenRegisterClass *DstRC = nullptr;208 209    for (const TreePatternNode &Op : InstPatNode.children()) {210      // Handle imm operands specially.211      if (!Op.isLeaf() && Op.getOperator()->getName() == "imm") {212        unsigned PredNo = 0;213        if (!Op.getPredicateCalls().empty()) {214          TreePredicateFn PredFn = Op.getPredicateCalls()[0].Fn;215          // If there is more than one predicate weighing in on this operand216          // then we don't handle it.  This doesn't typically happen for217          // immediates anyway.218          if (Op.getPredicateCalls().size() > 1 ||219              !PredFn.isImmediatePattern() || PredFn.usesOperands())220            return false;221          // Ignore any instruction with 'FastIselShouldIgnore', these are222          // not needed and just bloat the fast instruction selector.  For223          // example, X86 doesn't need to generate code to match ADD16ri8 since224          // ADD16ri will do just fine.225          const Record *Rec = PredFn.getOrigPatFragRecord()->getRecord();226          if (Rec->getValueAsBit("FastIselShouldIgnore"))227            return false;228 229          PredNo = ImmediatePredicates.getIDFor(PredFn) + 1;230        }231 232        Operands.push_back(OpKind::getImm(PredNo));233        continue;234      }235 236      // For now, filter out any operand with a predicate.237      // For now, filter out any operand with multiple values.238      if (!Op.getPredicateCalls().empty() || Op.getNumTypes() != 1)239        return false;240 241      if (!Op.isLeaf()) {242        if (Op.getOperator()->getName() == "fpimm") {243          Operands.push_back(OpKind::getFP());244          continue;245        }246        // For now, ignore other non-leaf nodes.247        return false;248      }249 250      assert(Op.hasConcreteType(0) && "Type infererence not done?");251 252      // For now, all the operands must have the same type (if they aren't253      // immediates).  Note that this causes us to reject variable sized shifts254      // on X86.255      if (Op.getSimpleType(0) != VT)256        return false;257 258      const DefInit *OpDI = dyn_cast<DefInit>(Op.getLeafValue());259      if (!OpDI)260        return false;261      const Record *OpLeafRec = OpDI->getDef();262 263      // For now, the only other thing we accept is register operands.264      const CodeGenRegisterClass *RC = nullptr;265      if (OpLeafRec->isSubClassOf("RegisterOperand"))266        OpLeafRec = OpLeafRec->getValueAsDef("RegClass");267      if (OpLeafRec->isSubClassOf("RegisterClass"))268        RC = &Target.getRegisterClass(OpLeafRec);269      else if (OpLeafRec->isSubClassOf("Register"))270        RC = Target.getRegBank().getRegClassForRegister(OpLeafRec);271      else if (OpLeafRec->isSubClassOf("ValueType"))272        RC = OrigDstRC;273      else274        return false;275 276      // For now, this needs to be a register class of some sort.277      if (!RC)278        return false;279 280      // For now, all the operands must have the same register class or be281      // a strict subclass of the destination.282      if (DstRC) {283        if (DstRC != RC && !DstRC->hasSubClass(RC))284          return false;285      } else {286        DstRC = RC;287      }288      Operands.push_back(OpKind::getReg());289    }290    return true;291  }292 293  void PrintParameters(raw_ostream &OS) const {294    ListSeparator LS;295    for (auto [Idx, Opnd] : enumerate(Operands)) {296      OS << LS;297      if (Opnd.isReg())298        OS << "Register Op" << Idx;299      else if (Opnd.isImm())300        OS << "uint64_t imm" << Idx;301      else if (Opnd.isFP())302        OS << "const ConstantFP *f" << Idx;303      else304        llvm_unreachable("Unknown operand kind!");305    }306  }307 308  void PrintArguments(raw_ostream &OS, ArrayRef<std::string> PhyRegs) const {309    ListSeparator LS;310    for (auto [Idx, Opnd, PhyReg] : enumerate(Operands, PhyRegs)) {311      if (!PhyReg.empty()) {312        // Implicit physical register operand.313        continue;314      }315 316      OS << LS;317      if (Opnd.isReg())318        OS << "Op" << Idx;319      else if (Opnd.isImm())320        OS << "imm" << Idx;321      else if (Opnd.isFP())322        OS << "f" << Idx;323      else324        llvm_unreachable("Unknown operand kind!");325    }326  }327 328  void PrintArguments(raw_ostream &OS) const {329    ListSeparator LS;330    for (auto [Idx, Opnd] : enumerate(Operands)) {331      OS << LS;332      if (Opnd.isReg())333        OS << "Op" << Idx;334      else if (Opnd.isImm())335        OS << "imm" << Idx;336      else if (Opnd.isFP())337        OS << "f" << Idx;338      else339        llvm_unreachable("Unknown operand kind!");340    }341  }342 343  void PrintManglingSuffix(raw_ostream &OS, ArrayRef<std::string> PhyRegs,344                           ImmPredicateSet &ImmPredicates,345                           bool StripImmCodes = false) const {346    for (auto [PhyReg, Opnd] : zip_equal(PhyRegs, Operands)) {347      if (!PhyReg.empty()) {348        // Implicit physical register operand. e.g. Instruction::Mul expect to349        // select to a binary op. On x86, mul may take a single operand with350        // the other operand being implicit. We must emit something that looks351        // like a binary instruction except for the very inner fastEmitInst_*352        // call.353        continue;354      }355      Opnd.printManglingSuffix(OS, ImmPredicates, StripImmCodes);356    }357  }358 359  void PrintManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,360                           bool StripImmCodes = false) const {361    for (OpKind Opnd : Operands)362      Opnd.printManglingSuffix(OS, ImmPredicates, StripImmCodes);363  }364};365 366class FastISelMap {367  // A multimap is needed instead of a "plain" map because the key is368  // the instruction's complexity (an int) and they are not unique.369  using PredMap = std::multimap<int, InstructionMemo>;370  using RetPredMap = std::map<MVT, PredMap>;371  using TypeRetPredMap = std::map<MVT, RetPredMap>;372  using OpcodeTypeRetPredMap = std::map<StringRef, TypeRetPredMap>;373  using OperandsOpcodeTypeRetPredMap =374      std::map<OperandsSignature, OpcodeTypeRetPredMap>;375 376  OperandsOpcodeTypeRetPredMap SimplePatterns;377 378  // This is used to check that there are no duplicate predicates379  std::set<std::tuple<OperandsSignature, StringRef, MVT, MVT, std::string>>380      SimplePatternsCheck;381 382  std::map<OperandsSignature, std::vector<OperandsSignature>>383      SignaturesWithConstantForms;384 385  StringRef InstNS;386  ImmPredicateSet ImmediatePredicates;387 388public:389  explicit FastISelMap(StringRef InstNS);390 391  void collectPatterns(const CodeGenDAGPatterns &CGP);392  void printImmediatePredicates(raw_ostream &OS);393  void printFunctionDefinitions(raw_ostream &OS);394 395private:396  void emitInstructionCode(raw_ostream &OS, const OperandsSignature &Operands,397                           const PredMap &PM, StringRef RetVTName);398};399} // End anonymous namespace400 401static std::string getLegalCName(StringRef OpName) {402  std::string CName = OpName.str();403  std::string::size_type Pos = CName.find("::");404  if (Pos != std::string::npos)405    CName.replace(Pos, 2, "_");406  return CName;407}408 409FastISelMap::FastISelMap(StringRef instns) : InstNS(instns) {}410 411static std::string PhysRegForNode(const TreePatternNode &Op,412                                  const CodeGenTarget &Target) {413  std::string PhysReg;414 415  if (!Op.isLeaf())416    return PhysReg;417 418  const Record *OpLeafRec = cast<DefInit>(Op.getLeafValue())->getDef();419  if (!OpLeafRec->isSubClassOf("Register"))420    return PhysReg;421 422  PhysReg += cast<StringInit>(OpLeafRec->getValue("Namespace")->getValue())423                 ->getValue();424  PhysReg += "::";425  PhysReg += Target.getRegBank().getReg(OpLeafRec)->getName();426  return PhysReg;427}428 429void FastISelMap::collectPatterns(const CodeGenDAGPatterns &CGP) {430  const CodeGenTarget &Target = CGP.getTargetInfo();431 432  // Scan through all the patterns and record the simple ones.433  for (const PatternToMatch &Pattern : CGP.ptms()) {434    // For now, just look at Instructions, so that we don't have to worry435    // about emitting multiple instructions for a pattern.436    TreePatternNode &Dst = Pattern.getDstPattern();437    if (Dst.isLeaf())438      continue;439    const Record *Op = Dst.getOperator();440    if (!Op->isSubClassOf("Instruction"))441      continue;442    const CodeGenInstruction &Inst = CGP.getTargetInfo().getInstruction(Op);443    if (Inst.Operands.empty())444      continue;445 446    // Allow instructions to be marked as unavailable for FastISel for447    // certain cases, i.e. an ISA has two 'and' instruction which differ448    // by what registers they can use but are otherwise identical for449    // codegen purposes.450    if (Inst.FastISelShouldIgnore)451      continue;452 453    // For now, ignore multi-instruction patterns.454    bool MultiInsts = false;455    for (const TreePatternNode &ChildOp : Dst.children()) {456      if (ChildOp.isLeaf())457        continue;458      if (ChildOp.getOperator()->isSubClassOf("Instruction")) {459        MultiInsts = true;460        break;461      }462    }463    if (MultiInsts)464      continue;465 466    // For now, ignore instructions where the first operand is not an467    // output register.468    const CodeGenRegisterClass *DstRC = nullptr;469    std::string SubRegNo;470    if (Op->getName() != "EXTRACT_SUBREG") {471      const Record *Op0Rec = Inst.Operands[0].Rec;472      if (Op0Rec->isSubClassOf("RegisterOperand"))473        Op0Rec = Op0Rec->getValueAsDef("RegClass");474      if (!Op0Rec->isSubClassOf("RegisterClass"))475        continue;476      DstRC = &Target.getRegisterClass(Op0Rec);477      if (!DstRC)478        continue;479    } else {480      // If this isn't a leaf, then continue since the register classes are481      // a bit too complicated for now.482      if (!Dst.getChild(1).isLeaf())483        continue;484 485      const DefInit *SR = dyn_cast<DefInit>(Dst.getChild(1).getLeafValue());486      if (SR)487        SubRegNo = getQualifiedName(SR->getDef());488      else489        SubRegNo = Dst.getChild(1).getLeafValue()->getAsString();490    }491 492    // Inspect the pattern.493    TreePatternNode &InstPatNode = Pattern.getSrcPattern();494    if (InstPatNode.isLeaf())495      continue;496 497    // Ignore multiple result nodes for now.498    if (InstPatNode.getNumTypes() > 1)499      continue;500 501    const Record *InstPatOp = InstPatNode.getOperator();502    StringRef OpcodeName = CGP.getSDNodeInfo(InstPatOp).getEnumName();503    MVT RetVT = MVT::isVoid;504    if (InstPatNode.getNumTypes())505      RetVT = InstPatNode.getSimpleType(0);506    MVT VT = RetVT;507    if (InstPatNode.getNumChildren()) {508      assert(InstPatNode.getChild(0).getNumTypes() == 1);509      VT = InstPatNode.getChild(0).getSimpleType(0);510    }511 512    // For now, filter out any instructions with predicates.513    if (!InstPatNode.getPredicateCalls().empty())514      continue;515 516    // Check all the operands.517    OperandsSignature Operands;518    if (!Operands.initialize(InstPatNode, Target, VT, ImmediatePredicates,519                             DstRC))520      continue;521 522    std::vector<std::string> PhysRegInputs;523    if (InstPatNode.getOperator()->getName() == "imm" ||524        InstPatNode.getOperator()->getName() == "fpimm")525      PhysRegInputs.push_back("");526    else {527      // Compute the PhysRegs used by the given pattern, and check that528      // the mapping from the src to dst patterns is simple.529      bool FoundNonSimplePattern = false;530      unsigned DstIndex = 0;531      for (const TreePatternNode &SrcChild : InstPatNode.children()) {532        std::string PhysReg = PhysRegForNode(SrcChild, Target);533        if (PhysReg.empty()) {534          if (DstIndex >= Dst.getNumChildren() ||535              Dst.getChild(DstIndex).getName() != SrcChild.getName()) {536            FoundNonSimplePattern = true;537            break;538          }539          ++DstIndex;540        }541 542        PhysRegInputs.push_back(std::move(PhysReg));543      }544 545      if (Op->getName() != "EXTRACT_SUBREG" && DstIndex < Dst.getNumChildren())546        FoundNonSimplePattern = true;547 548      if (FoundNonSimplePattern)549        continue;550    }551 552    // Check if the operands match one of the patterns handled by FastISel.553    std::string ManglingSuffix;554    raw_string_ostream SuffixOS(ManglingSuffix);555    Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true);556    if (!StringSwitch<bool>(ManglingSuffix)557             .Cases({"", "r", "rr", "ri", "i", "f"}, true)558             .Default(false))559      continue;560 561    // Get the predicate that guards this pattern.562    std::string PredicateCheck = Pattern.getPredicateCheck();563 564    // Ok, we found a pattern that we can handle. Remember it.565    InstructionMemo Memo(Pattern.getDstPattern().getOperator()->getName(),566                         DstRC, std::move(SubRegNo), std::move(PhysRegInputs),567                         PredicateCheck);568 569    int Complexity = Pattern.getPatternComplexity(CGP);570 571    auto inserted_simple_pattern = SimplePatternsCheck.insert(572        {Operands, OpcodeName, VT, RetVT, PredicateCheck});573    if (!inserted_simple_pattern.second) {574      PrintFatalError(Pattern.getSrcRecord()->getLoc(),575                      "Duplicate predicate in FastISel table!");576    }577 578    // Note: Instructions with the same complexity will appear in the order579    // that they are encountered.580    SimplePatterns[Operands][OpcodeName][VT][RetVT].emplace(Complexity,581                                                            std::move(Memo));582 583    // If any of the operands were immediates with predicates on them, strip584    // them down to a signature that doesn't have predicates so that we can585    // associate them with the stripped predicate version.586    if (Operands.hasAnyImmediateCodes()) {587      SignaturesWithConstantForms[Operands.getWithoutImmCodes()].push_back(588          Operands);589    }590  }591}592 593void FastISelMap::printImmediatePredicates(raw_ostream &OS) {594  if (ImmediatePredicates.begin() == ImmediatePredicates.end())595    return;596 597  OS << "\n// FastEmit Immediate Predicate functions.\n";598  for (auto ImmediatePredicate : ImmediatePredicates) {599    OS << "static bool " << ImmediatePredicate.getFnName()600       << "(int64_t Imm) {\n";601    OS << ImmediatePredicate.getImmediatePredicateCode() << "\n}\n";602  }603 604  OS << "\n\n";605}606 607void FastISelMap::emitInstructionCode(raw_ostream &OS,608                                      const OperandsSignature &Operands,609                                      const PredMap &PM, StringRef RetVTName) {610  // Emit code for each possible instruction. There may be611  // multiple if there are subtarget concerns.  A reverse iterator612  // is used to produce the ones with highest complexity first.613 614  bool OneHadNoPredicate = false;615  for (const auto &[_, Memo] : reverse(PM)) {616    std::string PredicateCheck = Memo.PredicateCheck;617 618    if (PredicateCheck.empty()) {619      assert(!OneHadNoPredicate &&620             "Multiple instructions match and more than one had "621             "no predicate!");622      OneHadNoPredicate = true;623    } else {624      if (OneHadNoPredicate) {625        PrintFatalError("Multiple instructions match and one with no "626                        "predicate came before one with a predicate!  "627                        "name:" +628                        Memo.Name + "  predicate: " + PredicateCheck);629      }630      OS << "  if (" + PredicateCheck + ") {\n";631      OS << "  ";632    }633 634    for (auto [Idx, PhyReg] : enumerate(Memo.PhysRegs)) {635      if (!PhyReg.empty())636        OS << "  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, "637           << "TII.get(TargetOpcode::COPY), " << PhyReg << ").addReg(Op" << Idx638           << ");\n";639    }640 641    OS << "  return fastEmitInst_";642    if (Memo.SubRegNo.empty()) {643      Operands.PrintManglingSuffix(OS, Memo.PhysRegs, ImmediatePredicates,644                                   true);645      OS << "(" << InstNS << "::" << Memo.Name << ", ";646      OS << "&" << InstNS << "::" << Memo.RC->getName() << "RegClass";647      if (!Operands.empty())648        OS << ", ";649      Operands.PrintArguments(OS, Memo.PhysRegs);650      OS << ");\n";651    } else {652      OS << "extractsubreg(" << RetVTName << ", Op0, " << Memo.SubRegNo653         << ");\n";654    }655 656    if (!PredicateCheck.empty())657      OS << "  }\n";658  }659  // Return Register() if all of the possibilities had predicates but none660  // were satisfied.661  if (!OneHadNoPredicate)662    OS << "  return Register();\n";663  OS << "}\n";664  OS << "\n";665}666 667void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {668  // Now emit code for all the patterns that we collected.669  for (const auto &SimplePattern : SimplePatterns) {670    const OperandsSignature &Operands = SimplePattern.first;671    const OpcodeTypeRetPredMap &OTM = SimplePattern.second;672 673    for (const auto &[Opcode, TM] : OTM) {674      OS << "// FastEmit functions for " << Opcode << ".\n";675      OS << "\n";676 677      // Emit one function for each opcode,type pair.678      for (const auto &[VT, RM] : TM) {679        if (RM.size() != 1) {680          for (const auto &[RetVT, PM] : RM) {681            OS << "Register fastEmit_" << getLegalCName(Opcode) << "_"682               << getLegalCName(getEnumName(VT)) << "_"683               << getLegalCName(getEnumName(RetVT)) << "_";684            Operands.PrintManglingSuffix(OS, ImmediatePredicates);685            OS << "(";686            Operands.PrintParameters(OS);687            OS << ") {\n";688 689            emitInstructionCode(OS, Operands, PM, getEnumName(RetVT));690          }691 692          // Emit one function for the type that demultiplexes on return type.693          OS << "Register fastEmit_" << getLegalCName(Opcode) << "_"694             << getLegalCName(getEnumName(VT)) << "_";695          Operands.PrintManglingSuffix(OS, ImmediatePredicates);696          OS << "(MVT RetVT";697          if (!Operands.empty())698            OS << ", ";699          Operands.PrintParameters(OS);700          OS << ") {\nswitch (RetVT.SimpleTy) {\n";701          for (const auto &[RetVT, _] : RM) {702            OS << "  case " << getEnumName(RetVT) << ": return fastEmit_"703               << getLegalCName(Opcode) << "_" << getLegalCName(getEnumName(VT))704               << "_" << getLegalCName(getEnumName(RetVT)) << "_";705            Operands.PrintManglingSuffix(OS, ImmediatePredicates);706            OS << "(";707            Operands.PrintArguments(OS);708            OS << ");\n";709          }710          OS << "  default: return Register();\n}\n}\n\n";711 712        } else {713          // Non-variadic return type.714          OS << "Register fastEmit_" << getLegalCName(Opcode) << "_"715             << getLegalCName(getEnumName(VT)) << "_";716          Operands.PrintManglingSuffix(OS, ImmediatePredicates);717          OS << "(MVT RetVT";718          if (!Operands.empty())719            OS << ", ";720          Operands.PrintParameters(OS);721          OS << ") {\n";722 723          OS << "  if (RetVT.SimpleTy != " << getEnumName(RM.begin()->first)724             << ")\n    return Register();\n";725 726          const PredMap &PM = RM.begin()->second;727 728          emitInstructionCode(OS, Operands, PM, "RetVT");729        }730      }731 732      // Emit one function for the opcode that demultiplexes based on the type.733      OS << "Register fastEmit_" << getLegalCName(Opcode) << "_";734      Operands.PrintManglingSuffix(OS, ImmediatePredicates);735      OS << "(MVT VT, MVT RetVT";736      if (!Operands.empty())737        OS << ", ";738      Operands.PrintParameters(OS);739      OS << ") {\n";740      OS << "  switch (VT.SimpleTy) {\n";741      for (const auto &[VT, _] : TM) {742        StringRef TypeName = getEnumName(VT);743        OS << "  case " << TypeName << ": return fastEmit_"744           << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_";745        Operands.PrintManglingSuffix(OS, ImmediatePredicates);746        OS << "(RetVT";747        if (!Operands.empty())748          OS << ", ";749        Operands.PrintArguments(OS);750        OS << ");\n";751      }752      OS << "  default: return Register();\n";753      OS << "  }\n";754      OS << "}\n";755      OS << "\n";756    }757 758    OS << "// Top-level FastEmit function.\n";759    OS << "\n";760 761    // Emit one function for the operand signature that demultiplexes based762    // on opcode and type.763    OS << "Register fastEmit_";764    Operands.PrintManglingSuffix(OS, ImmediatePredicates);765    OS << "(MVT VT, MVT RetVT, unsigned Opcode";766    if (!Operands.empty())767      OS << ", ";768    Operands.PrintParameters(OS);769    OS << ") ";770    if (!Operands.hasAnyImmediateCodes())771      OS << "override ";772    OS << "{\n";773 774    // If there are any forms of this signature available that operate on775    // constrained forms of the immediate (e.g., 32-bit sext immediate in a776    // 64-bit operand), check them first.777 778    std::map<OperandsSignature, std::vector<OperandsSignature>>::iterator MI =779        SignaturesWithConstantForms.find(Operands);780    if (MI != SignaturesWithConstantForms.end()) {781      // Unique any duplicates out of the list.782      llvm::sort(MI->second);783      MI->second.erase(llvm::unique(MI->second), MI->second.end());784 785      // Check each in order it was seen.  It would be nice to have a good786      // relative ordering between them, but we're not going for optimality787      // here.788      for (const OperandsSignature &Sig : MI->second) {789        OS << "  if (";790        Sig.emitImmediatePredicate(OS, ImmediatePredicates);791        OS << ")\n    if (Register Reg = fastEmit_";792        Sig.PrintManglingSuffix(OS, ImmediatePredicates);793        OS << "(VT, RetVT, Opcode";794        if (!Sig.empty())795          OS << ", ";796        Sig.PrintArguments(OS);797        OS << "))\n      return Reg;\n\n";798      }799 800      // Done with this, remove it.801      SignaturesWithConstantForms.erase(MI);802    }803 804    OS << "  switch (Opcode) {\n";805    for (const auto &[Opcode, _] : OTM) {806      OS << "  case " << Opcode << ": return fastEmit_" << getLegalCName(Opcode)807         << "_";808      Operands.PrintManglingSuffix(OS, ImmediatePredicates);809      OS << "(VT, RetVT";810      if (!Operands.empty())811        OS << ", ";812      Operands.PrintArguments(OS);813      OS << ");\n";814    }815    OS << "  default: return Register();\n";816    OS << "  }\n";817    OS << "}\n";818    OS << "\n";819  }820 821  // TODO: SignaturesWithConstantForms should be empty here.822}823 824static void EmitFastISel(const RecordKeeper &RK, raw_ostream &OS) {825  const CodeGenDAGPatterns CGP(RK);826  const CodeGenTarget &Target = CGP.getTargetInfo();827  emitSourceFileHeader("\"Fast\" Instruction Selector for the " +828                           Target.getName().str() + " target",829                       OS);830 831  // Determine the target's namespace name.832  StringRef InstNS = Target.getInstNamespace();833  assert(!InstNS.empty() && "Can't determine target-specific namespace!");834 835  FastISelMap F(InstNS);836  F.collectPatterns(CGP);837  F.printImmediatePredicates(OS);838  F.printFunctionDefinitions(OS);839}840 841static TableGen::Emitter::Opt X("gen-fast-isel", EmitFastISel,842                                "Generate a \"fast\" instruction selector");843