1*0fca6ea1SDimitry 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
19*0fca6ea1SDimitry Andric #include "Common/CodeGenDAGPatterns.h"
20*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h"
21*0fca6ea1SDimitry Andric #include "Common/CodeGenRegisters.h"
22*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h"
23*0fca6ea1SDimitry Andric #include "Common/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"
295f757f3fSDimitry Andric #include <set>
300b57cec5SDimitry Andric #include <utility>
310b57cec5SDimitry Andric using namespace llvm;
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
InstructionMemo__anon3cd78fb00111::InstructionMemo440b57cec5SDimitry 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
64*0fca6ea1SDimitry Andric public:
getIDFor(TreePredicateFn Pred)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
getPredicate(unsigned i)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;
begin() const800b57cec5SDimitry Andric iterator begin() const { return PredsByName.begin(); }
end() const810b57cec5SDimitry Andric iterator end() const { return PredsByName.end(); }
820b57cec5SDimitry Andric };
830b57cec5SDimitry Andric } // End anonymous namespace
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric /// OperandsSignature - This class holds a description of a list of operand
860b57cec5SDimitry Andric /// types. It has utility methods for emitting text based on the operands.
870b57cec5SDimitry Andric ///
880b57cec5SDimitry Andric namespace {
890b57cec5SDimitry Andric struct OperandsSignature {
900b57cec5SDimitry Andric class OpKind {
910b57cec5SDimitry Andric enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 };
920b57cec5SDimitry Andric char Repr;
930b57cec5SDimitry Andric
94*0fca6ea1SDimitry Andric public:
OpKind()950b57cec5SDimitry Andric OpKind() : Repr(OK_Invalid) {}
960b57cec5SDimitry Andric
operator <(OpKind RHS) const970b57cec5SDimitry Andric bool operator<(OpKind RHS) const { return Repr < RHS.Repr; }
operator ==(OpKind RHS) const980b57cec5SDimitry Andric bool operator==(OpKind RHS) const { return Repr == RHS.Repr; }
990b57cec5SDimitry Andric
getReg()100*0fca6ea1SDimitry Andric static OpKind getReg() {
101*0fca6ea1SDimitry Andric OpKind K;
102*0fca6ea1SDimitry Andric K.Repr = OK_Reg;
103*0fca6ea1SDimitry Andric return K;
104*0fca6ea1SDimitry Andric }
getFP()105*0fca6ea1SDimitry Andric static OpKind getFP() {
106*0fca6ea1SDimitry Andric OpKind K;
107*0fca6ea1SDimitry Andric K.Repr = OK_FP;
108*0fca6ea1SDimitry Andric return K;
109*0fca6ea1SDimitry Andric }
getImm(unsigned V)1100b57cec5SDimitry Andric static OpKind getImm(unsigned V) {
1110b57cec5SDimitry Andric assert((unsigned)OK_Imm + V < 128 &&
1120b57cec5SDimitry Andric "Too many integer predicates for the 'Repr' char");
113*0fca6ea1SDimitry Andric OpKind K;
114*0fca6ea1SDimitry Andric K.Repr = OK_Imm + V;
115*0fca6ea1SDimitry Andric return K;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric
isReg() const1180b57cec5SDimitry Andric bool isReg() const { return Repr == OK_Reg; }
isFP() const1190b57cec5SDimitry Andric bool isFP() const { return Repr == OK_FP; }
isImm() const1200b57cec5SDimitry Andric bool isImm() const { return Repr >= OK_Imm; }
1210b57cec5SDimitry Andric
getImmCode() const122*0fca6ea1SDimitry Andric unsigned getImmCode() const {
123*0fca6ea1SDimitry Andric assert(isImm());
124*0fca6ea1SDimitry Andric return Repr - OK_Imm;
125*0fca6ea1SDimitry Andric }
1260b57cec5SDimitry Andric
printManglingSuffix(raw_ostream & OS,ImmPredicateSet & ImmPredicates,bool StripImmCodes) const1270b57cec5SDimitry Andric void printManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,
1280b57cec5SDimitry Andric bool StripImmCodes) const {
1290b57cec5SDimitry Andric if (isReg())
1300b57cec5SDimitry Andric OS << 'r';
1310b57cec5SDimitry Andric else if (isFP())
1320b57cec5SDimitry Andric OS << 'f';
1330b57cec5SDimitry Andric else {
1340b57cec5SDimitry Andric OS << 'i';
1350b57cec5SDimitry Andric if (!StripImmCodes)
1360b57cec5SDimitry Andric if (unsigned Code = getImmCode())
1370b57cec5SDimitry Andric OS << "_" << ImmPredicates.getPredicate(Code - 1).getFnName();
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric };
1410b57cec5SDimitry Andric
1420b57cec5SDimitry Andric SmallVector<OpKind, 3> Operands;
1430b57cec5SDimitry Andric
operator <__anon3cd78fb00311::OperandsSignature1440b57cec5SDimitry Andric bool operator<(const OperandsSignature &O) const {
1450b57cec5SDimitry Andric return Operands < O.Operands;
1460b57cec5SDimitry Andric }
operator ==__anon3cd78fb00311::OperandsSignature1470b57cec5SDimitry Andric bool operator==(const OperandsSignature &O) const {
1480b57cec5SDimitry Andric return Operands == O.Operands;
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric
empty__anon3cd78fb00311::OperandsSignature1510b57cec5SDimitry Andric bool empty() const { return Operands.empty(); }
1520b57cec5SDimitry Andric
hasAnyImmediateCodes__anon3cd78fb00311::OperandsSignature1530b57cec5SDimitry Andric bool hasAnyImmediateCodes() const {
1540b57cec5SDimitry Andric for (unsigned i = 0, e = Operands.size(); i != e; ++i)
1550b57cec5SDimitry Andric if (Operands[i].isImm() && Operands[i].getImmCode() != 0)
1560b57cec5SDimitry Andric return true;
1570b57cec5SDimitry Andric return false;
1580b57cec5SDimitry Andric }
1590b57cec5SDimitry Andric
1600b57cec5SDimitry Andric /// getWithoutImmCodes - Return a copy of this with any immediate codes forced
1610b57cec5SDimitry Andric /// to zero.
getWithoutImmCodes__anon3cd78fb00311::OperandsSignature1620b57cec5SDimitry Andric OperandsSignature getWithoutImmCodes() const {
1630b57cec5SDimitry Andric OperandsSignature Result;
1640b57cec5SDimitry Andric for (unsigned i = 0, e = Operands.size(); i != e; ++i)
1650b57cec5SDimitry Andric if (!Operands[i].isImm())
1660b57cec5SDimitry Andric Result.Operands.push_back(Operands[i]);
1670b57cec5SDimitry Andric else
1680b57cec5SDimitry Andric Result.Operands.push_back(OpKind::getImm(0));
1690b57cec5SDimitry Andric return Result;
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric
emitImmediatePredicate__anon3cd78fb00311::OperandsSignature1720b57cec5SDimitry Andric void emitImmediatePredicate(raw_ostream &OS, ImmPredicateSet &ImmPredicates) {
1730b57cec5SDimitry Andric bool EmittedAnything = false;
1740b57cec5SDimitry Andric for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
175*0fca6ea1SDimitry Andric if (!Operands[i].isImm())
176*0fca6ea1SDimitry Andric continue;
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric unsigned Code = Operands[i].getImmCode();
179*0fca6ea1SDimitry Andric if (Code == 0)
180*0fca6ea1SDimitry Andric continue;
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric if (EmittedAnything)
1830b57cec5SDimitry Andric OS << " &&\n ";
1840b57cec5SDimitry Andric
1850b57cec5SDimitry Andric TreePredicateFn PredFn = ImmPredicates.getPredicate(Code - 1);
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric // Emit the type check.
1880b57cec5SDimitry Andric TreePattern *TP = PredFn.getOrigPatFragRecord();
1890b57cec5SDimitry Andric ValueTypeByHwMode VVT = TP->getTree(0)->getType(0);
1900b57cec5SDimitry Andric assert(VVT.isSimple() &&
1910b57cec5SDimitry Andric "Cannot use variable value types with fast isel");
1920b57cec5SDimitry Andric OS << "VT == " << getEnumName(VVT.getSimple().SimpleTy) << " && ";
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andric OS << PredFn.getFnName() << "(imm" << i << ')';
1950b57cec5SDimitry Andric EmittedAnything = true;
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric
1990b57cec5SDimitry Andric /// initialize - Examine the given pattern and initialize the contents
2000b57cec5SDimitry Andric /// of the Operands array accordingly. Return true if all the operands
2010b57cec5SDimitry Andric /// are supported, false otherwise.
2020b57cec5SDimitry Andric ///
initialize__anon3cd78fb00311::OperandsSignature203*0fca6ea1SDimitry Andric bool initialize(TreePatternNode &InstPatNode, const CodeGenTarget &Target,
204*0fca6ea1SDimitry Andric MVT::SimpleValueType VT, ImmPredicateSet &ImmediatePredicates,
2050b57cec5SDimitry Andric const CodeGenRegisterClass *OrigDstRC) {
206*0fca6ea1SDimitry Andric if (InstPatNode.isLeaf())
2070b57cec5SDimitry Andric return false;
2080b57cec5SDimitry Andric
209*0fca6ea1SDimitry Andric if (InstPatNode.getOperator()->getName() == "imm") {
2100b57cec5SDimitry Andric Operands.push_back(OpKind::getImm(0));
2110b57cec5SDimitry Andric return true;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric
214*0fca6ea1SDimitry Andric if (InstPatNode.getOperator()->getName() == "fpimm") {
2150b57cec5SDimitry Andric Operands.push_back(OpKind::getFP());
2160b57cec5SDimitry Andric return true;
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric
2190b57cec5SDimitry Andric const CodeGenRegisterClass *DstRC = nullptr;
2200b57cec5SDimitry Andric
221*0fca6ea1SDimitry Andric for (unsigned i = 0, e = InstPatNode.getNumChildren(); i != e; ++i) {
222*0fca6ea1SDimitry Andric TreePatternNode &Op = InstPatNode.getChild(i);
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric // Handle imm operands specially.
225*0fca6ea1SDimitry Andric if (!Op.isLeaf() && Op.getOperator()->getName() == "imm") {
2260b57cec5SDimitry Andric unsigned PredNo = 0;
227*0fca6ea1SDimitry Andric if (!Op.getPredicateCalls().empty()) {
228*0fca6ea1SDimitry Andric TreePredicateFn PredFn = Op.getPredicateCalls()[0].Fn;
2290b57cec5SDimitry Andric // If there is more than one predicate weighing in on this operand
2300b57cec5SDimitry Andric // then we don't handle it. This doesn't typically happen for
2310b57cec5SDimitry Andric // immediates anyway.
232*0fca6ea1SDimitry Andric if (Op.getPredicateCalls().size() > 1 ||
2330b57cec5SDimitry Andric !PredFn.isImmediatePattern() || PredFn.usesOperands())
2340b57cec5SDimitry Andric return false;
2350b57cec5SDimitry Andric // Ignore any instruction with 'FastIselShouldIgnore', these are
2360b57cec5SDimitry Andric // not needed and just bloat the fast instruction selector. For
2370b57cec5SDimitry Andric // example, X86 doesn't need to generate code to match ADD16ri8 since
2380b57cec5SDimitry Andric // ADD16ri will do just fine.
2390b57cec5SDimitry Andric Record *Rec = PredFn.getOrigPatFragRecord()->getRecord();
2400b57cec5SDimitry Andric if (Rec->getValueAsBit("FastIselShouldIgnore"))
2410b57cec5SDimitry Andric return false;
2420b57cec5SDimitry Andric
2430b57cec5SDimitry Andric PredNo = ImmediatePredicates.getIDFor(PredFn) + 1;
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric Operands.push_back(OpKind::getImm(PredNo));
2470b57cec5SDimitry Andric continue;
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andric // For now, filter out any operand with a predicate.
2510b57cec5SDimitry Andric // For now, filter out any operand with multiple values.
252*0fca6ea1SDimitry Andric if (!Op.getPredicateCalls().empty() || Op.getNumTypes() != 1)
2530b57cec5SDimitry Andric return false;
2540b57cec5SDimitry Andric
255*0fca6ea1SDimitry Andric if (!Op.isLeaf()) {
256*0fca6ea1SDimitry Andric if (Op.getOperator()->getName() == "fpimm") {
2570b57cec5SDimitry Andric Operands.push_back(OpKind::getFP());
2580b57cec5SDimitry Andric continue;
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric // For now, ignore other non-leaf nodes.
2610b57cec5SDimitry Andric return false;
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric
264*0fca6ea1SDimitry Andric assert(Op.hasConcreteType(0) && "Type infererence not done?");
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric // For now, all the operands must have the same type (if they aren't
2670b57cec5SDimitry Andric // immediates). Note that this causes us to reject variable sized shifts
2680b57cec5SDimitry Andric // on X86.
269*0fca6ea1SDimitry Andric if (Op.getSimpleType(0) != VT)
2700b57cec5SDimitry Andric return false;
2710b57cec5SDimitry Andric
272*0fca6ea1SDimitry Andric DefInit *OpDI = dyn_cast<DefInit>(Op.getLeafValue());
2730b57cec5SDimitry Andric if (!OpDI)
2740b57cec5SDimitry Andric return false;
2750b57cec5SDimitry Andric Record *OpLeafRec = OpDI->getDef();
2760b57cec5SDimitry Andric
2770b57cec5SDimitry Andric // For now, the only other thing we accept is register operands.
2780b57cec5SDimitry Andric const CodeGenRegisterClass *RC = nullptr;
2790b57cec5SDimitry Andric if (OpLeafRec->isSubClassOf("RegisterOperand"))
2800b57cec5SDimitry Andric OpLeafRec = OpLeafRec->getValueAsDef("RegClass");
2810b57cec5SDimitry Andric if (OpLeafRec->isSubClassOf("RegisterClass"))
2820b57cec5SDimitry Andric RC = &Target.getRegisterClass(OpLeafRec);
2830b57cec5SDimitry Andric else if (OpLeafRec->isSubClassOf("Register"))
2840b57cec5SDimitry Andric RC = Target.getRegBank().getRegClassForRegister(OpLeafRec);
2850b57cec5SDimitry Andric else if (OpLeafRec->isSubClassOf("ValueType")) {
2860b57cec5SDimitry Andric RC = OrigDstRC;
2870b57cec5SDimitry Andric } else
2880b57cec5SDimitry Andric return false;
2890b57cec5SDimitry Andric
2900b57cec5SDimitry Andric // For now, this needs to be a register class of some sort.
2910b57cec5SDimitry Andric if (!RC)
2920b57cec5SDimitry Andric return false;
2930b57cec5SDimitry Andric
2940b57cec5SDimitry Andric // For now, all the operands must have the same register class or be
2950b57cec5SDimitry Andric // a strict subclass of the destination.
2960b57cec5SDimitry Andric if (DstRC) {
2970b57cec5SDimitry Andric if (DstRC != RC && !DstRC->hasSubClass(RC))
2980b57cec5SDimitry Andric return false;
2990b57cec5SDimitry Andric } else
3000b57cec5SDimitry Andric DstRC = RC;
3010b57cec5SDimitry Andric Operands.push_back(OpKind::getReg());
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric return true;
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric
PrintParameters__anon3cd78fb00311::OperandsSignature3060b57cec5SDimitry Andric void PrintParameters(raw_ostream &OS) const {
307fe6060f1SDimitry Andric ListSeparator LS;
3080b57cec5SDimitry Andric for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
309fe6060f1SDimitry Andric OS << LS;
3100b57cec5SDimitry Andric if (Operands[i].isReg()) {
311fe6060f1SDimitry Andric OS << "unsigned Op" << i;
3120b57cec5SDimitry Andric } else if (Operands[i].isImm()) {
3130b57cec5SDimitry Andric OS << "uint64_t imm" << i;
3140b57cec5SDimitry Andric } else if (Operands[i].isFP()) {
3150b57cec5SDimitry Andric OS << "const ConstantFP *f" << i;
3160b57cec5SDimitry Andric } else {
3170b57cec5SDimitry Andric llvm_unreachable("Unknown operand kind!");
3180b57cec5SDimitry Andric }
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric
PrintArguments__anon3cd78fb00311::OperandsSignature3220b57cec5SDimitry Andric void PrintArguments(raw_ostream &OS,
3230b57cec5SDimitry Andric const std::vector<std::string> &PR) const {
3240b57cec5SDimitry Andric assert(PR.size() == Operands.size());
325fe6060f1SDimitry Andric ListSeparator LS;
3260b57cec5SDimitry Andric for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
3270b57cec5SDimitry Andric if (PR[i] != "")
3280b57cec5SDimitry Andric // Implicit physical register operand.
3290b57cec5SDimitry Andric continue;
3300b57cec5SDimitry Andric
331fe6060f1SDimitry Andric OS << LS;
3320b57cec5SDimitry Andric if (Operands[i].isReg()) {
333fe6060f1SDimitry Andric OS << "Op" << i;
3340b57cec5SDimitry Andric } else if (Operands[i].isImm()) {
3350b57cec5SDimitry Andric OS << "imm" << i;
3360b57cec5SDimitry Andric } else if (Operands[i].isFP()) {
3370b57cec5SDimitry Andric OS << "f" << i;
3380b57cec5SDimitry Andric } else {
3390b57cec5SDimitry Andric llvm_unreachable("Unknown operand kind!");
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric
PrintArguments__anon3cd78fb00311::OperandsSignature3440b57cec5SDimitry Andric void PrintArguments(raw_ostream &OS) const {
345fe6060f1SDimitry Andric ListSeparator LS;
3460b57cec5SDimitry Andric for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
347fe6060f1SDimitry Andric OS << LS;
3480b57cec5SDimitry Andric if (Operands[i].isReg()) {
349fe6060f1SDimitry Andric OS << "Op" << i;
3500b57cec5SDimitry Andric } else if (Operands[i].isImm()) {
3510b57cec5SDimitry Andric OS << "imm" << i;
3520b57cec5SDimitry Andric } else if (Operands[i].isFP()) {
3530b57cec5SDimitry Andric OS << "f" << i;
3540b57cec5SDimitry Andric } else {
3550b57cec5SDimitry Andric llvm_unreachable("Unknown operand kind!");
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric }
3590b57cec5SDimitry Andric
PrintManglingSuffix__anon3cd78fb00311::OperandsSignature3600b57cec5SDimitry Andric void PrintManglingSuffix(raw_ostream &OS, const std::vector<std::string> &PR,
3610b57cec5SDimitry Andric ImmPredicateSet &ImmPredicates,
3620b57cec5SDimitry Andric bool StripImmCodes = false) const {
3630b57cec5SDimitry Andric for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
3640b57cec5SDimitry Andric if (PR[i] != "")
3650b57cec5SDimitry Andric // Implicit physical register operand. e.g. Instruction::Mul expect to
3660b57cec5SDimitry Andric // select to a binary op. On x86, mul may take a single operand with
3670b57cec5SDimitry Andric // the other operand being implicit. We must emit something that looks
3680b57cec5SDimitry Andric // like a binary instruction except for the very inner fastEmitInst_*
3690b57cec5SDimitry Andric // call.
3700b57cec5SDimitry Andric continue;
3710b57cec5SDimitry Andric Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric
PrintManglingSuffix__anon3cd78fb00311::OperandsSignature3750b57cec5SDimitry Andric void PrintManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,
3760b57cec5SDimitry Andric bool StripImmCodes = false) const {
3770b57cec5SDimitry Andric for (unsigned i = 0, e = Operands.size(); i != e; ++i)
3780b57cec5SDimitry Andric Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric };
3810b57cec5SDimitry Andric } // End anonymous namespace
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric namespace {
3840b57cec5SDimitry Andric class FastISelMap {
3850b57cec5SDimitry Andric // A multimap is needed instead of a "plain" map because the key is
3860b57cec5SDimitry Andric // the instruction's complexity (an int) and they are not unique.
3870b57cec5SDimitry Andric typedef std::multimap<int, InstructionMemo> PredMap;
3880b57cec5SDimitry Andric typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap;
3890b57cec5SDimitry Andric typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap;
3900b57cec5SDimitry Andric typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap;
3910b57cec5SDimitry Andric typedef std::map<OperandsSignature, OpcodeTypeRetPredMap>
3920b57cec5SDimitry Andric OperandsOpcodeTypeRetPredMap;
3930b57cec5SDimitry Andric
3940b57cec5SDimitry Andric OperandsOpcodeTypeRetPredMap SimplePatterns;
3950b57cec5SDimitry Andric
3960b57cec5SDimitry Andric // This is used to check that there are no duplicate predicates
397bdd1243dSDimitry Andric std::set<std::tuple<OperandsSignature, std::string, MVT::SimpleValueType,
398bdd1243dSDimitry Andric MVT::SimpleValueType, std::string>>
399bdd1243dSDimitry Andric SimplePatternsCheck;
4000b57cec5SDimitry Andric
4010b57cec5SDimitry Andric std::map<OperandsSignature, std::vector<OperandsSignature>>
4020b57cec5SDimitry Andric SignaturesWithConstantForms;
4030b57cec5SDimitry Andric
4040b57cec5SDimitry Andric StringRef InstNS;
4050b57cec5SDimitry Andric ImmPredicateSet ImmediatePredicates;
406*0fca6ea1SDimitry Andric
4070b57cec5SDimitry Andric public:
4080b57cec5SDimitry Andric explicit FastISelMap(StringRef InstNS);
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andric void collectPatterns(CodeGenDAGPatterns &CGP);
4110b57cec5SDimitry Andric void printImmediatePredicates(raw_ostream &OS);
4120b57cec5SDimitry Andric void printFunctionDefinitions(raw_ostream &OS);
413*0fca6ea1SDimitry Andric
4140b57cec5SDimitry Andric private:
415*0fca6ea1SDimitry Andric void emitInstructionCode(raw_ostream &OS, const OperandsSignature &Operands,
416*0fca6ea1SDimitry Andric const PredMap &PM, const std::string &RetVTName);
4170b57cec5SDimitry Andric };
4180b57cec5SDimitry Andric } // End anonymous namespace
4190b57cec5SDimitry Andric
getOpcodeName(Record * Op,CodeGenDAGPatterns & CGP)4200b57cec5SDimitry Andric static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) {
4215ffd83dbSDimitry Andric return std::string(CGP.getSDNodeInfo(Op).getEnumName());
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric
getLegalCName(std::string OpName)4240b57cec5SDimitry Andric static std::string getLegalCName(std::string OpName) {
4250b57cec5SDimitry Andric std::string::size_type pos = OpName.find("::");
4260b57cec5SDimitry Andric if (pos != std::string::npos)
4270b57cec5SDimitry Andric OpName.replace(pos, 2, "_");
4280b57cec5SDimitry Andric return OpName;
4290b57cec5SDimitry Andric }
4300b57cec5SDimitry Andric
FastISelMap(StringRef instns)4310b57cec5SDimitry Andric FastISelMap::FastISelMap(StringRef instns) : InstNS(instns) {}
4320b57cec5SDimitry Andric
PhyRegForNode(TreePatternNode & Op,const CodeGenTarget & Target)433*0fca6ea1SDimitry Andric static std::string PhyRegForNode(TreePatternNode &Op,
4340b57cec5SDimitry Andric const CodeGenTarget &Target) {
4350b57cec5SDimitry Andric std::string PhysReg;
4360b57cec5SDimitry Andric
437*0fca6ea1SDimitry Andric if (!Op.isLeaf())
4380b57cec5SDimitry Andric return PhysReg;
4390b57cec5SDimitry Andric
440*0fca6ea1SDimitry Andric Record *OpLeafRec = cast<DefInit>(Op.getLeafValue())->getDef();
4410b57cec5SDimitry Andric if (!OpLeafRec->isSubClassOf("Register"))
4420b57cec5SDimitry Andric return PhysReg;
4430b57cec5SDimitry Andric
4440b57cec5SDimitry Andric PhysReg += cast<StringInit>(OpLeafRec->getValue("Namespace")->getValue())
4450b57cec5SDimitry Andric ->getValue();
4460b57cec5SDimitry Andric PhysReg += "::";
4470b57cec5SDimitry Andric PhysReg += Target.getRegBank().getReg(OpLeafRec)->getName();
4480b57cec5SDimitry Andric return PhysReg;
4490b57cec5SDimitry Andric }
4500b57cec5SDimitry Andric
collectPatterns(CodeGenDAGPatterns & CGP)4510b57cec5SDimitry Andric void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
4520b57cec5SDimitry Andric const CodeGenTarget &Target = CGP.getTargetInfo();
4530b57cec5SDimitry Andric
4540b57cec5SDimitry Andric // Scan through all the patterns and record the simple ones.
455*0fca6ea1SDimitry Andric for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end();
456*0fca6ea1SDimitry Andric I != E; ++I) {
4570b57cec5SDimitry Andric const PatternToMatch &Pattern = *I;
4580b57cec5SDimitry Andric
4590b57cec5SDimitry Andric // For now, just look at Instructions, so that we don't have to worry
4600b57cec5SDimitry Andric // about emitting multiple instructions for a pattern.
461*0fca6ea1SDimitry Andric TreePatternNode &Dst = Pattern.getDstPattern();
462*0fca6ea1SDimitry Andric if (Dst.isLeaf())
463*0fca6ea1SDimitry Andric continue;
464*0fca6ea1SDimitry Andric Record *Op = Dst.getOperator();
4650b57cec5SDimitry Andric if (!Op->isSubClassOf("Instruction"))
4660b57cec5SDimitry Andric continue;
4670b57cec5SDimitry Andric CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op);
4680b57cec5SDimitry Andric if (II.Operands.empty())
4690b57cec5SDimitry Andric continue;
4700b57cec5SDimitry Andric
4710b57cec5SDimitry Andric // Allow instructions to be marked as unavailable for FastISel for
4720b57cec5SDimitry Andric // certain cases, i.e. an ISA has two 'and' instruction which differ
4730b57cec5SDimitry Andric // by what registers they can use but are otherwise identical for
4740b57cec5SDimitry Andric // codegen purposes.
4750b57cec5SDimitry Andric if (II.FastISelShouldIgnore)
4760b57cec5SDimitry Andric continue;
4770b57cec5SDimitry Andric
4780b57cec5SDimitry Andric // For now, ignore multi-instruction patterns.
4790b57cec5SDimitry Andric bool MultiInsts = false;
480*0fca6ea1SDimitry Andric for (unsigned i = 0, e = Dst.getNumChildren(); i != e; ++i) {
481*0fca6ea1SDimitry Andric TreePatternNode &ChildOp = Dst.getChild(i);
482*0fca6ea1SDimitry Andric if (ChildOp.isLeaf())
4830b57cec5SDimitry Andric continue;
484*0fca6ea1SDimitry Andric if (ChildOp.getOperator()->isSubClassOf("Instruction")) {
4850b57cec5SDimitry Andric MultiInsts = true;
4860b57cec5SDimitry Andric break;
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric if (MultiInsts)
4900b57cec5SDimitry Andric continue;
4910b57cec5SDimitry Andric
4920b57cec5SDimitry Andric // For now, ignore instructions where the first operand is not an
4930b57cec5SDimitry Andric // output register.
4940b57cec5SDimitry Andric const CodeGenRegisterClass *DstRC = nullptr;
4950b57cec5SDimitry Andric std::string SubRegNo;
4960b57cec5SDimitry Andric if (Op->getName() != "EXTRACT_SUBREG") {
4970b57cec5SDimitry Andric Record *Op0Rec = II.Operands[0].Rec;
4980b57cec5SDimitry Andric if (Op0Rec->isSubClassOf("RegisterOperand"))
4990b57cec5SDimitry Andric Op0Rec = Op0Rec->getValueAsDef("RegClass");
5000b57cec5SDimitry Andric if (!Op0Rec->isSubClassOf("RegisterClass"))
5010b57cec5SDimitry Andric continue;
5020b57cec5SDimitry Andric DstRC = &Target.getRegisterClass(Op0Rec);
5030b57cec5SDimitry Andric if (!DstRC)
5040b57cec5SDimitry Andric continue;
5050b57cec5SDimitry Andric } else {
5060b57cec5SDimitry Andric // If this isn't a leaf, then continue since the register classes are
5070b57cec5SDimitry Andric // a bit too complicated for now.
508*0fca6ea1SDimitry Andric if (!Dst.getChild(1).isLeaf())
509*0fca6ea1SDimitry Andric continue;
5100b57cec5SDimitry Andric
511*0fca6ea1SDimitry Andric DefInit *SR = dyn_cast<DefInit>(Dst.getChild(1).getLeafValue());
5120b57cec5SDimitry Andric if (SR)
5130b57cec5SDimitry Andric SubRegNo = getQualifiedName(SR->getDef());
5140b57cec5SDimitry Andric else
515*0fca6ea1SDimitry Andric SubRegNo = Dst.getChild(1).getLeafValue()->getAsString();
5160b57cec5SDimitry Andric }
5170b57cec5SDimitry Andric
5180b57cec5SDimitry Andric // Inspect the pattern.
519*0fca6ea1SDimitry Andric TreePatternNode &InstPatNode = Pattern.getSrcPattern();
520*0fca6ea1SDimitry Andric if (InstPatNode.isLeaf())
521*0fca6ea1SDimitry Andric continue;
5220b57cec5SDimitry Andric
5230b57cec5SDimitry Andric // Ignore multiple result nodes for now.
524*0fca6ea1SDimitry Andric if (InstPatNode.getNumTypes() > 1)
525*0fca6ea1SDimitry Andric continue;
5260b57cec5SDimitry Andric
527*0fca6ea1SDimitry Andric Record *InstPatOp = InstPatNode.getOperator();
5280b57cec5SDimitry Andric std::string OpcodeName = getOpcodeName(InstPatOp, CGP);
5290b57cec5SDimitry Andric MVT::SimpleValueType RetVT = MVT::isVoid;
530*0fca6ea1SDimitry Andric if (InstPatNode.getNumTypes())
531*0fca6ea1SDimitry Andric RetVT = InstPatNode.getSimpleType(0);
5320b57cec5SDimitry Andric MVT::SimpleValueType VT = RetVT;
533*0fca6ea1SDimitry Andric if (InstPatNode.getNumChildren()) {
534*0fca6ea1SDimitry Andric assert(InstPatNode.getChild(0).getNumTypes() == 1);
535*0fca6ea1SDimitry Andric VT = InstPatNode.getChild(0).getSimpleType(0);
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric
5380b57cec5SDimitry Andric // For now, filter out any instructions with predicates.
539*0fca6ea1SDimitry Andric if (!InstPatNode.getPredicateCalls().empty())
5400b57cec5SDimitry Andric continue;
5410b57cec5SDimitry Andric
5420b57cec5SDimitry Andric // Check all the operands.
5430b57cec5SDimitry Andric OperandsSignature Operands;
5440b57cec5SDimitry Andric if (!Operands.initialize(InstPatNode, Target, VT, ImmediatePredicates,
5450b57cec5SDimitry Andric DstRC))
5460b57cec5SDimitry Andric continue;
5470b57cec5SDimitry Andric
5480b57cec5SDimitry Andric std::vector<std::string> PhysRegInputs;
549*0fca6ea1SDimitry Andric if (InstPatNode.getOperator()->getName() == "imm" ||
550*0fca6ea1SDimitry Andric InstPatNode.getOperator()->getName() == "fpimm")
5510b57cec5SDimitry Andric PhysRegInputs.push_back("");
5520b57cec5SDimitry Andric else {
5530b57cec5SDimitry Andric // Compute the PhysRegs used by the given pattern, and check that
5540b57cec5SDimitry Andric // the mapping from the src to dst patterns is simple.
5550b57cec5SDimitry Andric bool FoundNonSimplePattern = false;
5560b57cec5SDimitry Andric unsigned DstIndex = 0;
557*0fca6ea1SDimitry Andric for (unsigned i = 0, e = InstPatNode.getNumChildren(); i != e; ++i) {
558*0fca6ea1SDimitry Andric std::string PhysReg = PhyRegForNode(InstPatNode.getChild(i), Target);
5590b57cec5SDimitry Andric if (PhysReg.empty()) {
560*0fca6ea1SDimitry Andric if (DstIndex >= Dst.getNumChildren() ||
561*0fca6ea1SDimitry Andric Dst.getChild(DstIndex).getName() !=
562*0fca6ea1SDimitry Andric InstPatNode.getChild(i).getName()) {
5630b57cec5SDimitry Andric FoundNonSimplePattern = true;
5640b57cec5SDimitry Andric break;
5650b57cec5SDimitry Andric }
5660b57cec5SDimitry Andric ++DstIndex;
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric
5690b57cec5SDimitry Andric PhysRegInputs.push_back(PhysReg);
5700b57cec5SDimitry Andric }
5710b57cec5SDimitry Andric
572*0fca6ea1SDimitry Andric if (Op->getName() != "EXTRACT_SUBREG" && DstIndex < Dst.getNumChildren())
5730b57cec5SDimitry Andric FoundNonSimplePattern = true;
5740b57cec5SDimitry Andric
5750b57cec5SDimitry Andric if (FoundNonSimplePattern)
5760b57cec5SDimitry Andric continue;
5770b57cec5SDimitry Andric }
5780b57cec5SDimitry Andric
5790b57cec5SDimitry Andric // Check if the operands match one of the patterns handled by FastISel.
5800b57cec5SDimitry Andric std::string ManglingSuffix;
5810b57cec5SDimitry Andric raw_string_ostream SuffixOS(ManglingSuffix);
5820b57cec5SDimitry Andric Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true);
5830b57cec5SDimitry Andric if (!StringSwitch<bool>(ManglingSuffix)
5840b57cec5SDimitry Andric .Cases("", "r", "rr", "ri", "i", "f", true)
5850b57cec5SDimitry Andric .Default(false))
5860b57cec5SDimitry Andric continue;
5870b57cec5SDimitry Andric
5880b57cec5SDimitry Andric // Get the predicate that guards this pattern.
5890b57cec5SDimitry Andric std::string PredicateCheck = Pattern.getPredicateCheck();
5900b57cec5SDimitry Andric
5910b57cec5SDimitry Andric // Ok, we found a pattern that we can handle. Remember it.
592*0fca6ea1SDimitry Andric InstructionMemo Memo(Pattern.getDstPattern().getOperator()->getName(),
593*0fca6ea1SDimitry Andric DstRC, SubRegNo, PhysRegInputs, PredicateCheck);
5940b57cec5SDimitry Andric
5950b57cec5SDimitry Andric int complexity = Pattern.getPatternComplexity(CGP);
5960b57cec5SDimitry Andric
597bdd1243dSDimitry Andric auto inserted_simple_pattern = SimplePatternsCheck.insert(
598*0fca6ea1SDimitry Andric std::tuple(Operands, OpcodeName, VT, RetVT, PredicateCheck));
599bdd1243dSDimitry Andric if (!inserted_simple_pattern.second) {
6000b57cec5SDimitry Andric PrintFatalError(Pattern.getSrcRecord()->getLoc(),
6010b57cec5SDimitry Andric "Duplicate predicate in FastISel table!");
6020b57cec5SDimitry Andric }
6030b57cec5SDimitry Andric
6040b57cec5SDimitry Andric // Note: Instructions with the same complexity will appear in the order
6050b57cec5SDimitry Andric // that they are encountered.
6060b57cec5SDimitry Andric SimplePatterns[Operands][OpcodeName][VT][RetVT].emplace(complexity,
6070b57cec5SDimitry Andric std::move(Memo));
6080b57cec5SDimitry Andric
6090b57cec5SDimitry Andric // If any of the operands were immediates with predicates on them, strip
6100b57cec5SDimitry Andric // them down to a signature that doesn't have predicates so that we can
6110b57cec5SDimitry Andric // associate them with the stripped predicate version.
6120b57cec5SDimitry Andric if (Operands.hasAnyImmediateCodes()) {
613*0fca6ea1SDimitry Andric SignaturesWithConstantForms[Operands.getWithoutImmCodes()].push_back(
614*0fca6ea1SDimitry Andric Operands);
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric }
6170b57cec5SDimitry Andric }
6180b57cec5SDimitry Andric
printImmediatePredicates(raw_ostream & OS)6190b57cec5SDimitry Andric void FastISelMap::printImmediatePredicates(raw_ostream &OS) {
6200b57cec5SDimitry Andric if (ImmediatePredicates.begin() == ImmediatePredicates.end())
6210b57cec5SDimitry Andric return;
6220b57cec5SDimitry Andric
6230b57cec5SDimitry Andric OS << "\n// FastEmit Immediate Predicate functions.\n";
624fe6060f1SDimitry Andric for (auto ImmediatePredicate : ImmediatePredicates) {
625fe6060f1SDimitry Andric OS << "static bool " << ImmediatePredicate.getFnName()
626fe6060f1SDimitry Andric << "(int64_t Imm) {\n";
627fe6060f1SDimitry Andric OS << ImmediatePredicate.getImmediatePredicateCode() << "\n}\n";
6280b57cec5SDimitry Andric }
6290b57cec5SDimitry Andric
6300b57cec5SDimitry Andric OS << "\n\n";
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric
emitInstructionCode(raw_ostream & OS,const OperandsSignature & Operands,const PredMap & PM,const std::string & RetVTName)6330b57cec5SDimitry Andric void FastISelMap::emitInstructionCode(raw_ostream &OS,
6340b57cec5SDimitry Andric const OperandsSignature &Operands,
6350b57cec5SDimitry Andric const PredMap &PM,
6360b57cec5SDimitry Andric const std::string &RetVTName) {
6370b57cec5SDimitry Andric // Emit code for each possible instruction. There may be
6380b57cec5SDimitry Andric // multiple if there are subtarget concerns. A reverse iterator
6390b57cec5SDimitry Andric // is used to produce the ones with highest complexity first.
6400b57cec5SDimitry Andric
6410b57cec5SDimitry Andric bool OneHadNoPredicate = false;
6420b57cec5SDimitry Andric for (PredMap::const_reverse_iterator PI = PM.rbegin(), PE = PM.rend();
6430b57cec5SDimitry Andric PI != PE; ++PI) {
6440b57cec5SDimitry Andric const InstructionMemo &Memo = PI->second;
6450b57cec5SDimitry Andric std::string PredicateCheck = Memo.PredicateCheck;
6460b57cec5SDimitry Andric
6470b57cec5SDimitry Andric if (PredicateCheck.empty()) {
6480b57cec5SDimitry Andric assert(!OneHadNoPredicate &&
6490b57cec5SDimitry Andric "Multiple instructions match and more than one had "
6500b57cec5SDimitry Andric "no predicate!");
6510b57cec5SDimitry Andric OneHadNoPredicate = true;
6520b57cec5SDimitry Andric } else {
6530b57cec5SDimitry Andric if (OneHadNoPredicate) {
6540b57cec5SDimitry Andric PrintFatalError("Multiple instructions match and one with no "
6550b57cec5SDimitry Andric "predicate came before one with a predicate! "
656*0fca6ea1SDimitry Andric "name:" +
657*0fca6ea1SDimitry Andric Memo.Name + " predicate: " + PredicateCheck);
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric OS << " if (" + PredicateCheck + ") {\n";
6600b57cec5SDimitry Andric OS << " ";
6610b57cec5SDimitry Andric }
6620b57cec5SDimitry Andric
6630b57cec5SDimitry Andric for (unsigned i = 0; i < Memo.PhysRegs.size(); ++i) {
6640b57cec5SDimitry Andric if (Memo.PhysRegs[i] != "")
665bdd1243dSDimitry Andric OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, "
6660b57cec5SDimitry Andric << "TII.get(TargetOpcode::COPY), " << Memo.PhysRegs[i]
6670b57cec5SDimitry Andric << ").addReg(Op" << i << ");\n";
6680b57cec5SDimitry Andric }
6690b57cec5SDimitry Andric
6700b57cec5SDimitry Andric OS << " return fastEmitInst_";
6710b57cec5SDimitry Andric if (Memo.SubRegNo.empty()) {
6720b57cec5SDimitry Andric Operands.PrintManglingSuffix(OS, Memo.PhysRegs, ImmediatePredicates,
6730b57cec5SDimitry Andric true);
6740b57cec5SDimitry Andric OS << "(" << InstNS << "::" << Memo.Name << ", ";
6750b57cec5SDimitry Andric OS << "&" << InstNS << "::" << Memo.RC->getName() << "RegClass";
6760b57cec5SDimitry Andric if (!Operands.empty())
6770b57cec5SDimitry Andric OS << ", ";
6780b57cec5SDimitry Andric Operands.PrintArguments(OS, Memo.PhysRegs);
6790b57cec5SDimitry Andric OS << ");\n";
6800b57cec5SDimitry Andric } else {
681*0fca6ea1SDimitry Andric OS << "extractsubreg(" << RetVTName << ", Op0, " << Memo.SubRegNo
682*0fca6ea1SDimitry Andric << ");\n";
6830b57cec5SDimitry Andric }
6840b57cec5SDimitry Andric
6850b57cec5SDimitry Andric if (!PredicateCheck.empty()) {
6860b57cec5SDimitry Andric OS << " }\n";
6870b57cec5SDimitry Andric }
6880b57cec5SDimitry Andric }
6890b57cec5SDimitry Andric // Return 0 if all of the possibilities had predicates but none
6900b57cec5SDimitry Andric // were satisfied.
6910b57cec5SDimitry Andric if (!OneHadNoPredicate)
6920b57cec5SDimitry Andric OS << " return 0;\n";
6930b57cec5SDimitry Andric OS << "}\n";
6940b57cec5SDimitry Andric OS << "\n";
6950b57cec5SDimitry Andric }
6960b57cec5SDimitry Andric
printFunctionDefinitions(raw_ostream & OS)6970b57cec5SDimitry Andric void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
6980b57cec5SDimitry Andric // Now emit code for all the patterns that we collected.
699fe6060f1SDimitry Andric for (const auto &SimplePattern : SimplePatterns) {
700fe6060f1SDimitry Andric const OperandsSignature &Operands = SimplePattern.first;
701fe6060f1SDimitry Andric const OpcodeTypeRetPredMap &OTM = SimplePattern.second;
7020b57cec5SDimitry Andric
703fe6060f1SDimitry Andric for (const auto &I : OTM) {
704fe6060f1SDimitry Andric const std::string &Opcode = I.first;
705fe6060f1SDimitry Andric const TypeRetPredMap &TM = I.second;
7060b57cec5SDimitry Andric
7070b57cec5SDimitry Andric OS << "// FastEmit functions for " << Opcode << ".\n";
7080b57cec5SDimitry Andric OS << "\n";
7090b57cec5SDimitry Andric
7100b57cec5SDimitry Andric // Emit one function for each opcode,type pair.
711fe6060f1SDimitry Andric for (const auto &TI : TM) {
712fe6060f1SDimitry Andric MVT::SimpleValueType VT = TI.first;
713fe6060f1SDimitry Andric const RetPredMap &RM = TI.second;
7140b57cec5SDimitry Andric if (RM.size() != 1) {
715fe6060f1SDimitry Andric for (const auto &RI : RM) {
716fe6060f1SDimitry Andric MVT::SimpleValueType RetVT = RI.first;
717fe6060f1SDimitry Andric const PredMap &PM = RI.second;
7180b57cec5SDimitry Andric
7195ffd83dbSDimitry Andric OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"
7205ffd83dbSDimitry Andric << getLegalCName(std::string(getName(VT))) << "_"
7215ffd83dbSDimitry Andric << getLegalCName(std::string(getName(RetVT))) << "_";
7220b57cec5SDimitry Andric Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7230b57cec5SDimitry Andric OS << "(";
7240b57cec5SDimitry Andric Operands.PrintParameters(OS);
7250b57cec5SDimitry Andric OS << ") {\n";
7260b57cec5SDimitry Andric
7275ffd83dbSDimitry Andric emitInstructionCode(OS, Operands, PM, std::string(getName(RetVT)));
7280b57cec5SDimitry Andric }
7290b57cec5SDimitry Andric
7300b57cec5SDimitry Andric // Emit one function for the type that demultiplexes on return type.
7315ffd83dbSDimitry Andric OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"
7325ffd83dbSDimitry Andric << getLegalCName(std::string(getName(VT))) << "_";
7330b57cec5SDimitry Andric Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7340b57cec5SDimitry Andric OS << "(MVT RetVT";
7350b57cec5SDimitry Andric if (!Operands.empty())
7360b57cec5SDimitry Andric OS << ", ";
7370b57cec5SDimitry Andric Operands.PrintParameters(OS);
7380b57cec5SDimitry Andric OS << ") {\nswitch (RetVT.SimpleTy) {\n";
739fe6060f1SDimitry Andric for (const auto &RI : RM) {
740fe6060f1SDimitry Andric MVT::SimpleValueType RetVT = RI.first;
7410b57cec5SDimitry Andric OS << " case " << getName(RetVT) << ": return fastEmit_"
7425ffd83dbSDimitry Andric << getLegalCName(Opcode) << "_"
7435ffd83dbSDimitry Andric << getLegalCName(std::string(getName(VT))) << "_"
7445ffd83dbSDimitry Andric << getLegalCName(std::string(getName(RetVT))) << "_";
7450b57cec5SDimitry Andric Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7460b57cec5SDimitry Andric OS << "(";
7470b57cec5SDimitry Andric Operands.PrintArguments(OS);
7480b57cec5SDimitry Andric OS << ");\n";
7490b57cec5SDimitry Andric }
7500b57cec5SDimitry Andric OS << " default: return 0;\n}\n}\n\n";
7510b57cec5SDimitry Andric
7520b57cec5SDimitry Andric } else {
7530b57cec5SDimitry Andric // Non-variadic return type.
7545ffd83dbSDimitry Andric OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"
7555ffd83dbSDimitry Andric << getLegalCName(std::string(getName(VT))) << "_";
7560b57cec5SDimitry Andric Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7570b57cec5SDimitry Andric OS << "(MVT RetVT";
7580b57cec5SDimitry Andric if (!Operands.empty())
7590b57cec5SDimitry Andric OS << ", ";
7600b57cec5SDimitry Andric Operands.PrintParameters(OS);
7610b57cec5SDimitry Andric OS << ") {\n";
7620b57cec5SDimitry Andric
7630b57cec5SDimitry Andric OS << " if (RetVT.SimpleTy != " << getName(RM.begin()->first)
7640b57cec5SDimitry Andric << ")\n return 0;\n";
7650b57cec5SDimitry Andric
7660b57cec5SDimitry Andric const PredMap &PM = RM.begin()->second;
7670b57cec5SDimitry Andric
7680b57cec5SDimitry Andric emitInstructionCode(OS, Operands, PM, "RetVT");
7690b57cec5SDimitry Andric }
7700b57cec5SDimitry Andric }
7710b57cec5SDimitry Andric
7720b57cec5SDimitry Andric // Emit one function for the opcode that demultiplexes based on the type.
773*0fca6ea1SDimitry Andric OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_";
7740b57cec5SDimitry Andric Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7750b57cec5SDimitry Andric OS << "(MVT VT, MVT RetVT";
7760b57cec5SDimitry Andric if (!Operands.empty())
7770b57cec5SDimitry Andric OS << ", ";
7780b57cec5SDimitry Andric Operands.PrintParameters(OS);
7790b57cec5SDimitry Andric OS << ") {\n";
7800b57cec5SDimitry Andric OS << " switch (VT.SimpleTy) {\n";
781fe6060f1SDimitry Andric for (const auto &TI : TM) {
782fe6060f1SDimitry Andric MVT::SimpleValueType VT = TI.first;
7835ffd83dbSDimitry Andric std::string TypeName = std::string(getName(VT));
7840b57cec5SDimitry Andric OS << " case " << TypeName << ": return fastEmit_"
7850b57cec5SDimitry Andric << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_";
7860b57cec5SDimitry Andric Operands.PrintManglingSuffix(OS, ImmediatePredicates);
7870b57cec5SDimitry Andric OS << "(RetVT";
7880b57cec5SDimitry Andric if (!Operands.empty())
7890b57cec5SDimitry Andric OS << ", ";
7900b57cec5SDimitry Andric Operands.PrintArguments(OS);
7910b57cec5SDimitry Andric OS << ");\n";
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric OS << " default: return 0;\n";
7940b57cec5SDimitry Andric OS << " }\n";
7950b57cec5SDimitry Andric OS << "}\n";
7960b57cec5SDimitry Andric OS << "\n";
7970b57cec5SDimitry Andric }
7980b57cec5SDimitry Andric
7990b57cec5SDimitry Andric OS << "// Top-level FastEmit function.\n";
8000b57cec5SDimitry Andric OS << "\n";
8010b57cec5SDimitry Andric
8020b57cec5SDimitry Andric // Emit one function for the operand signature that demultiplexes based
8030b57cec5SDimitry Andric // on opcode and type.
8040b57cec5SDimitry Andric OS << "unsigned fastEmit_";
8050b57cec5SDimitry Andric Operands.PrintManglingSuffix(OS, ImmediatePredicates);
8060b57cec5SDimitry Andric OS << "(MVT VT, MVT RetVT, unsigned Opcode";
8070b57cec5SDimitry Andric if (!Operands.empty())
8080b57cec5SDimitry Andric OS << ", ";
8090b57cec5SDimitry Andric Operands.PrintParameters(OS);
8100b57cec5SDimitry Andric OS << ") ";
8110b57cec5SDimitry Andric if (!Operands.hasAnyImmediateCodes())
8120b57cec5SDimitry Andric OS << "override ";
8130b57cec5SDimitry Andric OS << "{\n";
8140b57cec5SDimitry Andric
8150b57cec5SDimitry Andric // If there are any forms of this signature available that operate on
8160b57cec5SDimitry Andric // constrained forms of the immediate (e.g., 32-bit sext immediate in a
8170b57cec5SDimitry Andric // 64-bit operand), check them first.
8180b57cec5SDimitry Andric
819*0fca6ea1SDimitry Andric std::map<OperandsSignature, std::vector<OperandsSignature>>::iterator MI =
820*0fca6ea1SDimitry Andric SignaturesWithConstantForms.find(Operands);
8210b57cec5SDimitry Andric if (MI != SignaturesWithConstantForms.end()) {
8220b57cec5SDimitry Andric // Unique any duplicates out of the list.
8230b57cec5SDimitry Andric llvm::sort(MI->second);
824*0fca6ea1SDimitry Andric MI->second.erase(llvm::unique(MI->second), MI->second.end());
8250b57cec5SDimitry Andric
8260b57cec5SDimitry Andric // Check each in order it was seen. It would be nice to have a good
8270b57cec5SDimitry Andric // relative ordering between them, but we're not going for optimality
8280b57cec5SDimitry Andric // here.
8290b57cec5SDimitry Andric for (unsigned i = 0, e = MI->second.size(); i != e; ++i) {
8300b57cec5SDimitry Andric OS << " if (";
8310b57cec5SDimitry Andric MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates);
8320b57cec5SDimitry Andric OS << ")\n if (unsigned Reg = fastEmit_";
8330b57cec5SDimitry Andric MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates);
8340b57cec5SDimitry Andric OS << "(VT, RetVT, Opcode";
8350b57cec5SDimitry Andric if (!MI->second[i].empty())
8360b57cec5SDimitry Andric OS << ", ";
8370b57cec5SDimitry Andric MI->second[i].PrintArguments(OS);
8380b57cec5SDimitry Andric OS << "))\n return Reg;\n\n";
8390b57cec5SDimitry Andric }
8400b57cec5SDimitry Andric
8410b57cec5SDimitry Andric // Done with this, remove it.
8420b57cec5SDimitry Andric SignaturesWithConstantForms.erase(MI);
8430b57cec5SDimitry Andric }
8440b57cec5SDimitry Andric
8450b57cec5SDimitry Andric OS << " switch (Opcode) {\n";
846fe6060f1SDimitry Andric for (const auto &I : OTM) {
847fe6060f1SDimitry Andric const std::string &Opcode = I.first;
8480b57cec5SDimitry Andric
849*0fca6ea1SDimitry Andric OS << " case " << Opcode << ": return fastEmit_" << getLegalCName(Opcode)
850*0fca6ea1SDimitry Andric << "_";
8510b57cec5SDimitry Andric Operands.PrintManglingSuffix(OS, ImmediatePredicates);
8520b57cec5SDimitry Andric OS << "(VT, RetVT";
8530b57cec5SDimitry Andric if (!Operands.empty())
8540b57cec5SDimitry Andric OS << ", ";
8550b57cec5SDimitry Andric Operands.PrintArguments(OS);
8560b57cec5SDimitry Andric OS << ");\n";
8570b57cec5SDimitry Andric }
8580b57cec5SDimitry Andric OS << " default: return 0;\n";
8590b57cec5SDimitry Andric OS << " }\n";
8600b57cec5SDimitry Andric OS << "}\n";
8610b57cec5SDimitry Andric OS << "\n";
8620b57cec5SDimitry Andric }
8630b57cec5SDimitry Andric
8640b57cec5SDimitry Andric // TODO: SignaturesWithConstantForms should be empty here.
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric
EmitFastISel(RecordKeeper & RK,raw_ostream & OS)86706c3fb27SDimitry Andric static void EmitFastISel(RecordKeeper &RK, raw_ostream &OS) {
8680b57cec5SDimitry Andric CodeGenDAGPatterns CGP(RK);
8690b57cec5SDimitry Andric const CodeGenTarget &Target = CGP.getTargetInfo();
8700b57cec5SDimitry Andric emitSourceFileHeader("\"Fast\" Instruction Selector for the " +
871*0fca6ea1SDimitry Andric Target.getName().str() + " target",
872*0fca6ea1SDimitry Andric OS);
8730b57cec5SDimitry Andric
8740b57cec5SDimitry Andric // Determine the target's namespace name.
8750b57cec5SDimitry Andric StringRef InstNS = Target.getInstNamespace();
8760b57cec5SDimitry Andric assert(!InstNS.empty() && "Can't determine target-specific namespace!");
8770b57cec5SDimitry Andric
8780b57cec5SDimitry Andric FastISelMap F(InstNS);
8790b57cec5SDimitry Andric F.collectPatterns(CGP);
8800b57cec5SDimitry Andric F.printImmediatePredicates(OS);
8810b57cec5SDimitry Andric F.printFunctionDefinitions(OS);
8820b57cec5SDimitry Andric }
8830b57cec5SDimitry Andric
88406c3fb27SDimitry Andric static TableGen::Emitter::Opt X("gen-fast-isel", EmitFastISel,
88506c3fb27SDimitry Andric "Generate a \"fast\" instruction selector");
886