xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/FastISelEmitter.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric ///===- FastISelEmitter.cpp - Generate an instruction selector -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This tablegen backend emits code for use by the "fast" instruction
100b57cec5SDimitry Andric // selection algorithm. See the comments at the top of
110b57cec5SDimitry Andric // lib/CodeGen/SelectionDAG/FastISel.cpp for background.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric // This file scans through the target's tablegen instruction-info files
140b57cec5SDimitry Andric // and extracts instructions with obvious-looking patterns, and it emits
150b57cec5SDimitry Andric // code to look up these instructions by type and operator.
160b57cec5SDimitry Andric //
170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "CodeGenDAGPatterns.h"
2081ad6265SDimitry Andric #include "CodeGenInstruction.h"
21*06c3fb27SDimitry Andric #include "CodeGenRegisters.h"
22*06c3fb27SDimitry Andric #include "CodeGenTarget.h"
23*06c3fb27SDimitry Andric #include "InfoByHwMode.h"
240b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
250b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
260b57cec5SDimitry Andric #include "llvm/TableGen/Error.h"
270b57cec5SDimitry Andric #include "llvm/TableGen/Record.h"
280b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
290b57cec5SDimitry Andric #include <utility>
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric /// InstructionMemo - This class holds additional information about an
340b57cec5SDimitry Andric /// instruction needed to emit code for it.
350b57cec5SDimitry Andric ///
360b57cec5SDimitry Andric namespace {
370b57cec5SDimitry Andric struct InstructionMemo {
380b57cec5SDimitry Andric   std::string Name;
390b57cec5SDimitry Andric   const CodeGenRegisterClass *RC;
400b57cec5SDimitry Andric   std::string SubRegNo;
410b57cec5SDimitry Andric   std::vector<std::string> PhysRegs;
420b57cec5SDimitry Andric   std::string PredicateCheck;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   InstructionMemo(StringRef Name, const CodeGenRegisterClass *RC,
450b57cec5SDimitry Andric                   std::string SubRegNo, std::vector<std::string> PhysRegs,
460b57cec5SDimitry Andric                   std::string PredicateCheck)
470b57cec5SDimitry Andric       : Name(Name), RC(RC), SubRegNo(std::move(SubRegNo)),
480b57cec5SDimitry Andric         PhysRegs(std::move(PhysRegs)),
490b57cec5SDimitry Andric         PredicateCheck(std::move(PredicateCheck)) {}
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   // Make sure we do not copy InstructionMemo.
520b57cec5SDimitry Andric   InstructionMemo(const InstructionMemo &Other) = delete;
530b57cec5SDimitry Andric   InstructionMemo(InstructionMemo &&Other) = default;
540b57cec5SDimitry Andric };
550b57cec5SDimitry Andric } // End anonymous namespace
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric /// ImmPredicateSet - This uniques predicates (represented as a string) and
580b57cec5SDimitry Andric /// gives them unique (small) integer ID's that start at 0.
590b57cec5SDimitry Andric namespace {
600b57cec5SDimitry Andric class ImmPredicateSet {
610b57cec5SDimitry Andric   DenseMap<TreePattern *, unsigned> ImmIDs;
620b57cec5SDimitry Andric   std::vector<TreePredicateFn> PredsByName;
630b57cec5SDimitry Andric public:
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   unsigned getIDFor(TreePredicateFn Pred) {
660b57cec5SDimitry Andric     unsigned &Entry = ImmIDs[Pred.getOrigPatFragRecord()];
670b57cec5SDimitry Andric     if (Entry == 0) {
680b57cec5SDimitry Andric       PredsByName.push_back(Pred);
690b57cec5SDimitry Andric       Entry = PredsByName.size();
700b57cec5SDimitry Andric     }
710b57cec5SDimitry Andric     return Entry-1;
720b57cec5SDimitry Andric   }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   const TreePredicateFn &getPredicate(unsigned i) {
750b57cec5SDimitry Andric     assert(i < PredsByName.size());
760b57cec5SDimitry Andric     return PredsByName[i];
770b57cec5SDimitry Andric   }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   typedef std::vector<TreePredicateFn>::const_iterator iterator;
800b57cec5SDimitry Andric   iterator begin() const { return PredsByName.begin(); }
810b57cec5SDimitry Andric   iterator end() const { return PredsByName.end(); }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric };
840b57cec5SDimitry Andric } // End anonymous namespace
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric /// OperandsSignature - This class holds a description of a list of operand
870b57cec5SDimitry Andric /// types. It has utility methods for emitting text based on the operands.
880b57cec5SDimitry Andric ///
890b57cec5SDimitry Andric namespace {
900b57cec5SDimitry Andric struct OperandsSignature {
910b57cec5SDimitry Andric   class OpKind {
920b57cec5SDimitry Andric     enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 };
930b57cec5SDimitry Andric     char Repr;
940b57cec5SDimitry Andric   public:
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric     OpKind() : Repr(OK_Invalid) {}
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric     bool operator<(OpKind RHS) const { return Repr < RHS.Repr; }
990b57cec5SDimitry Andric     bool operator==(OpKind RHS) const { return Repr == RHS.Repr; }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric     static OpKind getReg() { OpKind K; K.Repr = OK_Reg; return K; }
1020b57cec5SDimitry Andric     static OpKind getFP()  { OpKind K; K.Repr = OK_FP; return K; }
1030b57cec5SDimitry Andric     static OpKind getImm(unsigned V) {
1040b57cec5SDimitry Andric       assert((unsigned)OK_Imm+V < 128 &&
1050b57cec5SDimitry Andric              "Too many integer predicates for the 'Repr' char");
1060b57cec5SDimitry Andric       OpKind K; K.Repr = OK_Imm+V; return K;
1070b57cec5SDimitry Andric     }
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric     bool isReg() const { return Repr == OK_Reg; }
1100b57cec5SDimitry Andric     bool isFP() const  { return Repr == OK_FP; }
1110b57cec5SDimitry Andric     bool isImm() const { return Repr >= OK_Imm; }
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric     unsigned getImmCode() const { assert(isImm()); return Repr-OK_Imm; }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric     void printManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,
1160b57cec5SDimitry Andric                              bool StripImmCodes) const {
1170b57cec5SDimitry Andric       if (isReg())
1180b57cec5SDimitry Andric         OS << 'r';
1190b57cec5SDimitry Andric       else if (isFP())
1200b57cec5SDimitry Andric         OS << 'f';
1210b57cec5SDimitry Andric       else {
1220b57cec5SDimitry Andric         OS << 'i';
1230b57cec5SDimitry Andric         if (!StripImmCodes)
1240b57cec5SDimitry Andric           if (unsigned Code = getImmCode())
1250b57cec5SDimitry Andric             OS << "_" << ImmPredicates.getPredicate(Code-1).getFnName();
1260b57cec5SDimitry Andric       }
1270b57cec5SDimitry Andric     }
1280b57cec5SDimitry Andric   };
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   SmallVector<OpKind, 3> Operands;
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   bool operator<(const OperandsSignature &O) const {
1340b57cec5SDimitry Andric     return Operands < O.Operands;
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric   bool operator==(const OperandsSignature &O) const {
1370b57cec5SDimitry Andric     return Operands == O.Operands;
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   bool empty() const { return Operands.empty(); }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   bool hasAnyImmediateCodes() const {
1430b57cec5SDimitry Andric     for (unsigned i = 0, e = Operands.size(); i != e; ++i)
1440b57cec5SDimitry Andric       if (Operands[i].isImm() && Operands[i].getImmCode() != 0)
1450b57cec5SDimitry Andric         return true;
1460b57cec5SDimitry Andric     return false;
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   /// getWithoutImmCodes - Return a copy of this with any immediate codes forced
1500b57cec5SDimitry Andric   /// to zero.
1510b57cec5SDimitry Andric   OperandsSignature getWithoutImmCodes() const {
1520b57cec5SDimitry Andric     OperandsSignature Result;
1530b57cec5SDimitry Andric     for (unsigned i = 0, e = Operands.size(); i != e; ++i)
1540b57cec5SDimitry Andric       if (!Operands[i].isImm())
1550b57cec5SDimitry Andric         Result.Operands.push_back(Operands[i]);
1560b57cec5SDimitry Andric       else
1570b57cec5SDimitry Andric         Result.Operands.push_back(OpKind::getImm(0));
1580b57cec5SDimitry Andric     return Result;
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   void emitImmediatePredicate(raw_ostream &OS, ImmPredicateSet &ImmPredicates) {
1620b57cec5SDimitry Andric     bool EmittedAnything = false;
1630b57cec5SDimitry Andric     for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
1640b57cec5SDimitry Andric       if (!Operands[i].isImm()) continue;
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric       unsigned Code = Operands[i].getImmCode();
1670b57cec5SDimitry Andric       if (Code == 0) continue;
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric       if (EmittedAnything)
1700b57cec5SDimitry Andric         OS << " &&\n        ";
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric       TreePredicateFn PredFn = ImmPredicates.getPredicate(Code-1);
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric       // Emit the type check.
1750b57cec5SDimitry Andric       TreePattern *TP = PredFn.getOrigPatFragRecord();
1760b57cec5SDimitry Andric       ValueTypeByHwMode VVT = TP->getTree(0)->getType(0);
1770b57cec5SDimitry Andric       assert(VVT.isSimple() &&
1780b57cec5SDimitry Andric              "Cannot use variable value types with fast isel");
1790b57cec5SDimitry Andric       OS << "VT == " << getEnumName(VVT.getSimple().SimpleTy) << " && ";
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric       OS << PredFn.getFnName() << "(imm" << i <<')';
1820b57cec5SDimitry Andric       EmittedAnything = true;
1830b57cec5SDimitry Andric     }
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   /// initialize - Examine the given pattern and initialize the contents
1870b57cec5SDimitry Andric   /// of the Operands array accordingly. Return true if all the operands
1880b57cec5SDimitry Andric   /// are supported, false otherwise.
1890b57cec5SDimitry Andric   ///
1900b57cec5SDimitry Andric   bool initialize(TreePatternNode *InstPatNode, const CodeGenTarget &Target,
1910b57cec5SDimitry Andric                   MVT::SimpleValueType VT,
1920b57cec5SDimitry Andric                   ImmPredicateSet &ImmediatePredicates,
1930b57cec5SDimitry Andric                   const CodeGenRegisterClass *OrigDstRC) {
1940b57cec5SDimitry Andric     if (InstPatNode->isLeaf())
1950b57cec5SDimitry Andric       return false;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric     if (InstPatNode->getOperator()->getName() == "imm") {
1980b57cec5SDimitry Andric       Operands.push_back(OpKind::getImm(0));
1990b57cec5SDimitry Andric       return true;
2000b57cec5SDimitry Andric     }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric     if (InstPatNode->getOperator()->getName() == "fpimm") {
2030b57cec5SDimitry Andric       Operands.push_back(OpKind::getFP());
2040b57cec5SDimitry Andric       return true;
2050b57cec5SDimitry Andric     }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric     const CodeGenRegisterClass *DstRC = nullptr;
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric     for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) {
2100b57cec5SDimitry Andric       TreePatternNode *Op = InstPatNode->getChild(i);
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric       // Handle imm operands specially.
2130b57cec5SDimitry Andric       if (!Op->isLeaf() && Op->getOperator()->getName() == "imm") {
2140b57cec5SDimitry Andric         unsigned PredNo = 0;
2150b57cec5SDimitry Andric         if (!Op->getPredicateCalls().empty()) {
2160b57cec5SDimitry Andric           TreePredicateFn PredFn = Op->getPredicateCalls()[0].Fn;
2170b57cec5SDimitry Andric           // If there is more than one predicate weighing in on this operand
2180b57cec5SDimitry Andric           // then we don't handle it.  This doesn't typically happen for
2190b57cec5SDimitry Andric           // immediates anyway.
2200b57cec5SDimitry Andric           if (Op->getPredicateCalls().size() > 1 ||
2210b57cec5SDimitry Andric               !PredFn.isImmediatePattern() || PredFn.usesOperands())
2220b57cec5SDimitry Andric             return false;
2230b57cec5SDimitry Andric           // Ignore any instruction with 'FastIselShouldIgnore', these are
2240b57cec5SDimitry Andric           // not needed and just bloat the fast instruction selector.  For
2250b57cec5SDimitry Andric           // example, X86 doesn't need to generate code to match ADD16ri8 since
2260b57cec5SDimitry Andric           // ADD16ri will do just fine.
2270b57cec5SDimitry Andric           Record *Rec = PredFn.getOrigPatFragRecord()->getRecord();
2280b57cec5SDimitry Andric           if (Rec->getValueAsBit("FastIselShouldIgnore"))
2290b57cec5SDimitry Andric             return false;
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric           PredNo = ImmediatePredicates.getIDFor(PredFn)+1;
2320b57cec5SDimitry Andric         }
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric         Operands.push_back(OpKind::getImm(PredNo));
2350b57cec5SDimitry Andric         continue;
2360b57cec5SDimitry Andric       }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric       // For now, filter out any operand with a predicate.
2400b57cec5SDimitry Andric       // For now, filter out any operand with multiple values.
2410b57cec5SDimitry Andric       if (!Op->getPredicateCalls().empty() || Op->getNumTypes() != 1)
2420b57cec5SDimitry Andric         return false;
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric       if (!Op->isLeaf()) {
2450b57cec5SDimitry Andric          if (Op->getOperator()->getName() == "fpimm") {
2460b57cec5SDimitry Andric           Operands.push_back(OpKind::getFP());
2470b57cec5SDimitry Andric           continue;
2480b57cec5SDimitry Andric         }
2490b57cec5SDimitry Andric         // For now, ignore other non-leaf nodes.
2500b57cec5SDimitry Andric         return false;
2510b57cec5SDimitry Andric       }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric       assert(Op->hasConcreteType(0) && "Type infererence not done?");
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric       // For now, all the operands must have the same type (if they aren't
2560b57cec5SDimitry Andric       // immediates).  Note that this causes us to reject variable sized shifts
2570b57cec5SDimitry Andric       // on X86.
2580b57cec5SDimitry Andric       if (Op->getSimpleType(0) != VT)
2590b57cec5SDimitry Andric         return false;
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric       DefInit *OpDI = dyn_cast<DefInit>(Op->getLeafValue());
2620b57cec5SDimitry Andric       if (!OpDI)
2630b57cec5SDimitry Andric         return false;
2640b57cec5SDimitry Andric       Record *OpLeafRec = OpDI->getDef();
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric       // For now, the only other thing we accept is register operands.
2670b57cec5SDimitry Andric       const CodeGenRegisterClass *RC = nullptr;
2680b57cec5SDimitry Andric       if (OpLeafRec->isSubClassOf("RegisterOperand"))
2690b57cec5SDimitry Andric         OpLeafRec = OpLeafRec->getValueAsDef("RegClass");
2700b57cec5SDimitry Andric       if (OpLeafRec->isSubClassOf("RegisterClass"))
2710b57cec5SDimitry Andric         RC = &Target.getRegisterClass(OpLeafRec);
2720b57cec5SDimitry Andric       else if (OpLeafRec->isSubClassOf("Register"))
2730b57cec5SDimitry Andric         RC = Target.getRegBank().getRegClassForRegister(OpLeafRec);
2740b57cec5SDimitry Andric       else if (OpLeafRec->isSubClassOf("ValueType")) {
2750b57cec5SDimitry Andric         RC = OrigDstRC;
2760b57cec5SDimitry Andric       } else
2770b57cec5SDimitry Andric         return false;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric       // For now, this needs to be a register class of some sort.
2800b57cec5SDimitry Andric       if (!RC)
2810b57cec5SDimitry Andric         return false;
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric       // For now, all the operands must have the same register class or be
2840b57cec5SDimitry Andric       // a strict subclass of the destination.
2850b57cec5SDimitry Andric       if (DstRC) {
2860b57cec5SDimitry Andric         if (DstRC != RC && !DstRC->hasSubClass(RC))
2870b57cec5SDimitry Andric           return false;
2880b57cec5SDimitry Andric       } else
2890b57cec5SDimitry Andric         DstRC = RC;
2900b57cec5SDimitry Andric       Operands.push_back(OpKind::getReg());
2910b57cec5SDimitry Andric     }
2920b57cec5SDimitry Andric     return true;
2930b57cec5SDimitry Andric   }
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   void PrintParameters(raw_ostream &OS) const {
296fe6060f1SDimitry Andric     ListSeparator LS;
2970b57cec5SDimitry Andric     for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
298fe6060f1SDimitry Andric       OS << LS;
2990b57cec5SDimitry Andric       if (Operands[i].isReg()) {
300fe6060f1SDimitry Andric         OS << "unsigned Op" << i;
3010b57cec5SDimitry Andric       } else if (Operands[i].isImm()) {
3020b57cec5SDimitry Andric         OS << "uint64_t imm" << i;
3030b57cec5SDimitry Andric       } else if (Operands[i].isFP()) {
3040b57cec5SDimitry Andric         OS << "const ConstantFP *f" << i;
3050b57cec5SDimitry Andric       } else {
3060b57cec5SDimitry Andric         llvm_unreachable("Unknown operand kind!");
3070b57cec5SDimitry Andric       }
3080b57cec5SDimitry Andric     }
3090b57cec5SDimitry Andric   }
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   void PrintArguments(raw_ostream &OS,
3120b57cec5SDimitry Andric                       const std::vector<std::string> &PR) const {
3130b57cec5SDimitry Andric     assert(PR.size() == Operands.size());
314fe6060f1SDimitry Andric     ListSeparator LS;
3150b57cec5SDimitry Andric     for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
3160b57cec5SDimitry Andric       if (PR[i] != "")
3170b57cec5SDimitry Andric         // Implicit physical register operand.
3180b57cec5SDimitry Andric         continue;
3190b57cec5SDimitry Andric 
320fe6060f1SDimitry Andric       OS << LS;
3210b57cec5SDimitry Andric       if (Operands[i].isReg()) {
322fe6060f1SDimitry Andric         OS << "Op" << i;
3230b57cec5SDimitry Andric       } else if (Operands[i].isImm()) {
3240b57cec5SDimitry Andric         OS << "imm" << i;
3250b57cec5SDimitry Andric       } else if (Operands[i].isFP()) {
3260b57cec5SDimitry Andric         OS << "f" << i;
3270b57cec5SDimitry Andric       } else {
3280b57cec5SDimitry Andric         llvm_unreachable("Unknown operand kind!");
3290b57cec5SDimitry Andric       }
3300b57cec5SDimitry Andric     }
3310b57cec5SDimitry Andric   }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   void PrintArguments(raw_ostream &OS) const {
334fe6060f1SDimitry Andric     ListSeparator LS;
3350b57cec5SDimitry Andric     for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
336fe6060f1SDimitry Andric       OS << LS;
3370b57cec5SDimitry Andric       if (Operands[i].isReg()) {
338fe6060f1SDimitry Andric         OS << "Op" << i;
3390b57cec5SDimitry Andric       } else if (Operands[i].isImm()) {
3400b57cec5SDimitry Andric         OS << "imm" << i;
3410b57cec5SDimitry Andric       } else if (Operands[i].isFP()) {
3420b57cec5SDimitry Andric         OS << "f" << i;
3430b57cec5SDimitry Andric       } else {
3440b57cec5SDimitry Andric         llvm_unreachable("Unknown operand kind!");
3450b57cec5SDimitry Andric       }
3460b57cec5SDimitry Andric     }
3470b57cec5SDimitry Andric   }
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   void PrintManglingSuffix(raw_ostream &OS, const std::vector<std::string> &PR,
3510b57cec5SDimitry Andric                            ImmPredicateSet &ImmPredicates,
3520b57cec5SDimitry Andric                            bool StripImmCodes = false) const {
3530b57cec5SDimitry Andric     for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
3540b57cec5SDimitry Andric       if (PR[i] != "")
3550b57cec5SDimitry Andric         // Implicit physical register operand. e.g. Instruction::Mul expect to
3560b57cec5SDimitry Andric         // select to a binary op. On x86, mul may take a single operand with
3570b57cec5SDimitry Andric         // the other operand being implicit. We must emit something that looks
3580b57cec5SDimitry Andric         // like a binary instruction except for the very inner fastEmitInst_*
3590b57cec5SDimitry Andric         // call.
3600b57cec5SDimitry Andric         continue;
3610b57cec5SDimitry Andric       Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);
3620b57cec5SDimitry Andric     }
3630b57cec5SDimitry Andric   }
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   void PrintManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,
3660b57cec5SDimitry Andric                            bool StripImmCodes = false) const {
3670b57cec5SDimitry Andric     for (unsigned i = 0, e = Operands.size(); i != e; ++i)
3680b57cec5SDimitry Andric       Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);
3690b57cec5SDimitry Andric   }
3700b57cec5SDimitry Andric };
3710b57cec5SDimitry Andric } // End anonymous namespace
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric namespace {
3740b57cec5SDimitry Andric class FastISelMap {
3750b57cec5SDimitry Andric   // A multimap is needed instead of a "plain" map because the key is
3760b57cec5SDimitry Andric   // the instruction's complexity (an int) and they are not unique.
3770b57cec5SDimitry Andric   typedef std::multimap<int, InstructionMemo> PredMap;
3780b57cec5SDimitry Andric   typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap;
3790b57cec5SDimitry Andric   typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap;
3800b57cec5SDimitry Andric   typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap;
3810b57cec5SDimitry Andric   typedef std::map<OperandsSignature, OpcodeTypeRetPredMap>
3820b57cec5SDimitry Andric             OperandsOpcodeTypeRetPredMap;
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   OperandsOpcodeTypeRetPredMap SimplePatterns;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   // This is used to check that there are no duplicate predicates
387bdd1243dSDimitry Andric   std::set<std::tuple<OperandsSignature, std::string, MVT::SimpleValueType,
388bdd1243dSDimitry Andric                       MVT::SimpleValueType, std::string>>
389bdd1243dSDimitry Andric       SimplePatternsCheck;
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   std::map<OperandsSignature, std::vector<OperandsSignature> >
3920b57cec5SDimitry Andric     SignaturesWithConstantForms;
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric   StringRef InstNS;
3950b57cec5SDimitry Andric   ImmPredicateSet ImmediatePredicates;
3960b57cec5SDimitry Andric public:
3970b57cec5SDimitry Andric   explicit FastISelMap(StringRef InstNS);
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric   void collectPatterns(CodeGenDAGPatterns &CGP);
4000b57cec5SDimitry Andric   void printImmediatePredicates(raw_ostream &OS);
4010b57cec5SDimitry Andric   void printFunctionDefinitions(raw_ostream &OS);
4020b57cec5SDimitry Andric private:
4030b57cec5SDimitry Andric   void emitInstructionCode(raw_ostream &OS,
4040b57cec5SDimitry Andric                            const OperandsSignature &Operands,
4050b57cec5SDimitry Andric                            const PredMap &PM,
4060b57cec5SDimitry Andric                            const std::string &RetVTName);
4070b57cec5SDimitry Andric };
4080b57cec5SDimitry Andric } // End anonymous namespace
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) {
4115ffd83dbSDimitry Andric   return std::string(CGP.getSDNodeInfo(Op).getEnumName());
4120b57cec5SDimitry Andric }
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric static std::string getLegalCName(std::string OpName) {
4150b57cec5SDimitry Andric   std::string::size_type pos = OpName.find("::");
4160b57cec5SDimitry Andric   if (pos != std::string::npos)
4170b57cec5SDimitry Andric     OpName.replace(pos, 2, "_");
4180b57cec5SDimitry Andric   return OpName;
4190b57cec5SDimitry Andric }
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric FastISelMap::FastISelMap(StringRef instns) : InstNS(instns) {}
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric static std::string PhyRegForNode(TreePatternNode *Op,
4240b57cec5SDimitry Andric                                  const CodeGenTarget &Target) {
4250b57cec5SDimitry Andric   std::string PhysReg;
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   if (!Op->isLeaf())
4280b57cec5SDimitry Andric     return PhysReg;
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   Record *OpLeafRec = cast<DefInit>(Op->getLeafValue())->getDef();
4310b57cec5SDimitry Andric   if (!OpLeafRec->isSubClassOf("Register"))
4320b57cec5SDimitry Andric     return PhysReg;
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   PhysReg += cast<StringInit>(OpLeafRec->getValue("Namespace")->getValue())
4350b57cec5SDimitry Andric                ->getValue();
4360b57cec5SDimitry Andric   PhysReg += "::";
4370b57cec5SDimitry Andric   PhysReg += Target.getRegBank().getReg(OpLeafRec)->getName();
4380b57cec5SDimitry Andric   return PhysReg;
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
4420b57cec5SDimitry Andric   const CodeGenTarget &Target = CGP.getTargetInfo();
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   // Scan through all the patterns and record the simple ones.
4450b57cec5SDimitry Andric   for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
4460b57cec5SDimitry Andric        E = CGP.ptm_end(); I != E; ++I) {
4470b57cec5SDimitry Andric     const PatternToMatch &Pattern = *I;
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric     // For now, just look at Instructions, so that we don't have to worry
4500b57cec5SDimitry Andric     // about emitting multiple instructions for a pattern.
4510b57cec5SDimitry Andric     TreePatternNode *Dst = Pattern.getDstPattern();
4520b57cec5SDimitry Andric     if (Dst->isLeaf()) continue;
4530b57cec5SDimitry Andric     Record *Op = Dst->getOperator();
4540b57cec5SDimitry Andric     if (!Op->isSubClassOf("Instruction"))
4550b57cec5SDimitry Andric       continue;
4560b57cec5SDimitry Andric     CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op);
4570b57cec5SDimitry Andric     if (II.Operands.empty())
4580b57cec5SDimitry Andric       continue;
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric     // Allow instructions to be marked as unavailable for FastISel for
4610b57cec5SDimitry Andric     // certain cases, i.e. an ISA has two 'and' instruction which differ
4620b57cec5SDimitry Andric     // by what registers they can use but are otherwise identical for
4630b57cec5SDimitry Andric     // codegen purposes.
4640b57cec5SDimitry Andric     if (II.FastISelShouldIgnore)
4650b57cec5SDimitry Andric       continue;
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric     // For now, ignore multi-instruction patterns.
4680b57cec5SDimitry Andric     bool MultiInsts = false;
4690b57cec5SDimitry Andric     for (unsigned i = 0, e = Dst->getNumChildren(); i != e; ++i) {
4700b57cec5SDimitry Andric       TreePatternNode *ChildOp = Dst->getChild(i);
4710b57cec5SDimitry Andric       if (ChildOp->isLeaf())
4720b57cec5SDimitry Andric         continue;
4730b57cec5SDimitry Andric       if (ChildOp->getOperator()->isSubClassOf("Instruction")) {
4740b57cec5SDimitry Andric         MultiInsts = true;
4750b57cec5SDimitry Andric         break;
4760b57cec5SDimitry Andric       }
4770b57cec5SDimitry Andric     }
4780b57cec5SDimitry Andric     if (MultiInsts)
4790b57cec5SDimitry Andric       continue;
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric     // For now, ignore instructions where the first operand is not an
4820b57cec5SDimitry Andric     // output register.
4830b57cec5SDimitry Andric     const CodeGenRegisterClass *DstRC = nullptr;
4840b57cec5SDimitry Andric     std::string SubRegNo;
4850b57cec5SDimitry Andric     if (Op->getName() != "EXTRACT_SUBREG") {
4860b57cec5SDimitry Andric       Record *Op0Rec = II.Operands[0].Rec;
4870b57cec5SDimitry Andric       if (Op0Rec->isSubClassOf("RegisterOperand"))
4880b57cec5SDimitry Andric         Op0Rec = Op0Rec->getValueAsDef("RegClass");
4890b57cec5SDimitry Andric       if (!Op0Rec->isSubClassOf("RegisterClass"))
4900b57cec5SDimitry Andric         continue;
4910b57cec5SDimitry Andric       DstRC = &Target.getRegisterClass(Op0Rec);
4920b57cec5SDimitry Andric       if (!DstRC)
4930b57cec5SDimitry Andric         continue;
4940b57cec5SDimitry Andric     } else {
4950b57cec5SDimitry Andric       // If this isn't a leaf, then continue since the register classes are
4960b57cec5SDimitry Andric       // a bit too complicated for now.
4970b57cec5SDimitry Andric       if (!Dst->getChild(1)->isLeaf()) continue;
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric       DefInit *SR = dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue());
5000b57cec5SDimitry Andric       if (SR)
5010b57cec5SDimitry Andric         SubRegNo = getQualifiedName(SR->getDef());
5020b57cec5SDimitry Andric       else
5030b57cec5SDimitry Andric         SubRegNo = Dst->getChild(1)->getLeafValue()->getAsString();
5040b57cec5SDimitry Andric     }
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric     // Inspect the pattern.
5070b57cec5SDimitry Andric     TreePatternNode *InstPatNode = Pattern.getSrcPattern();
5080b57cec5SDimitry Andric     if (!InstPatNode) continue;
5090b57cec5SDimitry Andric     if (InstPatNode->isLeaf()) continue;
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric     // Ignore multiple result nodes for now.
5120b57cec5SDimitry Andric     if (InstPatNode->getNumTypes() > 1) continue;
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric     Record *InstPatOp = InstPatNode->getOperator();
5150b57cec5SDimitry Andric     std::string OpcodeName = getOpcodeName(InstPatOp, CGP);
5160b57cec5SDimitry Andric     MVT::SimpleValueType RetVT = MVT::isVoid;
5170b57cec5SDimitry Andric     if (InstPatNode->getNumTypes()) RetVT = InstPatNode->getSimpleType(0);
5180b57cec5SDimitry Andric     MVT::SimpleValueType VT = RetVT;
5190b57cec5SDimitry Andric     if (InstPatNode->getNumChildren()) {
5200b57cec5SDimitry Andric       assert(InstPatNode->getChild(0)->getNumTypes() == 1);
5210b57cec5SDimitry Andric       VT = InstPatNode->getChild(0)->getSimpleType(0);
5220b57cec5SDimitry Andric     }
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric     // For now, filter out any instructions with predicates.
5250b57cec5SDimitry Andric     if (!InstPatNode->getPredicateCalls().empty())
5260b57cec5SDimitry Andric       continue;
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric     // Check all the operands.
5290b57cec5SDimitry Andric     OperandsSignature Operands;
5300b57cec5SDimitry Andric     if (!Operands.initialize(InstPatNode, Target, VT, ImmediatePredicates,
5310b57cec5SDimitry Andric                              DstRC))
5320b57cec5SDimitry Andric       continue;
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric     std::vector<std::string> PhysRegInputs;
5350b57cec5SDimitry Andric     if (InstPatNode->getOperator()->getName() == "imm" ||
5360b57cec5SDimitry Andric         InstPatNode->getOperator()->getName() == "fpimm")
5370b57cec5SDimitry Andric       PhysRegInputs.push_back("");
5380b57cec5SDimitry Andric     else {
5390b57cec5SDimitry Andric       // Compute the PhysRegs used by the given pattern, and check that
5400b57cec5SDimitry Andric       // the mapping from the src to dst patterns is simple.
5410b57cec5SDimitry Andric       bool FoundNonSimplePattern = false;
5420b57cec5SDimitry Andric       unsigned DstIndex = 0;
5430b57cec5SDimitry Andric       for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) {
5440b57cec5SDimitry Andric         std::string PhysReg = PhyRegForNode(InstPatNode->getChild(i), Target);
5450b57cec5SDimitry Andric         if (PhysReg.empty()) {
5460b57cec5SDimitry Andric           if (DstIndex >= Dst->getNumChildren() ||
5470b57cec5SDimitry Andric               Dst->getChild(DstIndex)->getName() !=
5480b57cec5SDimitry Andric               InstPatNode->getChild(i)->getName()) {
5490b57cec5SDimitry Andric             FoundNonSimplePattern = true;
5500b57cec5SDimitry Andric             break;
5510b57cec5SDimitry Andric           }
5520b57cec5SDimitry Andric           ++DstIndex;
5530b57cec5SDimitry Andric         }
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric         PhysRegInputs.push_back(PhysReg);
5560b57cec5SDimitry Andric       }
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric       if (Op->getName() != "EXTRACT_SUBREG" && DstIndex < Dst->getNumChildren())
5590b57cec5SDimitry Andric         FoundNonSimplePattern = true;
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric       if (FoundNonSimplePattern)
5620b57cec5SDimitry Andric         continue;
5630b57cec5SDimitry Andric     }
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric     // Check if the operands match one of the patterns handled by FastISel.
5660b57cec5SDimitry Andric     std::string ManglingSuffix;
5670b57cec5SDimitry Andric     raw_string_ostream SuffixOS(ManglingSuffix);
5680b57cec5SDimitry Andric     Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true);
5690b57cec5SDimitry Andric     if (!StringSwitch<bool>(ManglingSuffix)
5700b57cec5SDimitry Andric         .Cases("", "r", "rr", "ri", "i", "f", true)
5710b57cec5SDimitry Andric         .Default(false))
5720b57cec5SDimitry Andric       continue;
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric     // Get the predicate that guards this pattern.
5750b57cec5SDimitry Andric     std::string PredicateCheck = Pattern.getPredicateCheck();
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric     // Ok, we found a pattern that we can handle. Remember it.
5780b57cec5SDimitry Andric     InstructionMemo Memo(
5790b57cec5SDimitry Andric       Pattern.getDstPattern()->getOperator()->getName(),
5800b57cec5SDimitry Andric       DstRC,
5810b57cec5SDimitry Andric       SubRegNo,
5820b57cec5SDimitry Andric       PhysRegInputs,
5830b57cec5SDimitry Andric       PredicateCheck
5840b57cec5SDimitry Andric     );
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric     int complexity = Pattern.getPatternComplexity(CGP);
5870b57cec5SDimitry Andric 
588bdd1243dSDimitry Andric     auto inserted_simple_pattern = SimplePatternsCheck.insert(
589bdd1243dSDimitry Andric         std::make_tuple(Operands, OpcodeName, VT, RetVT, PredicateCheck));
590bdd1243dSDimitry Andric     if (!inserted_simple_pattern.second) {
5910b57cec5SDimitry Andric       PrintFatalError(Pattern.getSrcRecord()->getLoc(),
5920b57cec5SDimitry Andric                     "Duplicate predicate in FastISel table!");
5930b57cec5SDimitry Andric     }
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric     // Note: Instructions with the same complexity will appear in the order
5960b57cec5SDimitry Andric     // that they are encountered.
5970b57cec5SDimitry Andric     SimplePatterns[Operands][OpcodeName][VT][RetVT].emplace(complexity,
5980b57cec5SDimitry Andric                                                             std::move(Memo));
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric     // If any of the operands were immediates with predicates on them, strip
6010b57cec5SDimitry Andric     // them down to a signature that doesn't have predicates so that we can
6020b57cec5SDimitry Andric     // associate them with the stripped predicate version.
6030b57cec5SDimitry Andric     if (Operands.hasAnyImmediateCodes()) {
6040b57cec5SDimitry Andric       SignaturesWithConstantForms[Operands.getWithoutImmCodes()]
6050b57cec5SDimitry Andric         .push_back(Operands);
6060b57cec5SDimitry Andric     }
6070b57cec5SDimitry Andric   }
6080b57cec5SDimitry Andric }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric void FastISelMap::printImmediatePredicates(raw_ostream &OS) {
6110b57cec5SDimitry Andric   if (ImmediatePredicates.begin() == ImmediatePredicates.end())
6120b57cec5SDimitry Andric     return;
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   OS << "\n// FastEmit Immediate Predicate functions.\n";
615fe6060f1SDimitry Andric   for (auto ImmediatePredicate : ImmediatePredicates) {
616fe6060f1SDimitry Andric     OS << "static bool " << ImmediatePredicate.getFnName()
617fe6060f1SDimitry Andric        << "(int64_t Imm) {\n";
618fe6060f1SDimitry Andric     OS << ImmediatePredicate.getImmediatePredicateCode() << "\n}\n";
6190b57cec5SDimitry Andric   }
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   OS << "\n\n";
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric void FastISelMap::emitInstructionCode(raw_ostream &OS,
6250b57cec5SDimitry Andric                                       const OperandsSignature &Operands,
6260b57cec5SDimitry Andric                                       const PredMap &PM,
6270b57cec5SDimitry Andric                                       const std::string &RetVTName) {
6280b57cec5SDimitry Andric   // Emit code for each possible instruction. There may be
6290b57cec5SDimitry Andric   // multiple if there are subtarget concerns.  A reverse iterator
6300b57cec5SDimitry Andric   // is used to produce the ones with highest complexity first.
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   bool OneHadNoPredicate = false;
6330b57cec5SDimitry Andric   for (PredMap::const_reverse_iterator PI = PM.rbegin(), PE = PM.rend();
6340b57cec5SDimitry Andric        PI != PE; ++PI) {
6350b57cec5SDimitry Andric     const InstructionMemo &Memo = PI->second;
6360b57cec5SDimitry Andric     std::string PredicateCheck = Memo.PredicateCheck;
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric     if (PredicateCheck.empty()) {
6390b57cec5SDimitry Andric       assert(!OneHadNoPredicate &&
6400b57cec5SDimitry Andric              "Multiple instructions match and more than one had "
6410b57cec5SDimitry Andric              "no predicate!");
6420b57cec5SDimitry Andric       OneHadNoPredicate = true;
6430b57cec5SDimitry Andric     } else {
6440b57cec5SDimitry Andric       if (OneHadNoPredicate) {
6450b57cec5SDimitry Andric         PrintFatalError("Multiple instructions match and one with no "
6460b57cec5SDimitry Andric                         "predicate came before one with a predicate!  "
6470b57cec5SDimitry Andric                         "name:" + Memo.Name + "  predicate: " + PredicateCheck);
6480b57cec5SDimitry Andric       }
6490b57cec5SDimitry Andric       OS << "  if (" + PredicateCheck + ") {\n";
6500b57cec5SDimitry Andric       OS << "  ";
6510b57cec5SDimitry Andric     }
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric     for (unsigned i = 0; i < Memo.PhysRegs.size(); ++i) {
6540b57cec5SDimitry Andric       if (Memo.PhysRegs[i] != "")
655bdd1243dSDimitry Andric         OS << "  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, "
6560b57cec5SDimitry Andric            << "TII.get(TargetOpcode::COPY), " << Memo.PhysRegs[i]
6570b57cec5SDimitry Andric            << ").addReg(Op" << i << ");\n";
6580b57cec5SDimitry Andric     }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric     OS << "  return fastEmitInst_";
6610b57cec5SDimitry Andric     if (Memo.SubRegNo.empty()) {
6620b57cec5SDimitry Andric       Operands.PrintManglingSuffix(OS, Memo.PhysRegs, ImmediatePredicates,
6630b57cec5SDimitry Andric                                    true);
6640b57cec5SDimitry Andric       OS << "(" << InstNS << "::" << Memo.Name << ", ";
6650b57cec5SDimitry Andric       OS << "&" << InstNS << "::" << Memo.RC->getName() << "RegClass";
6660b57cec5SDimitry Andric       if (!Operands.empty())
6670b57cec5SDimitry Andric         OS << ", ";
6680b57cec5SDimitry Andric       Operands.PrintArguments(OS, Memo.PhysRegs);
6690b57cec5SDimitry Andric       OS << ");\n";
6700b57cec5SDimitry Andric     } else {
6710b57cec5SDimitry Andric       OS << "extractsubreg(" << RetVTName
672fe6060f1SDimitry Andric          << ", Op0, " << Memo.SubRegNo << ");\n";
6730b57cec5SDimitry Andric     }
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric     if (!PredicateCheck.empty()) {
6760b57cec5SDimitry Andric       OS << "  }\n";
6770b57cec5SDimitry Andric     }
6780b57cec5SDimitry Andric   }
6790b57cec5SDimitry Andric   // Return 0 if all of the possibilities had predicates but none
6800b57cec5SDimitry Andric   // were satisfied.
6810b57cec5SDimitry Andric   if (!OneHadNoPredicate)
6820b57cec5SDimitry Andric     OS << "  return 0;\n";
6830b57cec5SDimitry Andric   OS << "}\n";
6840b57cec5SDimitry Andric   OS << "\n";
6850b57cec5SDimitry Andric }
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
6890b57cec5SDimitry Andric   // Now emit code for all the patterns that we collected.
690fe6060f1SDimitry Andric   for (const auto &SimplePattern : SimplePatterns) {
691fe6060f1SDimitry Andric     const OperandsSignature &Operands = SimplePattern.first;
692fe6060f1SDimitry Andric     const OpcodeTypeRetPredMap &OTM = SimplePattern.second;
6930b57cec5SDimitry Andric 
694fe6060f1SDimitry Andric     for (const auto &I : OTM) {
695fe6060f1SDimitry Andric       const std::string &Opcode = I.first;
696fe6060f1SDimitry Andric       const TypeRetPredMap &TM = I.second;
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric       OS << "// FastEmit functions for " << Opcode << ".\n";
6990b57cec5SDimitry Andric       OS << "\n";
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric       // Emit one function for each opcode,type pair.
702fe6060f1SDimitry Andric       for (const auto &TI : TM) {
703fe6060f1SDimitry Andric         MVT::SimpleValueType VT = TI.first;
704fe6060f1SDimitry Andric         const RetPredMap &RM = TI.second;
7050b57cec5SDimitry Andric         if (RM.size() != 1) {
706fe6060f1SDimitry Andric           for (const auto &RI : RM) {
707fe6060f1SDimitry Andric             MVT::SimpleValueType RetVT = RI.first;
708fe6060f1SDimitry Andric             const PredMap &PM = RI.second;
7090b57cec5SDimitry Andric 
7105ffd83dbSDimitry Andric             OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"
7115ffd83dbSDimitry Andric                << getLegalCName(std::string(getName(VT))) << "_"
7125ffd83dbSDimitry Andric                << getLegalCName(std::string(getName(RetVT))) << "_";
7130b57cec5SDimitry Andric             Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7140b57cec5SDimitry Andric             OS << "(";
7150b57cec5SDimitry Andric             Operands.PrintParameters(OS);
7160b57cec5SDimitry Andric             OS << ") {\n";
7170b57cec5SDimitry Andric 
7185ffd83dbSDimitry Andric             emitInstructionCode(OS, Operands, PM, std::string(getName(RetVT)));
7190b57cec5SDimitry Andric           }
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric           // Emit one function for the type that demultiplexes on return type.
7225ffd83dbSDimitry Andric           OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"
7235ffd83dbSDimitry Andric              << getLegalCName(std::string(getName(VT))) << "_";
7240b57cec5SDimitry Andric           Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7250b57cec5SDimitry Andric           OS << "(MVT RetVT";
7260b57cec5SDimitry Andric           if (!Operands.empty())
7270b57cec5SDimitry Andric             OS << ", ";
7280b57cec5SDimitry Andric           Operands.PrintParameters(OS);
7290b57cec5SDimitry Andric           OS << ") {\nswitch (RetVT.SimpleTy) {\n";
730fe6060f1SDimitry Andric           for (const auto &RI : RM) {
731fe6060f1SDimitry Andric             MVT::SimpleValueType RetVT = RI.first;
7320b57cec5SDimitry Andric             OS << "  case " << getName(RetVT) << ": return fastEmit_"
7335ffd83dbSDimitry Andric                << getLegalCName(Opcode) << "_"
7345ffd83dbSDimitry Andric                << getLegalCName(std::string(getName(VT))) << "_"
7355ffd83dbSDimitry Andric                << getLegalCName(std::string(getName(RetVT))) << "_";
7360b57cec5SDimitry Andric             Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7370b57cec5SDimitry Andric             OS << "(";
7380b57cec5SDimitry Andric             Operands.PrintArguments(OS);
7390b57cec5SDimitry Andric             OS << ");\n";
7400b57cec5SDimitry Andric           }
7410b57cec5SDimitry Andric           OS << "  default: return 0;\n}\n}\n\n";
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric         } else {
7440b57cec5SDimitry Andric           // Non-variadic return type.
7455ffd83dbSDimitry Andric           OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"
7465ffd83dbSDimitry Andric              << getLegalCName(std::string(getName(VT))) << "_";
7470b57cec5SDimitry Andric           Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7480b57cec5SDimitry Andric           OS << "(MVT RetVT";
7490b57cec5SDimitry Andric           if (!Operands.empty())
7500b57cec5SDimitry Andric             OS << ", ";
7510b57cec5SDimitry Andric           Operands.PrintParameters(OS);
7520b57cec5SDimitry Andric           OS << ") {\n";
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric           OS << "  if (RetVT.SimpleTy != " << getName(RM.begin()->first)
7550b57cec5SDimitry Andric              << ")\n    return 0;\n";
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric           const PredMap &PM = RM.begin()->second;
7580b57cec5SDimitry Andric 
7590b57cec5SDimitry Andric           emitInstructionCode(OS, Operands, PM, "RetVT");
7600b57cec5SDimitry Andric         }
7610b57cec5SDimitry Andric       }
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric       // Emit one function for the opcode that demultiplexes based on the type.
7640b57cec5SDimitry Andric       OS << "unsigned fastEmit_"
7650b57cec5SDimitry Andric          << getLegalCName(Opcode) << "_";
7660b57cec5SDimitry Andric       Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7670b57cec5SDimitry Andric       OS << "(MVT VT, MVT RetVT";
7680b57cec5SDimitry Andric       if (!Operands.empty())
7690b57cec5SDimitry Andric         OS << ", ";
7700b57cec5SDimitry Andric       Operands.PrintParameters(OS);
7710b57cec5SDimitry Andric       OS << ") {\n";
7720b57cec5SDimitry Andric       OS << "  switch (VT.SimpleTy) {\n";
773fe6060f1SDimitry Andric       for (const auto &TI : TM) {
774fe6060f1SDimitry Andric         MVT::SimpleValueType VT = TI.first;
7755ffd83dbSDimitry Andric         std::string TypeName = std::string(getName(VT));
7760b57cec5SDimitry Andric         OS << "  case " << TypeName << ": return fastEmit_"
7770b57cec5SDimitry Andric            << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_";
7780b57cec5SDimitry Andric         Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7790b57cec5SDimitry Andric         OS << "(RetVT";
7800b57cec5SDimitry Andric         if (!Operands.empty())
7810b57cec5SDimitry Andric           OS << ", ";
7820b57cec5SDimitry Andric         Operands.PrintArguments(OS);
7830b57cec5SDimitry Andric         OS << ");\n";
7840b57cec5SDimitry Andric       }
7850b57cec5SDimitry Andric       OS << "  default: return 0;\n";
7860b57cec5SDimitry Andric       OS << "  }\n";
7870b57cec5SDimitry Andric       OS << "}\n";
7880b57cec5SDimitry Andric       OS << "\n";
7890b57cec5SDimitry Andric     }
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric     OS << "// Top-level FastEmit function.\n";
7920b57cec5SDimitry Andric     OS << "\n";
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric     // Emit one function for the operand signature that demultiplexes based
7950b57cec5SDimitry Andric     // on opcode and type.
7960b57cec5SDimitry Andric     OS << "unsigned fastEmit_";
7970b57cec5SDimitry Andric     Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7980b57cec5SDimitry Andric     OS << "(MVT VT, MVT RetVT, unsigned Opcode";
7990b57cec5SDimitry Andric     if (!Operands.empty())
8000b57cec5SDimitry Andric       OS << ", ";
8010b57cec5SDimitry Andric     Operands.PrintParameters(OS);
8020b57cec5SDimitry Andric     OS << ") ";
8030b57cec5SDimitry Andric     if (!Operands.hasAnyImmediateCodes())
8040b57cec5SDimitry Andric       OS << "override ";
8050b57cec5SDimitry Andric     OS << "{\n";
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric     // If there are any forms of this signature available that operate on
8080b57cec5SDimitry Andric     // constrained forms of the immediate (e.g., 32-bit sext immediate in a
8090b57cec5SDimitry Andric     // 64-bit operand), check them first.
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric     std::map<OperandsSignature, std::vector<OperandsSignature> >::iterator MI
8120b57cec5SDimitry Andric       = SignaturesWithConstantForms.find(Operands);
8130b57cec5SDimitry Andric     if (MI != SignaturesWithConstantForms.end()) {
8140b57cec5SDimitry Andric       // Unique any duplicates out of the list.
8150b57cec5SDimitry Andric       llvm::sort(MI->second);
8160b57cec5SDimitry Andric       MI->second.erase(std::unique(MI->second.begin(), MI->second.end()),
8170b57cec5SDimitry Andric                        MI->second.end());
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric       // Check each in order it was seen.  It would be nice to have a good
8200b57cec5SDimitry Andric       // relative ordering between them, but we're not going for optimality
8210b57cec5SDimitry Andric       // here.
8220b57cec5SDimitry Andric       for (unsigned i = 0, e = MI->second.size(); i != e; ++i) {
8230b57cec5SDimitry Andric         OS << "  if (";
8240b57cec5SDimitry Andric         MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates);
8250b57cec5SDimitry Andric         OS << ")\n    if (unsigned Reg = fastEmit_";
8260b57cec5SDimitry Andric         MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates);
8270b57cec5SDimitry Andric         OS << "(VT, RetVT, Opcode";
8280b57cec5SDimitry Andric         if (!MI->second[i].empty())
8290b57cec5SDimitry Andric           OS << ", ";
8300b57cec5SDimitry Andric         MI->second[i].PrintArguments(OS);
8310b57cec5SDimitry Andric         OS << "))\n      return Reg;\n\n";
8320b57cec5SDimitry Andric       }
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric       // Done with this, remove it.
8350b57cec5SDimitry Andric       SignaturesWithConstantForms.erase(MI);
8360b57cec5SDimitry Andric     }
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric     OS << "  switch (Opcode) {\n";
839fe6060f1SDimitry Andric     for (const auto &I : OTM) {
840fe6060f1SDimitry Andric       const std::string &Opcode = I.first;
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric       OS << "  case " << Opcode << ": return fastEmit_"
8430b57cec5SDimitry Andric          << getLegalCName(Opcode) << "_";
8440b57cec5SDimitry Andric       Operands.PrintManglingSuffix(OS, ImmediatePredicates);
8450b57cec5SDimitry Andric       OS << "(VT, RetVT";
8460b57cec5SDimitry Andric       if (!Operands.empty())
8470b57cec5SDimitry Andric         OS << ", ";
8480b57cec5SDimitry Andric       Operands.PrintArguments(OS);
8490b57cec5SDimitry Andric       OS << ");\n";
8500b57cec5SDimitry Andric     }
8510b57cec5SDimitry Andric     OS << "  default: return 0;\n";
8520b57cec5SDimitry Andric     OS << "  }\n";
8530b57cec5SDimitry Andric     OS << "}\n";
8540b57cec5SDimitry Andric     OS << "\n";
8550b57cec5SDimitry Andric   }
8560b57cec5SDimitry Andric 
8570b57cec5SDimitry Andric   // TODO: SignaturesWithConstantForms should be empty here.
8580b57cec5SDimitry Andric }
8590b57cec5SDimitry Andric 
860*06c3fb27SDimitry Andric static void EmitFastISel(RecordKeeper &RK, raw_ostream &OS) {
8610b57cec5SDimitry Andric   CodeGenDAGPatterns CGP(RK);
8620b57cec5SDimitry Andric   const CodeGenTarget &Target = CGP.getTargetInfo();
8630b57cec5SDimitry Andric   emitSourceFileHeader("\"Fast\" Instruction Selector for the " +
8640b57cec5SDimitry Andric                        Target.getName().str() + " target", OS);
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric   // Determine the target's namespace name.
8670b57cec5SDimitry Andric   StringRef InstNS = Target.getInstNamespace();
8680b57cec5SDimitry Andric   assert(!InstNS.empty() && "Can't determine target-specific namespace!");
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric   FastISelMap F(InstNS);
8710b57cec5SDimitry Andric   F.collectPatterns(CGP);
8720b57cec5SDimitry Andric   F.printImmediatePredicates(OS);
8730b57cec5SDimitry Andric   F.printFunctionDefinitions(OS);
8740b57cec5SDimitry Andric }
8750b57cec5SDimitry Andric 
876*06c3fb27SDimitry Andric static TableGen::Emitter::Opt X("gen-fast-isel", EmitFastISel,
877*06c3fb27SDimitry Andric                                 "Generate a \"fast\" instruction selector");
878