10b57cec5SDimitry Andric //===- GlobalISelEmitter.cpp - Generate an instruction selector -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This tablegen backend emits code for use by the GlobalISel instruction
1106c3fb27SDimitry Andric /// selector. See include/llvm/Target/GlobalISel/Target.td.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric /// This file analyzes the patterns recognized by the SelectionDAGISel tablegen
140b57cec5SDimitry Andric /// backend, filters out the ones that are unsupported, maps
150b57cec5SDimitry Andric /// SelectionDAG-specific constructs to their GlobalISel counterpart
160b57cec5SDimitry Andric /// (when applicable: MVT to LLT; SDNode to generic Instruction).
170b57cec5SDimitry Andric ///
180b57cec5SDimitry Andric /// Not all patterns are supported: pass the tablegen invocation
190b57cec5SDimitry Andric /// "-warn-on-skipped-patterns" to emit a warning when a pattern is skipped,
200b57cec5SDimitry Andric /// as well as why.
210b57cec5SDimitry Andric ///
220b57cec5SDimitry Andric /// The generated file defines a single method:
230b57cec5SDimitry Andric /// bool <Target>InstructionSelector::selectImpl(MachineInstr &I) const;
240b57cec5SDimitry Andric /// intended to be used in InstructionSelector::select as the first-step
250b57cec5SDimitry Andric /// selector for the patterns that don't require complex C++.
260b57cec5SDimitry Andric ///
270b57cec5SDimitry Andric /// FIXME: We'll probably want to eventually define a base
280b57cec5SDimitry Andric /// "TargetGenInstructionSelector" class.
290b57cec5SDimitry Andric ///
300b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric #include "CodeGenDAGPatterns.h"
3381ad6265SDimitry Andric #include "CodeGenInstruction.h"
3406c3fb27SDimitry Andric #include "CodeGenIntrinsics.h"
3506c3fb27SDimitry Andric #include "CodeGenRegisters.h"
3606c3fb27SDimitry Andric #include "CodeGenTarget.h"
3706c3fb27SDimitry Andric #include "GlobalISelMatchTable.h"
3806c3fb27SDimitry Andric #include "GlobalISelMatchTableExecutorEmitter.h"
3906c3fb27SDimitry Andric #include "InfoByHwMode.h"
400b57cec5SDimitry Andric #include "SubtargetFeatureInfo.h"
410b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
4206c3fb27SDimitry Andric #include "llvm/CodeGen/LowLevelType.h"
4306c3fb27SDimitry Andric #include "llvm/CodeGen/MachineValueType.h"
440b57cec5SDimitry Andric #include "llvm/Support/CodeGenCoverage.h"
450b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
460b57cec5SDimitry Andric #include "llvm/Support/Error.h"
4706c3fb27SDimitry Andric #include "llvm/Support/SaveAndRestore.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 <numeric>
530b57cec5SDimitry Andric #include <string>
5406c3fb27SDimitry Andric
550b57cec5SDimitry Andric using namespace llvm;
5606c3fb27SDimitry Andric using namespace llvm::gi;
5706c3fb27SDimitry Andric
5806c3fb27SDimitry Andric using action_iterator = RuleMatcher::action_iterator;
590b57cec5SDimitry Andric
600b57cec5SDimitry Andric #define DEBUG_TYPE "gisel-emitter"
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric STATISTIC(NumPatternTotal, "Total number of patterns");
630b57cec5SDimitry Andric STATISTIC(NumPatternImported, "Number of patterns imported from SelectionDAG");
640b57cec5SDimitry Andric STATISTIC(NumPatternImportsSkipped, "Number of SelectionDAG imports skipped");
6506c3fb27SDimitry Andric STATISTIC(NumPatternsTested,
6606c3fb27SDimitry Andric "Number of patterns executed according to coverage information");
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric cl::OptionCategory GlobalISelEmitterCat("Options for -gen-global-isel");
690b57cec5SDimitry Andric
700b57cec5SDimitry Andric static cl::opt<bool> WarnOnSkippedPatterns(
710b57cec5SDimitry Andric "warn-on-skipped-patterns",
720b57cec5SDimitry Andric cl::desc("Explain why a pattern was skipped for inclusion "
730b57cec5SDimitry Andric "in the GlobalISel selector"),
740b57cec5SDimitry Andric cl::init(false), cl::cat(GlobalISelEmitterCat));
750b57cec5SDimitry Andric
760b57cec5SDimitry Andric static cl::opt<bool> GenerateCoverage(
770b57cec5SDimitry Andric "instrument-gisel-coverage",
780b57cec5SDimitry Andric cl::desc("Generate coverage instrumentation for GlobalISel"),
790b57cec5SDimitry Andric cl::init(false), cl::cat(GlobalISelEmitterCat));
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric static cl::opt<std::string> UseCoverageFile(
820b57cec5SDimitry Andric "gisel-coverage-file", cl::init(""),
830b57cec5SDimitry Andric cl::desc("Specify file to retrieve coverage information from"),
840b57cec5SDimitry Andric cl::cat(GlobalISelEmitterCat));
850b57cec5SDimitry Andric
860b57cec5SDimitry Andric static cl::opt<bool> OptimizeMatchTable(
870b57cec5SDimitry Andric "optimize-match-table",
880b57cec5SDimitry Andric cl::desc("Generate an optimized version of the match table"),
890b57cec5SDimitry Andric cl::init(true), cl::cat(GlobalISelEmitterCat));
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric namespace {
920b57cec5SDimitry Andric
explainPredicates(const TreePatternNode * N)930b57cec5SDimitry Andric static std::string explainPredicates(const TreePatternNode *N) {
94e8d8bef9SDimitry Andric std::string Explanation;
950b57cec5SDimitry Andric StringRef Separator = "";
960b57cec5SDimitry Andric for (const TreePredicateCall &Call : N->getPredicateCalls()) {
970b57cec5SDimitry Andric const TreePredicateFn &P = Call.Fn;
980b57cec5SDimitry Andric Explanation +=
990b57cec5SDimitry Andric (Separator + P.getOrigPatFragRecord()->getRecord()->getName()).str();
1000b57cec5SDimitry Andric Separator = ", ";
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric if (P.isAlwaysTrue())
1030b57cec5SDimitry Andric Explanation += " always-true";
1040b57cec5SDimitry Andric if (P.isImmediatePattern())
1050b57cec5SDimitry Andric Explanation += " immediate";
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric if (P.isUnindexed())
1080b57cec5SDimitry Andric Explanation += " unindexed";
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric if (P.isNonExtLoad())
1110b57cec5SDimitry Andric Explanation += " non-extload";
1120b57cec5SDimitry Andric if (P.isAnyExtLoad())
1130b57cec5SDimitry Andric Explanation += " extload";
1140b57cec5SDimitry Andric if (P.isSignExtLoad())
1150b57cec5SDimitry Andric Explanation += " sextload";
1160b57cec5SDimitry Andric if (P.isZeroExtLoad())
1170b57cec5SDimitry Andric Explanation += " zextload";
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric if (P.isNonTruncStore())
1200b57cec5SDimitry Andric Explanation += " non-truncstore";
1210b57cec5SDimitry Andric if (P.isTruncStore())
1220b57cec5SDimitry Andric Explanation += " truncstore";
1230b57cec5SDimitry Andric
1240b57cec5SDimitry Andric if (Record *VT = P.getMemoryVT())
1250b57cec5SDimitry Andric Explanation += (" MemVT=" + VT->getName()).str();
1260b57cec5SDimitry Andric if (Record *VT = P.getScalarMemoryVT())
1270b57cec5SDimitry Andric Explanation += (" ScalarVT(MemVT)=" + VT->getName()).str();
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andric if (ListInit *AddrSpaces = P.getAddressSpaces()) {
1300b57cec5SDimitry Andric raw_string_ostream OS(Explanation);
1310b57cec5SDimitry Andric OS << " AddressSpaces=[";
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric StringRef AddrSpaceSeparator;
1340b57cec5SDimitry Andric for (Init *Val : AddrSpaces->getValues()) {
1350b57cec5SDimitry Andric IntInit *IntVal = dyn_cast<IntInit>(Val);
1360b57cec5SDimitry Andric if (!IntVal)
1370b57cec5SDimitry Andric continue;
1380b57cec5SDimitry Andric
1390b57cec5SDimitry Andric OS << AddrSpaceSeparator << IntVal->getValue();
1400b57cec5SDimitry Andric AddrSpaceSeparator = ", ";
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric OS << ']';
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric
1468bcb0991SDimitry Andric int64_t MinAlign = P.getMinAlignment();
1478bcb0991SDimitry Andric if (MinAlign > 0)
1488bcb0991SDimitry Andric Explanation += " MinAlign=" + utostr(MinAlign);
1498bcb0991SDimitry Andric
1500b57cec5SDimitry Andric if (P.isAtomicOrderingMonotonic())
1510b57cec5SDimitry Andric Explanation += " monotonic";
1520b57cec5SDimitry Andric if (P.isAtomicOrderingAcquire())
1530b57cec5SDimitry Andric Explanation += " acquire";
1540b57cec5SDimitry Andric if (P.isAtomicOrderingRelease())
1550b57cec5SDimitry Andric Explanation += " release";
1560b57cec5SDimitry Andric if (P.isAtomicOrderingAcquireRelease())
1570b57cec5SDimitry Andric Explanation += " acq_rel";
1580b57cec5SDimitry Andric if (P.isAtomicOrderingSequentiallyConsistent())
1590b57cec5SDimitry Andric Explanation += " seq_cst";
1600b57cec5SDimitry Andric if (P.isAtomicOrderingAcquireOrStronger())
1610b57cec5SDimitry Andric Explanation += " >=acquire";
1620b57cec5SDimitry Andric if (P.isAtomicOrderingWeakerThanAcquire())
1630b57cec5SDimitry Andric Explanation += " <acquire";
1640b57cec5SDimitry Andric if (P.isAtomicOrderingReleaseOrStronger())
1650b57cec5SDimitry Andric Explanation += " >=release";
1660b57cec5SDimitry Andric if (P.isAtomicOrderingWeakerThanRelease())
1670b57cec5SDimitry Andric Explanation += " <release";
1680b57cec5SDimitry Andric }
1690b57cec5SDimitry Andric return Explanation;
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric
explainOperator(Record * Operator)1720b57cec5SDimitry Andric std::string explainOperator(Record *Operator) {
1730b57cec5SDimitry Andric if (Operator->isSubClassOf("SDNode"))
1740b57cec5SDimitry Andric return (" (" + Operator->getValueAsString("Opcode") + ")").str();
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric if (Operator->isSubClassOf("Intrinsic"))
1770b57cec5SDimitry Andric return (" (Operator is an Intrinsic, " + Operator->getName() + ")").str();
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric if (Operator->isSubClassOf("ComplexPattern"))
1800b57cec5SDimitry Andric return (" (Operator is an unmapped ComplexPattern, " + Operator->getName() +
1810b57cec5SDimitry Andric ")")
1820b57cec5SDimitry Andric .str();
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric if (Operator->isSubClassOf("SDNodeXForm"))
1850b57cec5SDimitry Andric return (" (Operator is an unmapped SDNodeXForm, " + Operator->getName() +
1860b57cec5SDimitry Andric ")")
1870b57cec5SDimitry Andric .str();
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric return (" (Operator " + Operator->getName() + " not understood)").str();
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric
1920b57cec5SDimitry Andric /// Helper function to let the emitter report skip reason error messages.
failedImport(const Twine & Reason)1930b57cec5SDimitry Andric static Error failedImport(const Twine &Reason) {
1940b57cec5SDimitry Andric return make_error<StringError>(Reason, inconvertibleErrorCode());
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric
isTrivialOperatorNode(const TreePatternNode * N)1970b57cec5SDimitry Andric static Error isTrivialOperatorNode(const TreePatternNode *N) {
198e8d8bef9SDimitry Andric std::string Explanation;
199e8d8bef9SDimitry Andric std::string Separator;
2000b57cec5SDimitry Andric
2010b57cec5SDimitry Andric bool HasUnsupportedPredicate = false;
2020b57cec5SDimitry Andric for (const TreePredicateCall &Call : N->getPredicateCalls()) {
2030b57cec5SDimitry Andric const TreePredicateFn &Predicate = Call.Fn;
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric if (Predicate.isAlwaysTrue())
2060b57cec5SDimitry Andric continue;
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andric if (Predicate.isImmediatePattern())
2090b57cec5SDimitry Andric continue;
2100b57cec5SDimitry Andric
211753f127fSDimitry Andric if (Predicate.hasNoUse())
212753f127fSDimitry Andric continue;
213753f127fSDimitry Andric
2140b57cec5SDimitry Andric if (Predicate.isNonExtLoad() || Predicate.isAnyExtLoad() ||
2150b57cec5SDimitry Andric Predicate.isSignExtLoad() || Predicate.isZeroExtLoad())
2160b57cec5SDimitry Andric continue;
2170b57cec5SDimitry Andric
2180b57cec5SDimitry Andric if (Predicate.isNonTruncStore() || Predicate.isTruncStore())
2190b57cec5SDimitry Andric continue;
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric if (Predicate.isLoad() && Predicate.getMemoryVT())
2220b57cec5SDimitry Andric continue;
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric if (Predicate.isLoad() || Predicate.isStore()) {
2250b57cec5SDimitry Andric if (Predicate.isUnindexed())
2260b57cec5SDimitry Andric continue;
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric
2290b57cec5SDimitry Andric if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) {
2300b57cec5SDimitry Andric const ListInit *AddrSpaces = Predicate.getAddressSpaces();
2310b57cec5SDimitry Andric if (AddrSpaces && !AddrSpaces->empty())
2320b57cec5SDimitry Andric continue;
2338bcb0991SDimitry Andric
2348bcb0991SDimitry Andric if (Predicate.getMinAlignment() > 0)
2358bcb0991SDimitry Andric continue;
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric
2380b57cec5SDimitry Andric if (Predicate.isAtomic() && Predicate.getMemoryVT())
2390b57cec5SDimitry Andric continue;
2400b57cec5SDimitry Andric
2410b57cec5SDimitry Andric if (Predicate.isAtomic() &&
2420b57cec5SDimitry Andric (Predicate.isAtomicOrderingMonotonic() ||
2430b57cec5SDimitry Andric Predicate.isAtomicOrderingAcquire() ||
2440b57cec5SDimitry Andric Predicate.isAtomicOrderingRelease() ||
2450b57cec5SDimitry Andric Predicate.isAtomicOrderingAcquireRelease() ||
2460b57cec5SDimitry Andric Predicate.isAtomicOrderingSequentiallyConsistent() ||
2470b57cec5SDimitry Andric Predicate.isAtomicOrderingAcquireOrStronger() ||
2480b57cec5SDimitry Andric Predicate.isAtomicOrderingWeakerThanAcquire() ||
2490b57cec5SDimitry Andric Predicate.isAtomicOrderingReleaseOrStronger() ||
2500b57cec5SDimitry Andric Predicate.isAtomicOrderingWeakerThanRelease()))
2510b57cec5SDimitry Andric continue;
2520b57cec5SDimitry Andric
2530b57cec5SDimitry Andric if (Predicate.hasGISelPredicateCode())
2540b57cec5SDimitry Andric continue;
2550b57cec5SDimitry Andric
2560b57cec5SDimitry Andric HasUnsupportedPredicate = true;
2570b57cec5SDimitry Andric Explanation = Separator + "Has a predicate (" + explainPredicates(N) + ")";
2580b57cec5SDimitry Andric Separator = ", ";
2590b57cec5SDimitry Andric Explanation += (Separator + "first-failing:" +
2600b57cec5SDimitry Andric Predicate.getOrigPatFragRecord()->getRecord()->getName())
2610b57cec5SDimitry Andric .str();
2620b57cec5SDimitry Andric break;
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric if (!HasUnsupportedPredicate)
2660b57cec5SDimitry Andric return Error::success();
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric return failedImport(Explanation);
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric
getInitValueAsRegClass(Init * V)2710b57cec5SDimitry Andric static Record *getInitValueAsRegClass(Init *V) {
2720b57cec5SDimitry Andric if (DefInit *VDefInit = dyn_cast<DefInit>(V)) {
2730b57cec5SDimitry Andric if (VDefInit->getDef()->isSubClassOf("RegisterOperand"))
2740b57cec5SDimitry Andric return VDefInit->getDef()->getValueAsDef("RegClass");
2750b57cec5SDimitry Andric if (VDefInit->getDef()->isSubClassOf("RegisterClass"))
2760b57cec5SDimitry Andric return VDefInit->getDef();
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric return nullptr;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric
getScopedName(unsigned Scope,const std::string & Name)281e8d8bef9SDimitry Andric static std::string getScopedName(unsigned Scope, const std::string &Name) {
282e8d8bef9SDimitry Andric return ("pred:" + Twine(Scope) + ":" + Name).str();
283e8d8bef9SDimitry Andric }
284e8d8bef9SDimitry Andric
getMangledRootDefName(StringRef DefOperandName)2855f757f3fSDimitry Andric static std::string getMangledRootDefName(StringRef DefOperandName) {
2865f757f3fSDimitry Andric return ("DstI[" + DefOperandName + "]").str();
2875f757f3fSDimitry Andric }
2885f757f3fSDimitry Andric
2890b57cec5SDimitry Andric //===- GlobalISelEmitter class --------------------------------------------===//
2900b57cec5SDimitry Andric
getInstResultType(const TreePatternNode * Dst)2915ffd83dbSDimitry Andric static Expected<LLTCodeGen> getInstResultType(const TreePatternNode *Dst) {
2925ffd83dbSDimitry Andric ArrayRef<TypeSetByHwMode> ChildTypes = Dst->getExtTypes();
2935ffd83dbSDimitry Andric if (ChildTypes.size() != 1)
2945ffd83dbSDimitry Andric return failedImport("Dst pattern child has multiple results");
2955ffd83dbSDimitry Andric
296bdd1243dSDimitry Andric std::optional<LLTCodeGen> MaybeOpTy;
2975ffd83dbSDimitry Andric if (ChildTypes.front().isMachineValueType()) {
29806c3fb27SDimitry Andric MaybeOpTy = MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy);
2995ffd83dbSDimitry Andric }
3005ffd83dbSDimitry Andric
3015ffd83dbSDimitry Andric if (!MaybeOpTy)
3025ffd83dbSDimitry Andric return failedImport("Dst operand has an unsupported type");
3035ffd83dbSDimitry Andric return *MaybeOpTy;
3045ffd83dbSDimitry Andric }
3055ffd83dbSDimitry Andric
30606c3fb27SDimitry Andric class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
3070b57cec5SDimitry Andric public:
3080b57cec5SDimitry Andric explicit GlobalISelEmitter(RecordKeeper &RK);
30906c3fb27SDimitry Andric
31006c3fb27SDimitry Andric void emitAdditionalImpl(raw_ostream &OS) override;
31106c3fb27SDimitry Andric
31206c3fb27SDimitry Andric void emitMIPredicateFns(raw_ostream &OS) override;
31306c3fb27SDimitry Andric void emitI64ImmPredicateFns(raw_ostream &OS) override;
31406c3fb27SDimitry Andric void emitAPFloatImmPredicateFns(raw_ostream &OS) override;
31506c3fb27SDimitry Andric void emitAPIntImmPredicateFns(raw_ostream &OS) override;
31606c3fb27SDimitry Andric void emitTestSimplePredicate(raw_ostream &OS) override;
31706c3fb27SDimitry Andric void emitRunCustomAction(raw_ostream &OS) override;
31806c3fb27SDimitry Andric
3195f757f3fSDimitry Andric void postProcessRule(RuleMatcher &M);
3205f757f3fSDimitry Andric
getTarget() const32106c3fb27SDimitry Andric const CodeGenTarget &getTarget() const override { return Target; }
getClassName() const32206c3fb27SDimitry Andric StringRef getClassName() const override { return ClassName; }
32306c3fb27SDimitry Andric
3240b57cec5SDimitry Andric void run(raw_ostream &OS);
3250b57cec5SDimitry Andric
3260b57cec5SDimitry Andric private:
32706c3fb27SDimitry Andric std::string ClassName;
32806c3fb27SDimitry Andric
3290b57cec5SDimitry Andric const RecordKeeper &RK;
3300b57cec5SDimitry Andric const CodeGenDAGPatterns CGP;
3310b57cec5SDimitry Andric const CodeGenTarget &Target;
3325ffd83dbSDimitry Andric CodeGenRegBank &CGRegs;
3330b57cec5SDimitry Andric
33406c3fb27SDimitry Andric std::vector<Record *> AllPatFrags;
33506c3fb27SDimitry Andric
3360b57cec5SDimitry Andric /// Keep track of the equivalence between SDNodes and Instruction by mapping
3370b57cec5SDimitry Andric /// SDNodes to the GINodeEquiv mapping. We need to map to the GINodeEquiv to
3380b57cec5SDimitry Andric /// check for attributes on the relation such as CheckMMOIsNonAtomic.
3390b57cec5SDimitry Andric /// This is defined using 'GINodeEquiv' in the target description.
3400b57cec5SDimitry Andric DenseMap<Record *, Record *> NodeEquivs;
3410b57cec5SDimitry Andric
3420b57cec5SDimitry Andric /// Keep track of the equivalence between ComplexPattern's and
3430b57cec5SDimitry Andric /// GIComplexOperandMatcher. Map entries are specified by subclassing
3440b57cec5SDimitry Andric /// GIComplexPatternEquiv.
3450b57cec5SDimitry Andric DenseMap<const Record *, const Record *> ComplexPatternEquivs;
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andric /// Keep track of the equivalence between SDNodeXForm's and
3480b57cec5SDimitry Andric /// GICustomOperandRenderer. Map entries are specified by subclassing
3490b57cec5SDimitry Andric /// GISDNodeXFormEquiv.
3500b57cec5SDimitry Andric DenseMap<const Record *, const Record *> SDNodeXFormEquivs;
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric /// Keep track of Scores of PatternsToMatch similar to how the DAG does.
3530b57cec5SDimitry Andric /// This adds compatibility for RuleMatchers to use this for ordering rules.
3540b57cec5SDimitry Andric DenseMap<uint64_t, int> RuleMatcherScores;
3550b57cec5SDimitry Andric
3560b57cec5SDimitry Andric // Rule coverage information.
357bdd1243dSDimitry Andric std::optional<CodeGenCoverage> RuleCoverage;
3580b57cec5SDimitry Andric
359e8d8bef9SDimitry Andric /// Variables used to help with collecting of named operands for predicates
360e8d8bef9SDimitry Andric /// with 'let PredicateCodeUsesOperands = 1'. WaitingForNamedOperands is set
361e8d8bef9SDimitry Andric /// to the number of named operands that predicate expects. Store locations in
362e8d8bef9SDimitry Andric /// StoreIdxForName correspond to the order in which operand names appear in
363e8d8bef9SDimitry Andric /// predicate's argument list.
3645f757f3fSDimitry Andric /// When we visit named operand and WaitingForNamedOperands is not zero, add
3655f757f3fSDimitry Andric /// matcher that will record operand and decrease counter.
366e8d8bef9SDimitry Andric unsigned WaitingForNamedOperands = 0;
367e8d8bef9SDimitry Andric StringMap<unsigned> StoreIdxForName;
368e8d8bef9SDimitry Andric
3690b57cec5SDimitry Andric void gatherOpcodeValues();
3700b57cec5SDimitry Andric void gatherTypeIDValues();
3710b57cec5SDimitry Andric void gatherNodeEquivs();
3720b57cec5SDimitry Andric
3730b57cec5SDimitry Andric Record *findNodeEquiv(Record *N) const;
3740b57cec5SDimitry Andric const CodeGenInstruction *getEquivNode(Record &Equiv,
3750b57cec5SDimitry Andric const TreePatternNode *N) const;
3760b57cec5SDimitry Andric
377fe6060f1SDimitry Andric Error importRulePredicates(RuleMatcher &M, ArrayRef<Record *> Predicates);
3780b57cec5SDimitry Andric Expected<InstructionMatcher &>
3790b57cec5SDimitry Andric createAndImportSelDAGMatcher(RuleMatcher &Rule,
3800b57cec5SDimitry Andric InstructionMatcher &InsnMatcher,
3810b57cec5SDimitry Andric const TreePatternNode *Src, unsigned &TempOpIdx);
3820b57cec5SDimitry Andric Error importComplexPatternOperandMatcher(OperandMatcher &OM, Record *R,
3830b57cec5SDimitry Andric unsigned &TempOpIdx) const;
3840b57cec5SDimitry Andric Error importChildMatcher(RuleMatcher &Rule, InstructionMatcher &InsnMatcher,
3850b57cec5SDimitry Andric const TreePatternNode *SrcChild,
386480093f4SDimitry Andric bool OperandIsAPointer, bool OperandIsImmArg,
387480093f4SDimitry Andric unsigned OpIdx, unsigned &TempOpIdx);
3880b57cec5SDimitry Andric
3898bcb0991SDimitry Andric Expected<BuildMIAction &> createAndImportInstructionRenderer(
3908bcb0991SDimitry Andric RuleMatcher &M, InstructionMatcher &InsnMatcher,
3918bcb0991SDimitry Andric const TreePatternNode *Src, const TreePatternNode *Dst);
3920b57cec5SDimitry Andric Expected<action_iterator> createAndImportSubInstructionRenderer(
3930b57cec5SDimitry Andric action_iterator InsertPt, RuleMatcher &M, const TreePatternNode *Dst,
39406c3fb27SDimitry Andric const TreePatternNode *Src, unsigned TempReg);
3950b57cec5SDimitry Andric Expected<action_iterator>
3960b57cec5SDimitry Andric createInstructionRenderer(action_iterator InsertPt, RuleMatcher &M,
3970b57cec5SDimitry Andric const TreePatternNode *Dst);
398e8d8bef9SDimitry Andric
39906c3fb27SDimitry Andric Expected<action_iterator> importExplicitDefRenderers(
40006c3fb27SDimitry Andric action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
40106c3fb27SDimitry Andric const TreePatternNode *Src, const TreePatternNode *Dst);
4028bcb0991SDimitry Andric
40306c3fb27SDimitry Andric Expected<action_iterator> importExplicitUseRenderers(
40406c3fb27SDimitry Andric action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
40506c3fb27SDimitry Andric const llvm::TreePatternNode *Dst, const TreePatternNode *Src);
40606c3fb27SDimitry Andric Expected<action_iterator> importExplicitUseRenderer(
40706c3fb27SDimitry Andric action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder,
40806c3fb27SDimitry Andric const TreePatternNode *DstChild, const TreePatternNode *Src);
4090b57cec5SDimitry Andric Error importDefaultOperandRenderers(action_iterator InsertPt, RuleMatcher &M,
4100b57cec5SDimitry Andric BuildMIAction &DstMIBuilder,
4115f757f3fSDimitry Andric const DAGDefaultOperand &DefaultOp) const;
4120b57cec5SDimitry Andric Error
4130b57cec5SDimitry Andric importImplicitDefRenderers(BuildMIAction &DstMIBuilder,
4140b57cec5SDimitry Andric const std::vector<Record *> &ImplicitDefs) const;
4150b57cec5SDimitry Andric
4160b57cec5SDimitry Andric /// Analyze pattern \p P, returning a matcher for it if possible.
4170b57cec5SDimitry Andric /// Otherwise, return an Error explaining why we don't support it.
4180b57cec5SDimitry Andric Expected<RuleMatcher> runOnPattern(const PatternToMatch &P);
4190b57cec5SDimitry Andric
4200b57cec5SDimitry Andric void declareSubtargetFeature(Record *Predicate);
4210b57cec5SDimitry Andric
4225f757f3fSDimitry Andric unsigned declareHwModeCheck(StringRef HwModeFeatures);
4235f757f3fSDimitry Andric
4240b57cec5SDimitry Andric MatchTable buildMatchTable(MutableArrayRef<RuleMatcher> Rules, bool Optimize,
4250b57cec5SDimitry Andric bool WithCoverage);
4260b57cec5SDimitry Andric
4278bcb0991SDimitry Andric /// Infer a CodeGenRegisterClass for the type of \p SuperRegNode. The returned
4288bcb0991SDimitry Andric /// CodeGenRegisterClass will support the CodeGenRegisterClass of
4298bcb0991SDimitry Andric /// \p SubRegNode, and the subregister index defined by \p SubRegIdxNode.
430bdd1243dSDimitry Andric /// If no register class is found, return std::nullopt.
431bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *>
4328bcb0991SDimitry Andric inferSuperRegisterClassForNode(const TypeSetByHwMode &Ty,
43306c3fb27SDimitry Andric const TreePatternNode *SuperRegNode,
43406c3fb27SDimitry Andric const TreePatternNode *SubRegIdxNode);
435bdd1243dSDimitry Andric std::optional<CodeGenSubRegIndex *>
43606c3fb27SDimitry Andric inferSubRegIndexForNode(const TreePatternNode *SubRegIdxNode);
4378bcb0991SDimitry Andric
4388bcb0991SDimitry Andric /// Infer a CodeGenRegisterClass which suppoorts \p Ty and \p SubRegIdxNode.
439bdd1243dSDimitry Andric /// Return std::nullopt if no such class exists.
440bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *>
4418bcb0991SDimitry Andric inferSuperRegisterClass(const TypeSetByHwMode &Ty,
44206c3fb27SDimitry Andric const TreePatternNode *SubRegIdxNode);
4438bcb0991SDimitry Andric
4448bcb0991SDimitry Andric /// Return the CodeGenRegisterClass associated with \p Leaf if it has one.
445bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *>
44606c3fb27SDimitry Andric getRegClassFromLeaf(const TreePatternNode *Leaf);
4478bcb0991SDimitry Andric
448bdd1243dSDimitry Andric /// Return a CodeGenRegisterClass for \p N if one can be found. Return
449bdd1243dSDimitry Andric /// std::nullopt otherwise.
450bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *>
45106c3fb27SDimitry Andric inferRegClassFromPattern(const TreePatternNode *N);
4528bcb0991SDimitry Andric
453fe6060f1SDimitry Andric /// Return the size of the MemoryVT in this predicate, if possible.
454bdd1243dSDimitry Andric std::optional<unsigned>
455fe6060f1SDimitry Andric getMemSizeBitsFromPredicate(const TreePredicateFn &Predicate);
456fe6060f1SDimitry Andric
457e8d8bef9SDimitry Andric // Add builtin predicates.
458e8d8bef9SDimitry Andric Expected<InstructionMatcher &>
459e8d8bef9SDimitry Andric addBuiltinPredicates(const Record *SrcGIEquivOrNull,
460e8d8bef9SDimitry Andric const TreePredicateFn &Predicate,
461e8d8bef9SDimitry Andric InstructionMatcher &InsnMatcher, bool &HasAddedMatcher);
4620b57cec5SDimitry Andric };
4630b57cec5SDimitry Andric
getPatFragPredicateEnumName(Record * R)46406c3fb27SDimitry Andric StringRef getPatFragPredicateEnumName(Record *R) { return R->getName(); }
46506c3fb27SDimitry Andric
gatherOpcodeValues()4660b57cec5SDimitry Andric void GlobalISelEmitter::gatherOpcodeValues() {
4670b57cec5SDimitry Andric InstructionOpcodeMatcher::initOpcodeValuesMap(Target);
4680b57cec5SDimitry Andric }
4690b57cec5SDimitry Andric
gatherTypeIDValues()4700b57cec5SDimitry Andric void GlobalISelEmitter::gatherTypeIDValues() {
4710b57cec5SDimitry Andric LLTOperandMatcher::initTypeIDValuesMap();
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric
gatherNodeEquivs()4740b57cec5SDimitry Andric void GlobalISelEmitter::gatherNodeEquivs() {
4750b57cec5SDimitry Andric assert(NodeEquivs.empty());
4760b57cec5SDimitry Andric for (Record *Equiv : RK.getAllDerivedDefinitions("GINodeEquiv"))
4770b57cec5SDimitry Andric NodeEquivs[Equiv->getValueAsDef("Node")] = Equiv;
4780b57cec5SDimitry Andric
4790b57cec5SDimitry Andric assert(ComplexPatternEquivs.empty());
4800b57cec5SDimitry Andric for (Record *Equiv : RK.getAllDerivedDefinitions("GIComplexPatternEquiv")) {
4810b57cec5SDimitry Andric Record *SelDAGEquiv = Equiv->getValueAsDef("SelDAGEquivalent");
4820b57cec5SDimitry Andric if (!SelDAGEquiv)
4830b57cec5SDimitry Andric continue;
4840b57cec5SDimitry Andric ComplexPatternEquivs[SelDAGEquiv] = Equiv;
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric
4870b57cec5SDimitry Andric assert(SDNodeXFormEquivs.empty());
4880b57cec5SDimitry Andric for (Record *Equiv : RK.getAllDerivedDefinitions("GISDNodeXFormEquiv")) {
4890b57cec5SDimitry Andric Record *SelDAGEquiv = Equiv->getValueAsDef("SelDAGEquivalent");
4900b57cec5SDimitry Andric if (!SelDAGEquiv)
4910b57cec5SDimitry Andric continue;
4920b57cec5SDimitry Andric SDNodeXFormEquivs[SelDAGEquiv] = Equiv;
4930b57cec5SDimitry Andric }
4940b57cec5SDimitry Andric }
4950b57cec5SDimitry Andric
findNodeEquiv(Record * N) const4960b57cec5SDimitry Andric Record *GlobalISelEmitter::findNodeEquiv(Record *N) const {
4970b57cec5SDimitry Andric return NodeEquivs.lookup(N);
4980b57cec5SDimitry Andric }
4990b57cec5SDimitry Andric
5000b57cec5SDimitry Andric const CodeGenInstruction *
getEquivNode(Record & Equiv,const TreePatternNode * N) const5010b57cec5SDimitry Andric GlobalISelEmitter::getEquivNode(Record &Equiv, const TreePatternNode *N) const {
5028bcb0991SDimitry Andric if (N->getNumChildren() >= 1) {
5038bcb0991SDimitry Andric // setcc operation maps to two different G_* instructions based on the type.
5048bcb0991SDimitry Andric if (!Equiv.isValueUnset("IfFloatingPoint") &&
5058bcb0991SDimitry Andric MVT(N->getChild(0)->getSimpleType(0)).isFloatingPoint())
5068bcb0991SDimitry Andric return &Target.getInstruction(Equiv.getValueAsDef("IfFloatingPoint"));
5078bcb0991SDimitry Andric }
5088bcb0991SDimitry Andric
5095f757f3fSDimitry Andric if (!Equiv.isValueUnset("IfConvergent") &&
5105f757f3fSDimitry Andric N->getIntrinsicInfo(CGP)->isConvergent)
5115f757f3fSDimitry Andric return &Target.getInstruction(Equiv.getValueAsDef("IfConvergent"));
5125f757f3fSDimitry Andric
5130b57cec5SDimitry Andric for (const TreePredicateCall &Call : N->getPredicateCalls()) {
5140b57cec5SDimitry Andric const TreePredicateFn &Predicate = Call.Fn;
515753f127fSDimitry Andric if (!Equiv.isValueUnset("IfSignExtend") &&
516753f127fSDimitry Andric (Predicate.isLoad() || Predicate.isAtomic()) &&
5170b57cec5SDimitry Andric Predicate.isSignExtLoad())
5180b57cec5SDimitry Andric return &Target.getInstruction(Equiv.getValueAsDef("IfSignExtend"));
519753f127fSDimitry Andric if (!Equiv.isValueUnset("IfZeroExtend") &&
520753f127fSDimitry Andric (Predicate.isLoad() || Predicate.isAtomic()) &&
5210b57cec5SDimitry Andric Predicate.isZeroExtLoad())
5220b57cec5SDimitry Andric return &Target.getInstruction(Equiv.getValueAsDef("IfZeroExtend"));
5230b57cec5SDimitry Andric }
5248bcb0991SDimitry Andric
5250b57cec5SDimitry Andric return &Target.getInstruction(Equiv.getValueAsDef("I"));
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric
GlobalISelEmitter(RecordKeeper & RK)5280b57cec5SDimitry Andric GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK)
52906c3fb27SDimitry Andric : GlobalISelMatchTableExecutorEmitter(), RK(RK), CGP(RK),
53006c3fb27SDimitry Andric Target(CGP.getTargetInfo()), CGRegs(Target.getRegBank()) {
53106c3fb27SDimitry Andric ClassName = Target.getName().str() + "InstructionSelector";
53206c3fb27SDimitry Andric }
5330b57cec5SDimitry Andric
5340b57cec5SDimitry Andric //===- Emitter ------------------------------------------------------------===//
5350b57cec5SDimitry Andric
importRulePredicates(RuleMatcher & M,ArrayRef<Record * > Predicates)536fe6060f1SDimitry Andric Error GlobalISelEmitter::importRulePredicates(RuleMatcher &M,
537fe6060f1SDimitry Andric ArrayRef<Record *> Predicates) {
538fe6060f1SDimitry Andric for (Record *Pred : Predicates) {
539fe6060f1SDimitry Andric if (Pred->getValueAsString("CondString").empty())
5400b57cec5SDimitry Andric continue;
541fe6060f1SDimitry Andric declareSubtargetFeature(Pred);
542fe6060f1SDimitry Andric M.addRequiredFeature(Pred);
5430b57cec5SDimitry Andric }
5440b57cec5SDimitry Andric
5450b57cec5SDimitry Andric return Error::success();
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric
getMemSizeBitsFromPredicate(const TreePredicateFn & Predicate)548bdd1243dSDimitry Andric std::optional<unsigned> GlobalISelEmitter::getMemSizeBitsFromPredicate(
549bdd1243dSDimitry Andric const TreePredicateFn &Predicate) {
550bdd1243dSDimitry Andric std::optional<LLTCodeGen> MemTyOrNone =
551fe6060f1SDimitry Andric MVTToLLT(getValueType(Predicate.getMemoryVT()));
552fe6060f1SDimitry Andric
553fe6060f1SDimitry Andric if (!MemTyOrNone)
554bdd1243dSDimitry Andric return std::nullopt;
555fe6060f1SDimitry Andric
556fe6060f1SDimitry Andric // Align so unusual types like i1 don't get rounded down.
557fe6060f1SDimitry Andric return llvm::alignTo(
558fe6060f1SDimitry Andric static_cast<unsigned>(MemTyOrNone->get().getSizeInBits()), 8);
559fe6060f1SDimitry Andric }
560fe6060f1SDimitry Andric
addBuiltinPredicates(const Record * SrcGIEquivOrNull,const TreePredicateFn & Predicate,InstructionMatcher & InsnMatcher,bool & HasAddedMatcher)561e8d8bef9SDimitry Andric Expected<InstructionMatcher &> GlobalISelEmitter::addBuiltinPredicates(
562e8d8bef9SDimitry Andric const Record *SrcGIEquivOrNull, const TreePredicateFn &Predicate,
563e8d8bef9SDimitry Andric InstructionMatcher &InsnMatcher, bool &HasAddedMatcher) {
564e8d8bef9SDimitry Andric if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) {
565e8d8bef9SDimitry Andric if (const ListInit *AddrSpaces = Predicate.getAddressSpaces()) {
566e8d8bef9SDimitry Andric SmallVector<unsigned, 4> ParsedAddrSpaces;
567e8d8bef9SDimitry Andric
568e8d8bef9SDimitry Andric for (Init *Val : AddrSpaces->getValues()) {
569e8d8bef9SDimitry Andric IntInit *IntVal = dyn_cast<IntInit>(Val);
570e8d8bef9SDimitry Andric if (!IntVal)
571e8d8bef9SDimitry Andric return failedImport("Address space is not an integer");
572e8d8bef9SDimitry Andric ParsedAddrSpaces.push_back(IntVal->getValue());
573e8d8bef9SDimitry Andric }
574e8d8bef9SDimitry Andric
575e8d8bef9SDimitry Andric if (!ParsedAddrSpaces.empty()) {
576e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryAddressSpacePredicateMatcher>(
577e8d8bef9SDimitry Andric 0, ParsedAddrSpaces);
57881ad6265SDimitry Andric return InsnMatcher;
579e8d8bef9SDimitry Andric }
580e8d8bef9SDimitry Andric }
581e8d8bef9SDimitry Andric
582e8d8bef9SDimitry Andric int64_t MinAlign = Predicate.getMinAlignment();
58381ad6265SDimitry Andric if (MinAlign > 0) {
584e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryAlignmentPredicateMatcher>(0, MinAlign);
58581ad6265SDimitry Andric return InsnMatcher;
58681ad6265SDimitry Andric }
587e8d8bef9SDimitry Andric }
588e8d8bef9SDimitry Andric
589e8d8bef9SDimitry Andric // G_LOAD is used for both non-extending and any-extending loads.
590e8d8bef9SDimitry Andric if (Predicate.isLoad() && Predicate.isNonExtLoad()) {
591e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>(
592e8d8bef9SDimitry Andric 0, MemoryVsLLTSizePredicateMatcher::EqualTo, 0);
593e8d8bef9SDimitry Andric return InsnMatcher;
594e8d8bef9SDimitry Andric }
595e8d8bef9SDimitry Andric if (Predicate.isLoad() && Predicate.isAnyExtLoad()) {
596e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>(
597e8d8bef9SDimitry Andric 0, MemoryVsLLTSizePredicateMatcher::LessThan, 0);
598e8d8bef9SDimitry Andric return InsnMatcher;
599e8d8bef9SDimitry Andric }
600e8d8bef9SDimitry Andric
601e8d8bef9SDimitry Andric if (Predicate.isStore()) {
602e8d8bef9SDimitry Andric if (Predicate.isTruncStore()) {
603fe6060f1SDimitry Andric if (Predicate.getMemoryVT() != nullptr) {
604e8d8bef9SDimitry Andric // FIXME: If MemoryVT is set, we end up with 2 checks for the MMO size.
605fe6060f1SDimitry Andric auto MemSizeInBits = getMemSizeBitsFromPredicate(Predicate);
606fe6060f1SDimitry Andric if (!MemSizeInBits)
607fe6060f1SDimitry Andric return failedImport("MemVT could not be converted to LLT");
608fe6060f1SDimitry Andric
609fe6060f1SDimitry Andric InsnMatcher.addPredicate<MemorySizePredicateMatcher>(0, *MemSizeInBits /
610fe6060f1SDimitry Andric 8);
611fe6060f1SDimitry Andric } else {
612e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>(
613e8d8bef9SDimitry Andric 0, MemoryVsLLTSizePredicateMatcher::LessThan, 0);
614fe6060f1SDimitry Andric }
615e8d8bef9SDimitry Andric return InsnMatcher;
616e8d8bef9SDimitry Andric }
617e8d8bef9SDimitry Andric if (Predicate.isNonTruncStore()) {
618e8d8bef9SDimitry Andric // We need to check the sizes match here otherwise we could incorrectly
619e8d8bef9SDimitry Andric // match truncating stores with non-truncating ones.
620e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>(
621e8d8bef9SDimitry Andric 0, MemoryVsLLTSizePredicateMatcher::EqualTo, 0);
622e8d8bef9SDimitry Andric }
623e8d8bef9SDimitry Andric }
624e8d8bef9SDimitry Andric
62506c3fb27SDimitry Andric assert(SrcGIEquivOrNull != nullptr && "Invalid SrcGIEquivOrNull value");
626e8d8bef9SDimitry Andric // No check required. We already did it by swapping the opcode.
627e8d8bef9SDimitry Andric if (!SrcGIEquivOrNull->isValueUnset("IfSignExtend") &&
628e8d8bef9SDimitry Andric Predicate.isSignExtLoad())
629e8d8bef9SDimitry Andric return InsnMatcher;
630e8d8bef9SDimitry Andric
631e8d8bef9SDimitry Andric // No check required. We already did it by swapping the opcode.
632e8d8bef9SDimitry Andric if (!SrcGIEquivOrNull->isValueUnset("IfZeroExtend") &&
633e8d8bef9SDimitry Andric Predicate.isZeroExtLoad())
634e8d8bef9SDimitry Andric return InsnMatcher;
635e8d8bef9SDimitry Andric
636e8d8bef9SDimitry Andric // No check required. G_STORE by itself is a non-extending store.
637e8d8bef9SDimitry Andric if (Predicate.isNonTruncStore())
638e8d8bef9SDimitry Andric return InsnMatcher;
639e8d8bef9SDimitry Andric
640e8d8bef9SDimitry Andric if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) {
641e8d8bef9SDimitry Andric if (Predicate.getMemoryVT() != nullptr) {
642fe6060f1SDimitry Andric auto MemSizeInBits = getMemSizeBitsFromPredicate(Predicate);
643fe6060f1SDimitry Andric if (!MemSizeInBits)
644e8d8bef9SDimitry Andric return failedImport("MemVT could not be converted to LLT");
645e8d8bef9SDimitry Andric
646e8d8bef9SDimitry Andric InsnMatcher.addPredicate<MemorySizePredicateMatcher>(0,
647fe6060f1SDimitry Andric *MemSizeInBits / 8);
648e8d8bef9SDimitry Andric return InsnMatcher;
649e8d8bef9SDimitry Andric }
650e8d8bef9SDimitry Andric }
651e8d8bef9SDimitry Andric
652e8d8bef9SDimitry Andric if (Predicate.isLoad() || Predicate.isStore()) {
653e8d8bef9SDimitry Andric // No check required. A G_LOAD/G_STORE is an unindexed load.
654e8d8bef9SDimitry Andric if (Predicate.isUnindexed())
655e8d8bef9SDimitry Andric return InsnMatcher;
656e8d8bef9SDimitry Andric }
657e8d8bef9SDimitry Andric
658e8d8bef9SDimitry Andric if (Predicate.isAtomic()) {
659e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingMonotonic()) {
660e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>("Monotonic");
661e8d8bef9SDimitry Andric return InsnMatcher;
662e8d8bef9SDimitry Andric }
663e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingAcquire()) {
664e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>("Acquire");
665e8d8bef9SDimitry Andric return InsnMatcher;
666e8d8bef9SDimitry Andric }
667e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingRelease()) {
668e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>("Release");
669e8d8bef9SDimitry Andric return InsnMatcher;
670e8d8bef9SDimitry Andric }
671e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingAcquireRelease()) {
672e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>(
673e8d8bef9SDimitry Andric "AcquireRelease");
674e8d8bef9SDimitry Andric return InsnMatcher;
675e8d8bef9SDimitry Andric }
676e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingSequentiallyConsistent()) {
677e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>(
678e8d8bef9SDimitry Andric "SequentiallyConsistent");
679e8d8bef9SDimitry Andric return InsnMatcher;
680e8d8bef9SDimitry Andric }
681e8d8bef9SDimitry Andric }
682e8d8bef9SDimitry Andric
683e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingAcquireOrStronger()) {
684e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>(
685e8d8bef9SDimitry Andric "Acquire", AtomicOrderingMMOPredicateMatcher::AO_OrStronger);
686e8d8bef9SDimitry Andric return InsnMatcher;
687e8d8bef9SDimitry Andric }
688e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingWeakerThanAcquire()) {
689e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>(
690e8d8bef9SDimitry Andric "Acquire", AtomicOrderingMMOPredicateMatcher::AO_WeakerThan);
691e8d8bef9SDimitry Andric return InsnMatcher;
692e8d8bef9SDimitry Andric }
693e8d8bef9SDimitry Andric
694e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingReleaseOrStronger()) {
695e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>(
696e8d8bef9SDimitry Andric "Release", AtomicOrderingMMOPredicateMatcher::AO_OrStronger);
697e8d8bef9SDimitry Andric return InsnMatcher;
698e8d8bef9SDimitry Andric }
699e8d8bef9SDimitry Andric if (Predicate.isAtomicOrderingWeakerThanRelease()) {
700e8d8bef9SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>(
701e8d8bef9SDimitry Andric "Release", AtomicOrderingMMOPredicateMatcher::AO_WeakerThan);
702e8d8bef9SDimitry Andric return InsnMatcher;
703e8d8bef9SDimitry Andric }
704e8d8bef9SDimitry Andric HasAddedMatcher = false;
705e8d8bef9SDimitry Andric return InsnMatcher;
706e8d8bef9SDimitry Andric }
707e8d8bef9SDimitry Andric
createAndImportSelDAGMatcher(RuleMatcher & Rule,InstructionMatcher & InsnMatcher,const TreePatternNode * Src,unsigned & TempOpIdx)7080b57cec5SDimitry Andric Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
7090b57cec5SDimitry Andric RuleMatcher &Rule, InstructionMatcher &InsnMatcher,
7100b57cec5SDimitry Andric const TreePatternNode *Src, unsigned &TempOpIdx) {
71106c3fb27SDimitry Andric const auto SavedFlags = Rule.setGISelFlags(Src->getGISelFlagsRecord());
71206c3fb27SDimitry Andric
7130b57cec5SDimitry Andric Record *SrcGIEquivOrNull = nullptr;
7140b57cec5SDimitry Andric const CodeGenInstruction *SrcGIOrNull = nullptr;
7150b57cec5SDimitry Andric
7160b57cec5SDimitry Andric // Start with the defined operands (i.e., the results of the root operator).
7170b57cec5SDimitry Andric if (Src->isLeaf()) {
7180b57cec5SDimitry Andric Init *SrcInit = Src->getLeafValue();
7190b57cec5SDimitry Andric if (isa<IntInit>(SrcInit)) {
7200b57cec5SDimitry Andric InsnMatcher.addPredicate<InstructionOpcodeMatcher>(
7210b57cec5SDimitry Andric &Target.getInstruction(RK.getDef("G_CONSTANT")));
7220b57cec5SDimitry Andric } else
7230b57cec5SDimitry Andric return failedImport(
7240b57cec5SDimitry Andric "Unable to deduce gMIR opcode to handle Src (which is a leaf)");
7250b57cec5SDimitry Andric } else {
7260b57cec5SDimitry Andric SrcGIEquivOrNull = findNodeEquiv(Src->getOperator());
7270b57cec5SDimitry Andric if (!SrcGIEquivOrNull)
7280b57cec5SDimitry Andric return failedImport("Pattern operator lacks an equivalent Instruction" +
7290b57cec5SDimitry Andric explainOperator(Src->getOperator()));
7300b57cec5SDimitry Andric SrcGIOrNull = getEquivNode(*SrcGIEquivOrNull, Src);
7310b57cec5SDimitry Andric
7320b57cec5SDimitry Andric // The operators look good: match the opcode
7330b57cec5SDimitry Andric InsnMatcher.addPredicate<InstructionOpcodeMatcher>(SrcGIOrNull);
7340b57cec5SDimitry Andric }
7350b57cec5SDimitry Andric
7360b57cec5SDimitry Andric unsigned OpIdx = 0;
7370b57cec5SDimitry Andric for (const TypeSetByHwMode &VTy : Src->getExtTypes()) {
7380b57cec5SDimitry Andric // Results don't have a name unless they are the root node. The caller will
7390b57cec5SDimitry Andric // set the name if appropriate.
740bdd1243dSDimitry Andric const bool OperandIsAPointer =
741bdd1243dSDimitry Andric SrcGIOrNull && SrcGIOrNull->isOutOperandAPointer(OpIdx);
7420b57cec5SDimitry Andric OperandMatcher &OM = InsnMatcher.addOperand(OpIdx++, "", TempOpIdx);
743bdd1243dSDimitry Andric if (auto Error = OM.addTypeCheckPredicate(VTy, OperandIsAPointer))
7440b57cec5SDimitry Andric return failedImport(toString(std::move(Error)) +
7450b57cec5SDimitry Andric " for result of Src pattern operator");
7460b57cec5SDimitry Andric }
7470b57cec5SDimitry Andric
7480b57cec5SDimitry Andric for (const TreePredicateCall &Call : Src->getPredicateCalls()) {
7490b57cec5SDimitry Andric const TreePredicateFn &Predicate = Call.Fn;
750e8d8bef9SDimitry Andric bool HasAddedBuiltinMatcher = true;
7510b57cec5SDimitry Andric if (Predicate.isAlwaysTrue())
7520b57cec5SDimitry Andric continue;
7530b57cec5SDimitry Andric
7540b57cec5SDimitry Andric if (Predicate.isImmediatePattern()) {
7550b57cec5SDimitry Andric InsnMatcher.addPredicate<InstructionImmPredicateMatcher>(Predicate);
7560b57cec5SDimitry Andric continue;
7570b57cec5SDimitry Andric }
7580b57cec5SDimitry Andric
759e8d8bef9SDimitry Andric auto InsnMatcherOrError = addBuiltinPredicates(
760e8d8bef9SDimitry Andric SrcGIEquivOrNull, Predicate, InsnMatcher, HasAddedBuiltinMatcher);
761e8d8bef9SDimitry Andric if (auto Error = InsnMatcherOrError.takeError())
762e8d8bef9SDimitry Andric return std::move(Error);
7630b57cec5SDimitry Andric
764753f127fSDimitry Andric // FIXME: This should be part of addBuiltinPredicates(). If we add this at
765753f127fSDimitry Andric // the start of addBuiltinPredicates() without returning, then there might
766753f127fSDimitry Andric // be cases where we hit the last return before which the
767753f127fSDimitry Andric // HasAddedBuiltinMatcher will be set to false. The predicate could be
768753f127fSDimitry Andric // missed if we add it in the middle or at the end due to return statements
769753f127fSDimitry Andric // after the addPredicate<>() calls.
770753f127fSDimitry Andric if (Predicate.hasNoUse()) {
771753f127fSDimitry Andric InsnMatcher.addPredicate<NoUsePredicateMatcher>();
772753f127fSDimitry Andric HasAddedBuiltinMatcher = true;
773753f127fSDimitry Andric }
774753f127fSDimitry Andric
7750b57cec5SDimitry Andric if (Predicate.hasGISelPredicateCode()) {
776e8d8bef9SDimitry Andric if (Predicate.usesOperands()) {
777e8d8bef9SDimitry Andric assert(WaitingForNamedOperands == 0 &&
778e8d8bef9SDimitry Andric "previous predicate didn't find all operands or "
779e8d8bef9SDimitry Andric "nested predicate that uses operands");
780e8d8bef9SDimitry Andric TreePattern *TP = Predicate.getOrigPatFragRecord();
781e8d8bef9SDimitry Andric WaitingForNamedOperands = TP->getNumArgs();
782e8d8bef9SDimitry Andric for (unsigned i = 0; i < WaitingForNamedOperands; ++i)
783e8d8bef9SDimitry Andric StoreIdxForName[getScopedName(Call.Scope, TP->getArgName(i))] = i;
784e8d8bef9SDimitry Andric }
7850b57cec5SDimitry Andric InsnMatcher.addPredicate<GenericInstructionPredicateMatcher>(Predicate);
7860b57cec5SDimitry Andric continue;
7870b57cec5SDimitry Andric }
788e8d8bef9SDimitry Andric if (!HasAddedBuiltinMatcher) {
7890b57cec5SDimitry Andric return failedImport("Src pattern child has predicate (" +
7900b57cec5SDimitry Andric explainPredicates(Src) + ")");
7910b57cec5SDimitry Andric }
792e8d8bef9SDimitry Andric }
793e8d8bef9SDimitry Andric
79406c3fb27SDimitry Andric if (SrcGIEquivOrNull &&
79506c3fb27SDimitry Andric SrcGIEquivOrNull->getValueAsBit("CheckMMOIsNonAtomic"))
7960b57cec5SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>("NotAtomic");
79706c3fb27SDimitry Andric else if (SrcGIEquivOrNull &&
79806c3fb27SDimitry Andric SrcGIEquivOrNull->getValueAsBit("CheckMMOIsAtomic")) {
7998bcb0991SDimitry Andric InsnMatcher.addPredicate<AtomicOrderingMMOPredicateMatcher>(
8008bcb0991SDimitry Andric "Unordered", AtomicOrderingMMOPredicateMatcher::AO_OrStronger);
8018bcb0991SDimitry Andric }
8020b57cec5SDimitry Andric
8030b57cec5SDimitry Andric if (Src->isLeaf()) {
8040b57cec5SDimitry Andric Init *SrcInit = Src->getLeafValue();
8050b57cec5SDimitry Andric if (IntInit *SrcIntInit = dyn_cast<IntInit>(SrcInit)) {
8060b57cec5SDimitry Andric OperandMatcher &OM =
8070b57cec5SDimitry Andric InsnMatcher.addOperand(OpIdx++, Src->getName(), TempOpIdx);
8080b57cec5SDimitry Andric OM.addPredicate<LiteralIntOperandMatcher>(SrcIntInit->getValue());
8090b57cec5SDimitry Andric } else
8100b57cec5SDimitry Andric return failedImport(
8110b57cec5SDimitry Andric "Unable to deduce gMIR opcode to handle Src (which is a leaf)");
8120b57cec5SDimitry Andric } else {
8130b57cec5SDimitry Andric assert(SrcGIOrNull &&
8140b57cec5SDimitry Andric "Expected to have already found an equivalent Instruction");
8150b57cec5SDimitry Andric if (SrcGIOrNull->TheDef->getName() == "G_CONSTANT" ||
8160b57cec5SDimitry Andric SrcGIOrNull->TheDef->getName() == "G_FCONSTANT") {
8170b57cec5SDimitry Andric // imm/fpimm still have operands but we don't need to do anything with it
8180b57cec5SDimitry Andric // here since we don't support ImmLeaf predicates yet. However, we still
8190b57cec5SDimitry Andric // need to note the hidden operand to get GIM_CheckNumOperands correct.
8200b57cec5SDimitry Andric InsnMatcher.addOperand(OpIdx++, "", TempOpIdx);
8210b57cec5SDimitry Andric return InsnMatcher;
8220b57cec5SDimitry Andric }
8230b57cec5SDimitry Andric
8248bcb0991SDimitry Andric // Special case because the operand order is changed from setcc. The
8258bcb0991SDimitry Andric // predicate operand needs to be swapped from the last operand to the first
8268bcb0991SDimitry Andric // source.
8278bcb0991SDimitry Andric
8288bcb0991SDimitry Andric unsigned NumChildren = Src->getNumChildren();
8298bcb0991SDimitry Andric bool IsFCmp = SrcGIOrNull->TheDef->getName() == "G_FCMP";
8308bcb0991SDimitry Andric
8318bcb0991SDimitry Andric if (IsFCmp || SrcGIOrNull->TheDef->getName() == "G_ICMP") {
83206c3fb27SDimitry Andric const TreePatternNode *SrcChild = Src->getChild(NumChildren - 1);
8338bcb0991SDimitry Andric if (SrcChild->isLeaf()) {
8348bcb0991SDimitry Andric DefInit *DI = dyn_cast<DefInit>(SrcChild->getLeafValue());
8358bcb0991SDimitry Andric Record *CCDef = DI ? DI->getDef() : nullptr;
8368bcb0991SDimitry Andric if (!CCDef || !CCDef->isSubClassOf("CondCode"))
8378bcb0991SDimitry Andric return failedImport("Unable to handle CondCode");
8388bcb0991SDimitry Andric
8398bcb0991SDimitry Andric OperandMatcher &OM =
8408bcb0991SDimitry Andric InsnMatcher.addOperand(OpIdx++, SrcChild->getName(), TempOpIdx);
84106c3fb27SDimitry Andric StringRef PredType = IsFCmp ? CCDef->getValueAsString("FCmpPredicate")
84206c3fb27SDimitry Andric : CCDef->getValueAsString("ICmpPredicate");
8438bcb0991SDimitry Andric
8448bcb0991SDimitry Andric if (!PredType.empty()) {
8455ffd83dbSDimitry Andric OM.addPredicate<CmpPredicateOperandMatcher>(std::string(PredType));
8468bcb0991SDimitry Andric // Process the other 2 operands normally.
8478bcb0991SDimitry Andric --NumChildren;
8488bcb0991SDimitry Andric }
8498bcb0991SDimitry Andric }
8508bcb0991SDimitry Andric }
8518bcb0991SDimitry Andric
8520b57cec5SDimitry Andric // Match the used operands (i.e. the children of the operator).
8538bcb0991SDimitry Andric bool IsIntrinsic =
8548bcb0991SDimitry Andric SrcGIOrNull->TheDef->getName() == "G_INTRINSIC" ||
8555f757f3fSDimitry Andric SrcGIOrNull->TheDef->getName() == "G_INTRINSIC_W_SIDE_EFFECTS" ||
8565f757f3fSDimitry Andric SrcGIOrNull->TheDef->getName() == "G_INTRINSIC_CONVERGENT" ||
8575f757f3fSDimitry Andric SrcGIOrNull->TheDef->getName() ==
8585f757f3fSDimitry Andric "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS";
8598bcb0991SDimitry Andric const CodeGenIntrinsic *II = Src->getIntrinsicInfo(CGP);
8608bcb0991SDimitry Andric if (IsIntrinsic && !II)
8618bcb0991SDimitry Andric return failedImport("Expected IntInit containing intrinsic ID)");
8628bcb0991SDimitry Andric
8638bcb0991SDimitry Andric for (unsigned i = 0; i != NumChildren; ++i) {
86406c3fb27SDimitry Andric const TreePatternNode *SrcChild = Src->getChild(i);
8650b57cec5SDimitry Andric
866480093f4SDimitry Andric // We need to determine the meaning of a literal integer based on the
867480093f4SDimitry Andric // context. If this is a field required to be an immediate (such as an
868480093f4SDimitry Andric // immarg intrinsic argument), the required predicates are different than
869480093f4SDimitry Andric // a constant which may be materialized in a register. If we have an
870480093f4SDimitry Andric // argument that is required to be an immediate, we should not emit an LLT
871480093f4SDimitry Andric // type check, and should not be looking for a G_CONSTANT defined
872480093f4SDimitry Andric // register.
873bdd1243dSDimitry Andric bool OperandIsImmArg = SrcGIOrNull->isInOperandImmArg(i);
874480093f4SDimitry Andric
8750b57cec5SDimitry Andric // SelectionDAG allows pointers to be represented with iN since it doesn't
87606c3fb27SDimitry Andric // distinguish between pointers and integers but they are different types
87706c3fb27SDimitry Andric // in GlobalISel. Coerce integers to pointers to address space 0 if the
87806c3fb27SDimitry Andric // context indicates a pointer.
879480093f4SDimitry Andric //
880bdd1243dSDimitry Andric bool OperandIsAPointer = SrcGIOrNull->isInOperandAPointer(i);
8810b57cec5SDimitry Andric
8828bcb0991SDimitry Andric if (IsIntrinsic) {
8830b57cec5SDimitry Andric // For G_INTRINSIC/G_INTRINSIC_W_SIDE_EFFECTS, the operand immediately
8840b57cec5SDimitry Andric // following the defs is an intrinsic ID.
8858bcb0991SDimitry Andric if (i == 0) {
8860b57cec5SDimitry Andric OperandMatcher &OM =
8870b57cec5SDimitry Andric InsnMatcher.addOperand(OpIdx++, SrcChild->getName(), TempOpIdx);
8880b57cec5SDimitry Andric OM.addPredicate<IntrinsicIDOperandMatcher>(II);
8890b57cec5SDimitry Andric continue;
8900b57cec5SDimitry Andric }
8910b57cec5SDimitry Andric
892480093f4SDimitry Andric // We have to check intrinsics for llvm_anyptr_ty and immarg parameters.
8938bcb0991SDimitry Andric //
8948bcb0991SDimitry Andric // Note that we have to look at the i-1th parameter, because we don't
8958bcb0991SDimitry Andric // have the intrinsic ID in the intrinsic's parameter list.
8968bcb0991SDimitry Andric OperandIsAPointer |= II->isParamAPointer(i - 1);
897480093f4SDimitry Andric OperandIsImmArg |= II->isParamImmArg(i - 1);
8980b57cec5SDimitry Andric }
8990b57cec5SDimitry Andric
9000b57cec5SDimitry Andric if (auto Error =
9010b57cec5SDimitry Andric importChildMatcher(Rule, InsnMatcher, SrcChild, OperandIsAPointer,
902480093f4SDimitry Andric OperandIsImmArg, OpIdx++, TempOpIdx))
9030b57cec5SDimitry Andric return std::move(Error);
9040b57cec5SDimitry Andric }
9050b57cec5SDimitry Andric }
9060b57cec5SDimitry Andric
9070b57cec5SDimitry Andric return InsnMatcher;
9080b57cec5SDimitry Andric }
9090b57cec5SDimitry Andric
importComplexPatternOperandMatcher(OperandMatcher & OM,Record * R,unsigned & TempOpIdx) const9100b57cec5SDimitry Andric Error GlobalISelEmitter::importComplexPatternOperandMatcher(
9110b57cec5SDimitry Andric OperandMatcher &OM, Record *R, unsigned &TempOpIdx) const {
9120b57cec5SDimitry Andric const auto &ComplexPattern = ComplexPatternEquivs.find(R);
9130b57cec5SDimitry Andric if (ComplexPattern == ComplexPatternEquivs.end())
9140b57cec5SDimitry Andric return failedImport("SelectionDAG ComplexPattern (" + R->getName() +
9150b57cec5SDimitry Andric ") not mapped to GlobalISel");
9160b57cec5SDimitry Andric
9170b57cec5SDimitry Andric OM.addPredicate<ComplexPatternOperandMatcher>(OM, *ComplexPattern->second);
9180b57cec5SDimitry Andric TempOpIdx++;
9190b57cec5SDimitry Andric return Error::success();
9200b57cec5SDimitry Andric }
9210b57cec5SDimitry Andric
9228bcb0991SDimitry Andric // Get the name to use for a pattern operand. For an anonymous physical register
9238bcb0991SDimitry Andric // input, this should use the register name.
getSrcChildName(const TreePatternNode * SrcChild,Record * & PhysReg)9248bcb0991SDimitry Andric static StringRef getSrcChildName(const TreePatternNode *SrcChild,
9258bcb0991SDimitry Andric Record *&PhysReg) {
9268bcb0991SDimitry Andric StringRef SrcChildName = SrcChild->getName();
9278bcb0991SDimitry Andric if (SrcChildName.empty() && SrcChild->isLeaf()) {
9288bcb0991SDimitry Andric if (auto *ChildDefInit = dyn_cast<DefInit>(SrcChild->getLeafValue())) {
9298bcb0991SDimitry Andric auto *ChildRec = ChildDefInit->getDef();
9308bcb0991SDimitry Andric if (ChildRec->isSubClassOf("Register")) {
9318bcb0991SDimitry Andric SrcChildName = ChildRec->getName();
9328bcb0991SDimitry Andric PhysReg = ChildRec;
9338bcb0991SDimitry Andric }
9348bcb0991SDimitry Andric }
9358bcb0991SDimitry Andric }
9368bcb0991SDimitry Andric
9378bcb0991SDimitry Andric return SrcChildName;
9388bcb0991SDimitry Andric }
9398bcb0991SDimitry Andric
importChildMatcher(RuleMatcher & Rule,InstructionMatcher & InsnMatcher,const TreePatternNode * SrcChild,bool OperandIsAPointer,bool OperandIsImmArg,unsigned OpIdx,unsigned & TempOpIdx)940480093f4SDimitry Andric Error GlobalISelEmitter::importChildMatcher(
941480093f4SDimitry Andric RuleMatcher &Rule, InstructionMatcher &InsnMatcher,
942480093f4SDimitry Andric const TreePatternNode *SrcChild, bool OperandIsAPointer,
943480093f4SDimitry Andric bool OperandIsImmArg, unsigned OpIdx, unsigned &TempOpIdx) {
9448bcb0991SDimitry Andric
9458bcb0991SDimitry Andric Record *PhysReg = nullptr;
946e8d8bef9SDimitry Andric std::string SrcChildName = std::string(getSrcChildName(SrcChild, PhysReg));
947e8d8bef9SDimitry Andric if (!SrcChild->isLeaf() &&
948e8d8bef9SDimitry Andric SrcChild->getOperator()->isSubClassOf("ComplexPattern")) {
949e8d8bef9SDimitry Andric // The "name" of a non-leaf complex pattern (MY_PAT $op1, $op2) is
950e8d8bef9SDimitry Andric // "MY_PAT:op1:op2" and the ones with same "name" represent same operand.
951e8d8bef9SDimitry Andric std::string PatternName = std::string(SrcChild->getOperator()->getName());
952e8d8bef9SDimitry Andric for (unsigned i = 0; i < SrcChild->getNumChildren(); ++i) {
953e8d8bef9SDimitry Andric PatternName += ":";
954e8d8bef9SDimitry Andric PatternName += SrcChild->getChild(i)->getName();
955e8d8bef9SDimitry Andric }
956e8d8bef9SDimitry Andric SrcChildName = PatternName;
957e8d8bef9SDimitry Andric }
9588bcb0991SDimitry Andric
9595ffd83dbSDimitry Andric OperandMatcher &OM =
960e8d8bef9SDimitry Andric PhysReg ? InsnMatcher.addPhysRegInput(PhysReg, OpIdx, TempOpIdx)
961e8d8bef9SDimitry Andric : InsnMatcher.addOperand(OpIdx, SrcChildName, TempOpIdx);
9620b57cec5SDimitry Andric if (OM.isSameAsAnotherOperand())
9630b57cec5SDimitry Andric return Error::success();
9640b57cec5SDimitry Andric
9650b57cec5SDimitry Andric ArrayRef<TypeSetByHwMode> ChildTypes = SrcChild->getExtTypes();
9660b57cec5SDimitry Andric if (ChildTypes.size() != 1)
9670b57cec5SDimitry Andric return failedImport("Src pattern child has multiple results");
9680b57cec5SDimitry Andric
9690b57cec5SDimitry Andric // Check MBB's before the type check since they are not a known type.
9700b57cec5SDimitry Andric if (!SrcChild->isLeaf()) {
9710b57cec5SDimitry Andric if (SrcChild->getOperator()->isSubClassOf("SDNode")) {
9720b57cec5SDimitry Andric auto &ChildSDNI = CGP.getSDNodeInfo(SrcChild->getOperator());
9730b57cec5SDimitry Andric if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") {
9740b57cec5SDimitry Andric OM.addPredicate<MBBOperandMatcher>();
9750b57cec5SDimitry Andric return Error::success();
9760b57cec5SDimitry Andric }
9778bcb0991SDimitry Andric if (SrcChild->getOperator()->getName() == "timm") {
9788bcb0991SDimitry Andric OM.addPredicate<ImmOperandMatcher>();
979fe6060f1SDimitry Andric
980fe6060f1SDimitry Andric // Add predicates, if any
981fe6060f1SDimitry Andric for (const TreePredicateCall &Call : SrcChild->getPredicateCalls()) {
982fe6060f1SDimitry Andric const TreePredicateFn &Predicate = Call.Fn;
983fe6060f1SDimitry Andric
984fe6060f1SDimitry Andric // Only handle immediate patterns for now
985fe6060f1SDimitry Andric if (Predicate.isImmediatePattern()) {
986fe6060f1SDimitry Andric OM.addPredicate<OperandImmPredicateMatcher>(Predicate);
987fe6060f1SDimitry Andric }
988fe6060f1SDimitry Andric }
989fe6060f1SDimitry Andric
9908bcb0991SDimitry Andric return Error::success();
9918bcb0991SDimitry Andric }
9920b57cec5SDimitry Andric }
9930b57cec5SDimitry Andric }
9940b57cec5SDimitry Andric
995480093f4SDimitry Andric // Immediate arguments have no meaningful type to check as they don't have
996480093f4SDimitry Andric // registers.
997480093f4SDimitry Andric if (!OperandIsImmArg) {
9980b57cec5SDimitry Andric if (auto Error =
9990b57cec5SDimitry Andric OM.addTypeCheckPredicate(ChildTypes.front(), OperandIsAPointer))
10000b57cec5SDimitry Andric return failedImport(toString(std::move(Error)) + " for Src operand (" +
10010b57cec5SDimitry Andric to_string(*SrcChild) + ")");
1002480093f4SDimitry Andric }
10030b57cec5SDimitry Andric
10045f757f3fSDimitry Andric // Try look up SrcChild for a (named) predicate operand if there is any.
10055f757f3fSDimitry Andric if (WaitingForNamedOperands) {
10065f757f3fSDimitry Andric auto &ScopedNames = SrcChild->getNamesAsPredicateArg();
10075f757f3fSDimitry Andric if (!ScopedNames.empty()) {
10085f757f3fSDimitry Andric auto PA = ScopedNames.begin();
10095f757f3fSDimitry Andric std::string Name = getScopedName(PA->getScope(), PA->getIdentifier());
10105f757f3fSDimitry Andric OM.addPredicate<RecordNamedOperandMatcher>(StoreIdxForName[Name], Name);
10115f757f3fSDimitry Andric --WaitingForNamedOperands;
10125f757f3fSDimitry Andric }
10135f757f3fSDimitry Andric }
10145f757f3fSDimitry Andric
10150b57cec5SDimitry Andric // Check for nested instructions.
10160b57cec5SDimitry Andric if (!SrcChild->isLeaf()) {
10170b57cec5SDimitry Andric if (SrcChild->getOperator()->isSubClassOf("ComplexPattern")) {
10180b57cec5SDimitry Andric // When a ComplexPattern is used as an operator, it should do the same
10190b57cec5SDimitry Andric // thing as when used as a leaf. However, the children of the operator
10200b57cec5SDimitry Andric // name the sub-operands that make up the complex operand and we must
10210b57cec5SDimitry Andric // prepare to reference them in the renderer too.
10220b57cec5SDimitry Andric unsigned RendererID = TempOpIdx;
10230b57cec5SDimitry Andric if (auto Error = importComplexPatternOperandMatcher(
10240b57cec5SDimitry Andric OM, SrcChild->getOperator(), TempOpIdx))
10250b57cec5SDimitry Andric return Error;
10260b57cec5SDimitry Andric
10270b57cec5SDimitry Andric for (unsigned i = 0, e = SrcChild->getNumChildren(); i != e; ++i) {
10280b57cec5SDimitry Andric auto *SubOperand = SrcChild->getChild(i);
10290b57cec5SDimitry Andric if (!SubOperand->getName().empty()) {
1030e8d8bef9SDimitry Andric if (auto Error = Rule.defineComplexSubOperand(
1031e8d8bef9SDimitry Andric SubOperand->getName(), SrcChild->getOperator(), RendererID, i,
1032e8d8bef9SDimitry Andric SrcChildName))
10330b57cec5SDimitry Andric return Error;
10340b57cec5SDimitry Andric }
10350b57cec5SDimitry Andric }
10360b57cec5SDimitry Andric
10370b57cec5SDimitry Andric return Error::success();
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric
10400b57cec5SDimitry Andric auto MaybeInsnOperand = OM.addPredicate<InstructionOperandMatcher>(
10410b57cec5SDimitry Andric InsnMatcher.getRuleMatcher(), SrcChild->getName());
104281ad6265SDimitry Andric if (!MaybeInsnOperand) {
10430b57cec5SDimitry Andric // This isn't strictly true. If the user were to provide exactly the same
10440b57cec5SDimitry Andric // matchers as the original operand then we could allow it. However, it's
10450b57cec5SDimitry Andric // simpler to not permit the redundant specification.
104606c3fb27SDimitry Andric return failedImport(
104706c3fb27SDimitry Andric "Nested instruction cannot be the same as another operand");
10480b57cec5SDimitry Andric }
10490b57cec5SDimitry Andric
10500b57cec5SDimitry Andric // Map the node to a gMIR instruction.
10510b57cec5SDimitry Andric InstructionOperandMatcher &InsnOperand = **MaybeInsnOperand;
10520b57cec5SDimitry Andric auto InsnMatcherOrError = createAndImportSelDAGMatcher(
10530b57cec5SDimitry Andric Rule, InsnOperand.getInsnMatcher(), SrcChild, TempOpIdx);
10540b57cec5SDimitry Andric if (auto Error = InsnMatcherOrError.takeError())
10550b57cec5SDimitry Andric return Error;
10560b57cec5SDimitry Andric
10570b57cec5SDimitry Andric return Error::success();
10580b57cec5SDimitry Andric }
10590b57cec5SDimitry Andric
10600b57cec5SDimitry Andric if (SrcChild->hasAnyPredicate())
10610b57cec5SDimitry Andric return failedImport("Src pattern child has unsupported predicate");
10620b57cec5SDimitry Andric
10630b57cec5SDimitry Andric // Check for constant immediates.
10640b57cec5SDimitry Andric if (auto *ChildInt = dyn_cast<IntInit>(SrcChild->getLeafValue())) {
1065480093f4SDimitry Andric if (OperandIsImmArg) {
1066480093f4SDimitry Andric // Checks for argument directly in operand list
1067480093f4SDimitry Andric OM.addPredicate<LiteralIntOperandMatcher>(ChildInt->getValue());
1068480093f4SDimitry Andric } else {
1069480093f4SDimitry Andric // Checks for materialized constant
10700b57cec5SDimitry Andric OM.addPredicate<ConstantIntOperandMatcher>(ChildInt->getValue());
1071480093f4SDimitry Andric }
10720b57cec5SDimitry Andric return Error::success();
10730b57cec5SDimitry Andric }
10740b57cec5SDimitry Andric
10750b57cec5SDimitry Andric // Check for def's like register classes or ComplexPattern's.
10760b57cec5SDimitry Andric if (auto *ChildDefInit = dyn_cast<DefInit>(SrcChild->getLeafValue())) {
10770b57cec5SDimitry Andric auto *ChildRec = ChildDefInit->getDef();
10780b57cec5SDimitry Andric
10790b57cec5SDimitry Andric // Check for register classes.
10800b57cec5SDimitry Andric if (ChildRec->isSubClassOf("RegisterClass") ||
10810b57cec5SDimitry Andric ChildRec->isSubClassOf("RegisterOperand")) {
10820b57cec5SDimitry Andric OM.addPredicate<RegisterBankOperandMatcher>(
10830b57cec5SDimitry Andric Target.getRegisterClass(getInitValueAsRegClass(ChildDefInit)));
10840b57cec5SDimitry Andric return Error::success();
10850b57cec5SDimitry Andric }
10860b57cec5SDimitry Andric
10878bcb0991SDimitry Andric if (ChildRec->isSubClassOf("Register")) {
10888bcb0991SDimitry Andric // This just be emitted as a copy to the specific register.
10898bcb0991SDimitry Andric ValueTypeByHwMode VT = ChildTypes.front().getValueTypeByHwMode();
109006c3fb27SDimitry Andric const CodeGenRegisterClass *RC =
109106c3fb27SDimitry Andric CGRegs.getMinimalPhysRegClass(ChildRec, &VT);
10928bcb0991SDimitry Andric if (!RC) {
10938bcb0991SDimitry Andric return failedImport(
10948bcb0991SDimitry Andric "Could not determine physical register class of pattern source");
10958bcb0991SDimitry Andric }
10968bcb0991SDimitry Andric
10978bcb0991SDimitry Andric OM.addPredicate<RegisterBankOperandMatcher>(*RC);
10988bcb0991SDimitry Andric return Error::success();
10998bcb0991SDimitry Andric }
11008bcb0991SDimitry Andric
11010b57cec5SDimitry Andric // Check for ValueType.
11020b57cec5SDimitry Andric if (ChildRec->isSubClassOf("ValueType")) {
11030b57cec5SDimitry Andric // We already added a type check as standard practice so this doesn't need
11040b57cec5SDimitry Andric // to do anything.
11050b57cec5SDimitry Andric return Error::success();
11060b57cec5SDimitry Andric }
11070b57cec5SDimitry Andric
11080b57cec5SDimitry Andric // Check for ComplexPattern's.
11090b57cec5SDimitry Andric if (ChildRec->isSubClassOf("ComplexPattern"))
11100b57cec5SDimitry Andric return importComplexPatternOperandMatcher(OM, ChildRec, TempOpIdx);
11110b57cec5SDimitry Andric
11120b57cec5SDimitry Andric if (ChildRec->isSubClassOf("ImmLeaf")) {
11130b57cec5SDimitry Andric return failedImport(
11140b57cec5SDimitry Andric "Src pattern child def is an unsupported tablegen class (ImmLeaf)");
11150b57cec5SDimitry Andric }
11160b57cec5SDimitry Andric
11175ffd83dbSDimitry Andric // Place holder for SRCVALUE nodes. Nothing to do here.
11185ffd83dbSDimitry Andric if (ChildRec->getName() == "srcvalue")
11195ffd83dbSDimitry Andric return Error::success();
11205ffd83dbSDimitry Andric
1121e8d8bef9SDimitry Andric const bool ImmAllOnesV = ChildRec->getName() == "immAllOnesV";
1122e8d8bef9SDimitry Andric if (ImmAllOnesV || ChildRec->getName() == "immAllZerosV") {
1123e8d8bef9SDimitry Andric auto MaybeInsnOperand = OM.addPredicate<InstructionOperandMatcher>(
1124e8d8bef9SDimitry Andric InsnMatcher.getRuleMatcher(), SrcChild->getName(), false);
1125e8d8bef9SDimitry Andric InstructionOperandMatcher &InsnOperand = **MaybeInsnOperand;
1126e8d8bef9SDimitry Andric
1127e8d8bef9SDimitry Andric ValueTypeByHwMode VTy = ChildTypes.front().getValueTypeByHwMode();
1128e8d8bef9SDimitry Andric
112906c3fb27SDimitry Andric const CodeGenInstruction &BuildVector =
113006c3fb27SDimitry Andric Target.getInstruction(RK.getDef("G_BUILD_VECTOR"));
113106c3fb27SDimitry Andric const CodeGenInstruction &BuildVectorTrunc =
113206c3fb27SDimitry Andric Target.getInstruction(RK.getDef("G_BUILD_VECTOR_TRUNC"));
1133e8d8bef9SDimitry Andric
1134e8d8bef9SDimitry Andric // Treat G_BUILD_VECTOR as the canonical opcode, and G_BUILD_VECTOR_TRUNC
1135e8d8bef9SDimitry Andric // as an alternative.
1136e8d8bef9SDimitry Andric InsnOperand.getInsnMatcher().addPredicate<InstructionOpcodeMatcher>(
1137bdd1243dSDimitry Andric ArrayRef({&BuildVector, &BuildVectorTrunc}));
1138e8d8bef9SDimitry Andric
1139e8d8bef9SDimitry Andric // TODO: Handle both G_BUILD_VECTOR and G_BUILD_VECTOR_TRUNC We could
1140e8d8bef9SDimitry Andric // theoretically not emit any opcode check, but getOpcodeMatcher currently
1141e8d8bef9SDimitry Andric // has to succeed.
1142e8d8bef9SDimitry Andric OperandMatcher &OM =
1143e8d8bef9SDimitry Andric InsnOperand.getInsnMatcher().addOperand(0, "", TempOpIdx);
1144e8d8bef9SDimitry Andric if (auto Error =
1145e8d8bef9SDimitry Andric OM.addTypeCheckPredicate(VTy, false /* OperandIsAPointer */))
1146e8d8bef9SDimitry Andric return failedImport(toString(std::move(Error)) +
1147e8d8bef9SDimitry Andric " for result of Src pattern operator");
1148e8d8bef9SDimitry Andric
1149e8d8bef9SDimitry Andric InsnOperand.getInsnMatcher().addPredicate<VectorSplatImmPredicateMatcher>(
1150e8d8bef9SDimitry Andric ImmAllOnesV ? VectorSplatImmPredicateMatcher::AllOnes
1151e8d8bef9SDimitry Andric : VectorSplatImmPredicateMatcher::AllZeros);
1152e8d8bef9SDimitry Andric return Error::success();
1153e8d8bef9SDimitry Andric }
1154e8d8bef9SDimitry Andric
11550b57cec5SDimitry Andric return failedImport(
11560b57cec5SDimitry Andric "Src pattern child def is an unsupported tablegen class");
11570b57cec5SDimitry Andric }
11580b57cec5SDimitry Andric
11590b57cec5SDimitry Andric return failedImport("Src pattern child is an unsupported kind");
11600b57cec5SDimitry Andric }
11610b57cec5SDimitry Andric
importExplicitUseRenderer(action_iterator InsertPt,RuleMatcher & Rule,BuildMIAction & DstMIBuilder,const TreePatternNode * DstChild,const TreePatternNode * Src)11620b57cec5SDimitry Andric Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
11630b57cec5SDimitry Andric action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder,
116406c3fb27SDimitry Andric const TreePatternNode *DstChild, const TreePatternNode *Src) {
11650b57cec5SDimitry Andric
11660b57cec5SDimitry Andric const auto &SubOperand = Rule.getComplexSubOperand(DstChild->getName());
116781ad6265SDimitry Andric if (SubOperand) {
11680b57cec5SDimitry Andric DstMIBuilder.addRenderer<RenderComplexPatternOperand>(
11690b57cec5SDimitry Andric *std::get<0>(*SubOperand), DstChild->getName(),
11700b57cec5SDimitry Andric std::get<1>(*SubOperand), std::get<2>(*SubOperand));
11710b57cec5SDimitry Andric return InsertPt;
11720b57cec5SDimitry Andric }
11730b57cec5SDimitry Andric
11740b57cec5SDimitry Andric if (!DstChild->isLeaf()) {
11750b57cec5SDimitry Andric if (DstChild->getOperator()->isSubClassOf("SDNodeXForm")) {
11760b57cec5SDimitry Andric auto Child = DstChild->getChild(0);
11770b57cec5SDimitry Andric auto I = SDNodeXFormEquivs.find(DstChild->getOperator());
11780b57cec5SDimitry Andric if (I != SDNodeXFormEquivs.end()) {
1179480093f4SDimitry Andric Record *XFormOpc = DstChild->getOperator()->getValueAsDef("Opcode");
1180480093f4SDimitry Andric if (XFormOpc->getName() == "timm") {
1181480093f4SDimitry Andric // If this is a TargetConstant, there won't be a corresponding
1182480093f4SDimitry Andric // instruction to transform. Instead, this will refer directly to an
1183480093f4SDimitry Andric // operand in an instruction's operand list.
1184480093f4SDimitry Andric DstMIBuilder.addRenderer<CustomOperandRenderer>(*I->second,
1185480093f4SDimitry Andric Child->getName());
1186480093f4SDimitry Andric } else {
1187480093f4SDimitry Andric DstMIBuilder.addRenderer<CustomRenderer>(*I->second,
1188480093f4SDimitry Andric Child->getName());
1189480093f4SDimitry Andric }
1190480093f4SDimitry Andric
11910b57cec5SDimitry Andric return InsertPt;
11920b57cec5SDimitry Andric }
11930b57cec5SDimitry Andric return failedImport("SDNodeXForm " + Child->getName() +
11940b57cec5SDimitry Andric " has no custom renderer");
11950b57cec5SDimitry Andric }
11960b57cec5SDimitry Andric
11970b57cec5SDimitry Andric // We accept 'bb' here. It's an operator because BasicBlockSDNode isn't
11980b57cec5SDimitry Andric // inline, but in MI it's just another operand.
11990b57cec5SDimitry Andric if (DstChild->getOperator()->isSubClassOf("SDNode")) {
12000b57cec5SDimitry Andric auto &ChildSDNI = CGP.getSDNodeInfo(DstChild->getOperator());
12010b57cec5SDimitry Andric if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") {
12020b57cec5SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(DstChild->getName());
12030b57cec5SDimitry Andric return InsertPt;
12040b57cec5SDimitry Andric }
12050b57cec5SDimitry Andric }
12060b57cec5SDimitry Andric
12070b57cec5SDimitry Andric // Similarly, imm is an operator in TreePatternNode's view but must be
12080b57cec5SDimitry Andric // rendered as operands.
12090b57cec5SDimitry Andric // FIXME: The target should be able to choose sign-extended when appropriate
12100b57cec5SDimitry Andric // (e.g. on Mips).
12118bcb0991SDimitry Andric if (DstChild->getOperator()->getName() == "timm") {
12128bcb0991SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(DstChild->getName());
12138bcb0991SDimitry Andric return InsertPt;
12148bcb0991SDimitry Andric } else if (DstChild->getOperator()->getName() == "imm") {
12150b57cec5SDimitry Andric DstMIBuilder.addRenderer<CopyConstantAsImmRenderer>(DstChild->getName());
12160b57cec5SDimitry Andric return InsertPt;
12170b57cec5SDimitry Andric } else if (DstChild->getOperator()->getName() == "fpimm") {
12180b57cec5SDimitry Andric DstMIBuilder.addRenderer<CopyFConstantAsFPImmRenderer>(
12190b57cec5SDimitry Andric DstChild->getName());
12200b57cec5SDimitry Andric return InsertPt;
12210b57cec5SDimitry Andric }
12220b57cec5SDimitry Andric
12230b57cec5SDimitry Andric if (DstChild->getOperator()->isSubClassOf("Instruction")) {
12245ffd83dbSDimitry Andric auto OpTy = getInstResultType(DstChild);
12255ffd83dbSDimitry Andric if (!OpTy)
12265ffd83dbSDimitry Andric return OpTy.takeError();
12270b57cec5SDimitry Andric
12280b57cec5SDimitry Andric unsigned TempRegID = Rule.allocateTempRegID();
122906c3fb27SDimitry Andric InsertPt =
123006c3fb27SDimitry Andric Rule.insertAction<MakeTempRegisterAction>(InsertPt, *OpTy, TempRegID);
12310b57cec5SDimitry Andric DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
12320b57cec5SDimitry Andric
12330b57cec5SDimitry Andric auto InsertPtOrError = createAndImportSubInstructionRenderer(
123406c3fb27SDimitry Andric ++InsertPt, Rule, DstChild, Src, TempRegID);
12350b57cec5SDimitry Andric if (auto Error = InsertPtOrError.takeError())
12360b57cec5SDimitry Andric return std::move(Error);
12370b57cec5SDimitry Andric return InsertPtOrError.get();
12380b57cec5SDimitry Andric }
12390b57cec5SDimitry Andric
124006c3fb27SDimitry Andric return failedImport("Dst pattern child isn't a leaf node or an MBB" +
124106c3fb27SDimitry Andric llvm::to_string(*DstChild));
12420b57cec5SDimitry Andric }
12430b57cec5SDimitry Andric
12440b57cec5SDimitry Andric // It could be a specific immediate in which case we should just check for
12450b57cec5SDimitry Andric // that immediate.
12460b57cec5SDimitry Andric if (const IntInit *ChildIntInit =
12470b57cec5SDimitry Andric dyn_cast<IntInit>(DstChild->getLeafValue())) {
12480b57cec5SDimitry Andric DstMIBuilder.addRenderer<ImmRenderer>(ChildIntInit->getValue());
12490b57cec5SDimitry Andric return InsertPt;
12500b57cec5SDimitry Andric }
12510b57cec5SDimitry Andric
12520b57cec5SDimitry Andric // Otherwise, we're looking for a bog-standard RegisterClass operand.
12530b57cec5SDimitry Andric if (auto *ChildDefInit = dyn_cast<DefInit>(DstChild->getLeafValue())) {
12540b57cec5SDimitry Andric auto *ChildRec = ChildDefInit->getDef();
12550b57cec5SDimitry Andric
12560b57cec5SDimitry Andric ArrayRef<TypeSetByHwMode> ChildTypes = DstChild->getExtTypes();
12570b57cec5SDimitry Andric if (ChildTypes.size() != 1)
12580b57cec5SDimitry Andric return failedImport("Dst pattern child has multiple results");
12590b57cec5SDimitry Andric
1260bdd1243dSDimitry Andric std::optional<LLTCodeGen> OpTyOrNone;
12610b57cec5SDimitry Andric if (ChildTypes.front().isMachineValueType())
12620b57cec5SDimitry Andric OpTyOrNone = MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy);
12630b57cec5SDimitry Andric if (!OpTyOrNone)
12640b57cec5SDimitry Andric return failedImport("Dst operand has an unsupported type");
12650b57cec5SDimitry Andric
12660b57cec5SDimitry Andric if (ChildRec->isSubClassOf("Register")) {
1267e8d8bef9SDimitry Andric DstMIBuilder.addRenderer<AddRegisterRenderer>(Target, ChildRec);
12680b57cec5SDimitry Andric return InsertPt;
12690b57cec5SDimitry Andric }
12700b57cec5SDimitry Andric
12710b57cec5SDimitry Andric if (ChildRec->isSubClassOf("RegisterClass") ||
12720b57cec5SDimitry Andric ChildRec->isSubClassOf("RegisterOperand") ||
12730b57cec5SDimitry Andric ChildRec->isSubClassOf("ValueType")) {
12740b57cec5SDimitry Andric if (ChildRec->isSubClassOf("RegisterOperand") &&
12750b57cec5SDimitry Andric !ChildRec->isValueUnset("GIZeroRegister")) {
12760b57cec5SDimitry Andric DstMIBuilder.addRenderer<CopyOrAddZeroRegRenderer>(
12770b57cec5SDimitry Andric DstChild->getName(), ChildRec->getValueAsDef("GIZeroRegister"));
12780b57cec5SDimitry Andric return InsertPt;
12790b57cec5SDimitry Andric }
12800b57cec5SDimitry Andric
12810b57cec5SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(DstChild->getName());
12820b57cec5SDimitry Andric return InsertPt;
12830b57cec5SDimitry Andric }
12840b57cec5SDimitry Andric
12858bcb0991SDimitry Andric if (ChildRec->isSubClassOf("SubRegIndex")) {
12868bcb0991SDimitry Andric CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(ChildRec);
12878bcb0991SDimitry Andric DstMIBuilder.addRenderer<ImmRenderer>(SubIdx->EnumValue);
12888bcb0991SDimitry Andric return InsertPt;
12898bcb0991SDimitry Andric }
12908bcb0991SDimitry Andric
12910b57cec5SDimitry Andric if (ChildRec->isSubClassOf("ComplexPattern")) {
12920b57cec5SDimitry Andric const auto &ComplexPattern = ComplexPatternEquivs.find(ChildRec);
12930b57cec5SDimitry Andric if (ComplexPattern == ComplexPatternEquivs.end())
12940b57cec5SDimitry Andric return failedImport(
12950b57cec5SDimitry Andric "SelectionDAG ComplexPattern not mapped to GlobalISel");
12960b57cec5SDimitry Andric
12970b57cec5SDimitry Andric const OperandMatcher &OM = Rule.getOperandMatcher(DstChild->getName());
12980b57cec5SDimitry Andric DstMIBuilder.addRenderer<RenderComplexPatternOperand>(
12990b57cec5SDimitry Andric *ComplexPattern->second, DstChild->getName(),
13000b57cec5SDimitry Andric OM.getAllocatedTemporariesBaseID());
13010b57cec5SDimitry Andric return InsertPt;
13020b57cec5SDimitry Andric }
13030b57cec5SDimitry Andric
13040b57cec5SDimitry Andric return failedImport(
13050b57cec5SDimitry Andric "Dst pattern child def is an unsupported tablegen class");
13060b57cec5SDimitry Andric }
130706c3fb27SDimitry Andric
130806c3fb27SDimitry Andric // Handle the case where the MVT/register class is omitted in the dest pattern
130906c3fb27SDimitry Andric // but MVT exists in the source pattern.
131006c3fb27SDimitry Andric if (isa<UnsetInit>(DstChild->getLeafValue())) {
131106c3fb27SDimitry Andric for (unsigned NumOp = 0; NumOp < Src->getNumChildren(); NumOp++)
131206c3fb27SDimitry Andric if (Src->getChild(NumOp)->getName() == DstChild->getName()) {
131306c3fb27SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(Src->getChild(NumOp)->getName());
131406c3fb27SDimitry Andric return InsertPt;
131506c3fb27SDimitry Andric }
131606c3fb27SDimitry Andric }
13170b57cec5SDimitry Andric return failedImport("Dst pattern child is an unsupported kind");
13180b57cec5SDimitry Andric }
13190b57cec5SDimitry Andric
createAndImportInstructionRenderer(RuleMatcher & M,InstructionMatcher & InsnMatcher,const TreePatternNode * Src,const TreePatternNode * Dst)13200b57cec5SDimitry Andric Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
13218bcb0991SDimitry Andric RuleMatcher &M, InstructionMatcher &InsnMatcher, const TreePatternNode *Src,
13228bcb0991SDimitry Andric const TreePatternNode *Dst) {
13230b57cec5SDimitry Andric auto InsertPtOrError = createInstructionRenderer(M.actions_end(), M, Dst);
13240b57cec5SDimitry Andric if (auto Error = InsertPtOrError.takeError())
13250b57cec5SDimitry Andric return std::move(Error);
13260b57cec5SDimitry Andric
13270b57cec5SDimitry Andric action_iterator InsertPt = InsertPtOrError.get();
13280b57cec5SDimitry Andric BuildMIAction &DstMIBuilder = *static_cast<BuildMIAction *>(InsertPt->get());
13290b57cec5SDimitry Andric
13308bcb0991SDimitry Andric for (auto PhysInput : InsnMatcher.getPhysRegInputs()) {
13318bcb0991SDimitry Andric InsertPt = M.insertAction<BuildMIAction>(
13328bcb0991SDimitry Andric InsertPt, M.allocateOutputInsnID(),
13338bcb0991SDimitry Andric &Target.getInstruction(RK.getDef("COPY")));
13348bcb0991SDimitry Andric BuildMIAction &CopyToPhysRegMIBuilder =
13358bcb0991SDimitry Andric *static_cast<BuildMIAction *>(InsertPt->get());
133606c3fb27SDimitry Andric CopyToPhysRegMIBuilder.addRenderer<AddRegisterRenderer>(
133706c3fb27SDimitry Andric Target, PhysInput.first, true);
13388bcb0991SDimitry Andric CopyToPhysRegMIBuilder.addRenderer<CopyPhysRegRenderer>(PhysInput.first);
13398bcb0991SDimitry Andric }
13408bcb0991SDimitry Andric
134106c3fb27SDimitry Andric if (auto Error =
134206c3fb27SDimitry Andric importExplicitDefRenderers(InsertPt, M, DstMIBuilder, Src, Dst)
1343e8d8bef9SDimitry Andric .takeError())
1344e8d8bef9SDimitry Andric return std::move(Error);
13450b57cec5SDimitry Andric
134606c3fb27SDimitry Andric if (auto Error =
134706c3fb27SDimitry Andric importExplicitUseRenderers(InsertPt, M, DstMIBuilder, Dst, Src)
13480b57cec5SDimitry Andric .takeError())
13490b57cec5SDimitry Andric return std::move(Error);
13500b57cec5SDimitry Andric
13510b57cec5SDimitry Andric return DstMIBuilder;
13520b57cec5SDimitry Andric }
13530b57cec5SDimitry Andric
13540b57cec5SDimitry Andric Expected<action_iterator>
createAndImportSubInstructionRenderer(const action_iterator InsertPt,RuleMatcher & M,const TreePatternNode * Dst,const TreePatternNode * Src,unsigned TempRegID)13550b57cec5SDimitry Andric GlobalISelEmitter::createAndImportSubInstructionRenderer(
13560b57cec5SDimitry Andric const action_iterator InsertPt, RuleMatcher &M, const TreePatternNode *Dst,
135706c3fb27SDimitry Andric const TreePatternNode *Src, unsigned TempRegID) {
13580b57cec5SDimitry Andric auto InsertPtOrError = createInstructionRenderer(InsertPt, M, Dst);
13590b57cec5SDimitry Andric
13600b57cec5SDimitry Andric // TODO: Assert there's exactly one result.
13610b57cec5SDimitry Andric
13620b57cec5SDimitry Andric if (auto Error = InsertPtOrError.takeError())
13630b57cec5SDimitry Andric return std::move(Error);
13640b57cec5SDimitry Andric
13650b57cec5SDimitry Andric BuildMIAction &DstMIBuilder =
13660b57cec5SDimitry Andric *static_cast<BuildMIAction *>(InsertPtOrError.get()->get());
13670b57cec5SDimitry Andric
13680b57cec5SDimitry Andric // Assign the result to TempReg.
13690b57cec5SDimitry Andric DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID, true);
13700b57cec5SDimitry Andric
137106c3fb27SDimitry Andric InsertPtOrError = importExplicitUseRenderers(InsertPtOrError.get(), M,
137206c3fb27SDimitry Andric DstMIBuilder, Dst, Src);
13730b57cec5SDimitry Andric if (auto Error = InsertPtOrError.takeError())
13740b57cec5SDimitry Andric return std::move(Error);
13750b57cec5SDimitry Andric
13768bcb0991SDimitry Andric // We need to make sure that when we import an INSERT_SUBREG as a
13778bcb0991SDimitry Andric // subinstruction that it ends up being constrained to the correct super
13788bcb0991SDimitry Andric // register and subregister classes.
13798bcb0991SDimitry Andric auto OpName = Target.getInstruction(Dst->getOperator()).TheDef->getName();
13808bcb0991SDimitry Andric if (OpName == "INSERT_SUBREG") {
13818bcb0991SDimitry Andric auto SubClass = inferRegClassFromPattern(Dst->getChild(1));
13828bcb0991SDimitry Andric if (!SubClass)
13838bcb0991SDimitry Andric return failedImport(
13848bcb0991SDimitry Andric "Cannot infer register class from INSERT_SUBREG operand #1");
1385bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *> SuperClass =
13868bcb0991SDimitry Andric inferSuperRegisterClassForNode(Dst->getExtType(0), Dst->getChild(0),
13878bcb0991SDimitry Andric Dst->getChild(2));
13888bcb0991SDimitry Andric if (!SuperClass)
13898bcb0991SDimitry Andric return failedImport(
13908bcb0991SDimitry Andric "Cannot infer register class for INSERT_SUBREG operand #0");
13918bcb0991SDimitry Andric // The destination and the super register source of an INSERT_SUBREG must
13928bcb0991SDimitry Andric // be the same register class.
13938bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>(
13948bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 0, **SuperClass);
13958bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>(
13968bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 1, **SuperClass);
13978bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>(
13988bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 2, **SubClass);
13998bcb0991SDimitry Andric return InsertPtOrError.get();
14008bcb0991SDimitry Andric }
14018bcb0991SDimitry Andric
14028bcb0991SDimitry Andric if (OpName == "EXTRACT_SUBREG") {
14038bcb0991SDimitry Andric // EXTRACT_SUBREG selects into a subregister COPY but unlike most
14048bcb0991SDimitry Andric // instructions, the result register class is controlled by the
14058bcb0991SDimitry Andric // subregisters of the operand. As a result, we must constrain the result
14068bcb0991SDimitry Andric // class rather than check that it's already the right one.
14078bcb0991SDimitry Andric auto SuperClass = inferRegClassFromPattern(Dst->getChild(0));
14088bcb0991SDimitry Andric if (!SuperClass)
14098bcb0991SDimitry Andric return failedImport(
14108bcb0991SDimitry Andric "Cannot infer register class from EXTRACT_SUBREG operand #0");
14118bcb0991SDimitry Andric
14128bcb0991SDimitry Andric auto SubIdx = inferSubRegIndexForNode(Dst->getChild(1));
14138bcb0991SDimitry Andric if (!SubIdx)
14148bcb0991SDimitry Andric return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");
14158bcb0991SDimitry Andric
14165ffd83dbSDimitry Andric const auto SrcRCDstRCPair =
14178bcb0991SDimitry Andric (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
14188bcb0991SDimitry Andric assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
14198bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>(
14208bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 0, *SrcRCDstRCPair->second);
14218bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>(
14228bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 1, *SrcRCDstRCPair->first);
14238bcb0991SDimitry Andric
14248bcb0991SDimitry Andric // We're done with this pattern! It's eligible for GISel emission; return
14258bcb0991SDimitry Andric // it.
14268bcb0991SDimitry Andric return InsertPtOrError.get();
14278bcb0991SDimitry Andric }
14288bcb0991SDimitry Andric
14298bcb0991SDimitry Andric // Similar to INSERT_SUBREG, we also have to handle SUBREG_TO_REG as a
14308bcb0991SDimitry Andric // subinstruction.
14318bcb0991SDimitry Andric if (OpName == "SUBREG_TO_REG") {
14328bcb0991SDimitry Andric auto SubClass = inferRegClassFromPattern(Dst->getChild(1));
14338bcb0991SDimitry Andric if (!SubClass)
14348bcb0991SDimitry Andric return failedImport(
14358bcb0991SDimitry Andric "Cannot infer register class from SUBREG_TO_REG child #1");
143606c3fb27SDimitry Andric auto SuperClass =
143706c3fb27SDimitry Andric inferSuperRegisterClass(Dst->getExtType(0), Dst->getChild(2));
14388bcb0991SDimitry Andric if (!SuperClass)
14398bcb0991SDimitry Andric return failedImport(
14408bcb0991SDimitry Andric "Cannot infer register class for SUBREG_TO_REG operand #0");
14418bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>(
14428bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 0, **SuperClass);
14438bcb0991SDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>(
14448bcb0991SDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 2, **SubClass);
14458bcb0991SDimitry Andric return InsertPtOrError.get();
14468bcb0991SDimitry Andric }
14478bcb0991SDimitry Andric
14485ffd83dbSDimitry Andric if (OpName == "REG_SEQUENCE") {
14495ffd83dbSDimitry Andric auto SuperClass = inferRegClassFromPattern(Dst->getChild(0));
14505ffd83dbSDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>(
14515ffd83dbSDimitry Andric InsertPt, DstMIBuilder.getInsnID(), 0, **SuperClass);
14525ffd83dbSDimitry Andric
14535ffd83dbSDimitry Andric unsigned Num = Dst->getNumChildren();
14545ffd83dbSDimitry Andric for (unsigned I = 1; I != Num; I += 2) {
145506c3fb27SDimitry Andric const TreePatternNode *SubRegChild = Dst->getChild(I + 1);
14565ffd83dbSDimitry Andric
14575ffd83dbSDimitry Andric auto SubIdx = inferSubRegIndexForNode(SubRegChild);
14585ffd83dbSDimitry Andric if (!SubIdx)
14595ffd83dbSDimitry Andric return failedImport("REG_SEQUENCE child is not a subreg index");
14605ffd83dbSDimitry Andric
14615ffd83dbSDimitry Andric const auto SrcRCDstRCPair =
14625ffd83dbSDimitry Andric (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
14635ffd83dbSDimitry Andric assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
14645ffd83dbSDimitry Andric M.insertAction<ConstrainOperandToRegClassAction>(
14655ffd83dbSDimitry Andric InsertPt, DstMIBuilder.getInsnID(), I, *SrcRCDstRCPair->second);
14665ffd83dbSDimitry Andric }
14675ffd83dbSDimitry Andric
14685ffd83dbSDimitry Andric return InsertPtOrError.get();
14695ffd83dbSDimitry Andric }
14705ffd83dbSDimitry Andric
14710b57cec5SDimitry Andric M.insertAction<ConstrainOperandsToDefinitionAction>(InsertPt,
14720b57cec5SDimitry Andric DstMIBuilder.getInsnID());
14730b57cec5SDimitry Andric return InsertPtOrError.get();
14740b57cec5SDimitry Andric }
14750b57cec5SDimitry Andric
createInstructionRenderer(action_iterator InsertPt,RuleMatcher & M,const TreePatternNode * Dst)14760b57cec5SDimitry Andric Expected<action_iterator> GlobalISelEmitter::createInstructionRenderer(
14770b57cec5SDimitry Andric action_iterator InsertPt, RuleMatcher &M, const TreePatternNode *Dst) {
14780b57cec5SDimitry Andric Record *DstOp = Dst->getOperator();
14790b57cec5SDimitry Andric if (!DstOp->isSubClassOf("Instruction")) {
14800b57cec5SDimitry Andric if (DstOp->isSubClassOf("ValueType"))
14810b57cec5SDimitry Andric return failedImport(
14820b57cec5SDimitry Andric "Pattern operator isn't an instruction (it's a ValueType)");
14830b57cec5SDimitry Andric return failedImport("Pattern operator isn't an instruction");
14840b57cec5SDimitry Andric }
14850b57cec5SDimitry Andric CodeGenInstruction *DstI = &Target.getInstruction(DstOp);
14860b57cec5SDimitry Andric
14870b57cec5SDimitry Andric // COPY_TO_REGCLASS is just a copy with a ConstrainOperandToRegClassAction
14880b57cec5SDimitry Andric // attached. Similarly for EXTRACT_SUBREG except that's a subregister copy.
14898bcb0991SDimitry Andric StringRef Name = DstI->TheDef->getName();
14908bcb0991SDimitry Andric if (Name == "COPY_TO_REGCLASS" || Name == "EXTRACT_SUBREG")
14910b57cec5SDimitry Andric DstI = &Target.getInstruction(RK.getDef("COPY"));
14920b57cec5SDimitry Andric
14930b57cec5SDimitry Andric return M.insertAction<BuildMIAction>(InsertPt, M.allocateOutputInsnID(),
14940b57cec5SDimitry Andric DstI);
14950b57cec5SDimitry Andric }
14960b57cec5SDimitry Andric
importExplicitDefRenderers(action_iterator InsertPt,RuleMatcher & M,BuildMIAction & DstMIBuilder,const TreePatternNode * Src,const TreePatternNode * Dst)1497e8d8bef9SDimitry Andric Expected<action_iterator> GlobalISelEmitter::importExplicitDefRenderers(
1498e8d8bef9SDimitry Andric action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
149906c3fb27SDimitry Andric const TreePatternNode *Src, const TreePatternNode *Dst) {
15000b57cec5SDimitry Andric const CodeGenInstruction *DstI = DstMIBuilder.getCGI();
150106c3fb27SDimitry Andric const unsigned SrcNumDefs = Src->getExtTypes().size();
150206c3fb27SDimitry Andric const unsigned DstNumDefs = DstI->Operands.NumDefs;
150306c3fb27SDimitry Andric if (DstNumDefs == 0)
1504e8d8bef9SDimitry Andric return InsertPt;
1505e8d8bef9SDimitry Andric
15065f757f3fSDimitry Andric for (unsigned I = 0; I < SrcNumDefs; ++I) {
15075f757f3fSDimitry Andric std::string OpName = getMangledRootDefName(DstI->Operands[I].Name);
15085f757f3fSDimitry Andric // CopyRenderer saves a StringRef, so cannot pass OpName itself -
15095f757f3fSDimitry Andric // let's use a string with an appropriate lifetime.
15105f757f3fSDimitry Andric StringRef PermanentRef = M.getOperandMatcher(OpName).getSymbolicName();
15115f757f3fSDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(PermanentRef);
15125f757f3fSDimitry Andric }
1513e8d8bef9SDimitry Andric
1514e8d8bef9SDimitry Andric // Some instructions have multiple defs, but are missing a type entry
1515e8d8bef9SDimitry Andric // (e.g. s_cc_out operands).
151606c3fb27SDimitry Andric if (Dst->getExtTypes().size() < DstNumDefs)
1517e8d8bef9SDimitry Andric return failedImport("unhandled discarded def");
1518e8d8bef9SDimitry Andric
151906c3fb27SDimitry Andric for (unsigned I = SrcNumDefs; I < DstNumDefs; ++I) {
1520e8d8bef9SDimitry Andric const TypeSetByHwMode &ExtTy = Dst->getExtType(I);
1521e8d8bef9SDimitry Andric if (!ExtTy.isMachineValueType())
1522e8d8bef9SDimitry Andric return failedImport("unsupported typeset");
1523e8d8bef9SDimitry Andric
1524e8d8bef9SDimitry Andric auto OpTy = MVTToLLT(ExtTy.getMachineValueType().SimpleTy);
1525e8d8bef9SDimitry Andric if (!OpTy)
1526e8d8bef9SDimitry Andric return failedImport("unsupported type");
1527e8d8bef9SDimitry Andric
1528e8d8bef9SDimitry Andric unsigned TempRegID = M.allocateTempRegID();
1529e8d8bef9SDimitry Andric InsertPt =
1530e8d8bef9SDimitry Andric M.insertAction<MakeTempRegisterAction>(InsertPt, *OpTy, TempRegID);
1531e8d8bef9SDimitry Andric DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID, true, nullptr, true);
15320b57cec5SDimitry Andric }
1533e8d8bef9SDimitry Andric
1534e8d8bef9SDimitry Andric return InsertPt;
15350b57cec5SDimitry Andric }
15360b57cec5SDimitry Andric
importExplicitUseRenderers(action_iterator InsertPt,RuleMatcher & M,BuildMIAction & DstMIBuilder,const llvm::TreePatternNode * Dst,const llvm::TreePatternNode * Src)15370b57cec5SDimitry Andric Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
15380b57cec5SDimitry Andric action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
153906c3fb27SDimitry Andric const llvm::TreePatternNode *Dst, const llvm::TreePatternNode *Src) {
15400b57cec5SDimitry Andric const CodeGenInstruction *DstI = DstMIBuilder.getCGI();
15410b57cec5SDimitry Andric CodeGenInstruction *OrigDstI = &Target.getInstruction(Dst->getOperator());
15420b57cec5SDimitry Andric
15438bcb0991SDimitry Andric StringRef Name = OrigDstI->TheDef->getName();
15448bcb0991SDimitry Andric unsigned ExpectedDstINumUses = Dst->getNumChildren();
15458bcb0991SDimitry Andric
15460b57cec5SDimitry Andric // EXTRACT_SUBREG needs to use a subregister COPY.
15478bcb0991SDimitry Andric if (Name == "EXTRACT_SUBREG") {
1548e8d8bef9SDimitry Andric if (!Dst->getChild(1)->isLeaf())
1549e8d8bef9SDimitry Andric return failedImport("EXTRACT_SUBREG child #1 is not a leaf");
15505ffd83dbSDimitry Andric DefInit *SubRegInit = dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue());
15515ffd83dbSDimitry Andric if (!SubRegInit)
15525ffd83dbSDimitry Andric return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");
15530b57cec5SDimitry Andric
15545ffd83dbSDimitry Andric CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
155506c3fb27SDimitry Andric const TreePatternNode *ValChild = Dst->getChild(0);
15565ffd83dbSDimitry Andric if (!ValChild->isLeaf()) {
15575ffd83dbSDimitry Andric // We really have to handle the source instruction, and then insert a
15585ffd83dbSDimitry Andric // copy from the subregister.
15595ffd83dbSDimitry Andric auto ExtractSrcTy = getInstResultType(ValChild);
15605ffd83dbSDimitry Andric if (!ExtractSrcTy)
15615ffd83dbSDimitry Andric return ExtractSrcTy.takeError();
15625ffd83dbSDimitry Andric
15635ffd83dbSDimitry Andric unsigned TempRegID = M.allocateTempRegID();
156406c3fb27SDimitry Andric InsertPt = M.insertAction<MakeTempRegisterAction>(InsertPt, *ExtractSrcTy,
156506c3fb27SDimitry Andric TempRegID);
15665ffd83dbSDimitry Andric
15675ffd83dbSDimitry Andric auto InsertPtOrError = createAndImportSubInstructionRenderer(
156806c3fb27SDimitry Andric ++InsertPt, M, ValChild, Src, TempRegID);
15695ffd83dbSDimitry Andric if (auto Error = InsertPtOrError.takeError())
15705ffd83dbSDimitry Andric return std::move(Error);
15715ffd83dbSDimitry Andric
15725ffd83dbSDimitry Andric DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID, false, SubIdx);
15735ffd83dbSDimitry Andric return InsertPt;
15745ffd83dbSDimitry Andric }
15755ffd83dbSDimitry Andric
15765ffd83dbSDimitry Andric // If this is a source operand, this is just a subregister copy.
15775ffd83dbSDimitry Andric Record *RCDef = getInitValueAsRegClass(ValChild->getLeafValue());
15780b57cec5SDimitry Andric if (!RCDef)
15790b57cec5SDimitry Andric return failedImport("EXTRACT_SUBREG child #0 could not "
15800b57cec5SDimitry Andric "be coerced to a register class");
15810b57cec5SDimitry Andric
15820b57cec5SDimitry Andric CodeGenRegisterClass *RC = CGRegs.getRegClass(RCDef);
15830b57cec5SDimitry Andric
15845ffd83dbSDimitry Andric const auto SrcRCDstRCPair =
15850b57cec5SDimitry Andric RC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);
158681ad6265SDimitry Andric if (SrcRCDstRCPair) {
15870b57cec5SDimitry Andric assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
15880b57cec5SDimitry Andric if (SrcRCDstRCPair->first != RC)
15890b57cec5SDimitry Andric return failedImport("EXTRACT_SUBREG requires an additional COPY");
15900b57cec5SDimitry Andric }
15910b57cec5SDimitry Andric
159206c3fb27SDimitry Andric StringRef RegOperandName = Dst->getChild(0)->getName();
159306c3fb27SDimitry Andric if (const auto &SubOperand = M.getComplexSubOperand(RegOperandName)) {
159406c3fb27SDimitry Andric DstMIBuilder.addRenderer<RenderComplexPatternOperand>(
159506c3fb27SDimitry Andric *std::get<0>(*SubOperand), RegOperandName, std::get<1>(*SubOperand),
159606c3fb27SDimitry Andric std::get<2>(*SubOperand), SubIdx);
159706c3fb27SDimitry Andric return InsertPt;
159806c3fb27SDimitry Andric }
159906c3fb27SDimitry Andric
160006c3fb27SDimitry Andric DstMIBuilder.addRenderer<CopySubRegRenderer>(RegOperandName, SubIdx);
16010b57cec5SDimitry Andric return InsertPt;
16020b57cec5SDimitry Andric }
16030b57cec5SDimitry Andric
16048bcb0991SDimitry Andric if (Name == "REG_SEQUENCE") {
16058bcb0991SDimitry Andric if (!Dst->getChild(0)->isLeaf())
16068bcb0991SDimitry Andric return failedImport("REG_SEQUENCE child #0 is not a leaf");
16078bcb0991SDimitry Andric
16088bcb0991SDimitry Andric Record *RCDef = getInitValueAsRegClass(Dst->getChild(0)->getLeafValue());
16098bcb0991SDimitry Andric if (!RCDef)
16108bcb0991SDimitry Andric return failedImport("REG_SEQUENCE child #0 could not "
16118bcb0991SDimitry Andric "be coerced to a register class");
16128bcb0991SDimitry Andric
16138bcb0991SDimitry Andric if ((ExpectedDstINumUses - 1) % 2 != 0)
16148bcb0991SDimitry Andric return failedImport("Malformed REG_SEQUENCE");
16158bcb0991SDimitry Andric
16168bcb0991SDimitry Andric for (unsigned I = 1; I != ExpectedDstINumUses; I += 2) {
161706c3fb27SDimitry Andric const TreePatternNode *ValChild = Dst->getChild(I);
161806c3fb27SDimitry Andric const TreePatternNode *SubRegChild = Dst->getChild(I + 1);
16198bcb0991SDimitry Andric
16208bcb0991SDimitry Andric if (DefInit *SubRegInit =
16218bcb0991SDimitry Andric dyn_cast<DefInit>(SubRegChild->getLeafValue())) {
16228bcb0991SDimitry Andric CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
16238bcb0991SDimitry Andric
16248bcb0991SDimitry Andric auto InsertPtOrError =
162506c3fb27SDimitry Andric importExplicitUseRenderer(InsertPt, M, DstMIBuilder, ValChild, Src);
16268bcb0991SDimitry Andric if (auto Error = InsertPtOrError.takeError())
16278bcb0991SDimitry Andric return std::move(Error);
16288bcb0991SDimitry Andric InsertPt = InsertPtOrError.get();
16298bcb0991SDimitry Andric DstMIBuilder.addRenderer<SubRegIndexRenderer>(SubIdx);
16308bcb0991SDimitry Andric }
16318bcb0991SDimitry Andric }
16328bcb0991SDimitry Andric
16338bcb0991SDimitry Andric return InsertPt;
16348bcb0991SDimitry Andric }
16358bcb0991SDimitry Andric
16360b57cec5SDimitry Andric // Render the explicit uses.
16370b57cec5SDimitry Andric unsigned DstINumUses = OrigDstI->Operands.size() - OrigDstI->Operands.NumDefs;
16388bcb0991SDimitry Andric if (Name == "COPY_TO_REGCLASS") {
16390b57cec5SDimitry Andric DstINumUses--; // Ignore the class constraint.
16400b57cec5SDimitry Andric ExpectedDstINumUses--;
16410b57cec5SDimitry Andric }
16420b57cec5SDimitry Andric
1643480093f4SDimitry Andric // NumResults - This is the number of results produced by the instruction in
1644480093f4SDimitry Andric // the "outs" list.
1645480093f4SDimitry Andric unsigned NumResults = OrigDstI->Operands.NumDefs;
1646480093f4SDimitry Andric
1647480093f4SDimitry Andric // Number of operands we know the output instruction must have. If it is
1648480093f4SDimitry Andric // variadic, we could have more operands.
1649480093f4SDimitry Andric unsigned NumFixedOperands = DstI->Operands.size();
1650480093f4SDimitry Andric
1651480093f4SDimitry Andric // Loop over all of the fixed operands of the instruction pattern, emitting
1652480093f4SDimitry Andric // code to fill them all in. The node 'N' usually has number children equal to
1653480093f4SDimitry Andric // the number of input operands of the instruction. However, in cases where
1654480093f4SDimitry Andric // there are predicate operands for an instruction, we need to fill in the
1655480093f4SDimitry Andric // 'execute always' values. Match up the node operands to the instruction
1656480093f4SDimitry Andric // operands to do this.
16570b57cec5SDimitry Andric unsigned Child = 0;
1658480093f4SDimitry Andric
1659480093f4SDimitry Andric // Similarly to the code in TreePatternNode::ApplyTypeConstraints, count the
1660480093f4SDimitry Andric // number of operands at the end of the list which have default values.
1661480093f4SDimitry Andric // Those can come from the pattern if it provides enough arguments, or be
1662480093f4SDimitry Andric // filled in with the default if the pattern hasn't provided them. But any
1663480093f4SDimitry Andric // operand with a default value _before_ the last mandatory one will be
1664480093f4SDimitry Andric // filled in with their defaults unconditionally.
1665480093f4SDimitry Andric unsigned NonOverridableOperands = NumFixedOperands;
1666480093f4SDimitry Andric while (NonOverridableOperands > NumResults &&
1667480093f4SDimitry Andric CGP.operandHasDefault(DstI->Operands[NonOverridableOperands - 1].Rec))
1668480093f4SDimitry Andric --NonOverridableOperands;
1669480093f4SDimitry Andric
16700b57cec5SDimitry Andric unsigned NumDefaultOps = 0;
16710b57cec5SDimitry Andric for (unsigned I = 0; I != DstINumUses; ++I) {
1672480093f4SDimitry Andric unsigned InstOpNo = DstI->Operands.NumDefs + I;
1673480093f4SDimitry Andric
1674480093f4SDimitry Andric // Determine what to emit for this operand.
1675480093f4SDimitry Andric Record *OperandNode = DstI->Operands[InstOpNo].Rec;
16760b57cec5SDimitry Andric
16770b57cec5SDimitry Andric // If the operand has default values, introduce them now.
1678480093f4SDimitry Andric if (CGP.operandHasDefault(OperandNode) &&
1679480093f4SDimitry Andric (InstOpNo < NonOverridableOperands || Child >= Dst->getNumChildren())) {
1680480093f4SDimitry Andric // This is a predicate or optional def operand which the pattern has not
1681480093f4SDimitry Andric // overridden, or which we aren't letting it override; emit the 'default
1682480093f4SDimitry Andric // ops' operands.
1683480093f4SDimitry Andric
16845f757f3fSDimitry Andric Record *OperandNode = DstI->Operands[InstOpNo].Rec;
16855f757f3fSDimitry Andric if (auto Error = importDefaultOperandRenderers(
16865f757f3fSDimitry Andric InsertPt, M, DstMIBuilder, CGP.getDefaultOperand(OperandNode)))
16870b57cec5SDimitry Andric return std::move(Error);
16885f757f3fSDimitry Andric
16890b57cec5SDimitry Andric ++NumDefaultOps;
16900b57cec5SDimitry Andric continue;
16910b57cec5SDimitry Andric }
16920b57cec5SDimitry Andric
16930b57cec5SDimitry Andric auto InsertPtOrError = importExplicitUseRenderer(InsertPt, M, DstMIBuilder,
169406c3fb27SDimitry Andric Dst->getChild(Child), Src);
16950b57cec5SDimitry Andric if (auto Error = InsertPtOrError.takeError())
16960b57cec5SDimitry Andric return std::move(Error);
16970b57cec5SDimitry Andric InsertPt = InsertPtOrError.get();
16980b57cec5SDimitry Andric ++Child;
16990b57cec5SDimitry Andric }
17000b57cec5SDimitry Andric
17010b57cec5SDimitry Andric if (NumDefaultOps + ExpectedDstINumUses != DstINumUses)
17020b57cec5SDimitry Andric return failedImport("Expected " + llvm::to_string(DstINumUses) +
17030b57cec5SDimitry Andric " used operands but found " +
17040b57cec5SDimitry Andric llvm::to_string(ExpectedDstINumUses) +
17050b57cec5SDimitry Andric " explicit ones and " + llvm::to_string(NumDefaultOps) +
17060b57cec5SDimitry Andric " default ones");
17070b57cec5SDimitry Andric
17080b57cec5SDimitry Andric return InsertPt;
17090b57cec5SDimitry Andric }
17100b57cec5SDimitry Andric
importDefaultOperandRenderers(action_iterator InsertPt,RuleMatcher & M,BuildMIAction & DstMIBuilder,const DAGDefaultOperand & DefaultOp) const17110b57cec5SDimitry Andric Error GlobalISelEmitter::importDefaultOperandRenderers(
17120b57cec5SDimitry Andric action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
17135f757f3fSDimitry Andric const DAGDefaultOperand &DefaultOp) const {
17145f757f3fSDimitry Andric for (const auto &Op : DefaultOp.DefaultOps) {
17155f757f3fSDimitry Andric const auto *N = Op.get();
17165f757f3fSDimitry Andric if (!N->isLeaf())
17175f757f3fSDimitry Andric return failedImport("Could not add default op");
17180b57cec5SDimitry Andric
17195f757f3fSDimitry Andric const auto *DefaultOp = N->getLeafValue();
17200b57cec5SDimitry Andric
17210b57cec5SDimitry Andric if (const DefInit *DefaultDefOp = dyn_cast<DefInit>(DefaultOp)) {
17225f757f3fSDimitry Andric std::optional<LLTCodeGen> OpTyOrNone = MVTToLLT(N->getSimpleType(0));
17230b57cec5SDimitry Andric auto Def = DefaultDefOp->getDef();
17240b57cec5SDimitry Andric if (Def->getName() == "undef_tied_input") {
17250b57cec5SDimitry Andric unsigned TempRegID = M.allocateTempRegID();
1726bdd1243dSDimitry Andric M.insertAction<MakeTempRegisterAction>(InsertPt, *OpTyOrNone,
1727753f127fSDimitry Andric TempRegID);
17280b57cec5SDimitry Andric InsertPt = M.insertAction<BuildMIAction>(
17290b57cec5SDimitry Andric InsertPt, M.allocateOutputInsnID(),
17300b57cec5SDimitry Andric &Target.getInstruction(RK.getDef("IMPLICIT_DEF")));
173106c3fb27SDimitry Andric BuildMIAction &IDMIBuilder =
173206c3fb27SDimitry Andric *static_cast<BuildMIAction *>(InsertPt->get());
17330b57cec5SDimitry Andric IDMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
17340b57cec5SDimitry Andric DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
17350b57cec5SDimitry Andric } else {
1736e8d8bef9SDimitry Andric DstMIBuilder.addRenderer<AddRegisterRenderer>(Target, Def);
17370b57cec5SDimitry Andric }
17380b57cec5SDimitry Andric continue;
17390b57cec5SDimitry Andric }
17400b57cec5SDimitry Andric
17410b57cec5SDimitry Andric if (const IntInit *DefaultIntOp = dyn_cast<IntInit>(DefaultOp)) {
17420b57cec5SDimitry Andric DstMIBuilder.addRenderer<ImmRenderer>(DefaultIntOp->getValue());
17430b57cec5SDimitry Andric continue;
17440b57cec5SDimitry Andric }
17450b57cec5SDimitry Andric
17460b57cec5SDimitry Andric return failedImport("Could not add default op");
17470b57cec5SDimitry Andric }
17480b57cec5SDimitry Andric
17490b57cec5SDimitry Andric return Error::success();
17500b57cec5SDimitry Andric }
17510b57cec5SDimitry Andric
importImplicitDefRenderers(BuildMIAction & DstMIBuilder,const std::vector<Record * > & ImplicitDefs) const17520b57cec5SDimitry Andric Error GlobalISelEmitter::importImplicitDefRenderers(
17530b57cec5SDimitry Andric BuildMIAction &DstMIBuilder,
17540b57cec5SDimitry Andric const std::vector<Record *> &ImplicitDefs) const {
17550b57cec5SDimitry Andric if (!ImplicitDefs.empty())
17560b57cec5SDimitry Andric return failedImport("Pattern defines a physical register");
17570b57cec5SDimitry Andric return Error::success();
17580b57cec5SDimitry Andric }
17590b57cec5SDimitry Andric
1760bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *>
getRegClassFromLeaf(const TreePatternNode * Leaf)176106c3fb27SDimitry Andric GlobalISelEmitter::getRegClassFromLeaf(const TreePatternNode *Leaf) {
17628bcb0991SDimitry Andric assert(Leaf && "Expected node?");
17638bcb0991SDimitry Andric assert(Leaf->isLeaf() && "Expected leaf?");
17648bcb0991SDimitry Andric Record *RCRec = getInitValueAsRegClass(Leaf->getLeafValue());
17658bcb0991SDimitry Andric if (!RCRec)
1766bdd1243dSDimitry Andric return std::nullopt;
17678bcb0991SDimitry Andric CodeGenRegisterClass *RC = CGRegs.getRegClass(RCRec);
17688bcb0991SDimitry Andric if (!RC)
1769bdd1243dSDimitry Andric return std::nullopt;
17708bcb0991SDimitry Andric return RC;
17718bcb0991SDimitry Andric }
17728bcb0991SDimitry Andric
1773bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *>
inferRegClassFromPattern(const TreePatternNode * N)177406c3fb27SDimitry Andric GlobalISelEmitter::inferRegClassFromPattern(const TreePatternNode *N) {
17758bcb0991SDimitry Andric if (!N)
1776bdd1243dSDimitry Andric return std::nullopt;
17778bcb0991SDimitry Andric
17788bcb0991SDimitry Andric if (N->isLeaf())
17798bcb0991SDimitry Andric return getRegClassFromLeaf(N);
17808bcb0991SDimitry Andric
17818bcb0991SDimitry Andric // We don't have a leaf node, so we have to try and infer something. Check
17828bcb0991SDimitry Andric // that we have an instruction that we an infer something from.
17838bcb0991SDimitry Andric
17848bcb0991SDimitry Andric // Only handle things that produce a single type.
17858bcb0991SDimitry Andric if (N->getNumTypes() != 1)
1786bdd1243dSDimitry Andric return std::nullopt;
17878bcb0991SDimitry Andric Record *OpRec = N->getOperator();
17888bcb0991SDimitry Andric
17898bcb0991SDimitry Andric // We only want instructions.
17908bcb0991SDimitry Andric if (!OpRec->isSubClassOf("Instruction"))
1791bdd1243dSDimitry Andric return std::nullopt;
17928bcb0991SDimitry Andric
17938bcb0991SDimitry Andric // Don't want to try and infer things when there could potentially be more
17948bcb0991SDimitry Andric // than one candidate register class.
17958bcb0991SDimitry Andric auto &Inst = Target.getInstruction(OpRec);
17968bcb0991SDimitry Andric if (Inst.Operands.NumDefs > 1)
1797bdd1243dSDimitry Andric return std::nullopt;
17988bcb0991SDimitry Andric
17998bcb0991SDimitry Andric // Handle any special-case instructions which we can safely infer register
18008bcb0991SDimitry Andric // classes from.
18018bcb0991SDimitry Andric StringRef InstName = Inst.TheDef->getName();
18028bcb0991SDimitry Andric bool IsRegSequence = InstName == "REG_SEQUENCE";
18038bcb0991SDimitry Andric if (IsRegSequence || InstName == "COPY_TO_REGCLASS") {
18048bcb0991SDimitry Andric // If we have a COPY_TO_REGCLASS, then we need to handle it specially. It
18058bcb0991SDimitry Andric // has the desired register class as the first child.
180606c3fb27SDimitry Andric const TreePatternNode *RCChild = N->getChild(IsRegSequence ? 0 : 1);
18078bcb0991SDimitry Andric if (!RCChild->isLeaf())
1808bdd1243dSDimitry Andric return std::nullopt;
18098bcb0991SDimitry Andric return getRegClassFromLeaf(RCChild);
18108bcb0991SDimitry Andric }
1811e8d8bef9SDimitry Andric if (InstName == "INSERT_SUBREG") {
181206c3fb27SDimitry Andric const TreePatternNode *Child0 = N->getChild(0);
1813e8d8bef9SDimitry Andric assert(Child0->getNumTypes() == 1 && "Unexpected number of types!");
1814e8d8bef9SDimitry Andric const TypeSetByHwMode &VTy = Child0->getExtType(0);
1815e8d8bef9SDimitry Andric return inferSuperRegisterClassForNode(VTy, Child0, N->getChild(2));
1816e8d8bef9SDimitry Andric }
1817e8d8bef9SDimitry Andric if (InstName == "EXTRACT_SUBREG") {
1818e8d8bef9SDimitry Andric assert(N->getNumTypes() == 1 && "Unexpected number of types!");
1819e8d8bef9SDimitry Andric const TypeSetByHwMode &VTy = N->getExtType(0);
1820e8d8bef9SDimitry Andric return inferSuperRegisterClass(VTy, N->getChild(1));
1821e8d8bef9SDimitry Andric }
18228bcb0991SDimitry Andric
18238bcb0991SDimitry Andric // Handle destination record types that we can safely infer a register class
18248bcb0991SDimitry Andric // from.
18258bcb0991SDimitry Andric const auto &DstIOperand = Inst.Operands[0];
18268bcb0991SDimitry Andric Record *DstIOpRec = DstIOperand.Rec;
18278bcb0991SDimitry Andric if (DstIOpRec->isSubClassOf("RegisterOperand")) {
18288bcb0991SDimitry Andric DstIOpRec = DstIOpRec->getValueAsDef("RegClass");
18298bcb0991SDimitry Andric const CodeGenRegisterClass &RC = Target.getRegisterClass(DstIOpRec);
18308bcb0991SDimitry Andric return &RC;
18318bcb0991SDimitry Andric }
18328bcb0991SDimitry Andric
18338bcb0991SDimitry Andric if (DstIOpRec->isSubClassOf("RegisterClass")) {
18348bcb0991SDimitry Andric const CodeGenRegisterClass &RC = Target.getRegisterClass(DstIOpRec);
18358bcb0991SDimitry Andric return &RC;
18368bcb0991SDimitry Andric }
18378bcb0991SDimitry Andric
1838bdd1243dSDimitry Andric return std::nullopt;
18398bcb0991SDimitry Andric }
18408bcb0991SDimitry Andric
1841bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *>
inferSuperRegisterClass(const TypeSetByHwMode & Ty,const TreePatternNode * SubRegIdxNode)184206c3fb27SDimitry Andric GlobalISelEmitter::inferSuperRegisterClass(
184306c3fb27SDimitry Andric const TypeSetByHwMode &Ty, const TreePatternNode *SubRegIdxNode) {
18448bcb0991SDimitry Andric assert(SubRegIdxNode && "Expected subregister index node!");
18458bcb0991SDimitry Andric // We need a ValueTypeByHwMode for getSuperRegForSubReg.
18468bcb0991SDimitry Andric if (!Ty.isValueTypeByHwMode(false))
1847bdd1243dSDimitry Andric return std::nullopt;
18488bcb0991SDimitry Andric if (!SubRegIdxNode->isLeaf())
1849bdd1243dSDimitry Andric return std::nullopt;
18508bcb0991SDimitry Andric DefInit *SubRegInit = dyn_cast<DefInit>(SubRegIdxNode->getLeafValue());
18518bcb0991SDimitry Andric if (!SubRegInit)
1852bdd1243dSDimitry Andric return std::nullopt;
18538bcb0991SDimitry Andric CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
18548bcb0991SDimitry Andric
18558bcb0991SDimitry Andric // Use the information we found above to find a minimal register class which
18568bcb0991SDimitry Andric // supports the subregister and type we want.
18578bcb0991SDimitry Andric auto RC =
1858e8d8bef9SDimitry Andric Target.getSuperRegForSubReg(Ty.getValueTypeByHwMode(), CGRegs, SubIdx,
1859e8d8bef9SDimitry Andric /* MustBeAllocatable */ true);
18608bcb0991SDimitry Andric if (!RC)
1861bdd1243dSDimitry Andric return std::nullopt;
18628bcb0991SDimitry Andric return *RC;
18638bcb0991SDimitry Andric }
18648bcb0991SDimitry Andric
1865bdd1243dSDimitry Andric std::optional<const CodeGenRegisterClass *>
inferSuperRegisterClassForNode(const TypeSetByHwMode & Ty,const TreePatternNode * SuperRegNode,const TreePatternNode * SubRegIdxNode)18668bcb0991SDimitry Andric GlobalISelEmitter::inferSuperRegisterClassForNode(
186706c3fb27SDimitry Andric const TypeSetByHwMode &Ty, const TreePatternNode *SuperRegNode,
186806c3fb27SDimitry Andric const TreePatternNode *SubRegIdxNode) {
18698bcb0991SDimitry Andric assert(SuperRegNode && "Expected super register node!");
18708bcb0991SDimitry Andric // Check if we already have a defined register class for the super register
18718bcb0991SDimitry Andric // node. If we do, then we should preserve that rather than inferring anything
18728bcb0991SDimitry Andric // from the subregister index node. We can assume that whoever wrote the
18738bcb0991SDimitry Andric // pattern in the first place made sure that the super register and
18748bcb0991SDimitry Andric // subregister are compatible.
1875bdd1243dSDimitry Andric if (std::optional<const CodeGenRegisterClass *> SuperRegisterClass =
18768bcb0991SDimitry Andric inferRegClassFromPattern(SuperRegNode))
18778bcb0991SDimitry Andric return *SuperRegisterClass;
18788bcb0991SDimitry Andric return inferSuperRegisterClass(Ty, SubRegIdxNode);
18798bcb0991SDimitry Andric }
18808bcb0991SDimitry Andric
inferSubRegIndexForNode(const TreePatternNode * SubRegIdxNode)188106c3fb27SDimitry Andric std::optional<CodeGenSubRegIndex *> GlobalISelEmitter::inferSubRegIndexForNode(
188206c3fb27SDimitry Andric const TreePatternNode *SubRegIdxNode) {
18838bcb0991SDimitry Andric if (!SubRegIdxNode->isLeaf())
1884bdd1243dSDimitry Andric return std::nullopt;
18858bcb0991SDimitry Andric
18868bcb0991SDimitry Andric DefInit *SubRegInit = dyn_cast<DefInit>(SubRegIdxNode->getLeafValue());
18878bcb0991SDimitry Andric if (!SubRegInit)
1888bdd1243dSDimitry Andric return std::nullopt;
18898bcb0991SDimitry Andric return CGRegs.getSubRegIdx(SubRegInit->getDef());
18908bcb0991SDimitry Andric }
18918bcb0991SDimitry Andric
runOnPattern(const PatternToMatch & P)18920b57cec5SDimitry Andric Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
18930b57cec5SDimitry Andric // Keep track of the matchers and actions to emit.
18940b57cec5SDimitry Andric int Score = P.getPatternComplexity(CGP);
18950b57cec5SDimitry Andric RuleMatcher M(P.getSrcRecord()->getLoc());
18960b57cec5SDimitry Andric RuleMatcherScores[M.getRuleID()] = Score;
18970b57cec5SDimitry Andric M.addAction<DebugCommentAction>(llvm::to_string(*P.getSrcPattern()) +
18980b57cec5SDimitry Andric " => " +
18990b57cec5SDimitry Andric llvm::to_string(*P.getDstPattern()));
19000b57cec5SDimitry Andric
1901fe6060f1SDimitry Andric SmallVector<Record *, 4> Predicates;
1902fe6060f1SDimitry Andric P.getPredicateRecords(Predicates);
1903fe6060f1SDimitry Andric if (auto Error = importRulePredicates(M, Predicates))
19040b57cec5SDimitry Andric return std::move(Error);
19050b57cec5SDimitry Andric
19065f757f3fSDimitry Andric if (!P.getHwModeFeatures().empty())
19075f757f3fSDimitry Andric M.addHwModeIdx(declareHwModeCheck(P.getHwModeFeatures()));
19085f757f3fSDimitry Andric
19090b57cec5SDimitry Andric // Next, analyze the pattern operators.
19100b57cec5SDimitry Andric TreePatternNode *Src = P.getSrcPattern();
19110b57cec5SDimitry Andric TreePatternNode *Dst = P.getDstPattern();
19120b57cec5SDimitry Andric
19130b57cec5SDimitry Andric // If the root of either pattern isn't a simple operator, ignore it.
19140b57cec5SDimitry Andric if (auto Err = isTrivialOperatorNode(Dst))
19150b57cec5SDimitry Andric return failedImport("Dst pattern root isn't a trivial operator (" +
19160b57cec5SDimitry Andric toString(std::move(Err)) + ")");
19170b57cec5SDimitry Andric if (auto Err = isTrivialOperatorNode(Src))
19180b57cec5SDimitry Andric return failedImport("Src pattern root isn't a trivial operator (" +
19190b57cec5SDimitry Andric toString(std::move(Err)) + ")");
19200b57cec5SDimitry Andric
19210b57cec5SDimitry Andric // The different predicates and matchers created during
19220b57cec5SDimitry Andric // addInstructionMatcher use the RuleMatcher M to set up their
19230b57cec5SDimitry Andric // instruction ID (InsnVarID) that are going to be used when
19240b57cec5SDimitry Andric // M is going to be emitted.
19250b57cec5SDimitry Andric // However, the code doing the emission still relies on the IDs
19260b57cec5SDimitry Andric // returned during that process by the RuleMatcher when issuing
19270b57cec5SDimitry Andric // the recordInsn opcodes.
19280b57cec5SDimitry Andric // Because of that:
19290b57cec5SDimitry Andric // 1. The order in which we created the predicates
19300b57cec5SDimitry Andric // and such must be the same as the order in which we emit them,
19310b57cec5SDimitry Andric // and
19320b57cec5SDimitry Andric // 2. We need to reset the generation of the IDs in M somewhere between
19330b57cec5SDimitry Andric // addInstructionMatcher and emit
19340b57cec5SDimitry Andric //
19350b57cec5SDimitry Andric // FIXME: Long term, we don't want to have to rely on this implicit
19360b57cec5SDimitry Andric // naming being the same. One possible solution would be to have
19370b57cec5SDimitry Andric // explicit operator for operation capture and reference those.
19380b57cec5SDimitry Andric // The plus side is that it would expose opportunities to share
19390b57cec5SDimitry Andric // the capture accross rules. The downside is that it would
19400b57cec5SDimitry Andric // introduce a dependency between predicates (captures must happen
19410b57cec5SDimitry Andric // before their first use.)
19420b57cec5SDimitry Andric InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher(Src->getName());
19430b57cec5SDimitry Andric unsigned TempOpIdx = 0;
194406c3fb27SDimitry Andric
194506c3fb27SDimitry Andric const auto SavedFlags = M.setGISelFlags(P.getSrcRecord());
194606c3fb27SDimitry Andric
19470b57cec5SDimitry Andric auto InsnMatcherOrError =
19480b57cec5SDimitry Andric createAndImportSelDAGMatcher(M, InsnMatcherTemp, Src, TempOpIdx);
19490b57cec5SDimitry Andric if (auto Error = InsnMatcherOrError.takeError())
19500b57cec5SDimitry Andric return std::move(Error);
19510b57cec5SDimitry Andric InstructionMatcher &InsnMatcher = InsnMatcherOrError.get();
19520b57cec5SDimitry Andric
19530b57cec5SDimitry Andric if (Dst->isLeaf()) {
19540b57cec5SDimitry Andric Record *RCDef = getInitValueAsRegClass(Dst->getLeafValue());
19550b57cec5SDimitry Andric if (RCDef) {
1956e8d8bef9SDimitry Andric const CodeGenRegisterClass &RC = Target.getRegisterClass(RCDef);
1957e8d8bef9SDimitry Andric
19580b57cec5SDimitry Andric // We need to replace the def and all its uses with the specified
19590b57cec5SDimitry Andric // operand. However, we must also insert COPY's wherever needed.
19600b57cec5SDimitry Andric // For now, emit a copy and let the register allocator clean up.
19610b57cec5SDimitry Andric auto &DstI = Target.getInstruction(RK.getDef("COPY"));
19620b57cec5SDimitry Andric const auto &DstIOperand = DstI.Operands[0];
19630b57cec5SDimitry Andric
19640b57cec5SDimitry Andric OperandMatcher &OM0 = InsnMatcher.getOperand(0);
19650b57cec5SDimitry Andric OM0.setSymbolicName(DstIOperand.Name);
19660b57cec5SDimitry Andric M.defineOperand(OM0.getSymbolicName(), OM0);
19670b57cec5SDimitry Andric OM0.addPredicate<RegisterBankOperandMatcher>(RC);
19680b57cec5SDimitry Andric
19690b57cec5SDimitry Andric auto &DstMIBuilder =
19700b57cec5SDimitry Andric M.addAction<BuildMIAction>(M.allocateOutputInsnID(), &DstI);
19710b57cec5SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(DstIOperand.Name);
19720b57cec5SDimitry Andric DstMIBuilder.addRenderer<CopyRenderer>(Dst->getName());
19730b57cec5SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 0, RC);
19740b57cec5SDimitry Andric
19757a6dacacSDimitry Andric // Erase the root.
19767a6dacacSDimitry Andric unsigned RootInsnID = M.getInsnVarID(InsnMatcher);
19777a6dacacSDimitry Andric M.addAction<EraseInstAction>(RootInsnID);
19787a6dacacSDimitry Andric
19790b57cec5SDimitry Andric // We're done with this pattern! It's eligible for GISel emission; return
19800b57cec5SDimitry Andric // it.
19810b57cec5SDimitry Andric ++NumPatternImported;
19820b57cec5SDimitry Andric return std::move(M);
19830b57cec5SDimitry Andric }
19840b57cec5SDimitry Andric
19850b57cec5SDimitry Andric return failedImport("Dst pattern root isn't a known leaf");
19860b57cec5SDimitry Andric }
19870b57cec5SDimitry Andric
19880b57cec5SDimitry Andric // Start with the defined operands (i.e., the results of the root operator).
19890b57cec5SDimitry Andric Record *DstOp = Dst->getOperator();
19900b57cec5SDimitry Andric if (!DstOp->isSubClassOf("Instruction"))
19910b57cec5SDimitry Andric return failedImport("Pattern operator isn't an instruction");
19920b57cec5SDimitry Andric
19930b57cec5SDimitry Andric auto &DstI = Target.getInstruction(DstOp);
19948bcb0991SDimitry Andric StringRef DstIName = DstI.TheDef->getName();
19958bcb0991SDimitry Andric
1996753f127fSDimitry Andric unsigned DstNumDefs = DstI.Operands.NumDefs,
1997753f127fSDimitry Andric SrcNumDefs = Src->getExtTypes().size();
1998753f127fSDimitry Andric if (DstNumDefs < SrcNumDefs) {
1999753f127fSDimitry Andric if (DstNumDefs != 0)
2000e8d8bef9SDimitry Andric return failedImport("Src pattern result has more defs than dst MI (" +
2001753f127fSDimitry Andric to_string(SrcNumDefs) + " def(s) vs " +
2002753f127fSDimitry Andric to_string(DstNumDefs) + " def(s))");
2003753f127fSDimitry Andric
2004753f127fSDimitry Andric bool FoundNoUsePred = false;
2005753f127fSDimitry Andric for (const auto &Pred : InsnMatcher.predicates()) {
2006753f127fSDimitry Andric if ((FoundNoUsePred = isa<NoUsePredicateMatcher>(Pred.get())))
2007753f127fSDimitry Andric break;
2008753f127fSDimitry Andric }
2009753f127fSDimitry Andric if (!FoundNoUsePred)
2010753f127fSDimitry Andric return failedImport("Src pattern result has " + to_string(SrcNumDefs) +
2011753f127fSDimitry Andric " def(s) without the HasNoUse predicate set to true "
2012753f127fSDimitry Andric "but Dst MI has no def");
2013753f127fSDimitry Andric }
20140b57cec5SDimitry Andric
20150b57cec5SDimitry Andric // The root of the match also has constraints on the register bank so that it
20160b57cec5SDimitry Andric // matches the result instruction.
20170b57cec5SDimitry Andric unsigned OpIdx = 0;
2018753f127fSDimitry Andric unsigned N = std::min(DstNumDefs, SrcNumDefs);
2019753f127fSDimitry Andric for (unsigned I = 0; I < N; ++I) {
2020753f127fSDimitry Andric const TypeSetByHwMode &VTy = Src->getExtType(I);
20210b57cec5SDimitry Andric
20220b57cec5SDimitry Andric const auto &DstIOperand = DstI.Operands[OpIdx];
20235f757f3fSDimitry Andric PointerUnion<Record *, const CodeGenRegisterClass *> MatchedRC =
20245f757f3fSDimitry Andric DstIOperand.Rec;
20258bcb0991SDimitry Andric if (DstIName == "COPY_TO_REGCLASS") {
20265f757f3fSDimitry Andric MatchedRC = getInitValueAsRegClass(Dst->getChild(1)->getLeafValue());
20270b57cec5SDimitry Andric
20285f757f3fSDimitry Andric if (MatchedRC.isNull())
20290b57cec5SDimitry Andric return failedImport(
20300b57cec5SDimitry Andric "COPY_TO_REGCLASS operand #1 isn't a register class");
20318bcb0991SDimitry Andric } else if (DstIName == "REG_SEQUENCE") {
20325f757f3fSDimitry Andric MatchedRC = getInitValueAsRegClass(Dst->getChild(0)->getLeafValue());
20335f757f3fSDimitry Andric if (MatchedRC.isNull())
20348bcb0991SDimitry Andric return failedImport("REG_SEQUENCE operand #0 isn't a register class");
20358bcb0991SDimitry Andric } else if (DstIName == "EXTRACT_SUBREG") {
20365ffd83dbSDimitry Andric auto InferredClass = inferRegClassFromPattern(Dst->getChild(0));
20375ffd83dbSDimitry Andric if (!InferredClass)
203806c3fb27SDimitry Andric return failedImport(
203906c3fb27SDimitry Andric "Could not infer class for EXTRACT_SUBREG operand #0");
20400b57cec5SDimitry Andric
20410b57cec5SDimitry Andric // We can assume that a subregister is in the same bank as it's super
20420b57cec5SDimitry Andric // register.
20435f757f3fSDimitry Andric MatchedRC = (*InferredClass)->getDef();
20448bcb0991SDimitry Andric } else if (DstIName == "INSERT_SUBREG") {
20458bcb0991SDimitry Andric auto MaybeSuperClass = inferSuperRegisterClassForNode(
20468bcb0991SDimitry Andric VTy, Dst->getChild(0), Dst->getChild(2));
20478bcb0991SDimitry Andric if (!MaybeSuperClass)
20480b57cec5SDimitry Andric return failedImport(
20498bcb0991SDimitry Andric "Cannot infer register class for INSERT_SUBREG operand #0");
20508bcb0991SDimitry Andric // Move to the next pattern here, because the register class we found
20518bcb0991SDimitry Andric // doesn't necessarily have a record associated with it. So, we can't
20528bcb0991SDimitry Andric // set DstIOpRec using this.
20535f757f3fSDimitry Andric MatchedRC = *MaybeSuperClass;
20548bcb0991SDimitry Andric } else if (DstIName == "SUBREG_TO_REG") {
20558bcb0991SDimitry Andric auto MaybeRegClass = inferSuperRegisterClass(VTy, Dst->getChild(2));
20568bcb0991SDimitry Andric if (!MaybeRegClass)
20578bcb0991SDimitry Andric return failedImport(
20588bcb0991SDimitry Andric "Cannot infer register class for SUBREG_TO_REG operand #0");
20595f757f3fSDimitry Andric MatchedRC = *MaybeRegClass;
20605f757f3fSDimitry Andric } else if (MatchedRC.get<Record *>()->isSubClassOf("RegisterOperand"))
20615f757f3fSDimitry Andric MatchedRC = MatchedRC.get<Record *>()->getValueAsDef("RegClass");
20625f757f3fSDimitry Andric else if (!MatchedRC.get<Record *>()->isSubClassOf("RegisterClass"))
20630b57cec5SDimitry Andric return failedImport("Dst MI def isn't a register class" +
20640b57cec5SDimitry Andric to_string(*Dst));
20650b57cec5SDimitry Andric
20660b57cec5SDimitry Andric OperandMatcher &OM = InsnMatcher.getOperand(OpIdx);
20675f757f3fSDimitry Andric // The operand names declared in the DstI instruction are unrelated to
20685f757f3fSDimitry Andric // those used in pattern's source and destination DAGs, so mangle the
20695f757f3fSDimitry Andric // former to prevent implicitly adding unexpected
20705f757f3fSDimitry Andric // GIM_CheckIsSameOperand predicates by the defineOperand method.
20715f757f3fSDimitry Andric OM.setSymbolicName(getMangledRootDefName(DstIOperand.Name));
20720b57cec5SDimitry Andric M.defineOperand(OM.getSymbolicName(), OM);
20735f757f3fSDimitry Andric if (MatchedRC.is<Record *>())
20745f757f3fSDimitry Andric MatchedRC = &Target.getRegisterClass(MatchedRC.get<Record *>());
20750b57cec5SDimitry Andric OM.addPredicate<RegisterBankOperandMatcher>(
20765f757f3fSDimitry Andric *MatchedRC.get<const CodeGenRegisterClass *>());
20770b57cec5SDimitry Andric ++OpIdx;
20780b57cec5SDimitry Andric }
20790b57cec5SDimitry Andric
20808bcb0991SDimitry Andric auto DstMIBuilderOrError =
20818bcb0991SDimitry Andric createAndImportInstructionRenderer(M, InsnMatcher, Src, Dst);
20820b57cec5SDimitry Andric if (auto Error = DstMIBuilderOrError.takeError())
20830b57cec5SDimitry Andric return std::move(Error);
20840b57cec5SDimitry Andric BuildMIAction &DstMIBuilder = DstMIBuilderOrError.get();
20850b57cec5SDimitry Andric
20860b57cec5SDimitry Andric // Render the implicit defs.
20870b57cec5SDimitry Andric // These are only added to the root of the result.
20880b57cec5SDimitry Andric if (auto Error = importImplicitDefRenderers(DstMIBuilder, P.getDstRegs()))
20890b57cec5SDimitry Andric return std::move(Error);
20900b57cec5SDimitry Andric
20910b57cec5SDimitry Andric DstMIBuilder.chooseInsnToMutate(M);
20920b57cec5SDimitry Andric
20930b57cec5SDimitry Andric // Constrain the registers to classes. This is normally derived from the
20940b57cec5SDimitry Andric // emitted instruction but a few instructions require special handling.
20958bcb0991SDimitry Andric if (DstIName == "COPY_TO_REGCLASS") {
20960b57cec5SDimitry Andric // COPY_TO_REGCLASS does not provide operand constraints itself but the
20970b57cec5SDimitry Andric // result is constrained to the class given by the second child.
20980b57cec5SDimitry Andric Record *DstIOpRec =
20990b57cec5SDimitry Andric getInitValueAsRegClass(Dst->getChild(1)->getLeafValue());
21000b57cec5SDimitry Andric
21010b57cec5SDimitry Andric if (DstIOpRec == nullptr)
21020b57cec5SDimitry Andric return failedImport("COPY_TO_REGCLASS operand #1 isn't a register class");
21030b57cec5SDimitry Andric
21040b57cec5SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(
21050b57cec5SDimitry Andric 0, 0, Target.getRegisterClass(DstIOpRec));
21067a6dacacSDimitry Andric } else if (DstIName == "EXTRACT_SUBREG") {
21078bcb0991SDimitry Andric auto SuperClass = inferRegClassFromPattern(Dst->getChild(0));
21088bcb0991SDimitry Andric if (!SuperClass)
21098bcb0991SDimitry Andric return failedImport(
21108bcb0991SDimitry Andric "Cannot infer register class from EXTRACT_SUBREG operand #0");
21110b57cec5SDimitry Andric
21128bcb0991SDimitry Andric auto SubIdx = inferSubRegIndexForNode(Dst->getChild(1));
21138bcb0991SDimitry Andric if (!SubIdx)
21140b57cec5SDimitry Andric return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");
21150b57cec5SDimitry Andric
21160b57cec5SDimitry Andric // It would be nice to leave this constraint implicit but we're required
21170b57cec5SDimitry Andric // to pick a register class so constrain the result to a register class
21180b57cec5SDimitry Andric // that can hold the correct MVT.
21190b57cec5SDimitry Andric //
21200b57cec5SDimitry Andric // FIXME: This may introduce an extra copy if the chosen class doesn't
21210b57cec5SDimitry Andric // actually contain the subregisters.
21220b57cec5SDimitry Andric assert(Src->getExtTypes().size() == 1 &&
21230b57cec5SDimitry Andric "Expected Src of EXTRACT_SUBREG to have one result type");
21240b57cec5SDimitry Andric
21255ffd83dbSDimitry Andric const auto SrcRCDstRCPair =
21268bcb0991SDimitry Andric (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
21275ffd83dbSDimitry Andric if (!SrcRCDstRCPair) {
21285ffd83dbSDimitry Andric return failedImport("subreg index is incompatible "
21295ffd83dbSDimitry Andric "with inferred reg class");
21305ffd83dbSDimitry Andric }
21315ffd83dbSDimitry Andric
21320b57cec5SDimitry Andric assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
213306c3fb27SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 0,
213406c3fb27SDimitry Andric *SrcRCDstRCPair->second);
21350b57cec5SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 1, *SrcRCDstRCPair->first);
21367a6dacacSDimitry Andric } else if (DstIName == "INSERT_SUBREG") {
21378bcb0991SDimitry Andric assert(Src->getExtTypes().size() == 1 &&
21388bcb0991SDimitry Andric "Expected Src of INSERT_SUBREG to have one result type");
21398bcb0991SDimitry Andric // We need to constrain the destination, a super regsister source, and a
21408bcb0991SDimitry Andric // subregister source.
21418bcb0991SDimitry Andric auto SubClass = inferRegClassFromPattern(Dst->getChild(1));
21428bcb0991SDimitry Andric if (!SubClass)
21438bcb0991SDimitry Andric return failedImport(
21448bcb0991SDimitry Andric "Cannot infer register class from INSERT_SUBREG operand #1");
21458bcb0991SDimitry Andric auto SuperClass = inferSuperRegisterClassForNode(
21468bcb0991SDimitry Andric Src->getExtType(0), Dst->getChild(0), Dst->getChild(2));
21478bcb0991SDimitry Andric if (!SuperClass)
21488bcb0991SDimitry Andric return failedImport(
21498bcb0991SDimitry Andric "Cannot infer register class for INSERT_SUBREG operand #0");
21508bcb0991SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 0, **SuperClass);
21518bcb0991SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 1, **SuperClass);
21528bcb0991SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 2, **SubClass);
21537a6dacacSDimitry Andric } else if (DstIName == "SUBREG_TO_REG") {
21548bcb0991SDimitry Andric // We need to constrain the destination and subregister source.
21558bcb0991SDimitry Andric assert(Src->getExtTypes().size() == 1 &&
21568bcb0991SDimitry Andric "Expected Src of SUBREG_TO_REG to have one result type");
21578bcb0991SDimitry Andric
21588bcb0991SDimitry Andric // Attempt to infer the subregister source from the first child. If it has
21598bcb0991SDimitry Andric // an explicitly given register class, we'll use that. Otherwise, we will
21608bcb0991SDimitry Andric // fail.
21618bcb0991SDimitry Andric auto SubClass = inferRegClassFromPattern(Dst->getChild(1));
21628bcb0991SDimitry Andric if (!SubClass)
21638bcb0991SDimitry Andric return failedImport(
21648bcb0991SDimitry Andric "Cannot infer register class from SUBREG_TO_REG child #1");
21658bcb0991SDimitry Andric // We don't have a child to look at that might have a super register node.
21668bcb0991SDimitry Andric auto SuperClass =
21678bcb0991SDimitry Andric inferSuperRegisterClass(Src->getExtType(0), Dst->getChild(2));
21688bcb0991SDimitry Andric if (!SuperClass)
21698bcb0991SDimitry Andric return failedImport(
21708bcb0991SDimitry Andric "Cannot infer register class for SUBREG_TO_REG operand #0");
21718bcb0991SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 0, **SuperClass);
21728bcb0991SDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 2, **SubClass);
21737a6dacacSDimitry Andric } else if (DstIName == "REG_SEQUENCE") {
21745ffd83dbSDimitry Andric auto SuperClass = inferRegClassFromPattern(Dst->getChild(0));
21755ffd83dbSDimitry Andric
21765ffd83dbSDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, 0, **SuperClass);
21775ffd83dbSDimitry Andric
21785ffd83dbSDimitry Andric unsigned Num = Dst->getNumChildren();
21795ffd83dbSDimitry Andric for (unsigned I = 1; I != Num; I += 2) {
21805ffd83dbSDimitry Andric TreePatternNode *SubRegChild = Dst->getChild(I + 1);
21815ffd83dbSDimitry Andric
21825ffd83dbSDimitry Andric auto SubIdx = inferSubRegIndexForNode(SubRegChild);
21835ffd83dbSDimitry Andric if (!SubIdx)
21845ffd83dbSDimitry Andric return failedImport("REG_SEQUENCE child is not a subreg index");
21855ffd83dbSDimitry Andric
21865ffd83dbSDimitry Andric const auto SrcRCDstRCPair =
21875ffd83dbSDimitry Andric (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
21885ffd83dbSDimitry Andric
21895ffd83dbSDimitry Andric M.addAction<ConstrainOperandToRegClassAction>(0, I,
21905ffd83dbSDimitry Andric *SrcRCDstRCPair->second);
21915ffd83dbSDimitry Andric }
21927a6dacacSDimitry Andric } else {
21937a6dacacSDimitry Andric M.addAction<ConstrainOperandsToDefinitionAction>(0);
21945ffd83dbSDimitry Andric }
21955ffd83dbSDimitry Andric
21967a6dacacSDimitry Andric // Erase the root.
21977a6dacacSDimitry Andric unsigned RootInsnID = M.getInsnVarID(InsnMatcher);
21987a6dacacSDimitry Andric M.addAction<EraseInstAction>(RootInsnID);
21990b57cec5SDimitry Andric
22000b57cec5SDimitry Andric // We're done with this pattern! It's eligible for GISel emission; return it.
22010b57cec5SDimitry Andric ++NumPatternImported;
22020b57cec5SDimitry Andric return std::move(M);
22030b57cec5SDimitry Andric }
22040b57cec5SDimitry Andric
22050b57cec5SDimitry Andric MatchTable
buildMatchTable(MutableArrayRef<RuleMatcher> Rules,bool Optimize,bool WithCoverage)22060b57cec5SDimitry Andric GlobalISelEmitter::buildMatchTable(MutableArrayRef<RuleMatcher> Rules,
22070b57cec5SDimitry Andric bool Optimize, bool WithCoverage) {
22080b57cec5SDimitry Andric std::vector<Matcher *> InputRules;
22090b57cec5SDimitry Andric for (Matcher &Rule : Rules)
22100b57cec5SDimitry Andric InputRules.push_back(&Rule);
22110b57cec5SDimitry Andric
22120b57cec5SDimitry Andric if (!Optimize)
22130b57cec5SDimitry Andric return MatchTable::buildTable(InputRules, WithCoverage);
22140b57cec5SDimitry Andric
22150b57cec5SDimitry Andric unsigned CurrentOrdering = 0;
22160b57cec5SDimitry Andric StringMap<unsigned> OpcodeOrder;
22170b57cec5SDimitry Andric for (RuleMatcher &Rule : Rules) {
22180b57cec5SDimitry Andric const StringRef Opcode = Rule.getOpcode();
22190b57cec5SDimitry Andric assert(!Opcode.empty() && "Didn't expect an undefined opcode");
22200b57cec5SDimitry Andric if (OpcodeOrder.count(Opcode) == 0)
22210b57cec5SDimitry Andric OpcodeOrder[Opcode] = CurrentOrdering++;
22220b57cec5SDimitry Andric }
22230b57cec5SDimitry Andric
2224e8d8bef9SDimitry Andric llvm::stable_sort(InputRules, [&OpcodeOrder](const Matcher *A,
2225e8d8bef9SDimitry Andric const Matcher *B) {
22260b57cec5SDimitry Andric auto *L = static_cast<const RuleMatcher *>(A);
22270b57cec5SDimitry Andric auto *R = static_cast<const RuleMatcher *>(B);
2228e8d8bef9SDimitry Andric return std::make_tuple(OpcodeOrder[L->getOpcode()], L->getNumOperands()) <
2229e8d8bef9SDimitry Andric std::make_tuple(OpcodeOrder[R->getOpcode()], R->getNumOperands());
22300b57cec5SDimitry Andric });
22310b57cec5SDimitry Andric
22320b57cec5SDimitry Andric for (Matcher *Rule : InputRules)
22330b57cec5SDimitry Andric Rule->optimize();
22340b57cec5SDimitry Andric
22350b57cec5SDimitry Andric std::vector<std::unique_ptr<Matcher>> MatcherStorage;
22360b57cec5SDimitry Andric std::vector<Matcher *> OptRules =
22370b57cec5SDimitry Andric optimizeRules<GroupMatcher>(InputRules, MatcherStorage);
22380b57cec5SDimitry Andric
22390b57cec5SDimitry Andric for (Matcher *Rule : OptRules)
22400b57cec5SDimitry Andric Rule->optimize();
22410b57cec5SDimitry Andric
22420b57cec5SDimitry Andric OptRules = optimizeRules<SwitchMatcher>(OptRules, MatcherStorage);
22430b57cec5SDimitry Andric
22440b57cec5SDimitry Andric return MatchTable::buildTable(OptRules, WithCoverage);
22450b57cec5SDimitry Andric }
22460b57cec5SDimitry Andric
emitAdditionalImpl(raw_ostream & OS)224706c3fb27SDimitry Andric void GlobalISelEmitter::emitAdditionalImpl(raw_ostream &OS) {
224806c3fb27SDimitry Andric OS << "bool " << getClassName()
224906c3fb27SDimitry Andric << "::selectImpl(MachineInstr &I, CodeGenCoverage "
225006c3fb27SDimitry Andric "&CoverageInfo) const {\n"
225106c3fb27SDimitry Andric << " const PredicateBitset AvailableFeatures = "
225206c3fb27SDimitry Andric "getAvailableFeatures();\n"
22535f757f3fSDimitry Andric << " MachineIRBuilder B(I);\n"
225406c3fb27SDimitry Andric << " State.MIs.clear();\n"
225506c3fb27SDimitry Andric << " State.MIs.push_back(&I);\n\n"
22565f757f3fSDimitry Andric << " if (executeMatchTable(*this, State, ExecInfo, B"
225706c3fb27SDimitry Andric << ", getMatchTable(), TII, MF->getRegInfo(), TRI, RBI, AvailableFeatures"
225806c3fb27SDimitry Andric << ", &CoverageInfo)) {\n"
225906c3fb27SDimitry Andric << " return true;\n"
226006c3fb27SDimitry Andric << " }\n\n"
226106c3fb27SDimitry Andric << " return false;\n"
226206c3fb27SDimitry Andric << "}\n\n";
22630b57cec5SDimitry Andric }
226406c3fb27SDimitry Andric
emitMIPredicateFns(raw_ostream & OS)226506c3fb27SDimitry Andric void GlobalISelEmitter::emitMIPredicateFns(raw_ostream &OS) {
226606c3fb27SDimitry Andric std::vector<Record *> MatchedRecords;
226706c3fb27SDimitry Andric std::copy_if(AllPatFrags.begin(), AllPatFrags.end(),
226806c3fb27SDimitry Andric std::back_inserter(MatchedRecords), [&](Record *R) {
226906c3fb27SDimitry Andric return !R->getValueAsString("GISelPredicateCode").empty();
22700b57cec5SDimitry Andric });
227106c3fb27SDimitry Andric emitMIPredicateFnsImpl<Record *>(
227206c3fb27SDimitry Andric OS,
227306c3fb27SDimitry Andric " const MachineFunction &MF = *MI.getParent()->getParent();\n"
227406c3fb27SDimitry Andric " const MachineRegisterInfo &MRI = MF.getRegInfo();\n"
227506c3fb27SDimitry Andric " const auto &Operands = State.RecordedOperands;\n"
227606c3fb27SDimitry Andric " (void)Operands;\n"
227706c3fb27SDimitry Andric " (void)MRI;",
227806c3fb27SDimitry Andric ArrayRef<Record *>(MatchedRecords), &getPatFragPredicateEnumName,
227906c3fb27SDimitry Andric [&](Record *R) { return R->getValueAsString("GISelPredicateCode"); },
228006c3fb27SDimitry Andric "PatFrag predicates.");
22810b57cec5SDimitry Andric }
228206c3fb27SDimitry Andric
emitI64ImmPredicateFns(raw_ostream & OS)228306c3fb27SDimitry Andric void GlobalISelEmitter::emitI64ImmPredicateFns(raw_ostream &OS) {
228406c3fb27SDimitry Andric std::vector<Record *> MatchedRecords;
228506c3fb27SDimitry Andric std::copy_if(AllPatFrags.begin(), AllPatFrags.end(),
228606c3fb27SDimitry Andric std::back_inserter(MatchedRecords), [&](Record *R) {
228706c3fb27SDimitry Andric bool Unset;
228806c3fb27SDimitry Andric return !R->getValueAsString("ImmediateCode").empty() &&
228906c3fb27SDimitry Andric !R->getValueAsBitOrUnset("IsAPFloat", Unset) &&
229006c3fb27SDimitry Andric !R->getValueAsBit("IsAPInt");
229106c3fb27SDimitry Andric });
229206c3fb27SDimitry Andric emitImmPredicateFnsImpl<Record *>(
229306c3fb27SDimitry Andric OS, "I64", "int64_t", ArrayRef<Record *>(MatchedRecords),
229406c3fb27SDimitry Andric &getPatFragPredicateEnumName,
229506c3fb27SDimitry Andric [&](Record *R) { return R->getValueAsString("ImmediateCode"); },
229606c3fb27SDimitry Andric "PatFrag predicates.");
229706c3fb27SDimitry Andric }
229806c3fb27SDimitry Andric
emitAPFloatImmPredicateFns(raw_ostream & OS)229906c3fb27SDimitry Andric void GlobalISelEmitter::emitAPFloatImmPredicateFns(raw_ostream &OS) {
230006c3fb27SDimitry Andric std::vector<Record *> MatchedRecords;
230106c3fb27SDimitry Andric std::copy_if(AllPatFrags.begin(), AllPatFrags.end(),
230206c3fb27SDimitry Andric std::back_inserter(MatchedRecords), [&](Record *R) {
230306c3fb27SDimitry Andric bool Unset;
230406c3fb27SDimitry Andric return !R->getValueAsString("ImmediateCode").empty() &&
230506c3fb27SDimitry Andric R->getValueAsBitOrUnset("IsAPFloat", Unset);
230606c3fb27SDimitry Andric });
230706c3fb27SDimitry Andric emitImmPredicateFnsImpl<Record *>(
230806c3fb27SDimitry Andric OS, "APFloat", "const APFloat &", ArrayRef<Record *>(MatchedRecords),
230906c3fb27SDimitry Andric &getPatFragPredicateEnumName,
231006c3fb27SDimitry Andric [&](Record *R) { return R->getValueAsString("ImmediateCode"); },
231106c3fb27SDimitry Andric "PatFrag predicates.");
231206c3fb27SDimitry Andric }
231306c3fb27SDimitry Andric
emitAPIntImmPredicateFns(raw_ostream & OS)231406c3fb27SDimitry Andric void GlobalISelEmitter::emitAPIntImmPredicateFns(raw_ostream &OS) {
231506c3fb27SDimitry Andric std::vector<Record *> MatchedRecords;
231606c3fb27SDimitry Andric std::copy_if(AllPatFrags.begin(), AllPatFrags.end(),
231706c3fb27SDimitry Andric std::back_inserter(MatchedRecords), [&](Record *R) {
231806c3fb27SDimitry Andric return !R->getValueAsString("ImmediateCode").empty() &&
231906c3fb27SDimitry Andric R->getValueAsBit("IsAPInt");
232006c3fb27SDimitry Andric });
232106c3fb27SDimitry Andric emitImmPredicateFnsImpl<Record *>(
232206c3fb27SDimitry Andric OS, "APInt", "const APInt &", ArrayRef<Record *>(MatchedRecords),
232306c3fb27SDimitry Andric &getPatFragPredicateEnumName,
232406c3fb27SDimitry Andric [&](Record *R) { return R->getValueAsString("ImmediateCode"); },
232506c3fb27SDimitry Andric "PatFrag predicates.");
232606c3fb27SDimitry Andric }
232706c3fb27SDimitry Andric
emitTestSimplePredicate(raw_ostream & OS)232806c3fb27SDimitry Andric void GlobalISelEmitter::emitTestSimplePredicate(raw_ostream &OS) {
232906c3fb27SDimitry Andric OS << "bool " << getClassName() << "::testSimplePredicate(unsigned) const {\n"
233006c3fb27SDimitry Andric << " llvm_unreachable(\"" + getClassName() +
233106c3fb27SDimitry Andric " does not support simple predicates!\");\n"
233206c3fb27SDimitry Andric << " return false;\n"
233306c3fb27SDimitry Andric << "}\n";
233406c3fb27SDimitry Andric }
233506c3fb27SDimitry Andric
emitRunCustomAction(raw_ostream & OS)233606c3fb27SDimitry Andric void GlobalISelEmitter::emitRunCustomAction(raw_ostream &OS) {
233706c3fb27SDimitry Andric OS << "void " << getClassName()
23385f757f3fSDimitry Andric << "::runCustomAction(unsigned, const MatcherState&, NewMIVector &) const "
23395f757f3fSDimitry Andric "{\n"
234006c3fb27SDimitry Andric << " llvm_unreachable(\"" + getClassName() +
234106c3fb27SDimitry Andric " does not support custom C++ actions!\");\n"
234206c3fb27SDimitry Andric << "}\n";
23430b57cec5SDimitry Andric }
23440b57cec5SDimitry Andric
postProcessRule(RuleMatcher & M)23455f757f3fSDimitry Andric void GlobalISelEmitter::postProcessRule(RuleMatcher &M) {
23465f757f3fSDimitry Andric SmallPtrSet<Record *, 16> UsedRegs;
23475f757f3fSDimitry Andric
23485f757f3fSDimitry Andric // TODO: deal with subregs?
23495f757f3fSDimitry Andric for (auto &A : M.actions()) {
23505f757f3fSDimitry Andric auto *MI = dyn_cast<BuildMIAction>(A.get());
23515f757f3fSDimitry Andric if (!MI)
23525f757f3fSDimitry Andric continue;
23535f757f3fSDimitry Andric
23545f757f3fSDimitry Andric for (auto *Use : MI->getCGI()->ImplicitUses)
23555f757f3fSDimitry Andric UsedRegs.insert(Use);
23565f757f3fSDimitry Andric }
23575f757f3fSDimitry Andric
23585f757f3fSDimitry Andric for (auto &A : M.actions()) {
23595f757f3fSDimitry Andric auto *MI = dyn_cast<BuildMIAction>(A.get());
23605f757f3fSDimitry Andric if (!MI)
23615f757f3fSDimitry Andric continue;
23625f757f3fSDimitry Andric
23635f757f3fSDimitry Andric for (auto *Def : MI->getCGI()->ImplicitDefs) {
23645f757f3fSDimitry Andric if (!UsedRegs.contains(Def))
23655f757f3fSDimitry Andric MI->setDeadImplicitDef(Def);
23665f757f3fSDimitry Andric }
23675f757f3fSDimitry Andric }
23685f757f3fSDimitry Andric }
23695f757f3fSDimitry Andric
run(raw_ostream & OS)23700b57cec5SDimitry Andric void GlobalISelEmitter::run(raw_ostream &OS) {
23710b57cec5SDimitry Andric if (!UseCoverageFile.empty()) {
23720b57cec5SDimitry Andric RuleCoverage = CodeGenCoverage();
23730b57cec5SDimitry Andric auto RuleCoverageBufOrErr = MemoryBuffer::getFile(UseCoverageFile);
23740b57cec5SDimitry Andric if (!RuleCoverageBufOrErr) {
23750b57cec5SDimitry Andric PrintWarning(SMLoc(), "Missing rule coverage data");
2376bdd1243dSDimitry Andric RuleCoverage = std::nullopt;
23770b57cec5SDimitry Andric } else {
23780b57cec5SDimitry Andric if (!RuleCoverage->parse(*RuleCoverageBufOrErr.get(), Target.getName())) {
23790b57cec5SDimitry Andric PrintWarning(SMLoc(), "Ignoring invalid or missing rule coverage data");
2380bdd1243dSDimitry Andric RuleCoverage = std::nullopt;
23810b57cec5SDimitry Andric }
23820b57cec5SDimitry Andric }
23830b57cec5SDimitry Andric }
23840b57cec5SDimitry Andric
23850b57cec5SDimitry Andric // Track the run-time opcode values
23860b57cec5SDimitry Andric gatherOpcodeValues();
23870b57cec5SDimitry Andric // Track the run-time LLT ID values
23880b57cec5SDimitry Andric gatherTypeIDValues();
23890b57cec5SDimitry Andric
23900b57cec5SDimitry Andric // Track the GINodeEquiv definitions.
23910b57cec5SDimitry Andric gatherNodeEquivs();
23920b57cec5SDimitry Andric
239306c3fb27SDimitry Andric AllPatFrags = RK.getAllDerivedDefinitions("PatFrags");
239406c3fb27SDimitry Andric
239506c3fb27SDimitry Andric emitSourceFileHeader(
239606c3fb27SDimitry Andric ("Global Instruction Selector for the " + Target.getName() + " target")
239706c3fb27SDimitry Andric .str(),
239806c3fb27SDimitry Andric OS);
23990b57cec5SDimitry Andric std::vector<RuleMatcher> Rules;
24000b57cec5SDimitry Andric // Look through the SelectionDAG patterns we found, possibly emitting some.
24010b57cec5SDimitry Andric for (const PatternToMatch &Pat : CGP.ptms()) {
24020b57cec5SDimitry Andric ++NumPatternTotal;
24030b57cec5SDimitry Andric
24040b57cec5SDimitry Andric auto MatcherOrErr = runOnPattern(Pat);
24050b57cec5SDimitry Andric
24060b57cec5SDimitry Andric // The pattern analysis can fail, indicating an unsupported pattern.
24070b57cec5SDimitry Andric // Report that if we've been asked to do so.
24080b57cec5SDimitry Andric if (auto Err = MatcherOrErr.takeError()) {
24090b57cec5SDimitry Andric if (WarnOnSkippedPatterns) {
24100b57cec5SDimitry Andric PrintWarning(Pat.getSrcRecord()->getLoc(),
24110b57cec5SDimitry Andric "Skipped pattern: " + toString(std::move(Err)));
24120b57cec5SDimitry Andric } else {
24130b57cec5SDimitry Andric consumeError(std::move(Err));
24140b57cec5SDimitry Andric }
24150b57cec5SDimitry Andric ++NumPatternImportsSkipped;
24160b57cec5SDimitry Andric continue;
24170b57cec5SDimitry Andric }
24180b57cec5SDimitry Andric
24190b57cec5SDimitry Andric if (RuleCoverage) {
24200b57cec5SDimitry Andric if (RuleCoverage->isCovered(MatcherOrErr->getRuleID()))
24210b57cec5SDimitry Andric ++NumPatternsTested;
24220b57cec5SDimitry Andric else
24230b57cec5SDimitry Andric PrintWarning(Pat.getSrcRecord()->getLoc(),
24240b57cec5SDimitry Andric "Pattern is not covered by a test");
24250b57cec5SDimitry Andric }
24260b57cec5SDimitry Andric Rules.push_back(std::move(MatcherOrErr.get()));
24275f757f3fSDimitry Andric postProcessRule(Rules.back());
24280b57cec5SDimitry Andric }
24290b57cec5SDimitry Andric
24300b57cec5SDimitry Andric // Comparison function to order records by name.
24310b57cec5SDimitry Andric auto orderByName = [](const Record *A, const Record *B) {
24320b57cec5SDimitry Andric return A->getName() < B->getName();
24330b57cec5SDimitry Andric };
24340b57cec5SDimitry Andric
24350b57cec5SDimitry Andric std::vector<Record *> ComplexPredicates =
24360b57cec5SDimitry Andric RK.getAllDerivedDefinitions("GIComplexOperandMatcher");
24370b57cec5SDimitry Andric llvm::sort(ComplexPredicates, orderByName);
24380b57cec5SDimitry Andric
2439fe6060f1SDimitry Andric std::vector<StringRef> CustomRendererFns;
2440fe6060f1SDimitry Andric transform(RK.getAllDerivedDefinitions("GICustomOperandRenderer"),
2441fe6060f1SDimitry Andric std::back_inserter(CustomRendererFns), [](const auto &Record) {
2442fe6060f1SDimitry Andric return Record->getValueAsString("RendererFn");
2443fe6060f1SDimitry Andric });
2444fe6060f1SDimitry Andric // Sort and remove duplicates to get a list of unique renderer functions, in
2445fe6060f1SDimitry Andric // case some were mentioned more than once.
2446fe6060f1SDimitry Andric llvm::sort(CustomRendererFns);
2447fe6060f1SDimitry Andric CustomRendererFns.erase(
2448fe6060f1SDimitry Andric std::unique(CustomRendererFns.begin(), CustomRendererFns.end()),
2449fe6060f1SDimitry Andric CustomRendererFns.end());
24500b57cec5SDimitry Andric
245106c3fb27SDimitry Andric // Create a table containing the LLT objects needed by the matcher and an enum
24520b57cec5SDimitry Andric // for the matcher to reference them with.
24530b57cec5SDimitry Andric std::vector<LLTCodeGen> TypeObjects;
2454e8d8bef9SDimitry Andric append_range(TypeObjects, KnownTypes);
24550b57cec5SDimitry Andric llvm::sort(TypeObjects);
24560b57cec5SDimitry Andric
245706c3fb27SDimitry Andric // Sort rules.
24580b57cec5SDimitry Andric llvm::stable_sort(Rules, [&](const RuleMatcher &A, const RuleMatcher &B) {
24590b57cec5SDimitry Andric int ScoreA = RuleMatcherScores[A.getRuleID()];
24600b57cec5SDimitry Andric int ScoreB = RuleMatcherScores[B.getRuleID()];
24610b57cec5SDimitry Andric if (ScoreA > ScoreB)
24620b57cec5SDimitry Andric return true;
24630b57cec5SDimitry Andric if (ScoreB > ScoreA)
24640b57cec5SDimitry Andric return false;
24650b57cec5SDimitry Andric if (A.isHigherPriorityThan(B)) {
24660b57cec5SDimitry Andric assert(!B.isHigherPriorityThan(A) && "Cannot be more important "
24670b57cec5SDimitry Andric "and less important at "
24680b57cec5SDimitry Andric "the same time");
24690b57cec5SDimitry Andric return true;
24700b57cec5SDimitry Andric }
24710b57cec5SDimitry Andric return false;
24720b57cec5SDimitry Andric });
24730b57cec5SDimitry Andric
247406c3fb27SDimitry Andric unsigned MaxTemporaries = 0;
247506c3fb27SDimitry Andric for (const auto &Rule : Rules)
247606c3fb27SDimitry Andric MaxTemporaries = std::max(MaxTemporaries, Rule.countRendererFns());
24770b57cec5SDimitry Andric
247806c3fb27SDimitry Andric // Build match table
24790b57cec5SDimitry Andric const MatchTable Table =
24800b57cec5SDimitry Andric buildMatchTable(Rules, OptimizeMatchTable, GenerateCoverage);
24810b57cec5SDimitry Andric
248206c3fb27SDimitry Andric emitPredicateBitset(OS, "GET_GLOBALISEL_PREDICATE_BITSET");
248306c3fb27SDimitry Andric emitTemporariesDecl(OS, "GET_GLOBALISEL_TEMPORARIES_DECL");
248406c3fb27SDimitry Andric emitTemporariesInit(OS, MaxTemporaries, "GET_GLOBALISEL_TEMPORARIES_INIT");
248506c3fb27SDimitry Andric emitExecutorImpl(OS, Table, TypeObjects, Rules, ComplexPredicates,
248606c3fb27SDimitry Andric CustomRendererFns, "GET_GLOBALISEL_IMPL");
248706c3fb27SDimitry Andric emitPredicatesDecl(OS, "GET_GLOBALISEL_PREDICATES_DECL");
248806c3fb27SDimitry Andric emitPredicatesInit(OS, "GET_GLOBALISEL_PREDICATES_INIT");
24890b57cec5SDimitry Andric }
24900b57cec5SDimitry Andric
declareSubtargetFeature(Record * Predicate)24910b57cec5SDimitry Andric void GlobalISelEmitter::declareSubtargetFeature(Record *Predicate) {
24925f757f3fSDimitry Andric SubtargetFeatures.try_emplace(Predicate, Predicate, SubtargetFeatures.size());
24935f757f3fSDimitry Andric }
24945f757f3fSDimitry Andric
declareHwModeCheck(StringRef HwModeFeatures)24955f757f3fSDimitry Andric unsigned GlobalISelEmitter::declareHwModeCheck(StringRef HwModeFeatures) {
24965f757f3fSDimitry Andric return HwModes.emplace(HwModeFeatures.str(), HwModes.size()).first->second;
24970b57cec5SDimitry Andric }
24980b57cec5SDimitry Andric
24990b57cec5SDimitry Andric } // end anonymous namespace
25000b57cec5SDimitry Andric
25010b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
25020b57cec5SDimitry Andric
250306c3fb27SDimitry Andric static TableGen::Emitter::OptClass<GlobalISelEmitter>
250406c3fb27SDimitry Andric X("gen-global-isel", "Generate GlobalISel selector");
2505