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