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