1*0fca6ea1SDimitry Andric 20b57cec5SDimitry Andric //===- GlobalISelEmitter.cpp - Generate an instruction selector -----------===// 30b57cec5SDimitry Andric // 40b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric // 80b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 90b57cec5SDimitry Andric // 100b57cec5SDimitry Andric /// \file 110b57cec5SDimitry Andric /// This tablegen backend emits code for use by the GlobalISel instruction 1206c3fb27SDimitry Andric /// selector. See include/llvm/Target/GlobalISel/Target.td. 130b57cec5SDimitry Andric /// 140b57cec5SDimitry Andric /// This file analyzes the patterns recognized by the SelectionDAGISel tablegen 150b57cec5SDimitry Andric /// backend, filters out the ones that are unsupported, maps 160b57cec5SDimitry Andric /// SelectionDAG-specific constructs to their GlobalISel counterpart 170b57cec5SDimitry Andric /// (when applicable: MVT to LLT; SDNode to generic Instruction). 180b57cec5SDimitry Andric /// 190b57cec5SDimitry Andric /// Not all patterns are supported: pass the tablegen invocation 200b57cec5SDimitry Andric /// "-warn-on-skipped-patterns" to emit a warning when a pattern is skipped, 210b57cec5SDimitry Andric /// as well as why. 220b57cec5SDimitry Andric /// 230b57cec5SDimitry Andric /// The generated file defines a single method: 240b57cec5SDimitry Andric /// bool <Target>InstructionSelector::selectImpl(MachineInstr &I) const; 250b57cec5SDimitry Andric /// intended to be used in InstructionSelector::select as the first-step 260b57cec5SDimitry Andric /// selector for the patterns that don't require complex C++. 270b57cec5SDimitry Andric /// 280b57cec5SDimitry Andric /// FIXME: We'll probably want to eventually define a base 290b57cec5SDimitry Andric /// "TargetGenInstructionSelector" class. 300b57cec5SDimitry Andric /// 310b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 320b57cec5SDimitry Andric 33*0fca6ea1SDimitry Andric #include "Basic/CodeGenIntrinsics.h" 34*0fca6ea1SDimitry Andric #include "Common/CodeGenDAGPatterns.h" 35*0fca6ea1SDimitry Andric #include "Common/CodeGenInstruction.h" 36*0fca6ea1SDimitry Andric #include "Common/CodeGenRegisters.h" 37*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h" 38*0fca6ea1SDimitry Andric #include "Common/GlobalISel/GlobalISelMatchTable.h" 39*0fca6ea1SDimitry Andric #include "Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h" 40*0fca6ea1SDimitry Andric #include "Common/InfoByHwMode.h" 41*0fca6ea1SDimitry Andric #include "Common/SubtargetFeatureInfo.h" 420b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 43*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/LowLevelType.h" 44*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/MachineValueType.h" 450b57cec5SDimitry Andric #include "llvm/Support/CodeGenCoverage.h" 460b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 470b57cec5SDimitry Andric #include "llvm/Support/Error.h" 480b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h" 490b57cec5SDimitry Andric #include "llvm/TableGen/Error.h" 500b57cec5SDimitry Andric #include "llvm/TableGen/Record.h" 510b57cec5SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 520b57cec5SDimitry Andric #include <string> 5306c3fb27SDimitry Andric 540b57cec5SDimitry Andric using namespace llvm; 5506c3fb27SDimitry Andric using namespace llvm::gi; 5606c3fb27SDimitry Andric 5706c3fb27SDimitry Andric using action_iterator = RuleMatcher::action_iterator; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric #define DEBUG_TYPE "gisel-emitter" 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric STATISTIC(NumPatternTotal, "Total number of patterns"); 620b57cec5SDimitry Andric STATISTIC(NumPatternImported, "Number of patterns imported from SelectionDAG"); 630b57cec5SDimitry Andric STATISTIC(NumPatternImportsSkipped, "Number of SelectionDAG imports skipped"); 6406c3fb27SDimitry Andric STATISTIC(NumPatternsTested, 6506c3fb27SDimitry Andric "Number of patterns executed according to coverage information"); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric cl::OptionCategory GlobalISelEmitterCat("Options for -gen-global-isel"); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric static cl::opt<bool> WarnOnSkippedPatterns( 700b57cec5SDimitry Andric "warn-on-skipped-patterns", 710b57cec5SDimitry Andric cl::desc("Explain why a pattern was skipped for inclusion " 720b57cec5SDimitry Andric "in the GlobalISel selector"), 730b57cec5SDimitry Andric cl::init(false), cl::cat(GlobalISelEmitterCat)); 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric static cl::opt<bool> GenerateCoverage( 760b57cec5SDimitry Andric "instrument-gisel-coverage", 770b57cec5SDimitry Andric cl::desc("Generate coverage instrumentation for GlobalISel"), 780b57cec5SDimitry Andric cl::init(false), cl::cat(GlobalISelEmitterCat)); 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric static cl::opt<std::string> UseCoverageFile( 810b57cec5SDimitry Andric "gisel-coverage-file", cl::init(""), 820b57cec5SDimitry Andric cl::desc("Specify file to retrieve coverage information from"), 830b57cec5SDimitry Andric cl::cat(GlobalISelEmitterCat)); 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric static cl::opt<bool> OptimizeMatchTable( 860b57cec5SDimitry Andric "optimize-match-table", 870b57cec5SDimitry Andric cl::desc("Generate an optimized version of the match table"), 880b57cec5SDimitry Andric cl::init(true), cl::cat(GlobalISelEmitterCat)); 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric namespace { 910b57cec5SDimitry Andric 92*0fca6ea1SDimitry Andric static std::string explainPredicates(const TreePatternNode &N) { 93e8d8bef9SDimitry Andric std::string Explanation; 940b57cec5SDimitry Andric StringRef Separator = ""; 95*0fca6ea1SDimitry Andric for (const TreePredicateCall &Call : N.getPredicateCalls()) { 960b57cec5SDimitry Andric const TreePredicateFn &P = Call.Fn; 970b57cec5SDimitry Andric Explanation += 980b57cec5SDimitry Andric (Separator + P.getOrigPatFragRecord()->getRecord()->getName()).str(); 990b57cec5SDimitry Andric Separator = ", "; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric if (P.isAlwaysTrue()) 1020b57cec5SDimitry Andric Explanation += " always-true"; 1030b57cec5SDimitry Andric if (P.isImmediatePattern()) 1040b57cec5SDimitry Andric Explanation += " immediate"; 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric if (P.isUnindexed()) 1070b57cec5SDimitry Andric Explanation += " unindexed"; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric if (P.isNonExtLoad()) 1100b57cec5SDimitry Andric Explanation += " non-extload"; 1110b57cec5SDimitry Andric if (P.isAnyExtLoad()) 1120b57cec5SDimitry Andric Explanation += " extload"; 1130b57cec5SDimitry Andric if (P.isSignExtLoad()) 1140b57cec5SDimitry Andric Explanation += " sextload"; 1150b57cec5SDimitry Andric if (P.isZeroExtLoad()) 1160b57cec5SDimitry Andric Explanation += " zextload"; 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric if (P.isNonTruncStore()) 1190b57cec5SDimitry Andric Explanation += " non-truncstore"; 1200b57cec5SDimitry Andric if (P.isTruncStore()) 1210b57cec5SDimitry Andric Explanation += " truncstore"; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric if (Record *VT = P.getMemoryVT()) 1240b57cec5SDimitry Andric Explanation += (" MemVT=" + VT->getName()).str(); 1250b57cec5SDimitry Andric if (Record *VT = P.getScalarMemoryVT()) 1260b57cec5SDimitry Andric Explanation += (" ScalarVT(MemVT)=" + VT->getName()).str(); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric if (ListInit *AddrSpaces = P.getAddressSpaces()) { 1290b57cec5SDimitry Andric raw_string_ostream OS(Explanation); 1300b57cec5SDimitry Andric OS << " AddressSpaces=["; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric StringRef AddrSpaceSeparator; 1330b57cec5SDimitry Andric for (Init *Val : AddrSpaces->getValues()) { 1340b57cec5SDimitry Andric IntInit *IntVal = dyn_cast<IntInit>(Val); 1350b57cec5SDimitry Andric if (!IntVal) 1360b57cec5SDimitry Andric continue; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric OS << AddrSpaceSeparator << IntVal->getValue(); 1390b57cec5SDimitry Andric AddrSpaceSeparator = ", "; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric OS << ']'; 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1458bcb0991SDimitry Andric int64_t MinAlign = P.getMinAlignment(); 1468bcb0991SDimitry Andric if (MinAlign > 0) 1478bcb0991SDimitry Andric Explanation += " MinAlign=" + utostr(MinAlign); 1488bcb0991SDimitry Andric 1490b57cec5SDimitry Andric if (P.isAtomicOrderingMonotonic()) 1500b57cec5SDimitry Andric Explanation += " monotonic"; 1510b57cec5SDimitry Andric if (P.isAtomicOrderingAcquire()) 1520b57cec5SDimitry Andric Explanation += " acquire"; 1530b57cec5SDimitry Andric if (P.isAtomicOrderingRelease()) 1540b57cec5SDimitry Andric Explanation += " release"; 1550b57cec5SDimitry Andric if (P.isAtomicOrderingAcquireRelease()) 1560b57cec5SDimitry Andric Explanation += " acq_rel"; 1570b57cec5SDimitry Andric if (P.isAtomicOrderingSequentiallyConsistent()) 1580b57cec5SDimitry Andric Explanation += " seq_cst"; 1590b57cec5SDimitry Andric if (P.isAtomicOrderingAcquireOrStronger()) 1600b57cec5SDimitry Andric Explanation += " >=acquire"; 1610b57cec5SDimitry Andric if (P.isAtomicOrderingWeakerThanAcquire()) 1620b57cec5SDimitry Andric Explanation += " <acquire"; 1630b57cec5SDimitry Andric if (P.isAtomicOrderingReleaseOrStronger()) 1640b57cec5SDimitry Andric Explanation += " >=release"; 1650b57cec5SDimitry Andric if (P.isAtomicOrderingWeakerThanRelease()) 1660b57cec5SDimitry Andric Explanation += " <release"; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric return Explanation; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric std::string explainOperator(Record *Operator) { 1720b57cec5SDimitry Andric if (Operator->isSubClassOf("SDNode")) 1730b57cec5SDimitry Andric return (" (" + Operator->getValueAsString("Opcode") + ")").str(); 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric if (Operator->isSubClassOf("Intrinsic")) 1760b57cec5SDimitry Andric return (" (Operator is an Intrinsic, " + Operator->getName() + ")").str(); 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric if (Operator->isSubClassOf("ComplexPattern")) 1790b57cec5SDimitry Andric return (" (Operator is an unmapped ComplexPattern, " + Operator->getName() + 1800b57cec5SDimitry Andric ")") 1810b57cec5SDimitry Andric .str(); 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric if (Operator->isSubClassOf("SDNodeXForm")) 1840b57cec5SDimitry Andric return (" (Operator is an unmapped SDNodeXForm, " + Operator->getName() + 1850b57cec5SDimitry Andric ")") 1860b57cec5SDimitry Andric .str(); 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric return (" (Operator " + Operator->getName() + " not understood)").str(); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric /// Helper function to let the emitter report skip reason error messages. 1920b57cec5SDimitry Andric static Error failedImport(const Twine &Reason) { 1930b57cec5SDimitry Andric return make_error<StringError>(Reason, inconvertibleErrorCode()); 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 196*0fca6ea1SDimitry Andric static Error isTrivialOperatorNode(const TreePatternNode &N) { 197e8d8bef9SDimitry Andric std::string Explanation; 198e8d8bef9SDimitry Andric std::string Separator; 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric bool HasUnsupportedPredicate = false; 201*0fca6ea1SDimitry Andric for (const TreePredicateCall &Call : N.getPredicateCalls()) { 2020b57cec5SDimitry Andric const TreePredicateFn &Predicate = Call.Fn; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric if (Predicate.isAlwaysTrue()) 2050b57cec5SDimitry Andric continue; 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric if (Predicate.isImmediatePattern()) 2080b57cec5SDimitry Andric continue; 2090b57cec5SDimitry Andric 210*0fca6ea1SDimitry Andric if (Predicate.hasNoUse() || Predicate.hasOneUse()) 211753f127fSDimitry Andric continue; 212753f127fSDimitry Andric 2130b57cec5SDimitry Andric if (Predicate.isNonExtLoad() || Predicate.isAnyExtLoad() || 2140b57cec5SDimitry Andric Predicate.isSignExtLoad() || Predicate.isZeroExtLoad()) 2150b57cec5SDimitry Andric continue; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric if (Predicate.isNonTruncStore() || Predicate.isTruncStore()) 2180b57cec5SDimitry Andric continue; 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric if (Predicate.isLoad() && Predicate.getMemoryVT()) 2210b57cec5SDimitry Andric continue; 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric if (Predicate.isLoad() || Predicate.isStore()) { 2240b57cec5SDimitry Andric if (Predicate.isUnindexed()) 2250b57cec5SDimitry Andric continue; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) { 2290b57cec5SDimitry Andric const ListInit *AddrSpaces = Predicate.getAddressSpaces(); 2300b57cec5SDimitry Andric if (AddrSpaces && !AddrSpaces->empty()) 2310b57cec5SDimitry Andric continue; 2328bcb0991SDimitry Andric 2338bcb0991SDimitry Andric if (Predicate.getMinAlignment() > 0) 2348bcb0991SDimitry Andric continue; 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric if (Predicate.isAtomic() && Predicate.getMemoryVT()) 2380b57cec5SDimitry Andric continue; 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric if (Predicate.isAtomic() && 2410b57cec5SDimitry Andric (Predicate.isAtomicOrderingMonotonic() || 2420b57cec5SDimitry Andric Predicate.isAtomicOrderingAcquire() || 2430b57cec5SDimitry Andric Predicate.isAtomicOrderingRelease() || 2440b57cec5SDimitry Andric Predicate.isAtomicOrderingAcquireRelease() || 2450b57cec5SDimitry Andric Predicate.isAtomicOrderingSequentiallyConsistent() || 2460b57cec5SDimitry Andric Predicate.isAtomicOrderingAcquireOrStronger() || 2470b57cec5SDimitry Andric Predicate.isAtomicOrderingWeakerThanAcquire() || 2480b57cec5SDimitry Andric Predicate.isAtomicOrderingReleaseOrStronger() || 2490b57cec5SDimitry Andric Predicate.isAtomicOrderingWeakerThanRelease())) 2500b57cec5SDimitry Andric continue; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric if (Predicate.hasGISelPredicateCode()) 2530b57cec5SDimitry Andric continue; 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric HasUnsupportedPredicate = true; 2560b57cec5SDimitry Andric Explanation = Separator + "Has a predicate (" + explainPredicates(N) + ")"; 2570b57cec5SDimitry Andric Separator = ", "; 2580b57cec5SDimitry Andric Explanation += (Separator + "first-failing:" + 2590b57cec5SDimitry Andric Predicate.getOrigPatFragRecord()->getRecord()->getName()) 2600b57cec5SDimitry Andric .str(); 2610b57cec5SDimitry Andric break; 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric if (!HasUnsupportedPredicate) 2650b57cec5SDimitry Andric return Error::success(); 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric return failedImport(Explanation); 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric static Record *getInitValueAsRegClass(Init *V) { 2710b57cec5SDimitry Andric if (DefInit *VDefInit = dyn_cast<DefInit>(V)) { 2720b57cec5SDimitry Andric if (VDefInit->getDef()->isSubClassOf("RegisterOperand")) 2730b57cec5SDimitry Andric return VDefInit->getDef()->getValueAsDef("RegClass"); 2740b57cec5SDimitry Andric if (VDefInit->getDef()->isSubClassOf("RegisterClass")) 2750b57cec5SDimitry Andric return VDefInit->getDef(); 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric return nullptr; 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric 280e8d8bef9SDimitry Andric static std::string getScopedName(unsigned Scope, const std::string &Name) { 281e8d8bef9SDimitry Andric return ("pred:" + Twine(Scope) + ":" + Name).str(); 282e8d8bef9SDimitry Andric } 283e8d8bef9SDimitry Andric 2845f757f3fSDimitry Andric static std::string getMangledRootDefName(StringRef DefOperandName) { 2855f757f3fSDimitry Andric return ("DstI[" + DefOperandName + "]").str(); 2865f757f3fSDimitry Andric } 2875f757f3fSDimitry Andric 2880b57cec5SDimitry Andric //===- GlobalISelEmitter class --------------------------------------------===// 2890b57cec5SDimitry Andric 290*0fca6ea1SDimitry Andric static Expected<LLTCodeGen> getInstResultType(const TreePatternNode &Dst, 291*0fca6ea1SDimitry Andric const CodeGenTarget &Target) { 292*0fca6ea1SDimitry Andric // While we allow more than one output (both implicit and explicit defs) 293*0fca6ea1SDimitry Andric // below, we only expect one explicit def here. 294*0fca6ea1SDimitry Andric assert(Dst.getOperator()->isSubClassOf("Instruction")); 295*0fca6ea1SDimitry Andric CodeGenInstruction &InstInfo = Target.getInstruction(Dst.getOperator()); 296*0fca6ea1SDimitry Andric if (!InstInfo.Operands.NumDefs) 297*0fca6ea1SDimitry Andric return failedImport("Dst pattern child needs a def"); 2985ffd83dbSDimitry Andric 299*0fca6ea1SDimitry Andric ArrayRef<TypeSetByHwMode> ChildTypes = Dst.getExtTypes(); 300*0fca6ea1SDimitry Andric if (ChildTypes.size() < 1) 301*0fca6ea1SDimitry Andric return failedImport("Dst pattern child has no result"); 302*0fca6ea1SDimitry Andric 303*0fca6ea1SDimitry Andric // If there are multiple results, just take the first one (this is how 304*0fca6ea1SDimitry Andric // SelectionDAG does it). 305bdd1243dSDimitry Andric std::optional<LLTCodeGen> MaybeOpTy; 3065ffd83dbSDimitry Andric if (ChildTypes.front().isMachineValueType()) { 30706c3fb27SDimitry Andric MaybeOpTy = MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy); 3085ffd83dbSDimitry Andric } 3095ffd83dbSDimitry Andric 3105ffd83dbSDimitry Andric if (!MaybeOpTy) 3115ffd83dbSDimitry Andric return failedImport("Dst operand has an unsupported type"); 3125ffd83dbSDimitry Andric return *MaybeOpTy; 3135ffd83dbSDimitry Andric } 3145ffd83dbSDimitry Andric 31506c3fb27SDimitry Andric class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter { 3160b57cec5SDimitry Andric public: 3170b57cec5SDimitry Andric explicit GlobalISelEmitter(RecordKeeper &RK); 31806c3fb27SDimitry Andric 31906c3fb27SDimitry Andric void emitAdditionalImpl(raw_ostream &OS) override; 32006c3fb27SDimitry Andric 32106c3fb27SDimitry Andric void emitMIPredicateFns(raw_ostream &OS) override; 32206c3fb27SDimitry Andric void emitI64ImmPredicateFns(raw_ostream &OS) override; 32306c3fb27SDimitry Andric void emitAPFloatImmPredicateFns(raw_ostream &OS) override; 32406c3fb27SDimitry Andric void emitAPIntImmPredicateFns(raw_ostream &OS) override; 32506c3fb27SDimitry Andric void emitTestSimplePredicate(raw_ostream &OS) override; 32606c3fb27SDimitry Andric void emitRunCustomAction(raw_ostream &OS) override; 32706c3fb27SDimitry Andric 3285f757f3fSDimitry Andric void postProcessRule(RuleMatcher &M); 3295f757f3fSDimitry Andric 33006c3fb27SDimitry Andric const CodeGenTarget &getTarget() const override { return Target; } 33106c3fb27SDimitry Andric StringRef getClassName() const override { return ClassName; } 33206c3fb27SDimitry Andric 3330b57cec5SDimitry Andric void run(raw_ostream &OS); 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric private: 33606c3fb27SDimitry Andric std::string ClassName; 33706c3fb27SDimitry Andric 3380b57cec5SDimitry Andric const RecordKeeper &RK; 3390b57cec5SDimitry Andric const CodeGenDAGPatterns CGP; 3400b57cec5SDimitry Andric const CodeGenTarget &Target; 3415ffd83dbSDimitry Andric CodeGenRegBank &CGRegs; 3420b57cec5SDimitry Andric 34306c3fb27SDimitry Andric std::vector<Record *> AllPatFrags; 34406c3fb27SDimitry Andric 3450b57cec5SDimitry Andric /// Keep track of the equivalence between SDNodes and Instruction by mapping 3460b57cec5SDimitry Andric /// SDNodes to the GINodeEquiv mapping. We need to map to the GINodeEquiv to 3470b57cec5SDimitry Andric /// check for attributes on the relation such as CheckMMOIsNonAtomic. 3480b57cec5SDimitry Andric /// This is defined using 'GINodeEquiv' in the target description. 3490b57cec5SDimitry Andric DenseMap<Record *, Record *> NodeEquivs; 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric /// Keep track of the equivalence between ComplexPattern's and 3520b57cec5SDimitry Andric /// GIComplexOperandMatcher. Map entries are specified by subclassing 3530b57cec5SDimitry Andric /// GIComplexPatternEquiv. 3540b57cec5SDimitry Andric DenseMap<const Record *, const Record *> ComplexPatternEquivs; 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric /// Keep track of the equivalence between SDNodeXForm's and 3570b57cec5SDimitry Andric /// GICustomOperandRenderer. Map entries are specified by subclassing 3580b57cec5SDimitry Andric /// GISDNodeXFormEquiv. 3590b57cec5SDimitry Andric DenseMap<const Record *, const Record *> SDNodeXFormEquivs; 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric /// Keep track of Scores of PatternsToMatch similar to how the DAG does. 3620b57cec5SDimitry Andric /// This adds compatibility for RuleMatchers to use this for ordering rules. 3630b57cec5SDimitry Andric DenseMap<uint64_t, int> RuleMatcherScores; 3640b57cec5SDimitry Andric 3650b57cec5SDimitry Andric // Rule coverage information. 366bdd1243dSDimitry Andric std::optional<CodeGenCoverage> RuleCoverage; 3670b57cec5SDimitry Andric 368e8d8bef9SDimitry Andric /// Variables used to help with collecting of named operands for predicates 369e8d8bef9SDimitry Andric /// with 'let PredicateCodeUsesOperands = 1'. WaitingForNamedOperands is set 370e8d8bef9SDimitry Andric /// to the number of named operands that predicate expects. Store locations in 371e8d8bef9SDimitry Andric /// StoreIdxForName correspond to the order in which operand names appear in 372e8d8bef9SDimitry Andric /// predicate's argument list. 3735f757f3fSDimitry Andric /// When we visit named operand and WaitingForNamedOperands is not zero, add 3745f757f3fSDimitry Andric /// matcher that will record operand and decrease counter. 375e8d8bef9SDimitry Andric unsigned WaitingForNamedOperands = 0; 376e8d8bef9SDimitry Andric StringMap<unsigned> StoreIdxForName; 377e8d8bef9SDimitry Andric 3780b57cec5SDimitry Andric void gatherOpcodeValues(); 3790b57cec5SDimitry Andric void gatherTypeIDValues(); 3800b57cec5SDimitry Andric void gatherNodeEquivs(); 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric Record *findNodeEquiv(Record *N) const; 3830b57cec5SDimitry Andric const CodeGenInstruction *getEquivNode(Record &Equiv, 384*0fca6ea1SDimitry Andric const TreePatternNode &N) const; 3850b57cec5SDimitry Andric 386fe6060f1SDimitry Andric Error importRulePredicates(RuleMatcher &M, ArrayRef<Record *> Predicates); 3870b57cec5SDimitry Andric Expected<InstructionMatcher &> 3880b57cec5SDimitry Andric createAndImportSelDAGMatcher(RuleMatcher &Rule, 3890b57cec5SDimitry Andric InstructionMatcher &InsnMatcher, 390*0fca6ea1SDimitry Andric const TreePatternNode &Src, unsigned &TempOpIdx); 3910b57cec5SDimitry Andric Error importComplexPatternOperandMatcher(OperandMatcher &OM, Record *R, 3920b57cec5SDimitry Andric unsigned &TempOpIdx) const; 3930b57cec5SDimitry Andric Error importChildMatcher(RuleMatcher &Rule, InstructionMatcher &InsnMatcher, 394*0fca6ea1SDimitry Andric const TreePatternNode &SrcChild, 395480093f4SDimitry Andric bool OperandIsAPointer, bool OperandIsImmArg, 396480093f4SDimitry Andric unsigned OpIdx, unsigned &TempOpIdx); 3970b57cec5SDimitry Andric 3988bcb0991SDimitry Andric Expected<BuildMIAction &> createAndImportInstructionRenderer( 3998bcb0991SDimitry Andric RuleMatcher &M, InstructionMatcher &InsnMatcher, 400*0fca6ea1SDimitry Andric const TreePatternNode &Src, const TreePatternNode &Dst); 4010b57cec5SDimitry Andric Expected<action_iterator> createAndImportSubInstructionRenderer( 402*0fca6ea1SDimitry Andric action_iterator InsertPt, RuleMatcher &M, const TreePatternNode &Dst, 403*0fca6ea1SDimitry Andric const TreePatternNode &Src, unsigned TempReg); 4040b57cec5SDimitry Andric Expected<action_iterator> 4050b57cec5SDimitry Andric createInstructionRenderer(action_iterator InsertPt, RuleMatcher &M, 406*0fca6ea1SDimitry Andric const TreePatternNode &Dst); 407e8d8bef9SDimitry Andric 408*0fca6ea1SDimitry Andric Expected<action_iterator> 409*0fca6ea1SDimitry Andric importExplicitDefRenderers(action_iterator InsertPt, RuleMatcher &M, 410*0fca6ea1SDimitry Andric BuildMIAction &DstMIBuilder, 411*0fca6ea1SDimitry Andric const TreePatternNode &Src, 412*0fca6ea1SDimitry Andric const TreePatternNode &Dst, unsigned Start = 0); 4138bcb0991SDimitry Andric 41406c3fb27SDimitry Andric Expected<action_iterator> importExplicitUseRenderers( 41506c3fb27SDimitry Andric action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder, 416*0fca6ea1SDimitry Andric const llvm::TreePatternNode &Dst, const TreePatternNode &Src); 41706c3fb27SDimitry Andric Expected<action_iterator> importExplicitUseRenderer( 41806c3fb27SDimitry Andric action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder, 419*0fca6ea1SDimitry Andric const TreePatternNode &DstChild, const TreePatternNode &Src); 4200b57cec5SDimitry Andric Error importDefaultOperandRenderers(action_iterator InsertPt, RuleMatcher &M, 4210b57cec5SDimitry Andric BuildMIAction &DstMIBuilder, 4225f757f3fSDimitry Andric const DAGDefaultOperand &DefaultOp) const; 4230b57cec5SDimitry Andric Error 4240b57cec5SDimitry Andric importImplicitDefRenderers(BuildMIAction &DstMIBuilder, 4250b57cec5SDimitry Andric const std::vector<Record *> &ImplicitDefs) const; 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric /// Analyze pattern \p P, returning a matcher for it if possible. 4280b57cec5SDimitry Andric /// Otherwise, return an Error explaining why we don't support it. 4290b57cec5SDimitry Andric Expected<RuleMatcher> runOnPattern(const PatternToMatch &P); 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric void declareSubtargetFeature(Record *Predicate); 4320b57cec5SDimitry Andric 4335f757f3fSDimitry Andric unsigned declareHwModeCheck(StringRef HwModeFeatures); 4345f757f3fSDimitry Andric 4350b57cec5SDimitry Andric MatchTable buildMatchTable(MutableArrayRef<RuleMatcher> Rules, bool Optimize, 4360b57cec5SDimitry Andric bool WithCoverage); 4370b57cec5SDimitry Andric 4388bcb0991SDimitry Andric /// Infer a CodeGenRegisterClass for the type of \p SuperRegNode. The returned 4398bcb0991SDimitry Andric /// CodeGenRegisterClass will support the CodeGenRegisterClass of 4408bcb0991SDimitry Andric /// \p SubRegNode, and the subregister index defined by \p SubRegIdxNode. 441bdd1243dSDimitry Andric /// If no register class is found, return std::nullopt. 442bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *> 4438bcb0991SDimitry Andric inferSuperRegisterClassForNode(const TypeSetByHwMode &Ty, 444*0fca6ea1SDimitry Andric const TreePatternNode &SuperRegNode, 445*0fca6ea1SDimitry Andric const TreePatternNode &SubRegIdxNode); 446bdd1243dSDimitry Andric std::optional<CodeGenSubRegIndex *> 447*0fca6ea1SDimitry Andric inferSubRegIndexForNode(const TreePatternNode &SubRegIdxNode); 4488bcb0991SDimitry Andric 4498bcb0991SDimitry Andric /// Infer a CodeGenRegisterClass which suppoorts \p Ty and \p SubRegIdxNode. 450bdd1243dSDimitry Andric /// Return std::nullopt if no such class exists. 451bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *> 4528bcb0991SDimitry Andric inferSuperRegisterClass(const TypeSetByHwMode &Ty, 453*0fca6ea1SDimitry Andric const TreePatternNode &SubRegIdxNode); 4548bcb0991SDimitry Andric 4558bcb0991SDimitry Andric /// Return the CodeGenRegisterClass associated with \p Leaf if it has one. 456bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *> 457*0fca6ea1SDimitry Andric getRegClassFromLeaf(const TreePatternNode &Leaf); 4588bcb0991SDimitry Andric 459bdd1243dSDimitry Andric /// Return a CodeGenRegisterClass for \p N if one can be found. Return 460bdd1243dSDimitry Andric /// std::nullopt otherwise. 461bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *> 462*0fca6ea1SDimitry Andric inferRegClassFromPattern(const TreePatternNode &N); 4638bcb0991SDimitry Andric 464fe6060f1SDimitry Andric /// Return the size of the MemoryVT in this predicate, if possible. 465bdd1243dSDimitry Andric std::optional<unsigned> 466fe6060f1SDimitry Andric getMemSizeBitsFromPredicate(const TreePredicateFn &Predicate); 467fe6060f1SDimitry Andric 468e8d8bef9SDimitry Andric // Add builtin predicates. 469e8d8bef9SDimitry Andric Expected<InstructionMatcher &> 470e8d8bef9SDimitry Andric addBuiltinPredicates(const Record *SrcGIEquivOrNull, 471e8d8bef9SDimitry Andric const TreePredicateFn &Predicate, 472e8d8bef9SDimitry Andric InstructionMatcher &InsnMatcher, bool &HasAddedMatcher); 4730b57cec5SDimitry Andric }; 4740b57cec5SDimitry Andric 47506c3fb27SDimitry Andric StringRef getPatFragPredicateEnumName(Record *R) { return R->getName(); } 47606c3fb27SDimitry Andric 4770b57cec5SDimitry Andric void GlobalISelEmitter::gatherOpcodeValues() { 4780b57cec5SDimitry Andric InstructionOpcodeMatcher::initOpcodeValuesMap(Target); 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric void GlobalISelEmitter::gatherTypeIDValues() { 4820b57cec5SDimitry Andric LLTOperandMatcher::initTypeIDValuesMap(); 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric void GlobalISelEmitter::gatherNodeEquivs() { 4860b57cec5SDimitry Andric assert(NodeEquivs.empty()); 4870b57cec5SDimitry Andric for (Record *Equiv : RK.getAllDerivedDefinitions("GINodeEquiv")) 4880b57cec5SDimitry Andric NodeEquivs[Equiv->getValueAsDef("Node")] = Equiv; 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric assert(ComplexPatternEquivs.empty()); 4910b57cec5SDimitry Andric for (Record *Equiv : RK.getAllDerivedDefinitions("GIComplexPatternEquiv")) { 4920b57cec5SDimitry Andric Record *SelDAGEquiv = Equiv->getValueAsDef("SelDAGEquivalent"); 4930b57cec5SDimitry Andric if (!SelDAGEquiv) 4940b57cec5SDimitry Andric continue; 4950b57cec5SDimitry Andric ComplexPatternEquivs[SelDAGEquiv] = Equiv; 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric assert(SDNodeXFormEquivs.empty()); 4990b57cec5SDimitry Andric for (Record *Equiv : RK.getAllDerivedDefinitions("GISDNodeXFormEquiv")) { 5000b57cec5SDimitry Andric Record *SelDAGEquiv = Equiv->getValueAsDef("SelDAGEquivalent"); 5010b57cec5SDimitry Andric if (!SelDAGEquiv) 5020b57cec5SDimitry Andric continue; 5030b57cec5SDimitry Andric SDNodeXFormEquivs[SelDAGEquiv] = Equiv; 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric Record *GlobalISelEmitter::findNodeEquiv(Record *N) const { 5080b57cec5SDimitry Andric return NodeEquivs.lookup(N); 5090b57cec5SDimitry Andric } 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andric const CodeGenInstruction * 512*0fca6ea1SDimitry Andric GlobalISelEmitter::getEquivNode(Record &Equiv, const TreePatternNode &N) const { 513*0fca6ea1SDimitry Andric if (N.getNumChildren() >= 1) { 5148bcb0991SDimitry Andric // setcc operation maps to two different G_* instructions based on the type. 5158bcb0991SDimitry Andric if (!Equiv.isValueUnset("IfFloatingPoint") && 516*0fca6ea1SDimitry Andric MVT(N.getChild(0).getSimpleType(0)).isFloatingPoint()) 5178bcb0991SDimitry Andric return &Target.getInstruction(Equiv.getValueAsDef("IfFloatingPoint")); 5188bcb0991SDimitry Andric } 5198bcb0991SDimitry Andric 5205f757f3fSDimitry Andric if (!Equiv.isValueUnset("IfConvergent") && 521*0fca6ea1SDimitry Andric N.getIntrinsicInfo(CGP)->isConvergent) 5225f757f3fSDimitry Andric return &Target.getInstruction(Equiv.getValueAsDef("IfConvergent")); 5235f757f3fSDimitry Andric 524*0fca6ea1SDimitry Andric for (const TreePredicateCall &Call : N.getPredicateCalls()) { 5250b57cec5SDimitry Andric const TreePredicateFn &Predicate = Call.Fn; 526753f127fSDimitry Andric if (!Equiv.isValueUnset("IfSignExtend") && 527753f127fSDimitry Andric (Predicate.isLoad() || Predicate.isAtomic()) && 5280b57cec5SDimitry Andric Predicate.isSignExtLoad()) 5290b57cec5SDimitry Andric return &Target.getInstruction(Equiv.getValueAsDef("IfSignExtend")); 530753f127fSDimitry Andric if (!Equiv.isValueUnset("IfZeroExtend") && 531753f127fSDimitry Andric (Predicate.isLoad() || Predicate.isAtomic()) && 5320b57cec5SDimitry Andric Predicate.isZeroExtLoad()) 5330b57cec5SDimitry Andric return &Target.getInstruction(Equiv.getValueAsDef("IfZeroExtend")); 5340b57cec5SDimitry Andric } 5358bcb0991SDimitry Andric 5360b57cec5SDimitry Andric return &Target.getInstruction(Equiv.getValueAsDef("I")); 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK) 54006c3fb27SDimitry Andric : GlobalISelMatchTableExecutorEmitter(), RK(RK), CGP(RK), 54106c3fb27SDimitry Andric Target(CGP.getTargetInfo()), CGRegs(Target.getRegBank()) { 54206c3fb27SDimitry Andric ClassName = Target.getName().str() + "InstructionSelector"; 54306c3fb27SDimitry Andric } 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric //===- Emitter ------------------------------------------------------------===// 5460b57cec5SDimitry Andric 547fe6060f1SDimitry Andric Error GlobalISelEmitter::importRulePredicates(RuleMatcher &M, 548fe6060f1SDimitry Andric ArrayRef<Record *> Predicates) { 549fe6060f1SDimitry Andric for (Record *Pred : Predicates) { 550fe6060f1SDimitry Andric if (Pred->getValueAsString("CondString").empty()) 5510b57cec5SDimitry Andric continue; 552fe6060f1SDimitry Andric declareSubtargetFeature(Pred); 553fe6060f1SDimitry Andric M.addRequiredFeature(Pred); 5540b57cec5SDimitry Andric } 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric return Error::success(); 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 559bdd1243dSDimitry Andric std::optional<unsigned> GlobalISelEmitter::getMemSizeBitsFromPredicate( 560bdd1243dSDimitry Andric const TreePredicateFn &Predicate) { 561bdd1243dSDimitry Andric std::optional<LLTCodeGen> MemTyOrNone = 562fe6060f1SDimitry Andric MVTToLLT(getValueType(Predicate.getMemoryVT())); 563fe6060f1SDimitry Andric 564fe6060f1SDimitry Andric if (!MemTyOrNone) 565bdd1243dSDimitry Andric return std::nullopt; 566fe6060f1SDimitry Andric 567fe6060f1SDimitry Andric // Align so unusual types like i1 don't get rounded down. 568fe6060f1SDimitry Andric return llvm::alignTo( 569fe6060f1SDimitry Andric static_cast<unsigned>(MemTyOrNone->get().getSizeInBits()), 8); 570fe6060f1SDimitry Andric } 571fe6060f1SDimitry Andric 572e8d8bef9SDimitry Andric Expected<InstructionMatcher &> GlobalISelEmitter::addBuiltinPredicates( 573e8d8bef9SDimitry Andric const Record *SrcGIEquivOrNull, const TreePredicateFn &Predicate, 574e8d8bef9SDimitry Andric InstructionMatcher &InsnMatcher, bool &HasAddedMatcher) { 575e8d8bef9SDimitry Andric if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) { 576e8d8bef9SDimitry Andric if (const ListInit *AddrSpaces = Predicate.getAddressSpaces()) { 577e8d8bef9SDimitry Andric SmallVector<unsigned, 4> ParsedAddrSpaces; 578e8d8bef9SDimitry Andric 579e8d8bef9SDimitry Andric for (Init *Val : AddrSpaces->getValues()) { 580e8d8bef9SDimitry Andric IntInit *IntVal = dyn_cast<IntInit>(Val); 581e8d8bef9SDimitry Andric if (!IntVal) 582e8d8bef9SDimitry Andric return failedImport("Address space is not an integer"); 583e8d8bef9SDimitry Andric ParsedAddrSpaces.push_back(IntVal->getValue()); 584e8d8bef9SDimitry Andric } 585e8d8bef9SDimitry Andric 586e8d8bef9SDimitry Andric if (!ParsedAddrSpaces.empty()) { 587e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryAddressSpacePredicateMatcher>( 588e8d8bef9SDimitry Andric 0, ParsedAddrSpaces); 58981ad6265SDimitry Andric return InsnMatcher; 590e8d8bef9SDimitry Andric } 591e8d8bef9SDimitry Andric } 592e8d8bef9SDimitry Andric 593e8d8bef9SDimitry Andric int64_t MinAlign = Predicate.getMinAlignment(); 59481ad6265SDimitry Andric if (MinAlign > 0) { 595e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryAlignmentPredicateMatcher>(0, MinAlign); 59681ad6265SDimitry Andric return InsnMatcher; 59781ad6265SDimitry Andric } 598e8d8bef9SDimitry Andric } 599e8d8bef9SDimitry Andric 600e8d8bef9SDimitry Andric // G_LOAD is used for both non-extending and any-extending loads. 601e8d8bef9SDimitry Andric if (Predicate.isLoad() && Predicate.isNonExtLoad()) { 602e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>( 603e8d8bef9SDimitry Andric 0, MemoryVsLLTSizePredicateMatcher::EqualTo, 0); 604e8d8bef9SDimitry Andric return InsnMatcher; 605e8d8bef9SDimitry Andric } 606e8d8bef9SDimitry Andric if (Predicate.isLoad() && Predicate.isAnyExtLoad()) { 607e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>( 608e8d8bef9SDimitry Andric 0, MemoryVsLLTSizePredicateMatcher::LessThan, 0); 609e8d8bef9SDimitry Andric return InsnMatcher; 610e8d8bef9SDimitry Andric } 611e8d8bef9SDimitry Andric 612e8d8bef9SDimitry Andric if (Predicate.isStore()) { 613e8d8bef9SDimitry Andric if (Predicate.isTruncStore()) { 614fe6060f1SDimitry Andric if (Predicate.getMemoryVT() != nullptr) { 615e8d8bef9SDimitry Andric // FIXME: If MemoryVT is set, we end up with 2 checks for the MMO size. 616fe6060f1SDimitry Andric auto MemSizeInBits = getMemSizeBitsFromPredicate(Predicate); 617fe6060f1SDimitry Andric if (!MemSizeInBits) 618fe6060f1SDimitry Andric return failedImport("MemVT could not be converted to LLT"); 619fe6060f1SDimitry Andric 620fe6060f1SDimitry Andric InsnMatcher.addPredicate<MemorySizePredicateMatcher>(0, *MemSizeInBits / 621fe6060f1SDimitry Andric 8); 622fe6060f1SDimitry Andric } else { 623e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>( 624e8d8bef9SDimitry Andric 0, MemoryVsLLTSizePredicateMatcher::LessThan, 0); 625fe6060f1SDimitry Andric } 626e8d8bef9SDimitry Andric return InsnMatcher; 627e8d8bef9SDimitry Andric } 628e8d8bef9SDimitry Andric if (Predicate.isNonTruncStore()) { 629e8d8bef9SDimitry Andric // We need to check the sizes match here otherwise we could incorrectly 630e8d8bef9SDimitry Andric // match truncating stores with non-truncating ones. 631e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>( 632e8d8bef9SDimitry Andric 0, MemoryVsLLTSizePredicateMatcher::EqualTo, 0); 633e8d8bef9SDimitry Andric } 634e8d8bef9SDimitry Andric } 635e8d8bef9SDimitry Andric 63606c3fb27SDimitry Andric assert(SrcGIEquivOrNull != nullptr && "Invalid SrcGIEquivOrNull value"); 637e8d8bef9SDimitry Andric // No check required. We already did it by swapping the opcode. 638e8d8bef9SDimitry Andric if (!SrcGIEquivOrNull->isValueUnset("IfSignExtend") && 639e8d8bef9SDimitry Andric Predicate.isSignExtLoad()) 640e8d8bef9SDimitry Andric return InsnMatcher; 641e8d8bef9SDimitry Andric 642e8d8bef9SDimitry Andric // No check required. We already did it by swapping the opcode. 643e8d8bef9SDimitry Andric if (!SrcGIEquivOrNull->isValueUnset("IfZeroExtend") && 644e8d8bef9SDimitry Andric Predicate.isZeroExtLoad()) 645e8d8bef9SDimitry Andric return InsnMatcher; 646e8d8bef9SDimitry Andric 647e8d8bef9SDimitry Andric // No check required. G_STORE by itself is a non-extending store. 648e8d8bef9SDimitry Andric if (Predicate.isNonTruncStore()) 649e8d8bef9SDimitry Andric return InsnMatcher; 650e8d8bef9SDimitry Andric 651e8d8bef9SDimitry Andric if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) { 652e8d8bef9SDimitry Andric if (Predicate.getMemoryVT() != nullptr) { 653fe6060f1SDimitry Andric auto MemSizeInBits = getMemSizeBitsFromPredicate(Predicate); 654fe6060f1SDimitry Andric if (!MemSizeInBits) 655e8d8bef9SDimitry Andric return failedImport("MemVT could not be converted to LLT"); 656e8d8bef9SDimitry Andric 657e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemorySizePredicateMatcher>(0, 658fe6060f1SDimitry Andric *MemSizeInBits / 8); 659e8d8bef9SDimitry Andric return InsnMatcher; 660e8d8bef9SDimitry Andric } 661e8d8bef9SDimitry Andric } 662e8d8bef9SDimitry Andric 663e8d8bef9SDimitry Andric if (Predicate.isLoad() || Predicate.isStore()) { 664e8d8bef9SDimitry Andric // No check required. A G_LOAD/G_STORE is an unindexed load. 665e8d8bef9SDimitry Andric if (Predicate.isUnindexed()) 666e8d8bef9SDimitry Andric return InsnMatcher; 667e8d8bef9SDimitry Andric } 668e8d8bef9SDimitry Andric 669e8d8bef9SDimitry Andric if (Predicate.isAtomic()) { 670e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingMonotonic()) { 671e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>("Monotonic"); 672e8d8bef9SDimitry Andric return InsnMatcher; 673e8d8bef9SDimitry Andric } 674e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingAcquire()) { 675e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>("Acquire"); 676e8d8bef9SDimitry Andric return InsnMatcher; 677e8d8bef9SDimitry Andric } 678e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingRelease()) { 679e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>("Release"); 680e8d8bef9SDimitry Andric return InsnMatcher; 681e8d8bef9SDimitry Andric } 682e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingAcquireRelease()) { 683e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>( 684e8d8bef9SDimitry Andric "AcquireRelease"); 685e8d8bef9SDimitry Andric return InsnMatcher; 686e8d8bef9SDimitry Andric } 687e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingSequentiallyConsistent()) { 688e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>( 689e8d8bef9SDimitry Andric "SequentiallyConsistent"); 690e8d8bef9SDimitry Andric return InsnMatcher; 691e8d8bef9SDimitry Andric } 692e8d8bef9SDimitry Andric } 693e8d8bef9SDimitry Andric 694e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingAcquireOrStronger()) { 695e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>( 696e8d8bef9SDimitry Andric "Acquire", AtomicOrderingMMOPredicateMatcher::AO_OrStronger); 697e8d8bef9SDimitry Andric return InsnMatcher; 698e8d8bef9SDimitry Andric } 699e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingWeakerThanAcquire()) { 700e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>( 701e8d8bef9SDimitry Andric "Acquire", AtomicOrderingMMOPredicateMatcher::AO_WeakerThan); 702e8d8bef9SDimitry Andric return InsnMatcher; 703e8d8bef9SDimitry Andric } 704e8d8bef9SDimitry Andric 705e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingReleaseOrStronger()) { 706e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>( 707e8d8bef9SDimitry Andric "Release", AtomicOrderingMMOPredicateMatcher::AO_OrStronger); 708e8d8bef9SDimitry Andric return InsnMatcher; 709e8d8bef9SDimitry Andric } 710e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingWeakerThanRelease()) { 711e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>( 712e8d8bef9SDimitry Andric "Release", AtomicOrderingMMOPredicateMatcher::AO_WeakerThan); 713e8d8bef9SDimitry Andric return InsnMatcher; 714e8d8bef9SDimitry Andric } 715e8d8bef9SDimitry Andric HasAddedMatcher = false; 716e8d8bef9SDimitry Andric return InsnMatcher; 717e8d8bef9SDimitry Andric } 718e8d8bef9SDimitry Andric 7190b57cec5SDimitry Andric Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher( 7200b57cec5SDimitry Andric RuleMatcher &Rule, InstructionMatcher &InsnMatcher, 721*0fca6ea1SDimitry Andric const TreePatternNode &Src, unsigned &TempOpIdx) { 722*0fca6ea1SDimitry Andric const auto SavedFlags = Rule.setGISelFlags(Src.getGISelFlagsRecord()); 72306c3fb27SDimitry Andric 7240b57cec5SDimitry Andric Record *SrcGIEquivOrNull = nullptr; 7250b57cec5SDimitry Andric const CodeGenInstruction *SrcGIOrNull = nullptr; 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric // Start with the defined operands (i.e., the results of the root operator). 728*0fca6ea1SDimitry Andric if (Src.isLeaf()) { 729*0fca6ea1SDimitry Andric Init *SrcInit = Src.getLeafValue(); 7300b57cec5SDimitry Andric if (isa<IntInit>(SrcInit)) { 7310b57cec5SDimitry Andric InsnMatcher.addPredicate<InstructionOpcodeMatcher>( 7320b57cec5SDimitry Andric &Target.getInstruction(RK.getDef("G_CONSTANT"))); 7330b57cec5SDimitry Andric } else 7340b57cec5SDimitry Andric return failedImport( 7350b57cec5SDimitry Andric "Unable to deduce gMIR opcode to handle Src (which is a leaf)"); 7360b57cec5SDimitry Andric } else { 737*0fca6ea1SDimitry Andric SrcGIEquivOrNull = findNodeEquiv(Src.getOperator()); 7380b57cec5SDimitry Andric if (!SrcGIEquivOrNull) 7390b57cec5SDimitry Andric return failedImport("Pattern operator lacks an equivalent Instruction" + 740*0fca6ea1SDimitry Andric explainOperator(Src.getOperator())); 7410b57cec5SDimitry Andric SrcGIOrNull = getEquivNode(*SrcGIEquivOrNull, Src); 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric // The operators look good: match the opcode 7440b57cec5SDimitry Andric InsnMatcher.addPredicate<InstructionOpcodeMatcher>(SrcGIOrNull); 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric unsigned OpIdx = 0; 748*0fca6ea1SDimitry Andric for (const TypeSetByHwMode &VTy : Src.getExtTypes()) { 7490b57cec5SDimitry Andric // Results don't have a name unless they are the root node. The caller will 7500b57cec5SDimitry Andric // set the name if appropriate. 751bdd1243dSDimitry Andric const bool OperandIsAPointer = 752bdd1243dSDimitry Andric SrcGIOrNull && SrcGIOrNull->isOutOperandAPointer(OpIdx); 7530b57cec5SDimitry Andric OperandMatcher &OM = InsnMatcher.addOperand(OpIdx++, "", TempOpIdx); 754bdd1243dSDimitry Andric if (auto Error = OM.addTypeCheckPredicate(VTy, OperandIsAPointer)) 7550b57cec5SDimitry Andric return failedImport(toString(std::move(Error)) + 7560b57cec5SDimitry Andric " for result of Src pattern operator"); 7570b57cec5SDimitry Andric } 7580b57cec5SDimitry Andric 759*0fca6ea1SDimitry Andric for (const TreePredicateCall &Call : Src.getPredicateCalls()) { 7600b57cec5SDimitry Andric const TreePredicateFn &Predicate = Call.Fn; 761e8d8bef9SDimitry Andric bool HasAddedBuiltinMatcher = true; 7620b57cec5SDimitry Andric if (Predicate.isAlwaysTrue()) 7630b57cec5SDimitry Andric continue; 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric if (Predicate.isImmediatePattern()) { 7660b57cec5SDimitry Andric InsnMatcher.addPredicate<InstructionImmPredicateMatcher>(Predicate); 7670b57cec5SDimitry Andric continue; 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric 770e8d8bef9SDimitry Andric auto InsnMatcherOrError = addBuiltinPredicates( 771e8d8bef9SDimitry Andric SrcGIEquivOrNull, Predicate, InsnMatcher, HasAddedBuiltinMatcher); 772e8d8bef9SDimitry Andric if (auto Error = InsnMatcherOrError.takeError()) 773e8d8bef9SDimitry Andric return std::move(Error); 7740b57cec5SDimitry Andric 775753f127fSDimitry Andric // FIXME: This should be part of addBuiltinPredicates(). If we add this at 776753f127fSDimitry Andric // the start of addBuiltinPredicates() without returning, then there might 777753f127fSDimitry Andric // be cases where we hit the last return before which the 778753f127fSDimitry Andric // HasAddedBuiltinMatcher will be set to false. The predicate could be 779753f127fSDimitry Andric // missed if we add it in the middle or at the end due to return statements 780753f127fSDimitry Andric // after the addPredicate<>() calls. 781753f127fSDimitry Andric if (Predicate.hasNoUse()) { 782753f127fSDimitry Andric InsnMatcher.addPredicate<NoUsePredicateMatcher>(); 783753f127fSDimitry Andric HasAddedBuiltinMatcher = true; 784753f127fSDimitry Andric } 785*0fca6ea1SDimitry Andric if (Predicate.hasOneUse()) { 786*0fca6ea1SDimitry Andric InsnMatcher.addPredicate<OneUsePredicateMatcher>(); 787*0fca6ea1SDimitry Andric HasAddedBuiltinMatcher = true; 788*0fca6ea1SDimitry Andric } 789753f127fSDimitry Andric 7900b57cec5SDimitry Andric if (Predicate.hasGISelPredicateCode()) { 791e8d8bef9SDimitry Andric if (Predicate.usesOperands()) { 792e8d8bef9SDimitry Andric assert(WaitingForNamedOperands == 0 && 793e8d8bef9SDimitry Andric "previous predicate didn't find all operands or " 794e8d8bef9SDimitry Andric "nested predicate that uses operands"); 795e8d8bef9SDimitry Andric TreePattern *TP = Predicate.getOrigPatFragRecord(); 796e8d8bef9SDimitry Andric WaitingForNamedOperands = TP->getNumArgs(); 797*0fca6ea1SDimitry Andric for (unsigned I = 0; I < WaitingForNamedOperands; ++I) 798*0fca6ea1SDimitry Andric StoreIdxForName[getScopedName(Call.Scope, TP->getArgName(I))] = I; 799e8d8bef9SDimitry Andric } 8000b57cec5SDimitry Andric InsnMatcher.addPredicate<GenericInstructionPredicateMatcher>(Predicate); 8010b57cec5SDimitry Andric continue; 8020b57cec5SDimitry Andric } 803e8d8bef9SDimitry Andric if (!HasAddedBuiltinMatcher) { 8040b57cec5SDimitry Andric return failedImport("Src pattern child has predicate (" + 8050b57cec5SDimitry Andric explainPredicates(Src) + ")"); 8060b57cec5SDimitry Andric } 807e8d8bef9SDimitry Andric } 808e8d8bef9SDimitry Andric 80906c3fb27SDimitry Andric if (SrcGIEquivOrNull && 81006c3fb27SDimitry Andric SrcGIEquivOrNull->getValueAsBit("CheckMMOIsNonAtomic")) 8110b57cec5SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>("NotAtomic"); 81206c3fb27SDimitry Andric else if (SrcGIEquivOrNull && 81306c3fb27SDimitry Andric SrcGIEquivOrNull->getValueAsBit("CheckMMOIsAtomic")) { 8148bcb0991SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>( 8158bcb0991SDimitry Andric "Unordered", AtomicOrderingMMOPredicateMatcher::AO_OrStronger); 8168bcb0991SDimitry Andric } 8170b57cec5SDimitry Andric 818*0fca6ea1SDimitry Andric if (Src.isLeaf()) { 819*0fca6ea1SDimitry Andric Init *SrcInit = Src.getLeafValue(); 8200b57cec5SDimitry Andric if (IntInit *SrcIntInit = dyn_cast<IntInit>(SrcInit)) { 8210b57cec5SDimitry Andric OperandMatcher &OM = 822*0fca6ea1SDimitry Andric InsnMatcher.addOperand(OpIdx++, Src.getName(), TempOpIdx); 8230b57cec5SDimitry Andric OM.addPredicate<LiteralIntOperandMatcher>(SrcIntInit->getValue()); 8240b57cec5SDimitry Andric } else 8250b57cec5SDimitry Andric return failedImport( 8260b57cec5SDimitry Andric "Unable to deduce gMIR opcode to handle Src (which is a leaf)"); 8270b57cec5SDimitry Andric } else { 8280b57cec5SDimitry Andric assert(SrcGIOrNull && 8290b57cec5SDimitry Andric "Expected to have already found an equivalent Instruction"); 8300b57cec5SDimitry Andric if (SrcGIOrNull->TheDef->getName() == "G_CONSTANT" || 8310b57cec5SDimitry Andric SrcGIOrNull->TheDef->getName() == "G_FCONSTANT") { 8320b57cec5SDimitry Andric // imm/fpimm still have operands but we don't need to do anything with it 8330b57cec5SDimitry Andric // here since we don't support ImmLeaf predicates yet. However, we still 8340b57cec5SDimitry Andric // need to note the hidden operand to get GIM_CheckNumOperands correct. 8350b57cec5SDimitry Andric InsnMatcher.addOperand(OpIdx++, "", TempOpIdx); 8360b57cec5SDimitry Andric return InsnMatcher; 8370b57cec5SDimitry Andric } 8380b57cec5SDimitry Andric 839*0fca6ea1SDimitry Andric if (SrcGIOrNull->TheDef->getName() == "G_FRAME_INDEX") { 840*0fca6ea1SDimitry Andric InsnMatcher.addOperand(OpIdx++, Src.getName(), TempOpIdx); 841*0fca6ea1SDimitry Andric return InsnMatcher; 842*0fca6ea1SDimitry Andric } 843*0fca6ea1SDimitry Andric 8448bcb0991SDimitry Andric // Special case because the operand order is changed from setcc. The 8458bcb0991SDimitry Andric // predicate operand needs to be swapped from the last operand to the first 8468bcb0991SDimitry Andric // source. 8478bcb0991SDimitry Andric 848*0fca6ea1SDimitry Andric unsigned NumChildren = Src.getNumChildren(); 8498bcb0991SDimitry Andric bool IsFCmp = SrcGIOrNull->TheDef->getName() == "G_FCMP"; 8508bcb0991SDimitry Andric 8518bcb0991SDimitry Andric if (IsFCmp || SrcGIOrNull->TheDef->getName() == "G_ICMP") { 852*0fca6ea1SDimitry Andric const TreePatternNode &SrcChild = Src.getChild(NumChildren - 1); 853*0fca6ea1SDimitry Andric if (SrcChild.isLeaf()) { 854*0fca6ea1SDimitry Andric DefInit *DI = dyn_cast<DefInit>(SrcChild.getLeafValue()); 8558bcb0991SDimitry Andric Record *CCDef = DI ? DI->getDef() : nullptr; 8568bcb0991SDimitry Andric if (!CCDef || !CCDef->isSubClassOf("CondCode")) 8578bcb0991SDimitry Andric return failedImport("Unable to handle CondCode"); 8588bcb0991SDimitry Andric 8598bcb0991SDimitry Andric OperandMatcher &OM = 860*0fca6ea1SDimitry Andric InsnMatcher.addOperand(OpIdx++, SrcChild.getName(), TempOpIdx); 86106c3fb27SDimitry Andric StringRef PredType = IsFCmp ? CCDef->getValueAsString("FCmpPredicate") 86206c3fb27SDimitry Andric : CCDef->getValueAsString("ICmpPredicate"); 8638bcb0991SDimitry Andric 8648bcb0991SDimitry Andric if (!PredType.empty()) { 8655ffd83dbSDimitry Andric OM.addPredicate<CmpPredicateOperandMatcher>(std::string(PredType)); 8668bcb0991SDimitry Andric // Process the other 2 operands normally. 8678bcb0991SDimitry Andric --NumChildren; 8688bcb0991SDimitry Andric } 8698bcb0991SDimitry Andric } 8708bcb0991SDimitry Andric } 8718bcb0991SDimitry Andric 8720b57cec5SDimitry Andric // Match the used operands (i.e. the children of the operator). 8738bcb0991SDimitry Andric bool IsIntrinsic = 8748bcb0991SDimitry Andric SrcGIOrNull->TheDef->getName() == "G_INTRINSIC" || 8755f757f3fSDimitry Andric SrcGIOrNull->TheDef->getName() == "G_INTRINSIC_W_SIDE_EFFECTS" || 8765f757f3fSDimitry Andric SrcGIOrNull->TheDef->getName() == "G_INTRINSIC_CONVERGENT" || 8775f757f3fSDimitry Andric SrcGIOrNull->TheDef->getName() == 8785f757f3fSDimitry Andric "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS"; 879*0fca6ea1SDimitry Andric const CodeGenIntrinsic *II = Src.getIntrinsicInfo(CGP); 8808bcb0991SDimitry Andric if (IsIntrinsic && !II) 8818bcb0991SDimitry Andric return failedImport("Expected IntInit containing intrinsic ID)"); 8828bcb0991SDimitry Andric 883*0fca6ea1SDimitry Andric for (unsigned I = 0; I != NumChildren; ++I) { 884*0fca6ea1SDimitry Andric const TreePatternNode &SrcChild = Src.getChild(I); 8850b57cec5SDimitry Andric 886480093f4SDimitry Andric // We need to determine the meaning of a literal integer based on the 887480093f4SDimitry Andric // context. If this is a field required to be an immediate (such as an 888480093f4SDimitry Andric // immarg intrinsic argument), the required predicates are different than 889480093f4SDimitry Andric // a constant which may be materialized in a register. If we have an 890480093f4SDimitry Andric // argument that is required to be an immediate, we should not emit an LLT 891480093f4SDimitry Andric // type check, and should not be looking for a G_CONSTANT defined 892480093f4SDimitry Andric // register. 893*0fca6ea1SDimitry Andric bool OperandIsImmArg = SrcGIOrNull->isInOperandImmArg(I); 894480093f4SDimitry Andric 8950b57cec5SDimitry Andric // SelectionDAG allows pointers to be represented with iN since it doesn't 89606c3fb27SDimitry Andric // distinguish between pointers and integers but they are different types 89706c3fb27SDimitry Andric // in GlobalISel. Coerce integers to pointers to address space 0 if the 89806c3fb27SDimitry Andric // context indicates a pointer. 899480093f4SDimitry Andric // 900*0fca6ea1SDimitry Andric bool OperandIsAPointer = SrcGIOrNull->isInOperandAPointer(I); 9010b57cec5SDimitry Andric 9028bcb0991SDimitry Andric if (IsIntrinsic) { 9030b57cec5SDimitry Andric // For G_INTRINSIC/G_INTRINSIC_W_SIDE_EFFECTS, the operand immediately 9040b57cec5SDimitry Andric // following the defs is an intrinsic ID. 905*0fca6ea1SDimitry Andric if (I == 0) { 9060b57cec5SDimitry Andric OperandMatcher &OM = 907*0fca6ea1SDimitry Andric InsnMatcher.addOperand(OpIdx++, SrcChild.getName(), TempOpIdx); 9080b57cec5SDimitry Andric OM.addPredicate<IntrinsicIDOperandMatcher>(II); 9090b57cec5SDimitry Andric continue; 9100b57cec5SDimitry Andric } 9110b57cec5SDimitry Andric 912480093f4SDimitry Andric // We have to check intrinsics for llvm_anyptr_ty and immarg parameters. 9138bcb0991SDimitry Andric // 9148bcb0991SDimitry Andric // Note that we have to look at the i-1th parameter, because we don't 9158bcb0991SDimitry Andric // have the intrinsic ID in the intrinsic's parameter list. 916*0fca6ea1SDimitry Andric OperandIsAPointer |= II->isParamAPointer(I - 1); 917*0fca6ea1SDimitry Andric OperandIsImmArg |= II->isParamImmArg(I - 1); 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric if (auto Error = 9210b57cec5SDimitry Andric importChildMatcher(Rule, InsnMatcher, SrcChild, OperandIsAPointer, 922480093f4SDimitry Andric OperandIsImmArg, OpIdx++, TempOpIdx)) 9230b57cec5SDimitry Andric return std::move(Error); 9240b57cec5SDimitry Andric } 9250b57cec5SDimitry Andric } 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric return InsnMatcher; 9280b57cec5SDimitry Andric } 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric Error GlobalISelEmitter::importComplexPatternOperandMatcher( 9310b57cec5SDimitry Andric OperandMatcher &OM, Record *R, unsigned &TempOpIdx) const { 9320b57cec5SDimitry Andric const auto &ComplexPattern = ComplexPatternEquivs.find(R); 9330b57cec5SDimitry Andric if (ComplexPattern == ComplexPatternEquivs.end()) 9340b57cec5SDimitry Andric return failedImport("SelectionDAG ComplexPattern (" + R->getName() + 9350b57cec5SDimitry Andric ") not mapped to GlobalISel"); 9360b57cec5SDimitry Andric 9370b57cec5SDimitry Andric OM.addPredicate<ComplexPatternOperandMatcher>(OM, *ComplexPattern->second); 9380b57cec5SDimitry Andric TempOpIdx++; 9390b57cec5SDimitry Andric return Error::success(); 9400b57cec5SDimitry Andric } 9410b57cec5SDimitry Andric 9428bcb0991SDimitry Andric // Get the name to use for a pattern operand. For an anonymous physical register 9438bcb0991SDimitry Andric // input, this should use the register name. 944*0fca6ea1SDimitry Andric static StringRef getSrcChildName(const TreePatternNode &SrcChild, 9458bcb0991SDimitry Andric Record *&PhysReg) { 946*0fca6ea1SDimitry Andric StringRef SrcChildName = SrcChild.getName(); 947*0fca6ea1SDimitry Andric if (SrcChildName.empty() && SrcChild.isLeaf()) { 948*0fca6ea1SDimitry Andric if (auto *ChildDefInit = dyn_cast<DefInit>(SrcChild.getLeafValue())) { 9498bcb0991SDimitry Andric auto *ChildRec = ChildDefInit->getDef(); 9508bcb0991SDimitry Andric if (ChildRec->isSubClassOf("Register")) { 9518bcb0991SDimitry Andric SrcChildName = ChildRec->getName(); 9528bcb0991SDimitry Andric PhysReg = ChildRec; 9538bcb0991SDimitry Andric } 9548bcb0991SDimitry Andric } 9558bcb0991SDimitry Andric } 9568bcb0991SDimitry Andric 9578bcb0991SDimitry Andric return SrcChildName; 9588bcb0991SDimitry Andric } 9598bcb0991SDimitry Andric 960480093f4SDimitry Andric Error GlobalISelEmitter::importChildMatcher( 961480093f4SDimitry Andric RuleMatcher &Rule, InstructionMatcher &InsnMatcher, 962*0fca6ea1SDimitry Andric const TreePatternNode &SrcChild, bool OperandIsAPointer, 963480093f4SDimitry Andric bool OperandIsImmArg, unsigned OpIdx, unsigned &TempOpIdx) { 9648bcb0991SDimitry Andric 9658bcb0991SDimitry Andric Record *PhysReg = nullptr; 966e8d8bef9SDimitry Andric std::string SrcChildName = std::string(getSrcChildName(SrcChild, PhysReg)); 967*0fca6ea1SDimitry Andric if (!SrcChild.isLeaf() && 968*0fca6ea1SDimitry Andric SrcChild.getOperator()->isSubClassOf("ComplexPattern")) { 969e8d8bef9SDimitry Andric // The "name" of a non-leaf complex pattern (MY_PAT $op1, $op2) is 970e8d8bef9SDimitry Andric // "MY_PAT:op1:op2" and the ones with same "name" represent same operand. 971*0fca6ea1SDimitry Andric std::string PatternName = std::string(SrcChild.getOperator()->getName()); 972*0fca6ea1SDimitry Andric for (unsigned I = 0; I < SrcChild.getNumChildren(); ++I) { 973e8d8bef9SDimitry Andric PatternName += ":"; 974*0fca6ea1SDimitry Andric PatternName += SrcChild.getChild(I).getName(); 975e8d8bef9SDimitry Andric } 976e8d8bef9SDimitry Andric SrcChildName = PatternName; 977e8d8bef9SDimitry Andric } 9788bcb0991SDimitry Andric 9795ffd83dbSDimitry Andric OperandMatcher &OM = 980e8d8bef9SDimitry Andric PhysReg ? InsnMatcher.addPhysRegInput(PhysReg, OpIdx, TempOpIdx) 981e8d8bef9SDimitry Andric : InsnMatcher.addOperand(OpIdx, SrcChildName, TempOpIdx); 9820b57cec5SDimitry Andric if (OM.isSameAsAnotherOperand()) 9830b57cec5SDimitry Andric return Error::success(); 9840b57cec5SDimitry Andric 985*0fca6ea1SDimitry Andric ArrayRef<TypeSetByHwMode> ChildTypes = SrcChild.getExtTypes(); 9860b57cec5SDimitry Andric if (ChildTypes.size() != 1) 9870b57cec5SDimitry Andric return failedImport("Src pattern child has multiple results"); 9880b57cec5SDimitry Andric 9890b57cec5SDimitry Andric // Check MBB's before the type check since they are not a known type. 990*0fca6ea1SDimitry Andric if (!SrcChild.isLeaf()) { 991*0fca6ea1SDimitry Andric if (SrcChild.getOperator()->isSubClassOf("SDNode")) { 992*0fca6ea1SDimitry Andric auto &ChildSDNI = CGP.getSDNodeInfo(SrcChild.getOperator()); 9930b57cec5SDimitry Andric if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") { 9940b57cec5SDimitry Andric OM.addPredicate<MBBOperandMatcher>(); 9950b57cec5SDimitry Andric return Error::success(); 9960b57cec5SDimitry Andric } 997*0fca6ea1SDimitry Andric if (SrcChild.getOperator()->getName() == "timm") { 9988bcb0991SDimitry Andric OM.addPredicate<ImmOperandMatcher>(); 999fe6060f1SDimitry Andric 1000fe6060f1SDimitry Andric // Add predicates, if any 1001*0fca6ea1SDimitry Andric for (const TreePredicateCall &Call : SrcChild.getPredicateCalls()) { 1002fe6060f1SDimitry Andric const TreePredicateFn &Predicate = Call.Fn; 1003fe6060f1SDimitry Andric 1004fe6060f1SDimitry Andric // Only handle immediate patterns for now 1005fe6060f1SDimitry Andric if (Predicate.isImmediatePattern()) { 1006fe6060f1SDimitry Andric OM.addPredicate<OperandImmPredicateMatcher>(Predicate); 1007fe6060f1SDimitry Andric } 1008fe6060f1SDimitry Andric } 1009fe6060f1SDimitry Andric 10108bcb0991SDimitry Andric return Error::success(); 10118bcb0991SDimitry Andric } 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric } 10140b57cec5SDimitry Andric 1015480093f4SDimitry Andric // Immediate arguments have no meaningful type to check as they don't have 1016480093f4SDimitry Andric // registers. 1017480093f4SDimitry Andric if (!OperandIsImmArg) { 10180b57cec5SDimitry Andric if (auto Error = 10190b57cec5SDimitry Andric OM.addTypeCheckPredicate(ChildTypes.front(), OperandIsAPointer)) 10200b57cec5SDimitry Andric return failedImport(toString(std::move(Error)) + " for Src operand (" + 1021*0fca6ea1SDimitry Andric to_string(SrcChild) + ")"); 1022480093f4SDimitry Andric } 10230b57cec5SDimitry Andric 10245f757f3fSDimitry Andric // Try look up SrcChild for a (named) predicate operand if there is any. 10255f757f3fSDimitry Andric if (WaitingForNamedOperands) { 1026*0fca6ea1SDimitry Andric auto &ScopedNames = SrcChild.getNamesAsPredicateArg(); 10275f757f3fSDimitry Andric if (!ScopedNames.empty()) { 10285f757f3fSDimitry Andric auto PA = ScopedNames.begin(); 10295f757f3fSDimitry Andric std::string Name = getScopedName(PA->getScope(), PA->getIdentifier()); 10305f757f3fSDimitry Andric OM.addPredicate<RecordNamedOperandMatcher>(StoreIdxForName[Name], Name); 10315f757f3fSDimitry Andric --WaitingForNamedOperands; 10325f757f3fSDimitry Andric } 10335f757f3fSDimitry Andric } 10345f757f3fSDimitry Andric 10350b57cec5SDimitry Andric // Check for nested instructions. 1036*0fca6ea1SDimitry Andric if (!SrcChild.isLeaf()) { 1037*0fca6ea1SDimitry Andric if (SrcChild.getOperator()->isSubClassOf("ComplexPattern")) { 10380b57cec5SDimitry Andric // When a ComplexPattern is used as an operator, it should do the same 10390b57cec5SDimitry Andric // thing as when used as a leaf. However, the children of the operator 10400b57cec5SDimitry Andric // name the sub-operands that make up the complex operand and we must 10410b57cec5SDimitry Andric // prepare to reference them in the renderer too. 10420b57cec5SDimitry Andric unsigned RendererID = TempOpIdx; 10430b57cec5SDimitry Andric if (auto Error = importComplexPatternOperandMatcher( 1044*0fca6ea1SDimitry Andric OM, SrcChild.getOperator(), TempOpIdx)) 10450b57cec5SDimitry Andric return Error; 10460b57cec5SDimitry Andric 1047*0fca6ea1SDimitry Andric for (unsigned I = 0, E = SrcChild.getNumChildren(); I != E; ++I) { 1048*0fca6ea1SDimitry Andric auto &SubOperand = SrcChild.getChild(I); 1049*0fca6ea1SDimitry Andric if (!SubOperand.getName().empty()) { 1050e8d8bef9SDimitry Andric if (auto Error = Rule.defineComplexSubOperand( 1051*0fca6ea1SDimitry Andric SubOperand.getName(), SrcChild.getOperator(), RendererID, I, 1052e8d8bef9SDimitry Andric SrcChildName)) 10530b57cec5SDimitry Andric return Error; 10540b57cec5SDimitry Andric } 10550b57cec5SDimitry Andric } 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric return Error::success(); 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric auto MaybeInsnOperand = OM.addPredicate<InstructionOperandMatcher>( 1061*0fca6ea1SDimitry Andric InsnMatcher.getRuleMatcher(), SrcChild.getName()); 106281ad6265SDimitry Andric if (!MaybeInsnOperand) { 10630b57cec5SDimitry Andric // This isn't strictly true. If the user were to provide exactly the same 10640b57cec5SDimitry Andric // matchers as the original operand then we could allow it. However, it's 10650b57cec5SDimitry Andric // simpler to not permit the redundant specification. 106606c3fb27SDimitry Andric return failedImport( 106706c3fb27SDimitry Andric "Nested instruction cannot be the same as another operand"); 10680b57cec5SDimitry Andric } 10690b57cec5SDimitry Andric 10700b57cec5SDimitry Andric // Map the node to a gMIR instruction. 10710b57cec5SDimitry Andric InstructionOperandMatcher &InsnOperand = **MaybeInsnOperand; 10720b57cec5SDimitry Andric auto InsnMatcherOrError = createAndImportSelDAGMatcher( 10730b57cec5SDimitry Andric Rule, InsnOperand.getInsnMatcher(), SrcChild, TempOpIdx); 10740b57cec5SDimitry Andric if (auto Error = InsnMatcherOrError.takeError()) 10750b57cec5SDimitry Andric return Error; 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andric return Error::success(); 10780b57cec5SDimitry Andric } 10790b57cec5SDimitry Andric 1080*0fca6ea1SDimitry Andric if (SrcChild.hasAnyPredicate()) 10810b57cec5SDimitry Andric return failedImport("Src pattern child has unsupported predicate"); 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric // Check for constant immediates. 1084*0fca6ea1SDimitry Andric if (auto *ChildInt = dyn_cast<IntInit>(SrcChild.getLeafValue())) { 1085480093f4SDimitry Andric if (OperandIsImmArg) { 1086480093f4SDimitry Andric // Checks for argument directly in operand list 1087480093f4SDimitry Andric OM.addPredicate<LiteralIntOperandMatcher>(ChildInt->getValue()); 1088480093f4SDimitry Andric } else { 1089480093f4SDimitry Andric // Checks for materialized constant 10900b57cec5SDimitry Andric OM.addPredicate<ConstantIntOperandMatcher>(ChildInt->getValue()); 1091480093f4SDimitry Andric } 10920b57cec5SDimitry Andric return Error::success(); 10930b57cec5SDimitry Andric } 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andric // Check for def's like register classes or ComplexPattern's. 1096*0fca6ea1SDimitry Andric if (auto *ChildDefInit = dyn_cast<DefInit>(SrcChild.getLeafValue())) { 10970b57cec5SDimitry Andric auto *ChildRec = ChildDefInit->getDef(); 10980b57cec5SDimitry Andric 10990b57cec5SDimitry Andric // Check for register classes. 11000b57cec5SDimitry Andric if (ChildRec->isSubClassOf("RegisterClass") || 11010b57cec5SDimitry Andric ChildRec->isSubClassOf("RegisterOperand")) { 11020b57cec5SDimitry Andric OM.addPredicate<RegisterBankOperandMatcher>( 11030b57cec5SDimitry Andric Target.getRegisterClass(getInitValueAsRegClass(ChildDefInit))); 11040b57cec5SDimitry Andric return Error::success(); 11050b57cec5SDimitry Andric } 11060b57cec5SDimitry Andric 11078bcb0991SDimitry Andric if (ChildRec->isSubClassOf("Register")) { 11088bcb0991SDimitry Andric // This just be emitted as a copy to the specific register. 11098bcb0991SDimitry Andric ValueTypeByHwMode VT = ChildTypes.front().getValueTypeByHwMode(); 111006c3fb27SDimitry Andric const CodeGenRegisterClass *RC = 111106c3fb27SDimitry Andric CGRegs.getMinimalPhysRegClass(ChildRec, &VT); 11128bcb0991SDimitry Andric if (!RC) { 11138bcb0991SDimitry Andric return failedImport( 11148bcb0991SDimitry Andric "Could not determine physical register class of pattern source"); 11158bcb0991SDimitry Andric } 11168bcb0991SDimitry Andric 11178bcb0991SDimitry Andric OM.addPredicate<RegisterBankOperandMatcher>(*RC); 11188bcb0991SDimitry Andric return Error::success(); 11198bcb0991SDimitry Andric } 11208bcb0991SDimitry Andric 11210b57cec5SDimitry Andric // Check for ValueType. 11220b57cec5SDimitry Andric if (ChildRec->isSubClassOf("ValueType")) { 11230b57cec5SDimitry Andric // We already added a type check as standard practice so this doesn't need 11240b57cec5SDimitry Andric // to do anything. 11250b57cec5SDimitry Andric return Error::success(); 11260b57cec5SDimitry Andric } 11270b57cec5SDimitry Andric 11280b57cec5SDimitry Andric // Check for ComplexPattern's. 11290b57cec5SDimitry Andric if (ChildRec->isSubClassOf("ComplexPattern")) 11300b57cec5SDimitry Andric return importComplexPatternOperandMatcher(OM, ChildRec, TempOpIdx); 11310b57cec5SDimitry Andric 11320b57cec5SDimitry Andric if (ChildRec->isSubClassOf("ImmLeaf")) { 11330b57cec5SDimitry Andric return failedImport( 11340b57cec5SDimitry Andric "Src pattern child def is an unsupported tablegen class (ImmLeaf)"); 11350b57cec5SDimitry Andric } 11360b57cec5SDimitry Andric 11375ffd83dbSDimitry Andric // Place holder for SRCVALUE nodes. Nothing to do here. 11385ffd83dbSDimitry Andric if (ChildRec->getName() == "srcvalue") 11395ffd83dbSDimitry Andric return Error::success(); 11405ffd83dbSDimitry Andric 1141e8d8bef9SDimitry Andric const bool ImmAllOnesV = ChildRec->getName() == "immAllOnesV"; 1142e8d8bef9SDimitry Andric if (ImmAllOnesV || ChildRec->getName() == "immAllZerosV") { 1143e8d8bef9SDimitry Andric auto MaybeInsnOperand = OM.addPredicate<InstructionOperandMatcher>( 1144*0fca6ea1SDimitry Andric InsnMatcher.getRuleMatcher(), SrcChild.getName(), false); 1145e8d8bef9SDimitry Andric InstructionOperandMatcher &InsnOperand = **MaybeInsnOperand; 1146e8d8bef9SDimitry Andric 1147e8d8bef9SDimitry Andric ValueTypeByHwMode VTy = ChildTypes.front().getValueTypeByHwMode(); 1148e8d8bef9SDimitry Andric 114906c3fb27SDimitry Andric const CodeGenInstruction &BuildVector = 115006c3fb27SDimitry Andric Target.getInstruction(RK.getDef("G_BUILD_VECTOR")); 115106c3fb27SDimitry Andric const CodeGenInstruction &BuildVectorTrunc = 115206c3fb27SDimitry Andric Target.getInstruction(RK.getDef("G_BUILD_VECTOR_TRUNC")); 1153e8d8bef9SDimitry Andric 1154e8d8bef9SDimitry Andric // Treat G_BUILD_VECTOR as the canonical opcode, and G_BUILD_VECTOR_TRUNC 1155e8d8bef9SDimitry Andric // as an alternative. 1156e8d8bef9SDimitry Andric InsnOperand.getInsnMatcher().addPredicate<InstructionOpcodeMatcher>( 1157bdd1243dSDimitry Andric ArrayRef({&BuildVector, &BuildVectorTrunc})); 1158e8d8bef9SDimitry Andric 1159e8d8bef9SDimitry Andric // TODO: Handle both G_BUILD_VECTOR and G_BUILD_VECTOR_TRUNC We could 1160e8d8bef9SDimitry Andric // theoretically not emit any opcode check, but getOpcodeMatcher currently 1161e8d8bef9SDimitry Andric // has to succeed. 1162e8d8bef9SDimitry Andric OperandMatcher &OM = 1163e8d8bef9SDimitry Andric InsnOperand.getInsnMatcher().addOperand(0, "", TempOpIdx); 1164e8d8bef9SDimitry Andric if (auto Error = 1165e8d8bef9SDimitry Andric OM.addTypeCheckPredicate(VTy, false /* OperandIsAPointer */)) 1166e8d8bef9SDimitry Andric return failedImport(toString(std::move(Error)) + 1167e8d8bef9SDimitry Andric " for result of Src pattern operator"); 1168e8d8bef9SDimitry Andric 1169e8d8bef9SDimitry Andric InsnOperand.getInsnMatcher().addPredicate<VectorSplatImmPredicateMatcher>( 1170e8d8bef9SDimitry Andric ImmAllOnesV ? VectorSplatImmPredicateMatcher::AllOnes 1171e8d8bef9SDimitry Andric : VectorSplatImmPredicateMatcher::AllZeros); 1172e8d8bef9SDimitry Andric return Error::success(); 1173e8d8bef9SDimitry Andric } 1174e8d8bef9SDimitry Andric 11750b57cec5SDimitry Andric return failedImport( 11760b57cec5SDimitry Andric "Src pattern child def is an unsupported tablegen class"); 11770b57cec5SDimitry Andric } 11780b57cec5SDimitry Andric 11790b57cec5SDimitry Andric return failedImport("Src pattern child is an unsupported kind"); 11800b57cec5SDimitry Andric } 11810b57cec5SDimitry Andric 11820b57cec5SDimitry Andric Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer( 11830b57cec5SDimitry Andric action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder, 1184*0fca6ea1SDimitry Andric const TreePatternNode &DstChild, const TreePatternNode &Src) { 11850b57cec5SDimitry Andric 1186*0fca6ea1SDimitry Andric const auto &SubOperand = Rule.getComplexSubOperand(DstChild.getName()); 118781ad6265SDimitry Andric if (SubOperand) { 11880b57cec5SDimitry Andric DstMIBuilder.addRenderer<RenderComplexPatternOperand>( 1189*0fca6ea1SDimitry Andric *std::get<0>(*SubOperand), DstChild.getName(), std::get<1>(*SubOperand), 1190*0fca6ea1SDimitry Andric std::get<2>(*SubOperand)); 11910b57cec5SDimitry Andric return InsertPt; 11920b57cec5SDimitry Andric } 11930b57cec5SDimitry Andric 1194*0fca6ea1SDimitry Andric if (!DstChild.isLeaf()) { 1195*0fca6ea1SDimitry Andric if (DstChild.getOperator()->isSubClassOf("SDNodeXForm")) { 1196*0fca6ea1SDimitry Andric auto &Child = DstChild.getChild(0); 1197*0fca6ea1SDimitry Andric auto I = SDNodeXFormEquivs.find(DstChild.getOperator()); 11980b57cec5SDimitry Andric if (I != SDNodeXFormEquivs.end()) { 1199*0fca6ea1SDimitry Andric Record *XFormOpc = DstChild.getOperator()->getValueAsDef("Opcode"); 1200480093f4SDimitry Andric if (XFormOpc->getName() == "timm") { 1201480093f4SDimitry Andric // If this is a TargetConstant, there won't be a corresponding 1202480093f4SDimitry Andric // instruction to transform. Instead, this will refer directly to an 1203480093f4SDimitry Andric // operand in an instruction's operand list. 1204480093f4SDimitry Andric DstMIBuilder.addRenderer<CustomOperandRenderer>(*I->second, 1205*0fca6ea1SDimitry Andric Child.getName()); 1206480093f4SDimitry Andric } else { 1207*0fca6ea1SDimitry Andric DstMIBuilder.addRenderer<CustomRenderer>(*I->second, Child.getName()); 1208480093f4SDimitry Andric } 1209480093f4SDimitry Andric 12100b57cec5SDimitry Andric return InsertPt; 12110b57cec5SDimitry Andric } 1212*0fca6ea1SDimitry Andric return failedImport("SDNodeXForm " + Child.getName() + 12130b57cec5SDimitry Andric " has no custom renderer"); 12140b57cec5SDimitry Andric } 12150b57cec5SDimitry Andric 12160b57cec5SDimitry Andric // We accept 'bb' here. It's an operator because BasicBlockSDNode isn't 12170b57cec5SDimitry Andric // inline, but in MI it's just another operand. 1218*0fca6ea1SDimitry Andric if (DstChild.getOperator()->isSubClassOf("SDNode")) { 1219*0fca6ea1SDimitry Andric auto &ChildSDNI = CGP.getSDNodeInfo(DstChild.getOperator()); 12200b57cec5SDimitry Andric if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") { 1221*0fca6ea1SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(DstChild.getName()); 12220b57cec5SDimitry Andric return InsertPt; 12230b57cec5SDimitry Andric } 12240b57cec5SDimitry Andric } 12250b57cec5SDimitry Andric 12260b57cec5SDimitry Andric // Similarly, imm is an operator in TreePatternNode's view but must be 12270b57cec5SDimitry Andric // rendered as operands. 12280b57cec5SDimitry Andric // FIXME: The target should be able to choose sign-extended when appropriate 12290b57cec5SDimitry Andric // (e.g. on Mips). 1230*0fca6ea1SDimitry Andric if (DstChild.getOperator()->getName() == "timm") { 1231*0fca6ea1SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(DstChild.getName()); 12328bcb0991SDimitry Andric return InsertPt; 1233*0fca6ea1SDimitry Andric } 1234*0fca6ea1SDimitry Andric if (DstChild.getOperator()->getName() == "tframeindex") { 1235*0fca6ea1SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(DstChild.getName()); 12360b57cec5SDimitry Andric return InsertPt; 1237*0fca6ea1SDimitry Andric } 1238*0fca6ea1SDimitry Andric if (DstChild.getOperator()->getName() == "imm") { 1239*0fca6ea1SDimitry Andric DstMIBuilder.addRenderer<CopyConstantAsImmRenderer>(DstChild.getName()); 1240*0fca6ea1SDimitry Andric return InsertPt; 1241*0fca6ea1SDimitry Andric } 1242*0fca6ea1SDimitry Andric if (DstChild.getOperator()->getName() == "fpimm") { 12430b57cec5SDimitry Andric DstMIBuilder.addRenderer<CopyFConstantAsFPImmRenderer>( 1244*0fca6ea1SDimitry Andric DstChild.getName()); 12450b57cec5SDimitry Andric return InsertPt; 12460b57cec5SDimitry Andric } 12470b57cec5SDimitry Andric 1248*0fca6ea1SDimitry Andric if (DstChild.getOperator()->isSubClassOf("Instruction")) { 1249*0fca6ea1SDimitry Andric auto OpTy = getInstResultType(DstChild, Target); 12505ffd83dbSDimitry Andric if (!OpTy) 12515ffd83dbSDimitry Andric return OpTy.takeError(); 12520b57cec5SDimitry Andric 12530b57cec5SDimitry Andric unsigned TempRegID = Rule.allocateTempRegID(); 125406c3fb27SDimitry Andric InsertPt = 125506c3fb27SDimitry Andric Rule.insertAction<MakeTempRegisterAction>(InsertPt, *OpTy, TempRegID); 12560b57cec5SDimitry Andric DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID); 12570b57cec5SDimitry Andric 12580b57cec5SDimitry Andric auto InsertPtOrError = createAndImportSubInstructionRenderer( 125906c3fb27SDimitry Andric ++InsertPt, Rule, DstChild, Src, TempRegID); 12600b57cec5SDimitry Andric if (auto Error = InsertPtOrError.takeError()) 12610b57cec5SDimitry Andric return std::move(Error); 12620b57cec5SDimitry Andric return InsertPtOrError.get(); 12630b57cec5SDimitry Andric } 12640b57cec5SDimitry Andric 126506c3fb27SDimitry Andric return failedImport("Dst pattern child isn't a leaf node or an MBB" + 1266*0fca6ea1SDimitry Andric llvm::to_string(DstChild)); 12670b57cec5SDimitry Andric } 12680b57cec5SDimitry Andric 12690b57cec5SDimitry Andric // It could be a specific immediate in which case we should just check for 12700b57cec5SDimitry Andric // that immediate. 12710b57cec5SDimitry Andric if (const IntInit *ChildIntInit = 1272*0fca6ea1SDimitry Andric dyn_cast<IntInit>(DstChild.getLeafValue())) { 12730b57cec5SDimitry Andric DstMIBuilder.addRenderer<ImmRenderer>(ChildIntInit->getValue()); 12740b57cec5SDimitry Andric return InsertPt; 12750b57cec5SDimitry Andric } 12760b57cec5SDimitry Andric 12770b57cec5SDimitry Andric // Otherwise, we're looking for a bog-standard RegisterClass operand. 1278*0fca6ea1SDimitry Andric if (auto *ChildDefInit = dyn_cast<DefInit>(DstChild.getLeafValue())) { 12790b57cec5SDimitry Andric auto *ChildRec = ChildDefInit->getDef(); 12800b57cec5SDimitry Andric 1281*0fca6ea1SDimitry Andric ArrayRef<TypeSetByHwMode> ChildTypes = DstChild.getExtTypes(); 12820b57cec5SDimitry Andric if (ChildTypes.size() != 1) 12830b57cec5SDimitry Andric return failedImport("Dst pattern child has multiple results"); 12840b57cec5SDimitry Andric 1285bdd1243dSDimitry Andric std::optional<LLTCodeGen> OpTyOrNone; 12860b57cec5SDimitry Andric if (ChildTypes.front().isMachineValueType()) 12870b57cec5SDimitry Andric OpTyOrNone = MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy); 12880b57cec5SDimitry Andric if (!OpTyOrNone) 12890b57cec5SDimitry Andric return failedImport("Dst operand has an unsupported type"); 12900b57cec5SDimitry Andric 12910b57cec5SDimitry Andric if (ChildRec->isSubClassOf("Register")) { 1292e8d8bef9SDimitry Andric DstMIBuilder.addRenderer<AddRegisterRenderer>(Target, ChildRec); 12930b57cec5SDimitry Andric return InsertPt; 12940b57cec5SDimitry Andric } 12950b57cec5SDimitry Andric 12960b57cec5SDimitry Andric if (ChildRec->isSubClassOf("RegisterClass") || 12970b57cec5SDimitry Andric ChildRec->isSubClassOf("RegisterOperand") || 12980b57cec5SDimitry Andric ChildRec->isSubClassOf("ValueType")) { 12990b57cec5SDimitry Andric if (ChildRec->isSubClassOf("RegisterOperand") && 13000b57cec5SDimitry Andric !ChildRec->isValueUnset("GIZeroRegister")) { 13010b57cec5SDimitry Andric DstMIBuilder.addRenderer<CopyOrAddZeroRegRenderer>( 1302*0fca6ea1SDimitry Andric DstChild.getName(), ChildRec->getValueAsDef("GIZeroRegister")); 13030b57cec5SDimitry Andric return InsertPt; 13040b57cec5SDimitry Andric } 13050b57cec5SDimitry Andric 1306*0fca6ea1SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(DstChild.getName()); 13070b57cec5SDimitry Andric return InsertPt; 13080b57cec5SDimitry Andric } 13090b57cec5SDimitry Andric 13108bcb0991SDimitry Andric if (ChildRec->isSubClassOf("SubRegIndex")) { 13118bcb0991SDimitry Andric CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(ChildRec); 13128bcb0991SDimitry Andric DstMIBuilder.addRenderer<ImmRenderer>(SubIdx->EnumValue); 13138bcb0991SDimitry Andric return InsertPt; 13148bcb0991SDimitry Andric } 13158bcb0991SDimitry Andric 13160b57cec5SDimitry Andric if (ChildRec->isSubClassOf("ComplexPattern")) { 13170b57cec5SDimitry Andric const auto &ComplexPattern = ComplexPatternEquivs.find(ChildRec); 13180b57cec5SDimitry Andric if (ComplexPattern == ComplexPatternEquivs.end()) 13190b57cec5SDimitry Andric return failedImport( 13200b57cec5SDimitry Andric "SelectionDAG ComplexPattern not mapped to GlobalISel"); 13210b57cec5SDimitry Andric 1322*0fca6ea1SDimitry Andric const OperandMatcher &OM = Rule.getOperandMatcher(DstChild.getName()); 13230b57cec5SDimitry Andric DstMIBuilder.addRenderer<RenderComplexPatternOperand>( 1324*0fca6ea1SDimitry Andric *ComplexPattern->second, DstChild.getName(), 13250b57cec5SDimitry Andric OM.getAllocatedTemporariesBaseID()); 13260b57cec5SDimitry Andric return InsertPt; 13270b57cec5SDimitry Andric } 13280b57cec5SDimitry Andric 13290b57cec5SDimitry Andric return failedImport( 13300b57cec5SDimitry Andric "Dst pattern child def is an unsupported tablegen class"); 13310b57cec5SDimitry Andric } 133206c3fb27SDimitry Andric 133306c3fb27SDimitry Andric // Handle the case where the MVT/register class is omitted in the dest pattern 133406c3fb27SDimitry Andric // but MVT exists in the source pattern. 1335*0fca6ea1SDimitry Andric if (isa<UnsetInit>(DstChild.getLeafValue())) { 1336*0fca6ea1SDimitry Andric for (unsigned NumOp = 0; NumOp < Src.getNumChildren(); NumOp++) 1337*0fca6ea1SDimitry Andric if (Src.getChild(NumOp).getName() == DstChild.getName()) { 1338*0fca6ea1SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(Src.getChild(NumOp).getName()); 133906c3fb27SDimitry Andric return InsertPt; 134006c3fb27SDimitry Andric } 134106c3fb27SDimitry Andric } 13420b57cec5SDimitry Andric return failedImport("Dst pattern child is an unsupported kind"); 13430b57cec5SDimitry Andric } 13440b57cec5SDimitry Andric 13450b57cec5SDimitry Andric Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer( 1346*0fca6ea1SDimitry Andric RuleMatcher &M, InstructionMatcher &InsnMatcher, const TreePatternNode &Src, 1347*0fca6ea1SDimitry Andric const TreePatternNode &Dst) { 13480b57cec5SDimitry Andric auto InsertPtOrError = createInstructionRenderer(M.actions_end(), M, Dst); 13490b57cec5SDimitry Andric if (auto Error = InsertPtOrError.takeError()) 13500b57cec5SDimitry Andric return std::move(Error); 13510b57cec5SDimitry Andric 13520b57cec5SDimitry Andric action_iterator InsertPt = InsertPtOrError.get(); 13530b57cec5SDimitry Andric BuildMIAction &DstMIBuilder = *static_cast<BuildMIAction *>(InsertPt->get()); 13540b57cec5SDimitry Andric 13558bcb0991SDimitry Andric for (auto PhysInput : InsnMatcher.getPhysRegInputs()) { 13568bcb0991SDimitry Andric InsertPt = M.insertAction<BuildMIAction>( 13578bcb0991SDimitry Andric InsertPt, M.allocateOutputInsnID(), 13588bcb0991SDimitry Andric &Target.getInstruction(RK.getDef("COPY"))); 13598bcb0991SDimitry Andric BuildMIAction &CopyToPhysRegMIBuilder = 13608bcb0991SDimitry Andric *static_cast<BuildMIAction *>(InsertPt->get()); 136106c3fb27SDimitry Andric CopyToPhysRegMIBuilder.addRenderer<AddRegisterRenderer>( 136206c3fb27SDimitry Andric Target, PhysInput.first, true); 13638bcb0991SDimitry Andric CopyToPhysRegMIBuilder.addRenderer<CopyPhysRegRenderer>(PhysInput.first); 13648bcb0991SDimitry Andric } 13658bcb0991SDimitry Andric 136606c3fb27SDimitry Andric if (auto Error = 136706c3fb27SDimitry Andric importExplicitDefRenderers(InsertPt, M, DstMIBuilder, Src, Dst) 1368e8d8bef9SDimitry Andric .takeError()) 1369e8d8bef9SDimitry Andric return std::move(Error); 13700b57cec5SDimitry Andric 137106c3fb27SDimitry Andric if (auto Error = 137206c3fb27SDimitry Andric importExplicitUseRenderers(InsertPt, M, DstMIBuilder, Dst, Src) 13730b57cec5SDimitry Andric .takeError()) 13740b57cec5SDimitry Andric return std::move(Error); 13750b57cec5SDimitry Andric 13760b57cec5SDimitry Andric return DstMIBuilder; 13770b57cec5SDimitry Andric } 13780b57cec5SDimitry Andric 13790b57cec5SDimitry Andric Expected<action_iterator> 13800b57cec5SDimitry Andric GlobalISelEmitter::createAndImportSubInstructionRenderer( 1381*0fca6ea1SDimitry Andric const action_iterator InsertPt, RuleMatcher &M, const TreePatternNode &Dst, 1382*0fca6ea1SDimitry Andric const TreePatternNode &Src, unsigned TempRegID) { 13830b57cec5SDimitry Andric auto InsertPtOrError = createInstructionRenderer(InsertPt, M, Dst); 13840b57cec5SDimitry Andric 13850b57cec5SDimitry Andric // TODO: Assert there's exactly one result. 13860b57cec5SDimitry Andric 13870b57cec5SDimitry Andric if (auto Error = InsertPtOrError.takeError()) 13880b57cec5SDimitry Andric return std::move(Error); 13890b57cec5SDimitry Andric 13900b57cec5SDimitry Andric BuildMIAction &DstMIBuilder = 13910b57cec5SDimitry Andric *static_cast<BuildMIAction *>(InsertPtOrError.get()->get()); 13920b57cec5SDimitry Andric 13930b57cec5SDimitry Andric // Assign the result to TempReg. 13940b57cec5SDimitry Andric DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID, true); 13950b57cec5SDimitry Andric 1396*0fca6ea1SDimitry Andric // Handle additional (ignored) results. 1397*0fca6ea1SDimitry Andric if (DstMIBuilder.getCGI()->Operands.NumDefs > 1) { 1398*0fca6ea1SDimitry Andric InsertPtOrError = importExplicitDefRenderers( 1399*0fca6ea1SDimitry Andric std::prev(*InsertPtOrError), M, DstMIBuilder, Src, Dst, /*Start=*/1); 1400*0fca6ea1SDimitry Andric if (auto Error = InsertPtOrError.takeError()) 1401*0fca6ea1SDimitry Andric return std::move(Error); 1402*0fca6ea1SDimitry Andric } 1403*0fca6ea1SDimitry Andric 140406c3fb27SDimitry Andric InsertPtOrError = importExplicitUseRenderers(InsertPtOrError.get(), M, 140506c3fb27SDimitry Andric DstMIBuilder, Dst, Src); 14060b57cec5SDimitry Andric if (auto Error = InsertPtOrError.takeError()) 14070b57cec5SDimitry Andric return std::move(Error); 14080b57cec5SDimitry Andric 14098bcb0991SDimitry Andric // We need to make sure that when we import an INSERT_SUBREG as a 14108bcb0991SDimitry Andric // subinstruction that it ends up being constrained to the correct super 14118bcb0991SDimitry Andric // register and subregister classes. 1412*0fca6ea1SDimitry Andric auto OpName = Target.getInstruction(Dst.getOperator()).TheDef->getName(); 14138bcb0991SDimitry Andric if (OpName == "INSERT_SUBREG") { 1414*0fca6ea1SDimitry Andric auto SubClass = inferRegClassFromPattern(Dst.getChild(1)); 14158bcb0991SDimitry Andric if (!SubClass) 14168bcb0991SDimitry Andric return failedImport( 14178bcb0991SDimitry Andric "Cannot infer register class from INSERT_SUBREG operand #1"); 1418bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *> SuperClass = 1419*0fca6ea1SDimitry Andric inferSuperRegisterClassForNode(Dst.getExtType(0), Dst.getChild(0), 1420*0fca6ea1SDimitry Andric Dst.getChild(2)); 14218bcb0991SDimitry Andric if (!SuperClass) 14228bcb0991SDimitry Andric return failedImport( 14238bcb0991SDimitry Andric "Cannot infer register class for INSERT_SUBREG operand #0"); 14248bcb0991SDimitry Andric // The destination and the super register source of an INSERT_SUBREG must 14258bcb0991SDimitry Andric // be the same register class. 14268bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>( 14278bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 0, **SuperClass); 14288bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>( 14298bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 1, **SuperClass); 14308bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>( 14318bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 2, **SubClass); 14328bcb0991SDimitry Andric return InsertPtOrError.get(); 14338bcb0991SDimitry Andric } 14348bcb0991SDimitry Andric 14358bcb0991SDimitry Andric if (OpName == "EXTRACT_SUBREG") { 14368bcb0991SDimitry Andric // EXTRACT_SUBREG selects into a subregister COPY but unlike most 14378bcb0991SDimitry Andric // instructions, the result register class is controlled by the 14388bcb0991SDimitry Andric // subregisters of the operand. As a result, we must constrain the result 14398bcb0991SDimitry Andric // class rather than check that it's already the right one. 1440*0fca6ea1SDimitry Andric auto SuperClass = inferRegClassFromPattern(Dst.getChild(0)); 14418bcb0991SDimitry Andric if (!SuperClass) 14428bcb0991SDimitry Andric return failedImport( 14438bcb0991SDimitry Andric "Cannot infer register class from EXTRACT_SUBREG operand #0"); 14448bcb0991SDimitry Andric 1445*0fca6ea1SDimitry Andric auto SubIdx = inferSubRegIndexForNode(Dst.getChild(1)); 14468bcb0991SDimitry Andric if (!SubIdx) 14478bcb0991SDimitry Andric return failedImport("EXTRACT_SUBREG child #1 is not a subreg index"); 14488bcb0991SDimitry Andric 14495ffd83dbSDimitry Andric const auto SrcRCDstRCPair = 14508bcb0991SDimitry Andric (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx); 14518bcb0991SDimitry Andric assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass"); 14528bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>( 14538bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 0, *SrcRCDstRCPair->second); 14548bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>( 14558bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 1, *SrcRCDstRCPair->first); 14568bcb0991SDimitry Andric 14578bcb0991SDimitry Andric // We're done with this pattern! It's eligible for GISel emission; return 14588bcb0991SDimitry Andric // it. 14598bcb0991SDimitry Andric return InsertPtOrError.get(); 14608bcb0991SDimitry Andric } 14618bcb0991SDimitry Andric 14628bcb0991SDimitry Andric // Similar to INSERT_SUBREG, we also have to handle SUBREG_TO_REG as a 14638bcb0991SDimitry Andric // subinstruction. 14648bcb0991SDimitry Andric if (OpName == "SUBREG_TO_REG") { 1465*0fca6ea1SDimitry Andric auto SubClass = inferRegClassFromPattern(Dst.getChild(1)); 14668bcb0991SDimitry Andric if (!SubClass) 14678bcb0991SDimitry Andric return failedImport( 14688bcb0991SDimitry Andric "Cannot infer register class from SUBREG_TO_REG child #1"); 146906c3fb27SDimitry Andric auto SuperClass = 1470*0fca6ea1SDimitry Andric inferSuperRegisterClass(Dst.getExtType(0), Dst.getChild(2)); 14718bcb0991SDimitry Andric if (!SuperClass) 14728bcb0991SDimitry Andric return failedImport( 14738bcb0991SDimitry Andric "Cannot infer register class for SUBREG_TO_REG operand #0"); 14748bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>( 14758bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 0, **SuperClass); 14768bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>( 14778bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 2, **SubClass); 14788bcb0991SDimitry Andric return InsertPtOrError.get(); 14798bcb0991SDimitry Andric } 14808bcb0991SDimitry Andric 14815ffd83dbSDimitry Andric if (OpName == "REG_SEQUENCE") { 1482*0fca6ea1SDimitry Andric auto SuperClass = inferRegClassFromPattern(Dst.getChild(0)); 14835ffd83dbSDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>( 14845ffd83dbSDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 0, **SuperClass); 14855ffd83dbSDimitry Andric 1486*0fca6ea1SDimitry Andric unsigned Num = Dst.getNumChildren(); 14875ffd83dbSDimitry Andric for (unsigned I = 1; I != Num; I += 2) { 1488*0fca6ea1SDimitry Andric const TreePatternNode &SubRegChild = Dst.getChild(I + 1); 14895ffd83dbSDimitry Andric 14905ffd83dbSDimitry Andric auto SubIdx = inferSubRegIndexForNode(SubRegChild); 14915ffd83dbSDimitry Andric if (!SubIdx) 14925ffd83dbSDimitry Andric return failedImport("REG_SEQUENCE child is not a subreg index"); 14935ffd83dbSDimitry Andric 14945ffd83dbSDimitry Andric const auto SrcRCDstRCPair = 14955ffd83dbSDimitry Andric (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx); 14965ffd83dbSDimitry Andric assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass"); 14975ffd83dbSDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>( 14985ffd83dbSDimitry Andric InsertPt, DstMIBuilder.getInsnID(), I, *SrcRCDstRCPair->second); 14995ffd83dbSDimitry Andric } 15005ffd83dbSDimitry Andric 15015ffd83dbSDimitry Andric return InsertPtOrError.get(); 15025ffd83dbSDimitry Andric } 15035ffd83dbSDimitry Andric 15040b57cec5SDimitry Andric M.insertAction<ConstrainOperandsToDefinitionAction>(InsertPt, 15050b57cec5SDimitry Andric DstMIBuilder.getInsnID()); 15060b57cec5SDimitry Andric return InsertPtOrError.get(); 15070b57cec5SDimitry Andric } 15080b57cec5SDimitry Andric 15090b57cec5SDimitry Andric Expected<action_iterator> GlobalISelEmitter::createInstructionRenderer( 1510*0fca6ea1SDimitry Andric action_iterator InsertPt, RuleMatcher &M, const TreePatternNode &Dst) { 1511*0fca6ea1SDimitry Andric Record *DstOp = Dst.getOperator(); 15120b57cec5SDimitry Andric if (!DstOp->isSubClassOf("Instruction")) { 15130b57cec5SDimitry Andric if (DstOp->isSubClassOf("ValueType")) 15140b57cec5SDimitry Andric return failedImport( 15150b57cec5SDimitry Andric "Pattern operator isn't an instruction (it's a ValueType)"); 15160b57cec5SDimitry Andric return failedImport("Pattern operator isn't an instruction"); 15170b57cec5SDimitry Andric } 15180b57cec5SDimitry Andric CodeGenInstruction *DstI = &Target.getInstruction(DstOp); 15190b57cec5SDimitry Andric 15200b57cec5SDimitry Andric // COPY_TO_REGCLASS is just a copy with a ConstrainOperandToRegClassAction 15210b57cec5SDimitry Andric // attached. Similarly for EXTRACT_SUBREG except that's a subregister copy. 15228bcb0991SDimitry Andric StringRef Name = DstI->TheDef->getName(); 15238bcb0991SDimitry Andric if (Name == "COPY_TO_REGCLASS" || Name == "EXTRACT_SUBREG") 15240b57cec5SDimitry Andric DstI = &Target.getInstruction(RK.getDef("COPY")); 15250b57cec5SDimitry Andric 15260b57cec5SDimitry Andric return M.insertAction<BuildMIAction>(InsertPt, M.allocateOutputInsnID(), 15270b57cec5SDimitry Andric DstI); 15280b57cec5SDimitry Andric } 15290b57cec5SDimitry Andric 1530e8d8bef9SDimitry Andric Expected<action_iterator> GlobalISelEmitter::importExplicitDefRenderers( 1531e8d8bef9SDimitry Andric action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder, 1532*0fca6ea1SDimitry Andric const TreePatternNode &Src, const TreePatternNode &Dst, unsigned Start) { 15330b57cec5SDimitry Andric const CodeGenInstruction *DstI = DstMIBuilder.getCGI(); 1534*0fca6ea1SDimitry Andric const unsigned SrcNumDefs = Src.getExtTypes().size(); 153506c3fb27SDimitry Andric const unsigned DstNumDefs = DstI->Operands.NumDefs; 153606c3fb27SDimitry Andric if (DstNumDefs == 0) 1537e8d8bef9SDimitry Andric return InsertPt; 1538e8d8bef9SDimitry Andric 1539*0fca6ea1SDimitry Andric for (unsigned I = Start; I < SrcNumDefs; ++I) { 15405f757f3fSDimitry Andric std::string OpName = getMangledRootDefName(DstI->Operands[I].Name); 15415f757f3fSDimitry Andric // CopyRenderer saves a StringRef, so cannot pass OpName itself - 15425f757f3fSDimitry Andric // let's use a string with an appropriate lifetime. 15435f757f3fSDimitry Andric StringRef PermanentRef = M.getOperandMatcher(OpName).getSymbolicName(); 15445f757f3fSDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(PermanentRef); 15455f757f3fSDimitry Andric } 1546e8d8bef9SDimitry Andric 1547e8d8bef9SDimitry Andric // Some instructions have multiple defs, but are missing a type entry 1548e8d8bef9SDimitry Andric // (e.g. s_cc_out operands). 1549*0fca6ea1SDimitry Andric if (Dst.getExtTypes().size() < DstNumDefs) 1550e8d8bef9SDimitry Andric return failedImport("unhandled discarded def"); 1551e8d8bef9SDimitry Andric 155206c3fb27SDimitry Andric for (unsigned I = SrcNumDefs; I < DstNumDefs; ++I) { 1553*0fca6ea1SDimitry Andric const TypeSetByHwMode &ExtTy = Dst.getExtType(I); 1554e8d8bef9SDimitry Andric if (!ExtTy.isMachineValueType()) 1555e8d8bef9SDimitry Andric return failedImport("unsupported typeset"); 1556e8d8bef9SDimitry Andric 1557e8d8bef9SDimitry Andric auto OpTy = MVTToLLT(ExtTy.getMachineValueType().SimpleTy); 1558e8d8bef9SDimitry Andric if (!OpTy) 1559e8d8bef9SDimitry Andric return failedImport("unsupported type"); 1560e8d8bef9SDimitry Andric 1561e8d8bef9SDimitry Andric unsigned TempRegID = M.allocateTempRegID(); 1562e8d8bef9SDimitry Andric InsertPt = 1563e8d8bef9SDimitry Andric M.insertAction<MakeTempRegisterAction>(InsertPt, *OpTy, TempRegID); 1564e8d8bef9SDimitry Andric DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID, true, nullptr, true); 15650b57cec5SDimitry Andric } 1566e8d8bef9SDimitry Andric 1567e8d8bef9SDimitry Andric return InsertPt; 15680b57cec5SDimitry Andric } 15690b57cec5SDimitry Andric 15700b57cec5SDimitry Andric Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers( 15710b57cec5SDimitry Andric action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder, 1572*0fca6ea1SDimitry Andric const llvm::TreePatternNode &Dst, const llvm::TreePatternNode &Src) { 15730b57cec5SDimitry Andric const CodeGenInstruction *DstI = DstMIBuilder.getCGI(); 1574*0fca6ea1SDimitry Andric CodeGenInstruction *OrigDstI = &Target.getInstruction(Dst.getOperator()); 15750b57cec5SDimitry Andric 15768bcb0991SDimitry Andric StringRef Name = OrigDstI->TheDef->getName(); 1577*0fca6ea1SDimitry Andric unsigned ExpectedDstINumUses = Dst.getNumChildren(); 15788bcb0991SDimitry Andric 15790b57cec5SDimitry Andric // EXTRACT_SUBREG needs to use a subregister COPY. 15808bcb0991SDimitry Andric if (Name == "EXTRACT_SUBREG") { 1581*0fca6ea1SDimitry Andric if (!Dst.getChild(1).isLeaf()) 1582e8d8bef9SDimitry Andric return failedImport("EXTRACT_SUBREG child #1 is not a leaf"); 1583*0fca6ea1SDimitry Andric DefInit *SubRegInit = dyn_cast<DefInit>(Dst.getChild(1).getLeafValue()); 15845ffd83dbSDimitry Andric if (!SubRegInit) 15855ffd83dbSDimitry Andric return failedImport("EXTRACT_SUBREG child #1 is not a subreg index"); 15860b57cec5SDimitry Andric 15875ffd83dbSDimitry Andric CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef()); 1588*0fca6ea1SDimitry Andric const TreePatternNode &ValChild = Dst.getChild(0); 1589*0fca6ea1SDimitry Andric if (!ValChild.isLeaf()) { 15905ffd83dbSDimitry Andric // We really have to handle the source instruction, and then insert a 15915ffd83dbSDimitry Andric // copy from the subregister. 1592*0fca6ea1SDimitry Andric auto ExtractSrcTy = getInstResultType(ValChild, Target); 15935ffd83dbSDimitry Andric if (!ExtractSrcTy) 15945ffd83dbSDimitry Andric return ExtractSrcTy.takeError(); 15955ffd83dbSDimitry Andric 15965ffd83dbSDimitry Andric unsigned TempRegID = M.allocateTempRegID(); 159706c3fb27SDimitry Andric InsertPt = M.insertAction<MakeTempRegisterAction>(InsertPt, *ExtractSrcTy, 159806c3fb27SDimitry Andric TempRegID); 15995ffd83dbSDimitry Andric 16005ffd83dbSDimitry Andric auto InsertPtOrError = createAndImportSubInstructionRenderer( 160106c3fb27SDimitry Andric ++InsertPt, M, ValChild, Src, TempRegID); 16025ffd83dbSDimitry Andric if (auto Error = InsertPtOrError.takeError()) 16035ffd83dbSDimitry Andric return std::move(Error); 16045ffd83dbSDimitry Andric 16055ffd83dbSDimitry Andric DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID, false, SubIdx); 16065ffd83dbSDimitry Andric return InsertPt; 16075ffd83dbSDimitry Andric } 16085ffd83dbSDimitry Andric 16095ffd83dbSDimitry Andric // If this is a source operand, this is just a subregister copy. 1610*0fca6ea1SDimitry Andric Record *RCDef = getInitValueAsRegClass(ValChild.getLeafValue()); 16110b57cec5SDimitry Andric if (!RCDef) 16120b57cec5SDimitry Andric return failedImport("EXTRACT_SUBREG child #0 could not " 16130b57cec5SDimitry Andric "be coerced to a register class"); 16140b57cec5SDimitry Andric 16150b57cec5SDimitry Andric CodeGenRegisterClass *RC = CGRegs.getRegClass(RCDef); 16160b57cec5SDimitry Andric 16175ffd83dbSDimitry Andric const auto SrcRCDstRCPair = 16180b57cec5SDimitry Andric RC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx); 161981ad6265SDimitry Andric if (SrcRCDstRCPair) { 16200b57cec5SDimitry Andric assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass"); 16210b57cec5SDimitry Andric if (SrcRCDstRCPair->first != RC) 16220b57cec5SDimitry Andric return failedImport("EXTRACT_SUBREG requires an additional COPY"); 16230b57cec5SDimitry Andric } 16240b57cec5SDimitry Andric 1625*0fca6ea1SDimitry Andric StringRef RegOperandName = Dst.getChild(0).getName(); 162606c3fb27SDimitry Andric if (const auto &SubOperand = M.getComplexSubOperand(RegOperandName)) { 162706c3fb27SDimitry Andric DstMIBuilder.addRenderer<RenderComplexPatternOperand>( 162806c3fb27SDimitry Andric *std::get<0>(*SubOperand), RegOperandName, std::get<1>(*SubOperand), 162906c3fb27SDimitry Andric std::get<2>(*SubOperand), SubIdx); 163006c3fb27SDimitry Andric return InsertPt; 163106c3fb27SDimitry Andric } 163206c3fb27SDimitry Andric 163306c3fb27SDimitry Andric DstMIBuilder.addRenderer<CopySubRegRenderer>(RegOperandName, SubIdx); 16340b57cec5SDimitry Andric return InsertPt; 16350b57cec5SDimitry Andric } 16360b57cec5SDimitry Andric 16378bcb0991SDimitry Andric if (Name == "REG_SEQUENCE") { 1638*0fca6ea1SDimitry Andric if (!Dst.getChild(0).isLeaf()) 16398bcb0991SDimitry Andric return failedImport("REG_SEQUENCE child #0 is not a leaf"); 16408bcb0991SDimitry Andric 1641*0fca6ea1SDimitry Andric Record *RCDef = getInitValueAsRegClass(Dst.getChild(0).getLeafValue()); 16428bcb0991SDimitry Andric if (!RCDef) 16438bcb0991SDimitry Andric return failedImport("REG_SEQUENCE child #0 could not " 16448bcb0991SDimitry Andric "be coerced to a register class"); 16458bcb0991SDimitry Andric 16468bcb0991SDimitry Andric if ((ExpectedDstINumUses - 1) % 2 != 0) 16478bcb0991SDimitry Andric return failedImport("Malformed REG_SEQUENCE"); 16488bcb0991SDimitry Andric 16498bcb0991SDimitry Andric for (unsigned I = 1; I != ExpectedDstINumUses; I += 2) { 1650*0fca6ea1SDimitry Andric const TreePatternNode &ValChild = Dst.getChild(I); 1651*0fca6ea1SDimitry Andric const TreePatternNode &SubRegChild = Dst.getChild(I + 1); 16528bcb0991SDimitry Andric 1653*0fca6ea1SDimitry Andric if (DefInit *SubRegInit = dyn_cast<DefInit>(SubRegChild.getLeafValue())) { 16548bcb0991SDimitry Andric CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef()); 16558bcb0991SDimitry Andric 16568bcb0991SDimitry Andric auto InsertPtOrError = 165706c3fb27SDimitry Andric importExplicitUseRenderer(InsertPt, M, DstMIBuilder, ValChild, Src); 16588bcb0991SDimitry Andric if (auto Error = InsertPtOrError.takeError()) 16598bcb0991SDimitry Andric return std::move(Error); 16608bcb0991SDimitry Andric InsertPt = InsertPtOrError.get(); 16618bcb0991SDimitry Andric DstMIBuilder.addRenderer<SubRegIndexRenderer>(SubIdx); 16628bcb0991SDimitry Andric } 16638bcb0991SDimitry Andric } 16648bcb0991SDimitry Andric 16658bcb0991SDimitry Andric return InsertPt; 16668bcb0991SDimitry Andric } 16678bcb0991SDimitry Andric 16680b57cec5SDimitry Andric // Render the explicit uses. 16690b57cec5SDimitry Andric unsigned DstINumUses = OrigDstI->Operands.size() - OrigDstI->Operands.NumDefs; 16708bcb0991SDimitry Andric if (Name == "COPY_TO_REGCLASS") { 16710b57cec5SDimitry Andric DstINumUses--; // Ignore the class constraint. 16720b57cec5SDimitry Andric ExpectedDstINumUses--; 16730b57cec5SDimitry Andric } 16740b57cec5SDimitry Andric 1675480093f4SDimitry Andric // NumResults - This is the number of results produced by the instruction in 1676480093f4SDimitry Andric // the "outs" list. 1677480093f4SDimitry Andric unsigned NumResults = OrigDstI->Operands.NumDefs; 1678480093f4SDimitry Andric 1679480093f4SDimitry Andric // Number of operands we know the output instruction must have. If it is 1680480093f4SDimitry Andric // variadic, we could have more operands. 1681480093f4SDimitry Andric unsigned NumFixedOperands = DstI->Operands.size(); 1682480093f4SDimitry Andric 1683480093f4SDimitry Andric // Loop over all of the fixed operands of the instruction pattern, emitting 1684480093f4SDimitry Andric // code to fill them all in. The node 'N' usually has number children equal to 1685480093f4SDimitry Andric // the number of input operands of the instruction. However, in cases where 1686480093f4SDimitry Andric // there are predicate operands for an instruction, we need to fill in the 1687480093f4SDimitry Andric // 'execute always' values. Match up the node operands to the instruction 1688480093f4SDimitry Andric // operands to do this. 16890b57cec5SDimitry Andric unsigned Child = 0; 1690480093f4SDimitry Andric 1691480093f4SDimitry Andric // Similarly to the code in TreePatternNode::ApplyTypeConstraints, count the 1692480093f4SDimitry Andric // number of operands at the end of the list which have default values. 1693480093f4SDimitry Andric // Those can come from the pattern if it provides enough arguments, or be 1694480093f4SDimitry Andric // filled in with the default if the pattern hasn't provided them. But any 1695480093f4SDimitry Andric // operand with a default value _before_ the last mandatory one will be 1696480093f4SDimitry Andric // filled in with their defaults unconditionally. 1697480093f4SDimitry Andric unsigned NonOverridableOperands = NumFixedOperands; 1698480093f4SDimitry Andric while (NonOverridableOperands > NumResults && 1699480093f4SDimitry Andric CGP.operandHasDefault(DstI->Operands[NonOverridableOperands - 1].Rec)) 1700480093f4SDimitry Andric --NonOverridableOperands; 1701480093f4SDimitry Andric 17020b57cec5SDimitry Andric unsigned NumDefaultOps = 0; 17030b57cec5SDimitry Andric for (unsigned I = 0; I != DstINumUses; ++I) { 1704480093f4SDimitry Andric unsigned InstOpNo = DstI->Operands.NumDefs + I; 1705480093f4SDimitry Andric 1706480093f4SDimitry Andric // Determine what to emit for this operand. 1707480093f4SDimitry Andric Record *OperandNode = DstI->Operands[InstOpNo].Rec; 17080b57cec5SDimitry Andric 17090b57cec5SDimitry Andric // If the operand has default values, introduce them now. 1710480093f4SDimitry Andric if (CGP.operandHasDefault(OperandNode) && 1711*0fca6ea1SDimitry Andric (InstOpNo < NonOverridableOperands || Child >= Dst.getNumChildren())) { 1712480093f4SDimitry Andric // This is a predicate or optional def operand which the pattern has not 1713480093f4SDimitry Andric // overridden, or which we aren't letting it override; emit the 'default 1714480093f4SDimitry Andric // ops' operands. 1715480093f4SDimitry Andric 17165f757f3fSDimitry Andric Record *OperandNode = DstI->Operands[InstOpNo].Rec; 17175f757f3fSDimitry Andric if (auto Error = importDefaultOperandRenderers( 17185f757f3fSDimitry Andric InsertPt, M, DstMIBuilder, CGP.getDefaultOperand(OperandNode))) 17190b57cec5SDimitry Andric return std::move(Error); 17205f757f3fSDimitry Andric 17210b57cec5SDimitry Andric ++NumDefaultOps; 17220b57cec5SDimitry Andric continue; 17230b57cec5SDimitry Andric } 17240b57cec5SDimitry Andric 17250b57cec5SDimitry Andric auto InsertPtOrError = importExplicitUseRenderer(InsertPt, M, DstMIBuilder, 1726*0fca6ea1SDimitry Andric Dst.getChild(Child), Src); 17270b57cec5SDimitry Andric if (auto Error = InsertPtOrError.takeError()) 17280b57cec5SDimitry Andric return std::move(Error); 17290b57cec5SDimitry Andric InsertPt = InsertPtOrError.get(); 17300b57cec5SDimitry Andric ++Child; 17310b57cec5SDimitry Andric } 17320b57cec5SDimitry Andric 17330b57cec5SDimitry Andric if (NumDefaultOps + ExpectedDstINumUses != DstINumUses) 17340b57cec5SDimitry Andric return failedImport("Expected " + llvm::to_string(DstINumUses) + 17350b57cec5SDimitry Andric " used operands but found " + 17360b57cec5SDimitry Andric llvm::to_string(ExpectedDstINumUses) + 17370b57cec5SDimitry Andric " explicit ones and " + llvm::to_string(NumDefaultOps) + 17380b57cec5SDimitry Andric " default ones"); 17390b57cec5SDimitry Andric 17400b57cec5SDimitry Andric return InsertPt; 17410b57cec5SDimitry Andric } 17420b57cec5SDimitry Andric 17430b57cec5SDimitry Andric Error GlobalISelEmitter::importDefaultOperandRenderers( 17440b57cec5SDimitry Andric action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder, 17455f757f3fSDimitry Andric const DAGDefaultOperand &DefaultOp) const { 17465f757f3fSDimitry Andric for (const auto &Op : DefaultOp.DefaultOps) { 1747*0fca6ea1SDimitry Andric const auto &N = *Op; 1748*0fca6ea1SDimitry Andric if (!N.isLeaf()) 17495f757f3fSDimitry Andric return failedImport("Could not add default op"); 17500b57cec5SDimitry Andric 1751*0fca6ea1SDimitry Andric const auto *DefaultOp = N.getLeafValue(); 17520b57cec5SDimitry Andric 17530b57cec5SDimitry Andric if (const DefInit *DefaultDefOp = dyn_cast<DefInit>(DefaultOp)) { 1754*0fca6ea1SDimitry Andric std::optional<LLTCodeGen> OpTyOrNone = MVTToLLT(N.getSimpleType(0)); 1755*0fca6ea1SDimitry Andric auto *Def = DefaultDefOp->getDef(); 17560b57cec5SDimitry Andric if (Def->getName() == "undef_tied_input") { 17570b57cec5SDimitry Andric unsigned TempRegID = M.allocateTempRegID(); 1758bdd1243dSDimitry Andric M.insertAction<MakeTempRegisterAction>(InsertPt, *OpTyOrNone, 1759753f127fSDimitry Andric TempRegID); 17600b57cec5SDimitry Andric InsertPt = M.insertAction<BuildMIAction>( 17610b57cec5SDimitry Andric InsertPt, M.allocateOutputInsnID(), 17620b57cec5SDimitry Andric &Target.getInstruction(RK.getDef("IMPLICIT_DEF"))); 176306c3fb27SDimitry Andric BuildMIAction &IDMIBuilder = 176406c3fb27SDimitry Andric *static_cast<BuildMIAction *>(InsertPt->get()); 17650b57cec5SDimitry Andric IDMIBuilder.addRenderer<TempRegRenderer>(TempRegID); 17660b57cec5SDimitry Andric DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID); 17670b57cec5SDimitry Andric } else { 1768e8d8bef9SDimitry Andric DstMIBuilder.addRenderer<AddRegisterRenderer>(Target, Def); 17690b57cec5SDimitry Andric } 17700b57cec5SDimitry Andric continue; 17710b57cec5SDimitry Andric } 17720b57cec5SDimitry Andric 17730b57cec5SDimitry Andric if (const IntInit *DefaultIntOp = dyn_cast<IntInit>(DefaultOp)) { 17740b57cec5SDimitry Andric DstMIBuilder.addRenderer<ImmRenderer>(DefaultIntOp->getValue()); 17750b57cec5SDimitry Andric continue; 17760b57cec5SDimitry Andric } 17770b57cec5SDimitry Andric 17780b57cec5SDimitry Andric return failedImport("Could not add default op"); 17790b57cec5SDimitry Andric } 17800b57cec5SDimitry Andric 17810b57cec5SDimitry Andric return Error::success(); 17820b57cec5SDimitry Andric } 17830b57cec5SDimitry Andric 17840b57cec5SDimitry Andric Error GlobalISelEmitter::importImplicitDefRenderers( 17850b57cec5SDimitry Andric BuildMIAction &DstMIBuilder, 17860b57cec5SDimitry Andric const std::vector<Record *> &ImplicitDefs) const { 17870b57cec5SDimitry Andric if (!ImplicitDefs.empty()) 17880b57cec5SDimitry Andric return failedImport("Pattern defines a physical register"); 17890b57cec5SDimitry Andric return Error::success(); 17900b57cec5SDimitry Andric } 17910b57cec5SDimitry Andric 1792bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *> 1793*0fca6ea1SDimitry Andric GlobalISelEmitter::getRegClassFromLeaf(const TreePatternNode &Leaf) { 1794*0fca6ea1SDimitry Andric assert(Leaf.isLeaf() && "Expected leaf?"); 1795*0fca6ea1SDimitry Andric Record *RCRec = getInitValueAsRegClass(Leaf.getLeafValue()); 17968bcb0991SDimitry Andric if (!RCRec) 1797bdd1243dSDimitry Andric return std::nullopt; 17988bcb0991SDimitry Andric CodeGenRegisterClass *RC = CGRegs.getRegClass(RCRec); 17998bcb0991SDimitry Andric if (!RC) 1800bdd1243dSDimitry Andric return std::nullopt; 18018bcb0991SDimitry Andric return RC; 18028bcb0991SDimitry Andric } 18038bcb0991SDimitry Andric 1804bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *> 1805*0fca6ea1SDimitry Andric GlobalISelEmitter::inferRegClassFromPattern(const TreePatternNode &N) { 1806*0fca6ea1SDimitry Andric if (N.isLeaf()) 18078bcb0991SDimitry Andric return getRegClassFromLeaf(N); 18088bcb0991SDimitry Andric 18098bcb0991SDimitry Andric // We don't have a leaf node, so we have to try and infer something. Check 1810*0fca6ea1SDimitry Andric // that we have an instruction that we can infer something from. 18118bcb0991SDimitry Andric 1812*0fca6ea1SDimitry Andric // Only handle things that produce at least one value (if multiple values, 1813*0fca6ea1SDimitry Andric // just take the first one). 1814*0fca6ea1SDimitry Andric if (N.getNumTypes() < 1) 1815bdd1243dSDimitry Andric return std::nullopt; 1816*0fca6ea1SDimitry Andric Record *OpRec = N.getOperator(); 18178bcb0991SDimitry Andric 18188bcb0991SDimitry Andric // We only want instructions. 18198bcb0991SDimitry Andric if (!OpRec->isSubClassOf("Instruction")) 1820bdd1243dSDimitry Andric return std::nullopt; 18218bcb0991SDimitry Andric 18228bcb0991SDimitry Andric // Don't want to try and infer things when there could potentially be more 18238bcb0991SDimitry Andric // than one candidate register class. 18248bcb0991SDimitry Andric auto &Inst = Target.getInstruction(OpRec); 18258bcb0991SDimitry Andric 18268bcb0991SDimitry Andric // Handle any special-case instructions which we can safely infer register 18278bcb0991SDimitry Andric // classes from. 18288bcb0991SDimitry Andric StringRef InstName = Inst.TheDef->getName(); 18298bcb0991SDimitry Andric bool IsRegSequence = InstName == "REG_SEQUENCE"; 18308bcb0991SDimitry Andric if (IsRegSequence || InstName == "COPY_TO_REGCLASS") { 18318bcb0991SDimitry Andric // If we have a COPY_TO_REGCLASS, then we need to handle it specially. It 18328bcb0991SDimitry Andric // has the desired register class as the first child. 1833*0fca6ea1SDimitry Andric const TreePatternNode &RCChild = N.getChild(IsRegSequence ? 0 : 1); 1834*0fca6ea1SDimitry Andric if (!RCChild.isLeaf()) 1835bdd1243dSDimitry Andric return std::nullopt; 18368bcb0991SDimitry Andric return getRegClassFromLeaf(RCChild); 18378bcb0991SDimitry Andric } 1838e8d8bef9SDimitry Andric if (InstName == "INSERT_SUBREG") { 1839*0fca6ea1SDimitry Andric const TreePatternNode &Child0 = N.getChild(0); 1840*0fca6ea1SDimitry Andric assert(Child0.getNumTypes() == 1 && "Unexpected number of types!"); 1841*0fca6ea1SDimitry Andric const TypeSetByHwMode &VTy = Child0.getExtType(0); 1842*0fca6ea1SDimitry Andric return inferSuperRegisterClassForNode(VTy, Child0, N.getChild(2)); 1843e8d8bef9SDimitry Andric } 1844e8d8bef9SDimitry Andric if (InstName == "EXTRACT_SUBREG") { 1845*0fca6ea1SDimitry Andric assert(N.getNumTypes() == 1 && "Unexpected number of types!"); 1846*0fca6ea1SDimitry Andric const TypeSetByHwMode &VTy = N.getExtType(0); 1847*0fca6ea1SDimitry Andric return inferSuperRegisterClass(VTy, N.getChild(1)); 1848e8d8bef9SDimitry Andric } 18498bcb0991SDimitry Andric 18508bcb0991SDimitry Andric // Handle destination record types that we can safely infer a register class 18518bcb0991SDimitry Andric // from. 18528bcb0991SDimitry Andric const auto &DstIOperand = Inst.Operands[0]; 18538bcb0991SDimitry Andric Record *DstIOpRec = DstIOperand.Rec; 18548bcb0991SDimitry Andric if (DstIOpRec->isSubClassOf("RegisterOperand")) { 18558bcb0991SDimitry Andric DstIOpRec = DstIOpRec->getValueAsDef("RegClass"); 18568bcb0991SDimitry Andric const CodeGenRegisterClass &RC = Target.getRegisterClass(DstIOpRec); 18578bcb0991SDimitry Andric return &RC; 18588bcb0991SDimitry Andric } 18598bcb0991SDimitry Andric 18608bcb0991SDimitry Andric if (DstIOpRec->isSubClassOf("RegisterClass")) { 18618bcb0991SDimitry Andric const CodeGenRegisterClass &RC = Target.getRegisterClass(DstIOpRec); 18628bcb0991SDimitry Andric return &RC; 18638bcb0991SDimitry Andric } 18648bcb0991SDimitry Andric 1865bdd1243dSDimitry Andric return std::nullopt; 18668bcb0991SDimitry Andric } 18678bcb0991SDimitry Andric 1868bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *> 186906c3fb27SDimitry Andric GlobalISelEmitter::inferSuperRegisterClass( 1870*0fca6ea1SDimitry Andric const TypeSetByHwMode &Ty, const TreePatternNode &SubRegIdxNode) { 18718bcb0991SDimitry Andric // We need a ValueTypeByHwMode for getSuperRegForSubReg. 18728bcb0991SDimitry Andric if (!Ty.isValueTypeByHwMode(false)) 1873bdd1243dSDimitry Andric return std::nullopt; 1874*0fca6ea1SDimitry Andric if (!SubRegIdxNode.isLeaf()) 1875bdd1243dSDimitry Andric return std::nullopt; 1876*0fca6ea1SDimitry Andric DefInit *SubRegInit = dyn_cast<DefInit>(SubRegIdxNode.getLeafValue()); 18778bcb0991SDimitry Andric if (!SubRegInit) 1878bdd1243dSDimitry Andric return std::nullopt; 18798bcb0991SDimitry Andric CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef()); 18808bcb0991SDimitry Andric 18818bcb0991SDimitry Andric // Use the information we found above to find a minimal register class which 18828bcb0991SDimitry Andric // supports the subregister and type we want. 18838bcb0991SDimitry Andric auto RC = 1884e8d8bef9SDimitry Andric Target.getSuperRegForSubReg(Ty.getValueTypeByHwMode(), CGRegs, SubIdx, 1885e8d8bef9SDimitry Andric /* MustBeAllocatable */ true); 18868bcb0991SDimitry Andric if (!RC) 1887bdd1243dSDimitry Andric return std::nullopt; 18888bcb0991SDimitry Andric return *RC; 18898bcb0991SDimitry Andric } 18908bcb0991SDimitry Andric 1891bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *> 18928bcb0991SDimitry Andric GlobalISelEmitter::inferSuperRegisterClassForNode( 1893*0fca6ea1SDimitry Andric const TypeSetByHwMode &Ty, const TreePatternNode &SuperRegNode, 1894*0fca6ea1SDimitry Andric const TreePatternNode &SubRegIdxNode) { 18958bcb0991SDimitry Andric // Check if we already have a defined register class for the super register 18968bcb0991SDimitry Andric // node. If we do, then we should preserve that rather than inferring anything 18978bcb0991SDimitry Andric // from the subregister index node. We can assume that whoever wrote the 18988bcb0991SDimitry Andric // pattern in the first place made sure that the super register and 18998bcb0991SDimitry Andric // subregister are compatible. 1900bdd1243dSDimitry Andric if (std::optional<const CodeGenRegisterClass *> SuperRegisterClass = 19018bcb0991SDimitry Andric inferRegClassFromPattern(SuperRegNode)) 19028bcb0991SDimitry Andric return *SuperRegisterClass; 19038bcb0991SDimitry Andric return inferSuperRegisterClass(Ty, SubRegIdxNode); 19048bcb0991SDimitry Andric } 19058bcb0991SDimitry Andric 190606c3fb27SDimitry Andric std::optional<CodeGenSubRegIndex *> GlobalISelEmitter::inferSubRegIndexForNode( 1907*0fca6ea1SDimitry Andric const TreePatternNode &SubRegIdxNode) { 1908*0fca6ea1SDimitry Andric if (!SubRegIdxNode.isLeaf()) 1909bdd1243dSDimitry Andric return std::nullopt; 19108bcb0991SDimitry Andric 1911*0fca6ea1SDimitry Andric DefInit *SubRegInit = dyn_cast<DefInit>(SubRegIdxNode.getLeafValue()); 19128bcb0991SDimitry Andric if (!SubRegInit) 1913bdd1243dSDimitry Andric return std::nullopt; 19148bcb0991SDimitry Andric return CGRegs.getSubRegIdx(SubRegInit->getDef()); 19158bcb0991SDimitry Andric } 19168bcb0991SDimitry Andric 19170b57cec5SDimitry Andric Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) { 19180b57cec5SDimitry Andric // Keep track of the matchers and actions to emit. 19190b57cec5SDimitry Andric int Score = P.getPatternComplexity(CGP); 19200b57cec5SDimitry Andric RuleMatcher M(P.getSrcRecord()->getLoc()); 19210b57cec5SDimitry Andric RuleMatcherScores[M.getRuleID()] = Score; 1922*0fca6ea1SDimitry Andric M.addAction<DebugCommentAction>(llvm::to_string(P.getSrcPattern()) + 19230b57cec5SDimitry Andric " => " + 1924*0fca6ea1SDimitry Andric llvm::to_string(P.getDstPattern())); 19250b57cec5SDimitry Andric 1926fe6060f1SDimitry Andric SmallVector<Record *, 4> Predicates; 1927fe6060f1SDimitry Andric P.getPredicateRecords(Predicates); 1928fe6060f1SDimitry Andric if (auto Error = importRulePredicates(M, Predicates)) 19290b57cec5SDimitry Andric return std::move(Error); 19300b57cec5SDimitry Andric 19315f757f3fSDimitry Andric if (!P.getHwModeFeatures().empty()) 19325f757f3fSDimitry Andric M.addHwModeIdx(declareHwModeCheck(P.getHwModeFeatures())); 19335f757f3fSDimitry Andric 19340b57cec5SDimitry Andric // Next, analyze the pattern operators. 1935*0fca6ea1SDimitry Andric TreePatternNode &Src = P.getSrcPattern(); 1936*0fca6ea1SDimitry Andric TreePatternNode &Dst = P.getDstPattern(); 19370b57cec5SDimitry Andric 19380b57cec5SDimitry Andric // If the root of either pattern isn't a simple operator, ignore it. 19390b57cec5SDimitry Andric if (auto Err = isTrivialOperatorNode(Dst)) 19400b57cec5SDimitry Andric return failedImport("Dst pattern root isn't a trivial operator (" + 19410b57cec5SDimitry Andric toString(std::move(Err)) + ")"); 19420b57cec5SDimitry Andric if (auto Err = isTrivialOperatorNode(Src)) 19430b57cec5SDimitry Andric return failedImport("Src pattern root isn't a trivial operator (" + 19440b57cec5SDimitry Andric toString(std::move(Err)) + ")"); 19450b57cec5SDimitry Andric 19460b57cec5SDimitry Andric // The different predicates and matchers created during 19470b57cec5SDimitry Andric // addInstructionMatcher use the RuleMatcher M to set up their 19480b57cec5SDimitry Andric // instruction ID (InsnVarID) that are going to be used when 19490b57cec5SDimitry Andric // M is going to be emitted. 19500b57cec5SDimitry Andric // However, the code doing the emission still relies on the IDs 19510b57cec5SDimitry Andric // returned during that process by the RuleMatcher when issuing 19520b57cec5SDimitry Andric // the recordInsn opcodes. 19530b57cec5SDimitry Andric // Because of that: 19540b57cec5SDimitry Andric // 1. The order in which we created the predicates 19550b57cec5SDimitry Andric // and such must be the same as the order in which we emit them, 19560b57cec5SDimitry Andric // and 19570b57cec5SDimitry Andric // 2. We need to reset the generation of the IDs in M somewhere between 19580b57cec5SDimitry Andric // addInstructionMatcher and emit 19590b57cec5SDimitry Andric // 19600b57cec5SDimitry Andric // FIXME: Long term, we don't want to have to rely on this implicit 19610b57cec5SDimitry Andric // naming being the same. One possible solution would be to have 19620b57cec5SDimitry Andric // explicit operator for operation capture and reference those. 19630b57cec5SDimitry Andric // The plus side is that it would expose opportunities to share 19640b57cec5SDimitry Andric // the capture accross rules. The downside is that it would 19650b57cec5SDimitry Andric // introduce a dependency between predicates (captures must happen 19660b57cec5SDimitry Andric // before their first use.) 1967*0fca6ea1SDimitry Andric InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher(Src.getName()); 19680b57cec5SDimitry Andric unsigned TempOpIdx = 0; 196906c3fb27SDimitry Andric 197006c3fb27SDimitry Andric const auto SavedFlags = M.setGISelFlags(P.getSrcRecord()); 197106c3fb27SDimitry Andric 19720b57cec5SDimitry Andric auto InsnMatcherOrError = 19730b57cec5SDimitry Andric createAndImportSelDAGMatcher(M, InsnMatcherTemp, Src, TempOpIdx); 19740b57cec5SDimitry Andric if (auto Error = InsnMatcherOrError.takeError()) 19750b57cec5SDimitry Andric return std::move(Error); 19760b57cec5SDimitry Andric InstructionMatcher &InsnMatcher = InsnMatcherOrError.get(); 19770b57cec5SDimitry Andric 1978*0fca6ea1SDimitry Andric if (Dst.isLeaf()) { 1979*0fca6ea1SDimitry Andric Record *RCDef = getInitValueAsRegClass(Dst.getLeafValue()); 19800b57cec5SDimitry Andric if (RCDef) { 1981e8d8bef9SDimitry Andric const CodeGenRegisterClass &RC = Target.getRegisterClass(RCDef); 1982e8d8bef9SDimitry Andric 19830b57cec5SDimitry Andric // We need to replace the def and all its uses with the specified 19840b57cec5SDimitry Andric // operand. However, we must also insert COPY's wherever needed. 19850b57cec5SDimitry Andric // For now, emit a copy and let the register allocator clean up. 19860b57cec5SDimitry Andric auto &DstI = Target.getInstruction(RK.getDef("COPY")); 19870b57cec5SDimitry Andric const auto &DstIOperand = DstI.Operands[0]; 19880b57cec5SDimitry Andric 19890b57cec5SDimitry Andric OperandMatcher &OM0 = InsnMatcher.getOperand(0); 19900b57cec5SDimitry Andric OM0.setSymbolicName(DstIOperand.Name); 19910b57cec5SDimitry Andric M.defineOperand(OM0.getSymbolicName(), OM0); 19920b57cec5SDimitry Andric OM0.addPredicate<RegisterBankOperandMatcher>(RC); 19930b57cec5SDimitry Andric 19940b57cec5SDimitry Andric auto &DstMIBuilder = 19950b57cec5SDimitry Andric M.addAction<BuildMIAction>(M.allocateOutputInsnID(), &DstI); 19960b57cec5SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(DstIOperand.Name); 1997*0fca6ea1SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(Dst.getName()); 19980b57cec5SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 0, RC); 19990b57cec5SDimitry Andric 20007a6dacacSDimitry Andric // Erase the root. 20017a6dacacSDimitry Andric unsigned RootInsnID = M.getInsnVarID(InsnMatcher); 20027a6dacacSDimitry Andric M.addAction<EraseInstAction>(RootInsnID); 20037a6dacacSDimitry Andric 20040b57cec5SDimitry Andric // We're done with this pattern! It's eligible for GISel emission; return 20050b57cec5SDimitry Andric // it. 20060b57cec5SDimitry Andric ++NumPatternImported; 20070b57cec5SDimitry Andric return std::move(M); 20080b57cec5SDimitry Andric } 20090b57cec5SDimitry Andric 20100b57cec5SDimitry Andric return failedImport("Dst pattern root isn't a known leaf"); 20110b57cec5SDimitry Andric } 20120b57cec5SDimitry Andric 20130b57cec5SDimitry Andric // Start with the defined operands (i.e., the results of the root operator). 2014*0fca6ea1SDimitry Andric Record *DstOp = Dst.getOperator(); 20150b57cec5SDimitry Andric if (!DstOp->isSubClassOf("Instruction")) 20160b57cec5SDimitry Andric return failedImport("Pattern operator isn't an instruction"); 20170b57cec5SDimitry Andric 20180b57cec5SDimitry Andric auto &DstI = Target.getInstruction(DstOp); 20198bcb0991SDimitry Andric StringRef DstIName = DstI.TheDef->getName(); 20208bcb0991SDimitry Andric 2021753f127fSDimitry Andric unsigned DstNumDefs = DstI.Operands.NumDefs, 2022*0fca6ea1SDimitry Andric SrcNumDefs = Src.getExtTypes().size(); 2023753f127fSDimitry Andric if (DstNumDefs < SrcNumDefs) { 2024753f127fSDimitry Andric if (DstNumDefs != 0) 2025e8d8bef9SDimitry Andric return failedImport("Src pattern result has more defs than dst MI (" + 2026753f127fSDimitry Andric to_string(SrcNumDefs) + " def(s) vs " + 2027753f127fSDimitry Andric to_string(DstNumDefs) + " def(s))"); 2028753f127fSDimitry Andric 2029753f127fSDimitry Andric bool FoundNoUsePred = false; 2030753f127fSDimitry Andric for (const auto &Pred : InsnMatcher.predicates()) { 2031753f127fSDimitry Andric if ((FoundNoUsePred = isa<NoUsePredicateMatcher>(Pred.get()))) 2032753f127fSDimitry Andric break; 2033753f127fSDimitry Andric } 2034753f127fSDimitry Andric if (!FoundNoUsePred) 2035753f127fSDimitry Andric return failedImport("Src pattern result has " + to_string(SrcNumDefs) + 2036753f127fSDimitry Andric " def(s) without the HasNoUse predicate set to true " 2037753f127fSDimitry Andric "but Dst MI has no def"); 2038753f127fSDimitry Andric } 20390b57cec5SDimitry Andric 20400b57cec5SDimitry Andric // The root of the match also has constraints on the register bank so that it 20410b57cec5SDimitry Andric // matches the result instruction. 20420b57cec5SDimitry Andric unsigned OpIdx = 0; 2043753f127fSDimitry Andric unsigned N = std::min(DstNumDefs, SrcNumDefs); 2044753f127fSDimitry Andric for (unsigned I = 0; I < N; ++I) { 2045*0fca6ea1SDimitry Andric const TypeSetByHwMode &VTy = Src.getExtType(I); 20460b57cec5SDimitry Andric 20470b57cec5SDimitry Andric const auto &DstIOperand = DstI.Operands[OpIdx]; 20485f757f3fSDimitry Andric PointerUnion<Record *, const CodeGenRegisterClass *> MatchedRC = 20495f757f3fSDimitry Andric DstIOperand.Rec; 20508bcb0991SDimitry Andric if (DstIName == "COPY_TO_REGCLASS") { 2051*0fca6ea1SDimitry Andric MatchedRC = getInitValueAsRegClass(Dst.getChild(1).getLeafValue()); 20520b57cec5SDimitry Andric 20535f757f3fSDimitry Andric if (MatchedRC.isNull()) 20540b57cec5SDimitry Andric return failedImport( 20550b57cec5SDimitry Andric "COPY_TO_REGCLASS operand #1 isn't a register class"); 20568bcb0991SDimitry Andric } else if (DstIName == "REG_SEQUENCE") { 2057*0fca6ea1SDimitry Andric MatchedRC = getInitValueAsRegClass(Dst.getChild(0).getLeafValue()); 20585f757f3fSDimitry Andric if (MatchedRC.isNull()) 20598bcb0991SDimitry Andric return failedImport("REG_SEQUENCE operand #0 isn't a register class"); 20608bcb0991SDimitry Andric } else if (DstIName == "EXTRACT_SUBREG") { 2061*0fca6ea1SDimitry Andric auto InferredClass = inferRegClassFromPattern(Dst.getChild(0)); 20625ffd83dbSDimitry Andric if (!InferredClass) 206306c3fb27SDimitry Andric return failedImport( 206406c3fb27SDimitry Andric "Could not infer class for EXTRACT_SUBREG operand #0"); 20650b57cec5SDimitry Andric 20660b57cec5SDimitry Andric // We can assume that a subregister is in the same bank as it's super 20670b57cec5SDimitry Andric // register. 20685f757f3fSDimitry Andric MatchedRC = (*InferredClass)->getDef(); 20698bcb0991SDimitry Andric } else if (DstIName == "INSERT_SUBREG") { 2070*0fca6ea1SDimitry Andric auto MaybeSuperClass = 2071*0fca6ea1SDimitry Andric inferSuperRegisterClassForNode(VTy, Dst.getChild(0), Dst.getChild(2)); 20728bcb0991SDimitry Andric if (!MaybeSuperClass) 20730b57cec5SDimitry Andric return failedImport( 20748bcb0991SDimitry Andric "Cannot infer register class for INSERT_SUBREG operand #0"); 20758bcb0991SDimitry Andric // Move to the next pattern here, because the register class we found 20768bcb0991SDimitry Andric // doesn't necessarily have a record associated with it. So, we can't 20778bcb0991SDimitry Andric // set DstIOpRec using this. 20785f757f3fSDimitry Andric MatchedRC = *MaybeSuperClass; 20798bcb0991SDimitry Andric } else if (DstIName == "SUBREG_TO_REG") { 2080*0fca6ea1SDimitry Andric auto MaybeRegClass = inferSuperRegisterClass(VTy, Dst.getChild(2)); 20818bcb0991SDimitry Andric if (!MaybeRegClass) 20828bcb0991SDimitry Andric return failedImport( 20838bcb0991SDimitry Andric "Cannot infer register class for SUBREG_TO_REG operand #0"); 20845f757f3fSDimitry Andric MatchedRC = *MaybeRegClass; 20855f757f3fSDimitry Andric } else if (MatchedRC.get<Record *>()->isSubClassOf("RegisterOperand")) 20865f757f3fSDimitry Andric MatchedRC = MatchedRC.get<Record *>()->getValueAsDef("RegClass"); 20875f757f3fSDimitry Andric else if (!MatchedRC.get<Record *>()->isSubClassOf("RegisterClass")) 2088*0fca6ea1SDimitry Andric return failedImport("Dst MI def isn't a register class" + to_string(Dst)); 20890b57cec5SDimitry Andric 20900b57cec5SDimitry Andric OperandMatcher &OM = InsnMatcher.getOperand(OpIdx); 20915f757f3fSDimitry Andric // The operand names declared in the DstI instruction are unrelated to 20925f757f3fSDimitry Andric // those used in pattern's source and destination DAGs, so mangle the 20935f757f3fSDimitry Andric // former to prevent implicitly adding unexpected 20945f757f3fSDimitry Andric // GIM_CheckIsSameOperand predicates by the defineOperand method. 20955f757f3fSDimitry Andric OM.setSymbolicName(getMangledRootDefName(DstIOperand.Name)); 20960b57cec5SDimitry Andric M.defineOperand(OM.getSymbolicName(), OM); 20975f757f3fSDimitry Andric if (MatchedRC.is<Record *>()) 20985f757f3fSDimitry Andric MatchedRC = &Target.getRegisterClass(MatchedRC.get<Record *>()); 20990b57cec5SDimitry Andric OM.addPredicate<RegisterBankOperandMatcher>( 21005f757f3fSDimitry Andric *MatchedRC.get<const CodeGenRegisterClass *>()); 21010b57cec5SDimitry Andric ++OpIdx; 21020b57cec5SDimitry Andric } 21030b57cec5SDimitry Andric 21048bcb0991SDimitry Andric auto DstMIBuilderOrError = 21058bcb0991SDimitry Andric createAndImportInstructionRenderer(M, InsnMatcher, Src, Dst); 21060b57cec5SDimitry Andric if (auto Error = DstMIBuilderOrError.takeError()) 21070b57cec5SDimitry Andric return std::move(Error); 21080b57cec5SDimitry Andric BuildMIAction &DstMIBuilder = DstMIBuilderOrError.get(); 21090b57cec5SDimitry Andric 21100b57cec5SDimitry Andric // Render the implicit defs. 21110b57cec5SDimitry Andric // These are only added to the root of the result. 21120b57cec5SDimitry Andric if (auto Error = importImplicitDefRenderers(DstMIBuilder, P.getDstRegs())) 21130b57cec5SDimitry Andric return std::move(Error); 21140b57cec5SDimitry Andric 21150b57cec5SDimitry Andric DstMIBuilder.chooseInsnToMutate(M); 21160b57cec5SDimitry Andric 21170b57cec5SDimitry Andric // Constrain the registers to classes. This is normally derived from the 21180b57cec5SDimitry Andric // emitted instruction but a few instructions require special handling. 21198bcb0991SDimitry Andric if (DstIName == "COPY_TO_REGCLASS") { 21200b57cec5SDimitry Andric // COPY_TO_REGCLASS does not provide operand constraints itself but the 21210b57cec5SDimitry Andric // result is constrained to the class given by the second child. 2122*0fca6ea1SDimitry Andric Record *DstIOpRec = getInitValueAsRegClass(Dst.getChild(1).getLeafValue()); 21230b57cec5SDimitry Andric 21240b57cec5SDimitry Andric if (DstIOpRec == nullptr) 21250b57cec5SDimitry Andric return failedImport("COPY_TO_REGCLASS operand #1 isn't a register class"); 21260b57cec5SDimitry Andric 21270b57cec5SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>( 21280b57cec5SDimitry Andric 0, 0, Target.getRegisterClass(DstIOpRec)); 21297a6dacacSDimitry Andric } else if (DstIName == "EXTRACT_SUBREG") { 2130*0fca6ea1SDimitry Andric auto SuperClass = inferRegClassFromPattern(Dst.getChild(0)); 21318bcb0991SDimitry Andric if (!SuperClass) 21328bcb0991SDimitry Andric return failedImport( 21338bcb0991SDimitry Andric "Cannot infer register class from EXTRACT_SUBREG operand #0"); 21340b57cec5SDimitry Andric 2135*0fca6ea1SDimitry Andric auto SubIdx = inferSubRegIndexForNode(Dst.getChild(1)); 21368bcb0991SDimitry Andric if (!SubIdx) 21370b57cec5SDimitry Andric return failedImport("EXTRACT_SUBREG child #1 is not a subreg index"); 21380b57cec5SDimitry Andric 21390b57cec5SDimitry Andric // It would be nice to leave this constraint implicit but we're required 21400b57cec5SDimitry Andric // to pick a register class so constrain the result to a register class 21410b57cec5SDimitry Andric // that can hold the correct MVT. 21420b57cec5SDimitry Andric // 21430b57cec5SDimitry Andric // FIXME: This may introduce an extra copy if the chosen class doesn't 21440b57cec5SDimitry Andric // actually contain the subregisters. 2145*0fca6ea1SDimitry Andric assert(Src.getExtTypes().size() == 1 && 21460b57cec5SDimitry Andric "Expected Src of EXTRACT_SUBREG to have one result type"); 21470b57cec5SDimitry Andric 21485ffd83dbSDimitry Andric const auto SrcRCDstRCPair = 21498bcb0991SDimitry Andric (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx); 21505ffd83dbSDimitry Andric if (!SrcRCDstRCPair) { 21515ffd83dbSDimitry Andric return failedImport("subreg index is incompatible " 21525ffd83dbSDimitry Andric "with inferred reg class"); 21535ffd83dbSDimitry Andric } 21545ffd83dbSDimitry Andric 21550b57cec5SDimitry Andric assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass"); 215606c3fb27SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 0, 215706c3fb27SDimitry Andric *SrcRCDstRCPair->second); 21580b57cec5SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 1, *SrcRCDstRCPair->first); 21597a6dacacSDimitry Andric } else if (DstIName == "INSERT_SUBREG") { 2160*0fca6ea1SDimitry Andric assert(Src.getExtTypes().size() == 1 && 21618bcb0991SDimitry Andric "Expected Src of INSERT_SUBREG to have one result type"); 21628bcb0991SDimitry Andric // We need to constrain the destination, a super regsister source, and a 21638bcb0991SDimitry Andric // subregister source. 2164*0fca6ea1SDimitry Andric auto SubClass = inferRegClassFromPattern(Dst.getChild(1)); 21658bcb0991SDimitry Andric if (!SubClass) 21668bcb0991SDimitry Andric return failedImport( 21678bcb0991SDimitry Andric "Cannot infer register class from INSERT_SUBREG operand #1"); 21688bcb0991SDimitry Andric auto SuperClass = inferSuperRegisterClassForNode( 2169*0fca6ea1SDimitry Andric Src.getExtType(0), Dst.getChild(0), Dst.getChild(2)); 21708bcb0991SDimitry Andric if (!SuperClass) 21718bcb0991SDimitry Andric return failedImport( 21728bcb0991SDimitry Andric "Cannot infer register class for INSERT_SUBREG operand #0"); 21738bcb0991SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 0, **SuperClass); 21748bcb0991SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 1, **SuperClass); 21758bcb0991SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 2, **SubClass); 21767a6dacacSDimitry Andric } else if (DstIName == "SUBREG_TO_REG") { 21778bcb0991SDimitry Andric // We need to constrain the destination and subregister source. 2178*0fca6ea1SDimitry Andric assert(Src.getExtTypes().size() == 1 && 21798bcb0991SDimitry Andric "Expected Src of SUBREG_TO_REG to have one result type"); 21808bcb0991SDimitry Andric 21818bcb0991SDimitry Andric // Attempt to infer the subregister source from the first child. If it has 21828bcb0991SDimitry Andric // an explicitly given register class, we'll use that. Otherwise, we will 21838bcb0991SDimitry Andric // fail. 2184*0fca6ea1SDimitry Andric auto SubClass = inferRegClassFromPattern(Dst.getChild(1)); 21858bcb0991SDimitry Andric if (!SubClass) 21868bcb0991SDimitry Andric return failedImport( 21878bcb0991SDimitry Andric "Cannot infer register class from SUBREG_TO_REG child #1"); 21888bcb0991SDimitry Andric // We don't have a child to look at that might have a super register node. 21898bcb0991SDimitry Andric auto SuperClass = 2190*0fca6ea1SDimitry Andric inferSuperRegisterClass(Src.getExtType(0), Dst.getChild(2)); 21918bcb0991SDimitry Andric if (!SuperClass) 21928bcb0991SDimitry Andric return failedImport( 21938bcb0991SDimitry Andric "Cannot infer register class for SUBREG_TO_REG operand #0"); 21948bcb0991SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 0, **SuperClass); 21958bcb0991SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 2, **SubClass); 21967a6dacacSDimitry Andric } else if (DstIName == "REG_SEQUENCE") { 2197*0fca6ea1SDimitry Andric auto SuperClass = inferRegClassFromPattern(Dst.getChild(0)); 21985ffd83dbSDimitry Andric 21995ffd83dbSDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 0, **SuperClass); 22005ffd83dbSDimitry Andric 2201*0fca6ea1SDimitry Andric unsigned Num = Dst.getNumChildren(); 22025ffd83dbSDimitry Andric for (unsigned I = 1; I != Num; I += 2) { 2203*0fca6ea1SDimitry Andric TreePatternNode &SubRegChild = Dst.getChild(I + 1); 22045ffd83dbSDimitry Andric 22055ffd83dbSDimitry Andric auto SubIdx = inferSubRegIndexForNode(SubRegChild); 22065ffd83dbSDimitry Andric if (!SubIdx) 22075ffd83dbSDimitry Andric return failedImport("REG_SEQUENCE child is not a subreg index"); 22085ffd83dbSDimitry Andric 22095ffd83dbSDimitry Andric const auto SrcRCDstRCPair = 22105ffd83dbSDimitry Andric (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx); 22115ffd83dbSDimitry Andric 22125ffd83dbSDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, I, 22135ffd83dbSDimitry Andric *SrcRCDstRCPair->second); 22145ffd83dbSDimitry Andric } 22157a6dacacSDimitry Andric } else { 22167a6dacacSDimitry Andric M.addAction<ConstrainOperandsToDefinitionAction>(0); 22175ffd83dbSDimitry Andric } 22185ffd83dbSDimitry Andric 22197a6dacacSDimitry Andric // Erase the root. 22207a6dacacSDimitry Andric unsigned RootInsnID = M.getInsnVarID(InsnMatcher); 22217a6dacacSDimitry Andric M.addAction<EraseInstAction>(RootInsnID); 22220b57cec5SDimitry Andric 22230b57cec5SDimitry Andric // We're done with this pattern! It's eligible for GISel emission; return it. 22240b57cec5SDimitry Andric ++NumPatternImported; 22250b57cec5SDimitry Andric return std::move(M); 22260b57cec5SDimitry Andric } 22270b57cec5SDimitry Andric 22280b57cec5SDimitry Andric MatchTable 22290b57cec5SDimitry Andric GlobalISelEmitter::buildMatchTable(MutableArrayRef<RuleMatcher> Rules, 22300b57cec5SDimitry Andric bool Optimize, bool WithCoverage) { 22310b57cec5SDimitry Andric std::vector<Matcher *> InputRules; 22320b57cec5SDimitry Andric for (Matcher &Rule : Rules) 22330b57cec5SDimitry Andric InputRules.push_back(&Rule); 22340b57cec5SDimitry Andric 22350b57cec5SDimitry Andric if (!Optimize) 22360b57cec5SDimitry Andric return MatchTable::buildTable(InputRules, WithCoverage); 22370b57cec5SDimitry Andric 22380b57cec5SDimitry Andric unsigned CurrentOrdering = 0; 22390b57cec5SDimitry Andric StringMap<unsigned> OpcodeOrder; 22400b57cec5SDimitry Andric for (RuleMatcher &Rule : Rules) { 22410b57cec5SDimitry Andric const StringRef Opcode = Rule.getOpcode(); 22420b57cec5SDimitry Andric assert(!Opcode.empty() && "Didn't expect an undefined opcode"); 22430b57cec5SDimitry Andric if (OpcodeOrder.count(Opcode) == 0) 22440b57cec5SDimitry Andric OpcodeOrder[Opcode] = CurrentOrdering++; 22450b57cec5SDimitry Andric } 22460b57cec5SDimitry Andric 2247e8d8bef9SDimitry Andric llvm::stable_sort(InputRules, [&OpcodeOrder](const Matcher *A, 2248e8d8bef9SDimitry Andric const Matcher *B) { 22490b57cec5SDimitry Andric auto *L = static_cast<const RuleMatcher *>(A); 22500b57cec5SDimitry Andric auto *R = static_cast<const RuleMatcher *>(B); 2251*0fca6ea1SDimitry Andric return std::tuple(OpcodeOrder[L->getOpcode()], L->getNumOperands()) < 2252*0fca6ea1SDimitry Andric std::tuple(OpcodeOrder[R->getOpcode()], R->getNumOperands()); 22530b57cec5SDimitry Andric }); 22540b57cec5SDimitry Andric 22550b57cec5SDimitry Andric for (Matcher *Rule : InputRules) 22560b57cec5SDimitry Andric Rule->optimize(); 22570b57cec5SDimitry Andric 22580b57cec5SDimitry Andric std::vector<std::unique_ptr<Matcher>> MatcherStorage; 22590b57cec5SDimitry Andric std::vector<Matcher *> OptRules = 22600b57cec5SDimitry Andric optimizeRules<GroupMatcher>(InputRules, MatcherStorage); 22610b57cec5SDimitry Andric 22620b57cec5SDimitry Andric for (Matcher *Rule : OptRules) 22630b57cec5SDimitry Andric Rule->optimize(); 22640b57cec5SDimitry Andric 22650b57cec5SDimitry Andric OptRules = optimizeRules<SwitchMatcher>(OptRules, MatcherStorage); 22660b57cec5SDimitry Andric 22670b57cec5SDimitry Andric return MatchTable::buildTable(OptRules, WithCoverage); 22680b57cec5SDimitry Andric } 22690b57cec5SDimitry Andric 227006c3fb27SDimitry Andric void GlobalISelEmitter::emitAdditionalImpl(raw_ostream &OS) { 227106c3fb27SDimitry Andric OS << "bool " << getClassName() 227206c3fb27SDimitry Andric << "::selectImpl(MachineInstr &I, CodeGenCoverage " 227306c3fb27SDimitry Andric "&CoverageInfo) const {\n" 227406c3fb27SDimitry Andric << " const PredicateBitset AvailableFeatures = " 227506c3fb27SDimitry Andric "getAvailableFeatures();\n" 22765f757f3fSDimitry Andric << " MachineIRBuilder B(I);\n" 227706c3fb27SDimitry Andric << " State.MIs.clear();\n" 227806c3fb27SDimitry Andric << " State.MIs.push_back(&I);\n\n" 22795f757f3fSDimitry Andric << " if (executeMatchTable(*this, State, ExecInfo, B" 228006c3fb27SDimitry Andric << ", getMatchTable(), TII, MF->getRegInfo(), TRI, RBI, AvailableFeatures" 228106c3fb27SDimitry Andric << ", &CoverageInfo)) {\n" 228206c3fb27SDimitry Andric << " return true;\n" 228306c3fb27SDimitry Andric << " }\n\n" 228406c3fb27SDimitry Andric << " return false;\n" 228506c3fb27SDimitry Andric << "}\n\n"; 22860b57cec5SDimitry Andric } 228706c3fb27SDimitry Andric 228806c3fb27SDimitry Andric void GlobalISelEmitter::emitMIPredicateFns(raw_ostream &OS) { 228906c3fb27SDimitry Andric std::vector<Record *> MatchedRecords; 229006c3fb27SDimitry Andric std::copy_if(AllPatFrags.begin(), AllPatFrags.end(), 229106c3fb27SDimitry Andric std::back_inserter(MatchedRecords), [&](Record *R) { 229206c3fb27SDimitry Andric return !R->getValueAsString("GISelPredicateCode").empty(); 22930b57cec5SDimitry Andric }); 229406c3fb27SDimitry Andric emitMIPredicateFnsImpl<Record *>( 229506c3fb27SDimitry Andric OS, 229606c3fb27SDimitry Andric " const MachineFunction &MF = *MI.getParent()->getParent();\n" 229706c3fb27SDimitry Andric " const MachineRegisterInfo &MRI = MF.getRegInfo();\n" 229806c3fb27SDimitry Andric " const auto &Operands = State.RecordedOperands;\n" 229906c3fb27SDimitry Andric " (void)Operands;\n" 230006c3fb27SDimitry Andric " (void)MRI;", 230106c3fb27SDimitry Andric ArrayRef<Record *>(MatchedRecords), &getPatFragPredicateEnumName, 230206c3fb27SDimitry Andric [&](Record *R) { return R->getValueAsString("GISelPredicateCode"); }, 230306c3fb27SDimitry Andric "PatFrag predicates."); 23040b57cec5SDimitry Andric } 230506c3fb27SDimitry Andric 230606c3fb27SDimitry Andric void GlobalISelEmitter::emitI64ImmPredicateFns(raw_ostream &OS) { 230706c3fb27SDimitry Andric std::vector<Record *> MatchedRecords; 230806c3fb27SDimitry Andric std::copy_if(AllPatFrags.begin(), AllPatFrags.end(), 230906c3fb27SDimitry Andric std::back_inserter(MatchedRecords), [&](Record *R) { 231006c3fb27SDimitry Andric bool Unset; 231106c3fb27SDimitry Andric return !R->getValueAsString("ImmediateCode").empty() && 231206c3fb27SDimitry Andric !R->getValueAsBitOrUnset("IsAPFloat", Unset) && 231306c3fb27SDimitry Andric !R->getValueAsBit("IsAPInt"); 231406c3fb27SDimitry Andric }); 231506c3fb27SDimitry Andric emitImmPredicateFnsImpl<Record *>( 231606c3fb27SDimitry Andric OS, "I64", "int64_t", ArrayRef<Record *>(MatchedRecords), 231706c3fb27SDimitry Andric &getPatFragPredicateEnumName, 231806c3fb27SDimitry Andric [&](Record *R) { return R->getValueAsString("ImmediateCode"); }, 231906c3fb27SDimitry Andric "PatFrag predicates."); 232006c3fb27SDimitry Andric } 232106c3fb27SDimitry Andric 232206c3fb27SDimitry Andric void GlobalISelEmitter::emitAPFloatImmPredicateFns(raw_ostream &OS) { 232306c3fb27SDimitry Andric std::vector<Record *> MatchedRecords; 232406c3fb27SDimitry Andric std::copy_if(AllPatFrags.begin(), AllPatFrags.end(), 232506c3fb27SDimitry Andric std::back_inserter(MatchedRecords), [&](Record *R) { 232606c3fb27SDimitry Andric bool Unset; 232706c3fb27SDimitry Andric return !R->getValueAsString("ImmediateCode").empty() && 232806c3fb27SDimitry Andric R->getValueAsBitOrUnset("IsAPFloat", Unset); 232906c3fb27SDimitry Andric }); 233006c3fb27SDimitry Andric emitImmPredicateFnsImpl<Record *>( 233106c3fb27SDimitry Andric OS, "APFloat", "const APFloat &", ArrayRef<Record *>(MatchedRecords), 233206c3fb27SDimitry Andric &getPatFragPredicateEnumName, 233306c3fb27SDimitry Andric [&](Record *R) { return R->getValueAsString("ImmediateCode"); }, 233406c3fb27SDimitry Andric "PatFrag predicates."); 233506c3fb27SDimitry Andric } 233606c3fb27SDimitry Andric 233706c3fb27SDimitry Andric void GlobalISelEmitter::emitAPIntImmPredicateFns(raw_ostream &OS) { 233806c3fb27SDimitry Andric std::vector<Record *> MatchedRecords; 233906c3fb27SDimitry Andric std::copy_if(AllPatFrags.begin(), AllPatFrags.end(), 234006c3fb27SDimitry Andric std::back_inserter(MatchedRecords), [&](Record *R) { 234106c3fb27SDimitry Andric return !R->getValueAsString("ImmediateCode").empty() && 234206c3fb27SDimitry Andric R->getValueAsBit("IsAPInt"); 234306c3fb27SDimitry Andric }); 234406c3fb27SDimitry Andric emitImmPredicateFnsImpl<Record *>( 234506c3fb27SDimitry Andric OS, "APInt", "const APInt &", ArrayRef<Record *>(MatchedRecords), 234606c3fb27SDimitry Andric &getPatFragPredicateEnumName, 234706c3fb27SDimitry Andric [&](Record *R) { return R->getValueAsString("ImmediateCode"); }, 234806c3fb27SDimitry Andric "PatFrag predicates."); 234906c3fb27SDimitry Andric } 235006c3fb27SDimitry Andric 235106c3fb27SDimitry Andric void GlobalISelEmitter::emitTestSimplePredicate(raw_ostream &OS) { 235206c3fb27SDimitry Andric OS << "bool " << getClassName() << "::testSimplePredicate(unsigned) const {\n" 235306c3fb27SDimitry Andric << " llvm_unreachable(\"" + getClassName() + 235406c3fb27SDimitry Andric " does not support simple predicates!\");\n" 235506c3fb27SDimitry Andric << " return false;\n" 235606c3fb27SDimitry Andric << "}\n"; 235706c3fb27SDimitry Andric } 235806c3fb27SDimitry Andric 235906c3fb27SDimitry Andric void GlobalISelEmitter::emitRunCustomAction(raw_ostream &OS) { 2360*0fca6ea1SDimitry Andric OS << "bool " << getClassName() 23615f757f3fSDimitry Andric << "::runCustomAction(unsigned, const MatcherState&, NewMIVector &) const " 23625f757f3fSDimitry Andric "{\n" 236306c3fb27SDimitry Andric << " llvm_unreachable(\"" + getClassName() + 236406c3fb27SDimitry Andric " does not support custom C++ actions!\");\n" 236506c3fb27SDimitry Andric << "}\n"; 23660b57cec5SDimitry Andric } 23670b57cec5SDimitry Andric 23685f757f3fSDimitry Andric void GlobalISelEmitter::postProcessRule(RuleMatcher &M) { 23695f757f3fSDimitry Andric SmallPtrSet<Record *, 16> UsedRegs; 23705f757f3fSDimitry Andric 23715f757f3fSDimitry Andric // TODO: deal with subregs? 23725f757f3fSDimitry Andric for (auto &A : M.actions()) { 23735f757f3fSDimitry Andric auto *MI = dyn_cast<BuildMIAction>(A.get()); 23745f757f3fSDimitry Andric if (!MI) 23755f757f3fSDimitry Andric continue; 23765f757f3fSDimitry Andric 23775f757f3fSDimitry Andric for (auto *Use : MI->getCGI()->ImplicitUses) 23785f757f3fSDimitry Andric UsedRegs.insert(Use); 23795f757f3fSDimitry Andric } 23805f757f3fSDimitry Andric 23815f757f3fSDimitry Andric for (auto &A : M.actions()) { 23825f757f3fSDimitry Andric auto *MI = dyn_cast<BuildMIAction>(A.get()); 23835f757f3fSDimitry Andric if (!MI) 23845f757f3fSDimitry Andric continue; 23855f757f3fSDimitry Andric 23865f757f3fSDimitry Andric for (auto *Def : MI->getCGI()->ImplicitDefs) { 23875f757f3fSDimitry Andric if (!UsedRegs.contains(Def)) 23885f757f3fSDimitry Andric MI->setDeadImplicitDef(Def); 23895f757f3fSDimitry Andric } 23905f757f3fSDimitry Andric } 23915f757f3fSDimitry Andric } 23925f757f3fSDimitry Andric 23930b57cec5SDimitry Andric void GlobalISelEmitter::run(raw_ostream &OS) { 23940b57cec5SDimitry Andric if (!UseCoverageFile.empty()) { 23950b57cec5SDimitry Andric RuleCoverage = CodeGenCoverage(); 23960b57cec5SDimitry Andric auto RuleCoverageBufOrErr = MemoryBuffer::getFile(UseCoverageFile); 23970b57cec5SDimitry Andric if (!RuleCoverageBufOrErr) { 23980b57cec5SDimitry Andric PrintWarning(SMLoc(), "Missing rule coverage data"); 2399bdd1243dSDimitry Andric RuleCoverage = std::nullopt; 24000b57cec5SDimitry Andric } else { 24010b57cec5SDimitry Andric if (!RuleCoverage->parse(*RuleCoverageBufOrErr.get(), Target.getName())) { 24020b57cec5SDimitry Andric PrintWarning(SMLoc(), "Ignoring invalid or missing rule coverage data"); 2403bdd1243dSDimitry Andric RuleCoverage = std::nullopt; 24040b57cec5SDimitry Andric } 24050b57cec5SDimitry Andric } 24060b57cec5SDimitry Andric } 24070b57cec5SDimitry Andric 24080b57cec5SDimitry Andric // Track the run-time opcode values 24090b57cec5SDimitry Andric gatherOpcodeValues(); 24100b57cec5SDimitry Andric // Track the run-time LLT ID values 24110b57cec5SDimitry Andric gatherTypeIDValues(); 24120b57cec5SDimitry Andric 24130b57cec5SDimitry Andric // Track the GINodeEquiv definitions. 24140b57cec5SDimitry Andric gatherNodeEquivs(); 24150b57cec5SDimitry Andric 241606c3fb27SDimitry Andric AllPatFrags = RK.getAllDerivedDefinitions("PatFrags"); 241706c3fb27SDimitry Andric 241806c3fb27SDimitry Andric emitSourceFileHeader( 241906c3fb27SDimitry Andric ("Global Instruction Selector for the " + Target.getName() + " target") 242006c3fb27SDimitry Andric .str(), 242106c3fb27SDimitry Andric OS); 24220b57cec5SDimitry Andric std::vector<RuleMatcher> Rules; 24230b57cec5SDimitry Andric // Look through the SelectionDAG patterns we found, possibly emitting some. 24240b57cec5SDimitry Andric for (const PatternToMatch &Pat : CGP.ptms()) { 24250b57cec5SDimitry Andric ++NumPatternTotal; 24260b57cec5SDimitry Andric 2427*0fca6ea1SDimitry Andric if (Pat.getGISelShouldIgnore()) 2428*0fca6ea1SDimitry Andric continue; // skip without warning 24290b57cec5SDimitry Andric auto MatcherOrErr = runOnPattern(Pat); 24300b57cec5SDimitry Andric 24310b57cec5SDimitry Andric // The pattern analysis can fail, indicating an unsupported pattern. 24320b57cec5SDimitry Andric // Report that if we've been asked to do so. 24330b57cec5SDimitry Andric if (auto Err = MatcherOrErr.takeError()) { 24340b57cec5SDimitry Andric if (WarnOnSkippedPatterns) { 24350b57cec5SDimitry Andric PrintWarning(Pat.getSrcRecord()->getLoc(), 24360b57cec5SDimitry Andric "Skipped pattern: " + toString(std::move(Err))); 24370b57cec5SDimitry Andric } else { 24380b57cec5SDimitry Andric consumeError(std::move(Err)); 24390b57cec5SDimitry Andric } 24400b57cec5SDimitry Andric ++NumPatternImportsSkipped; 24410b57cec5SDimitry Andric continue; 24420b57cec5SDimitry Andric } 24430b57cec5SDimitry Andric 24440b57cec5SDimitry Andric if (RuleCoverage) { 24450b57cec5SDimitry Andric if (RuleCoverage->isCovered(MatcherOrErr->getRuleID())) 24460b57cec5SDimitry Andric ++NumPatternsTested; 24470b57cec5SDimitry Andric else 24480b57cec5SDimitry Andric PrintWarning(Pat.getSrcRecord()->getLoc(), 24490b57cec5SDimitry Andric "Pattern is not covered by a test"); 24500b57cec5SDimitry Andric } 24510b57cec5SDimitry Andric Rules.push_back(std::move(MatcherOrErr.get())); 24525f757f3fSDimitry Andric postProcessRule(Rules.back()); 24530b57cec5SDimitry Andric } 24540b57cec5SDimitry Andric 24550b57cec5SDimitry Andric // Comparison function to order records by name. 2456*0fca6ea1SDimitry Andric auto OrderByName = [](const Record *A, const Record *B) { 24570b57cec5SDimitry Andric return A->getName() < B->getName(); 24580b57cec5SDimitry Andric }; 24590b57cec5SDimitry Andric 24600b57cec5SDimitry Andric std::vector<Record *> ComplexPredicates = 24610b57cec5SDimitry Andric RK.getAllDerivedDefinitions("GIComplexOperandMatcher"); 2462*0fca6ea1SDimitry Andric llvm::sort(ComplexPredicates, OrderByName); 24630b57cec5SDimitry Andric 2464fe6060f1SDimitry Andric std::vector<StringRef> CustomRendererFns; 2465fe6060f1SDimitry Andric transform(RK.getAllDerivedDefinitions("GICustomOperandRenderer"), 2466fe6060f1SDimitry Andric std::back_inserter(CustomRendererFns), [](const auto &Record) { 2467fe6060f1SDimitry Andric return Record->getValueAsString("RendererFn"); 2468fe6060f1SDimitry Andric }); 2469fe6060f1SDimitry Andric // Sort and remove duplicates to get a list of unique renderer functions, in 2470fe6060f1SDimitry Andric // case some were mentioned more than once. 2471fe6060f1SDimitry Andric llvm::sort(CustomRendererFns); 2472*0fca6ea1SDimitry Andric CustomRendererFns.erase(llvm::unique(CustomRendererFns), 2473fe6060f1SDimitry Andric CustomRendererFns.end()); 24740b57cec5SDimitry Andric 247506c3fb27SDimitry Andric // Create a table containing the LLT objects needed by the matcher and an enum 24760b57cec5SDimitry Andric // for the matcher to reference them with. 24770b57cec5SDimitry Andric std::vector<LLTCodeGen> TypeObjects; 2478e8d8bef9SDimitry Andric append_range(TypeObjects, KnownTypes); 24790b57cec5SDimitry Andric llvm::sort(TypeObjects); 24800b57cec5SDimitry Andric 248106c3fb27SDimitry Andric // Sort rules. 24820b57cec5SDimitry Andric llvm::stable_sort(Rules, [&](const RuleMatcher &A, const RuleMatcher &B) { 24830b57cec5SDimitry Andric int ScoreA = RuleMatcherScores[A.getRuleID()]; 24840b57cec5SDimitry Andric int ScoreB = RuleMatcherScores[B.getRuleID()]; 24850b57cec5SDimitry Andric if (ScoreA > ScoreB) 24860b57cec5SDimitry Andric return true; 24870b57cec5SDimitry Andric if (ScoreB > ScoreA) 24880b57cec5SDimitry Andric return false; 24890b57cec5SDimitry Andric if (A.isHigherPriorityThan(B)) { 24900b57cec5SDimitry Andric assert(!B.isHigherPriorityThan(A) && "Cannot be more important " 24910b57cec5SDimitry Andric "and less important at " 24920b57cec5SDimitry Andric "the same time"); 24930b57cec5SDimitry Andric return true; 24940b57cec5SDimitry Andric } 24950b57cec5SDimitry Andric return false; 24960b57cec5SDimitry Andric }); 24970b57cec5SDimitry Andric 249806c3fb27SDimitry Andric unsigned MaxTemporaries = 0; 249906c3fb27SDimitry Andric for (const auto &Rule : Rules) 250006c3fb27SDimitry Andric MaxTemporaries = std::max(MaxTemporaries, Rule.countRendererFns()); 25010b57cec5SDimitry Andric 250206c3fb27SDimitry Andric // Build match table 25030b57cec5SDimitry Andric const MatchTable Table = 25040b57cec5SDimitry Andric buildMatchTable(Rules, OptimizeMatchTable, GenerateCoverage); 25050b57cec5SDimitry Andric 250606c3fb27SDimitry Andric emitPredicateBitset(OS, "GET_GLOBALISEL_PREDICATE_BITSET"); 250706c3fb27SDimitry Andric emitTemporariesDecl(OS, "GET_GLOBALISEL_TEMPORARIES_DECL"); 250806c3fb27SDimitry Andric emitTemporariesInit(OS, MaxTemporaries, "GET_GLOBALISEL_TEMPORARIES_INIT"); 250906c3fb27SDimitry Andric emitExecutorImpl(OS, Table, TypeObjects, Rules, ComplexPredicates, 251006c3fb27SDimitry Andric CustomRendererFns, "GET_GLOBALISEL_IMPL"); 251106c3fb27SDimitry Andric emitPredicatesDecl(OS, "GET_GLOBALISEL_PREDICATES_DECL"); 251206c3fb27SDimitry Andric emitPredicatesInit(OS, "GET_GLOBALISEL_PREDICATES_INIT"); 25130b57cec5SDimitry Andric } 25140b57cec5SDimitry Andric 25150b57cec5SDimitry Andric void GlobalISelEmitter::declareSubtargetFeature(Record *Predicate) { 25165f757f3fSDimitry Andric SubtargetFeatures.try_emplace(Predicate, Predicate, SubtargetFeatures.size()); 25175f757f3fSDimitry Andric } 25185f757f3fSDimitry Andric 25195f757f3fSDimitry Andric unsigned GlobalISelEmitter::declareHwModeCheck(StringRef HwModeFeatures) { 25205f757f3fSDimitry Andric return HwModes.emplace(HwModeFeatures.str(), HwModes.size()).first->second; 25210b57cec5SDimitry Andric } 25220b57cec5SDimitry Andric 25230b57cec5SDimitry Andric } // end anonymous namespace 25240b57cec5SDimitry Andric 25250b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 25260b57cec5SDimitry Andric 252706c3fb27SDimitry Andric static TableGen::Emitter::OptClass<GlobalISelEmitter> 252806c3fb27SDimitry Andric X("gen-global-isel", "Generate GlobalISel selector"); 2529