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