Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/FastISelEmitter.cpp
35258 views
///===- FastISelEmitter.cpp - Generate an instruction selector ------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This tablegen backend emits code for use by the "fast" instruction9// selection algorithm. See the comments at the top of10// lib/CodeGen/SelectionDAG/FastISel.cpp for background.11//12// This file scans through the target's tablegen instruction-info files13// and extracts instructions with obvious-looking patterns, and it emits14// code to look up these instructions by type and operator.15//16//===----------------------------------------------------------------------===//1718#include "Common/CodeGenDAGPatterns.h"19#include "Common/CodeGenInstruction.h"20#include "Common/CodeGenRegisters.h"21#include "Common/CodeGenTarget.h"22#include "Common/InfoByHwMode.h"23#include "llvm/ADT/StringSwitch.h"24#include "llvm/Support/ErrorHandling.h"25#include "llvm/TableGen/Error.h"26#include "llvm/TableGen/Record.h"27#include "llvm/TableGen/TableGenBackend.h"28#include <set>29#include <utility>30using namespace llvm;3132/// InstructionMemo - This class holds additional information about an33/// instruction needed to emit code for it.34///35namespace {36struct InstructionMemo {37std::string Name;38const CodeGenRegisterClass *RC;39std::string SubRegNo;40std::vector<std::string> PhysRegs;41std::string PredicateCheck;4243InstructionMemo(StringRef Name, const CodeGenRegisterClass *RC,44std::string SubRegNo, std::vector<std::string> PhysRegs,45std::string PredicateCheck)46: Name(Name), RC(RC), SubRegNo(std::move(SubRegNo)),47PhysRegs(std::move(PhysRegs)),48PredicateCheck(std::move(PredicateCheck)) {}4950// Make sure we do not copy InstructionMemo.51InstructionMemo(const InstructionMemo &Other) = delete;52InstructionMemo(InstructionMemo &&Other) = default;53};54} // End anonymous namespace5556/// ImmPredicateSet - This uniques predicates (represented as a string) and57/// gives them unique (small) integer ID's that start at 0.58namespace {59class ImmPredicateSet {60DenseMap<TreePattern *, unsigned> ImmIDs;61std::vector<TreePredicateFn> PredsByName;6263public:64unsigned getIDFor(TreePredicateFn Pred) {65unsigned &Entry = ImmIDs[Pred.getOrigPatFragRecord()];66if (Entry == 0) {67PredsByName.push_back(Pred);68Entry = PredsByName.size();69}70return Entry - 1;71}7273const TreePredicateFn &getPredicate(unsigned i) {74assert(i < PredsByName.size());75return PredsByName[i];76}7778typedef std::vector<TreePredicateFn>::const_iterator iterator;79iterator begin() const { return PredsByName.begin(); }80iterator end() const { return PredsByName.end(); }81};82} // End anonymous namespace8384/// OperandsSignature - This class holds a description of a list of operand85/// types. It has utility methods for emitting text based on the operands.86///87namespace {88struct OperandsSignature {89class OpKind {90enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 };91char Repr;9293public:94OpKind() : Repr(OK_Invalid) {}9596bool operator<(OpKind RHS) const { return Repr < RHS.Repr; }97bool operator==(OpKind RHS) const { return Repr == RHS.Repr; }9899static OpKind getReg() {100OpKind K;101K.Repr = OK_Reg;102return K;103}104static OpKind getFP() {105OpKind K;106K.Repr = OK_FP;107return K;108}109static OpKind getImm(unsigned V) {110assert((unsigned)OK_Imm + V < 128 &&111"Too many integer predicates for the 'Repr' char");112OpKind K;113K.Repr = OK_Imm + V;114return K;115}116117bool isReg() const { return Repr == OK_Reg; }118bool isFP() const { return Repr == OK_FP; }119bool isImm() const { return Repr >= OK_Imm; }120121unsigned getImmCode() const {122assert(isImm());123return Repr - OK_Imm;124}125126void printManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,127bool StripImmCodes) const {128if (isReg())129OS << 'r';130else if (isFP())131OS << 'f';132else {133OS << 'i';134if (!StripImmCodes)135if (unsigned Code = getImmCode())136OS << "_" << ImmPredicates.getPredicate(Code - 1).getFnName();137}138}139};140141SmallVector<OpKind, 3> Operands;142143bool operator<(const OperandsSignature &O) const {144return Operands < O.Operands;145}146bool operator==(const OperandsSignature &O) const {147return Operands == O.Operands;148}149150bool empty() const { return Operands.empty(); }151152bool hasAnyImmediateCodes() const {153for (unsigned i = 0, e = Operands.size(); i != e; ++i)154if (Operands[i].isImm() && Operands[i].getImmCode() != 0)155return true;156return false;157}158159/// getWithoutImmCodes - Return a copy of this with any immediate codes forced160/// to zero.161OperandsSignature getWithoutImmCodes() const {162OperandsSignature Result;163for (unsigned i = 0, e = Operands.size(); i != e; ++i)164if (!Operands[i].isImm())165Result.Operands.push_back(Operands[i]);166else167Result.Operands.push_back(OpKind::getImm(0));168return Result;169}170171void emitImmediatePredicate(raw_ostream &OS, ImmPredicateSet &ImmPredicates) {172bool EmittedAnything = false;173for (unsigned i = 0, e = Operands.size(); i != e; ++i) {174if (!Operands[i].isImm())175continue;176177unsigned Code = Operands[i].getImmCode();178if (Code == 0)179continue;180181if (EmittedAnything)182OS << " &&\n ";183184TreePredicateFn PredFn = ImmPredicates.getPredicate(Code - 1);185186// Emit the type check.187TreePattern *TP = PredFn.getOrigPatFragRecord();188ValueTypeByHwMode VVT = TP->getTree(0)->getType(0);189assert(VVT.isSimple() &&190"Cannot use variable value types with fast isel");191OS << "VT == " << getEnumName(VVT.getSimple().SimpleTy) << " && ";192193OS << PredFn.getFnName() << "(imm" << i << ')';194EmittedAnything = true;195}196}197198/// initialize - Examine the given pattern and initialize the contents199/// of the Operands array accordingly. Return true if all the operands200/// are supported, false otherwise.201///202bool initialize(TreePatternNode &InstPatNode, const CodeGenTarget &Target,203MVT::SimpleValueType VT, ImmPredicateSet &ImmediatePredicates,204const CodeGenRegisterClass *OrigDstRC) {205if (InstPatNode.isLeaf())206return false;207208if (InstPatNode.getOperator()->getName() == "imm") {209Operands.push_back(OpKind::getImm(0));210return true;211}212213if (InstPatNode.getOperator()->getName() == "fpimm") {214Operands.push_back(OpKind::getFP());215return true;216}217218const CodeGenRegisterClass *DstRC = nullptr;219220for (unsigned i = 0, e = InstPatNode.getNumChildren(); i != e; ++i) {221TreePatternNode &Op = InstPatNode.getChild(i);222223// Handle imm operands specially.224if (!Op.isLeaf() && Op.getOperator()->getName() == "imm") {225unsigned PredNo = 0;226if (!Op.getPredicateCalls().empty()) {227TreePredicateFn PredFn = Op.getPredicateCalls()[0].Fn;228// If there is more than one predicate weighing in on this operand229// then we don't handle it. This doesn't typically happen for230// immediates anyway.231if (Op.getPredicateCalls().size() > 1 ||232!PredFn.isImmediatePattern() || PredFn.usesOperands())233return false;234// Ignore any instruction with 'FastIselShouldIgnore', these are235// not needed and just bloat the fast instruction selector. For236// example, X86 doesn't need to generate code to match ADD16ri8 since237// ADD16ri will do just fine.238Record *Rec = PredFn.getOrigPatFragRecord()->getRecord();239if (Rec->getValueAsBit("FastIselShouldIgnore"))240return false;241242PredNo = ImmediatePredicates.getIDFor(PredFn) + 1;243}244245Operands.push_back(OpKind::getImm(PredNo));246continue;247}248249// For now, filter out any operand with a predicate.250// For now, filter out any operand with multiple values.251if (!Op.getPredicateCalls().empty() || Op.getNumTypes() != 1)252return false;253254if (!Op.isLeaf()) {255if (Op.getOperator()->getName() == "fpimm") {256Operands.push_back(OpKind::getFP());257continue;258}259// For now, ignore other non-leaf nodes.260return false;261}262263assert(Op.hasConcreteType(0) && "Type infererence not done?");264265// For now, all the operands must have the same type (if they aren't266// immediates). Note that this causes us to reject variable sized shifts267// on X86.268if (Op.getSimpleType(0) != VT)269return false;270271DefInit *OpDI = dyn_cast<DefInit>(Op.getLeafValue());272if (!OpDI)273return false;274Record *OpLeafRec = OpDI->getDef();275276// For now, the only other thing we accept is register operands.277const CodeGenRegisterClass *RC = nullptr;278if (OpLeafRec->isSubClassOf("RegisterOperand"))279OpLeafRec = OpLeafRec->getValueAsDef("RegClass");280if (OpLeafRec->isSubClassOf("RegisterClass"))281RC = &Target.getRegisterClass(OpLeafRec);282else if (OpLeafRec->isSubClassOf("Register"))283RC = Target.getRegBank().getRegClassForRegister(OpLeafRec);284else if (OpLeafRec->isSubClassOf("ValueType")) {285RC = OrigDstRC;286} else287return false;288289// For now, this needs to be a register class of some sort.290if (!RC)291return false;292293// For now, all the operands must have the same register class or be294// a strict subclass of the destination.295if (DstRC) {296if (DstRC != RC && !DstRC->hasSubClass(RC))297return false;298} else299DstRC = RC;300Operands.push_back(OpKind::getReg());301}302return true;303}304305void PrintParameters(raw_ostream &OS) const {306ListSeparator LS;307for (unsigned i = 0, e = Operands.size(); i != e; ++i) {308OS << LS;309if (Operands[i].isReg()) {310OS << "unsigned Op" << i;311} else if (Operands[i].isImm()) {312OS << "uint64_t imm" << i;313} else if (Operands[i].isFP()) {314OS << "const ConstantFP *f" << i;315} else {316llvm_unreachable("Unknown operand kind!");317}318}319}320321void PrintArguments(raw_ostream &OS,322const std::vector<std::string> &PR) const {323assert(PR.size() == Operands.size());324ListSeparator LS;325for (unsigned i = 0, e = Operands.size(); i != e; ++i) {326if (PR[i] != "")327// Implicit physical register operand.328continue;329330OS << LS;331if (Operands[i].isReg()) {332OS << "Op" << i;333} else if (Operands[i].isImm()) {334OS << "imm" << i;335} else if (Operands[i].isFP()) {336OS << "f" << i;337} else {338llvm_unreachable("Unknown operand kind!");339}340}341}342343void PrintArguments(raw_ostream &OS) const {344ListSeparator LS;345for (unsigned i = 0, e = Operands.size(); i != e; ++i) {346OS << LS;347if (Operands[i].isReg()) {348OS << "Op" << i;349} else if (Operands[i].isImm()) {350OS << "imm" << i;351} else if (Operands[i].isFP()) {352OS << "f" << i;353} else {354llvm_unreachable("Unknown operand kind!");355}356}357}358359void PrintManglingSuffix(raw_ostream &OS, const std::vector<std::string> &PR,360ImmPredicateSet &ImmPredicates,361bool StripImmCodes = false) const {362for (unsigned i = 0, e = Operands.size(); i != e; ++i) {363if (PR[i] != "")364// Implicit physical register operand. e.g. Instruction::Mul expect to365// select to a binary op. On x86, mul may take a single operand with366// the other operand being implicit. We must emit something that looks367// like a binary instruction except for the very inner fastEmitInst_*368// call.369continue;370Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);371}372}373374void PrintManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,375bool StripImmCodes = false) const {376for (unsigned i = 0, e = Operands.size(); i != e; ++i)377Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);378}379};380} // End anonymous namespace381382namespace {383class FastISelMap {384// A multimap is needed instead of a "plain" map because the key is385// the instruction's complexity (an int) and they are not unique.386typedef std::multimap<int, InstructionMemo> PredMap;387typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap;388typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap;389typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap;390typedef std::map<OperandsSignature, OpcodeTypeRetPredMap>391OperandsOpcodeTypeRetPredMap;392393OperandsOpcodeTypeRetPredMap SimplePatterns;394395// This is used to check that there are no duplicate predicates396std::set<std::tuple<OperandsSignature, std::string, MVT::SimpleValueType,397MVT::SimpleValueType, std::string>>398SimplePatternsCheck;399400std::map<OperandsSignature, std::vector<OperandsSignature>>401SignaturesWithConstantForms;402403StringRef InstNS;404ImmPredicateSet ImmediatePredicates;405406public:407explicit FastISelMap(StringRef InstNS);408409void collectPatterns(CodeGenDAGPatterns &CGP);410void printImmediatePredicates(raw_ostream &OS);411void printFunctionDefinitions(raw_ostream &OS);412413private:414void emitInstructionCode(raw_ostream &OS, const OperandsSignature &Operands,415const PredMap &PM, const std::string &RetVTName);416};417} // End anonymous namespace418419static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) {420return std::string(CGP.getSDNodeInfo(Op).getEnumName());421}422423static std::string getLegalCName(std::string OpName) {424std::string::size_type pos = OpName.find("::");425if (pos != std::string::npos)426OpName.replace(pos, 2, "_");427return OpName;428}429430FastISelMap::FastISelMap(StringRef instns) : InstNS(instns) {}431432static std::string PhyRegForNode(TreePatternNode &Op,433const CodeGenTarget &Target) {434std::string PhysReg;435436if (!Op.isLeaf())437return PhysReg;438439Record *OpLeafRec = cast<DefInit>(Op.getLeafValue())->getDef();440if (!OpLeafRec->isSubClassOf("Register"))441return PhysReg;442443PhysReg += cast<StringInit>(OpLeafRec->getValue("Namespace")->getValue())444->getValue();445PhysReg += "::";446PhysReg += Target.getRegBank().getReg(OpLeafRec)->getName();447return PhysReg;448}449450void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {451const CodeGenTarget &Target = CGP.getTargetInfo();452453// Scan through all the patterns and record the simple ones.454for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end();455I != E; ++I) {456const PatternToMatch &Pattern = *I;457458// For now, just look at Instructions, so that we don't have to worry459// about emitting multiple instructions for a pattern.460TreePatternNode &Dst = Pattern.getDstPattern();461if (Dst.isLeaf())462continue;463Record *Op = Dst.getOperator();464if (!Op->isSubClassOf("Instruction"))465continue;466CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op);467if (II.Operands.empty())468continue;469470// Allow instructions to be marked as unavailable for FastISel for471// certain cases, i.e. an ISA has two 'and' instruction which differ472// by what registers they can use but are otherwise identical for473// codegen purposes.474if (II.FastISelShouldIgnore)475continue;476477// For now, ignore multi-instruction patterns.478bool MultiInsts = false;479for (unsigned i = 0, e = Dst.getNumChildren(); i != e; ++i) {480TreePatternNode &ChildOp = Dst.getChild(i);481if (ChildOp.isLeaf())482continue;483if (ChildOp.getOperator()->isSubClassOf("Instruction")) {484MultiInsts = true;485break;486}487}488if (MultiInsts)489continue;490491// For now, ignore instructions where the first operand is not an492// output register.493const CodeGenRegisterClass *DstRC = nullptr;494std::string SubRegNo;495if (Op->getName() != "EXTRACT_SUBREG") {496Record *Op0Rec = II.Operands[0].Rec;497if (Op0Rec->isSubClassOf("RegisterOperand"))498Op0Rec = Op0Rec->getValueAsDef("RegClass");499if (!Op0Rec->isSubClassOf("RegisterClass"))500continue;501DstRC = &Target.getRegisterClass(Op0Rec);502if (!DstRC)503continue;504} else {505// If this isn't a leaf, then continue since the register classes are506// a bit too complicated for now.507if (!Dst.getChild(1).isLeaf())508continue;509510DefInit *SR = dyn_cast<DefInit>(Dst.getChild(1).getLeafValue());511if (SR)512SubRegNo = getQualifiedName(SR->getDef());513else514SubRegNo = Dst.getChild(1).getLeafValue()->getAsString();515}516517// Inspect the pattern.518TreePatternNode &InstPatNode = Pattern.getSrcPattern();519if (InstPatNode.isLeaf())520continue;521522// Ignore multiple result nodes for now.523if (InstPatNode.getNumTypes() > 1)524continue;525526Record *InstPatOp = InstPatNode.getOperator();527std::string OpcodeName = getOpcodeName(InstPatOp, CGP);528MVT::SimpleValueType RetVT = MVT::isVoid;529if (InstPatNode.getNumTypes())530RetVT = InstPatNode.getSimpleType(0);531MVT::SimpleValueType VT = RetVT;532if (InstPatNode.getNumChildren()) {533assert(InstPatNode.getChild(0).getNumTypes() == 1);534VT = InstPatNode.getChild(0).getSimpleType(0);535}536537// For now, filter out any instructions with predicates.538if (!InstPatNode.getPredicateCalls().empty())539continue;540541// Check all the operands.542OperandsSignature Operands;543if (!Operands.initialize(InstPatNode, Target, VT, ImmediatePredicates,544DstRC))545continue;546547std::vector<std::string> PhysRegInputs;548if (InstPatNode.getOperator()->getName() == "imm" ||549InstPatNode.getOperator()->getName() == "fpimm")550PhysRegInputs.push_back("");551else {552// Compute the PhysRegs used by the given pattern, and check that553// the mapping from the src to dst patterns is simple.554bool FoundNonSimplePattern = false;555unsigned DstIndex = 0;556for (unsigned i = 0, e = InstPatNode.getNumChildren(); i != e; ++i) {557std::string PhysReg = PhyRegForNode(InstPatNode.getChild(i), Target);558if (PhysReg.empty()) {559if (DstIndex >= Dst.getNumChildren() ||560Dst.getChild(DstIndex).getName() !=561InstPatNode.getChild(i).getName()) {562FoundNonSimplePattern = true;563break;564}565++DstIndex;566}567568PhysRegInputs.push_back(PhysReg);569}570571if (Op->getName() != "EXTRACT_SUBREG" && DstIndex < Dst.getNumChildren())572FoundNonSimplePattern = true;573574if (FoundNonSimplePattern)575continue;576}577578// Check if the operands match one of the patterns handled by FastISel.579std::string ManglingSuffix;580raw_string_ostream SuffixOS(ManglingSuffix);581Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true);582if (!StringSwitch<bool>(ManglingSuffix)583.Cases("", "r", "rr", "ri", "i", "f", true)584.Default(false))585continue;586587// Get the predicate that guards this pattern.588std::string PredicateCheck = Pattern.getPredicateCheck();589590// Ok, we found a pattern that we can handle. Remember it.591InstructionMemo Memo(Pattern.getDstPattern().getOperator()->getName(),592DstRC, SubRegNo, PhysRegInputs, PredicateCheck);593594int complexity = Pattern.getPatternComplexity(CGP);595596auto inserted_simple_pattern = SimplePatternsCheck.insert(597std::tuple(Operands, OpcodeName, VT, RetVT, PredicateCheck));598if (!inserted_simple_pattern.second) {599PrintFatalError(Pattern.getSrcRecord()->getLoc(),600"Duplicate predicate in FastISel table!");601}602603// Note: Instructions with the same complexity will appear in the order604// that they are encountered.605SimplePatterns[Operands][OpcodeName][VT][RetVT].emplace(complexity,606std::move(Memo));607608// If any of the operands were immediates with predicates on them, strip609// them down to a signature that doesn't have predicates so that we can610// associate them with the stripped predicate version.611if (Operands.hasAnyImmediateCodes()) {612SignaturesWithConstantForms[Operands.getWithoutImmCodes()].push_back(613Operands);614}615}616}617618void FastISelMap::printImmediatePredicates(raw_ostream &OS) {619if (ImmediatePredicates.begin() == ImmediatePredicates.end())620return;621622OS << "\n// FastEmit Immediate Predicate functions.\n";623for (auto ImmediatePredicate : ImmediatePredicates) {624OS << "static bool " << ImmediatePredicate.getFnName()625<< "(int64_t Imm) {\n";626OS << ImmediatePredicate.getImmediatePredicateCode() << "\n}\n";627}628629OS << "\n\n";630}631632void FastISelMap::emitInstructionCode(raw_ostream &OS,633const OperandsSignature &Operands,634const PredMap &PM,635const std::string &RetVTName) {636// Emit code for each possible instruction. There may be637// multiple if there are subtarget concerns. A reverse iterator638// is used to produce the ones with highest complexity first.639640bool OneHadNoPredicate = false;641for (PredMap::const_reverse_iterator PI = PM.rbegin(), PE = PM.rend();642PI != PE; ++PI) {643const InstructionMemo &Memo = PI->second;644std::string PredicateCheck = Memo.PredicateCheck;645646if (PredicateCheck.empty()) {647assert(!OneHadNoPredicate &&648"Multiple instructions match and more than one had "649"no predicate!");650OneHadNoPredicate = true;651} else {652if (OneHadNoPredicate) {653PrintFatalError("Multiple instructions match and one with no "654"predicate came before one with a predicate! "655"name:" +656Memo.Name + " predicate: " + PredicateCheck);657}658OS << " if (" + PredicateCheck + ") {\n";659OS << " ";660}661662for (unsigned i = 0; i < Memo.PhysRegs.size(); ++i) {663if (Memo.PhysRegs[i] != "")664OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, "665<< "TII.get(TargetOpcode::COPY), " << Memo.PhysRegs[i]666<< ").addReg(Op" << i << ");\n";667}668669OS << " return fastEmitInst_";670if (Memo.SubRegNo.empty()) {671Operands.PrintManglingSuffix(OS, Memo.PhysRegs, ImmediatePredicates,672true);673OS << "(" << InstNS << "::" << Memo.Name << ", ";674OS << "&" << InstNS << "::" << Memo.RC->getName() << "RegClass";675if (!Operands.empty())676OS << ", ";677Operands.PrintArguments(OS, Memo.PhysRegs);678OS << ");\n";679} else {680OS << "extractsubreg(" << RetVTName << ", Op0, " << Memo.SubRegNo681<< ");\n";682}683684if (!PredicateCheck.empty()) {685OS << " }\n";686}687}688// Return 0 if all of the possibilities had predicates but none689// were satisfied.690if (!OneHadNoPredicate)691OS << " return 0;\n";692OS << "}\n";693OS << "\n";694}695696void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {697// Now emit code for all the patterns that we collected.698for (const auto &SimplePattern : SimplePatterns) {699const OperandsSignature &Operands = SimplePattern.first;700const OpcodeTypeRetPredMap &OTM = SimplePattern.second;701702for (const auto &I : OTM) {703const std::string &Opcode = I.first;704const TypeRetPredMap &TM = I.second;705706OS << "// FastEmit functions for " << Opcode << ".\n";707OS << "\n";708709// Emit one function for each opcode,type pair.710for (const auto &TI : TM) {711MVT::SimpleValueType VT = TI.first;712const RetPredMap &RM = TI.second;713if (RM.size() != 1) {714for (const auto &RI : RM) {715MVT::SimpleValueType RetVT = RI.first;716const PredMap &PM = RI.second;717718OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"719<< getLegalCName(std::string(getName(VT))) << "_"720<< getLegalCName(std::string(getName(RetVT))) << "_";721Operands.PrintManglingSuffix(OS, ImmediatePredicates);722OS << "(";723Operands.PrintParameters(OS);724OS << ") {\n";725726emitInstructionCode(OS, Operands, PM, std::string(getName(RetVT)));727}728729// Emit one function for the type that demultiplexes on return type.730OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"731<< getLegalCName(std::string(getName(VT))) << "_";732Operands.PrintManglingSuffix(OS, ImmediatePredicates);733OS << "(MVT RetVT";734if (!Operands.empty())735OS << ", ";736Operands.PrintParameters(OS);737OS << ") {\nswitch (RetVT.SimpleTy) {\n";738for (const auto &RI : RM) {739MVT::SimpleValueType RetVT = RI.first;740OS << " case " << getName(RetVT) << ": return fastEmit_"741<< getLegalCName(Opcode) << "_"742<< getLegalCName(std::string(getName(VT))) << "_"743<< getLegalCName(std::string(getName(RetVT))) << "_";744Operands.PrintManglingSuffix(OS, ImmediatePredicates);745OS << "(";746Operands.PrintArguments(OS);747OS << ");\n";748}749OS << " default: return 0;\n}\n}\n\n";750751} else {752// Non-variadic return type.753OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"754<< getLegalCName(std::string(getName(VT))) << "_";755Operands.PrintManglingSuffix(OS, ImmediatePredicates);756OS << "(MVT RetVT";757if (!Operands.empty())758OS << ", ";759Operands.PrintParameters(OS);760OS << ") {\n";761762OS << " if (RetVT.SimpleTy != " << getName(RM.begin()->first)763<< ")\n return 0;\n";764765const PredMap &PM = RM.begin()->second;766767emitInstructionCode(OS, Operands, PM, "RetVT");768}769}770771// Emit one function for the opcode that demultiplexes based on the type.772OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_";773Operands.PrintManglingSuffix(OS, ImmediatePredicates);774OS << "(MVT VT, MVT RetVT";775if (!Operands.empty())776OS << ", ";777Operands.PrintParameters(OS);778OS << ") {\n";779OS << " switch (VT.SimpleTy) {\n";780for (const auto &TI : TM) {781MVT::SimpleValueType VT = TI.first;782std::string TypeName = std::string(getName(VT));783OS << " case " << TypeName << ": return fastEmit_"784<< getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_";785Operands.PrintManglingSuffix(OS, ImmediatePredicates);786OS << "(RetVT";787if (!Operands.empty())788OS << ", ";789Operands.PrintArguments(OS);790OS << ");\n";791}792OS << " default: return 0;\n";793OS << " }\n";794OS << "}\n";795OS << "\n";796}797798OS << "// Top-level FastEmit function.\n";799OS << "\n";800801// Emit one function for the operand signature that demultiplexes based802// on opcode and type.803OS << "unsigned fastEmit_";804Operands.PrintManglingSuffix(OS, ImmediatePredicates);805OS << "(MVT VT, MVT RetVT, unsigned Opcode";806if (!Operands.empty())807OS << ", ";808Operands.PrintParameters(OS);809OS << ") ";810if (!Operands.hasAnyImmediateCodes())811OS << "override ";812OS << "{\n";813814// If there are any forms of this signature available that operate on815// constrained forms of the immediate (e.g., 32-bit sext immediate in a816// 64-bit operand), check them first.817818std::map<OperandsSignature, std::vector<OperandsSignature>>::iterator MI =819SignaturesWithConstantForms.find(Operands);820if (MI != SignaturesWithConstantForms.end()) {821// Unique any duplicates out of the list.822llvm::sort(MI->second);823MI->second.erase(llvm::unique(MI->second), MI->second.end());824825// Check each in order it was seen. It would be nice to have a good826// relative ordering between them, but we're not going for optimality827// here.828for (unsigned i = 0, e = MI->second.size(); i != e; ++i) {829OS << " if (";830MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates);831OS << ")\n if (unsigned Reg = fastEmit_";832MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates);833OS << "(VT, RetVT, Opcode";834if (!MI->second[i].empty())835OS << ", ";836MI->second[i].PrintArguments(OS);837OS << "))\n return Reg;\n\n";838}839840// Done with this, remove it.841SignaturesWithConstantForms.erase(MI);842}843844OS << " switch (Opcode) {\n";845for (const auto &I : OTM) {846const std::string &Opcode = I.first;847848OS << " case " << Opcode << ": return fastEmit_" << getLegalCName(Opcode)849<< "_";850Operands.PrintManglingSuffix(OS, ImmediatePredicates);851OS << "(VT, RetVT";852if (!Operands.empty())853OS << ", ";854Operands.PrintArguments(OS);855OS << ");\n";856}857OS << " default: return 0;\n";858OS << " }\n";859OS << "}\n";860OS << "\n";861}862863// TODO: SignaturesWithConstantForms should be empty here.864}865866static void EmitFastISel(RecordKeeper &RK, raw_ostream &OS) {867CodeGenDAGPatterns CGP(RK);868const CodeGenTarget &Target = CGP.getTargetInfo();869emitSourceFileHeader("\"Fast\" Instruction Selector for the " +870Target.getName().str() + " target",871OS);872873// Determine the target's namespace name.874StringRef InstNS = Target.getInstNamespace();875assert(!InstNS.empty() && "Can't determine target-specific namespace!");876877FastISelMap F(InstNS);878F.collectPatterns(CGP);879F.printImmediatePredicates(OS);880F.printFunctionDefinitions(OS);881}882883static TableGen::Emitter::Opt X("gen-fast-isel", EmitFastISel,884"Generate a \"fast\" instruction selector");885886887