Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h
35313 views
//===- GlobalISelMatchTable.h ---------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8/// \file9/// This file contains the code related to the GlobalISel Match Table emitted by10/// GlobalISelEmitter.cpp. The generated match table is interpreted at runtime11/// by `GIMatchTableExecutorImpl.h` to match & apply ISel patterns.12///13//===----------------------------------------------------------------------===//1415#ifndef LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLE_H16#define LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLE_H1718#include "Common/CodeGenDAGPatterns.h"19#include "llvm/ADT/ArrayRef.h"20#include "llvm/ADT/DenseMap.h"21#include "llvm/ADT/SmallPtrSet.h"22#include "llvm/ADT/StringMap.h"23#include "llvm/ADT/StringRef.h"24#include "llvm/CodeGenTypes/LowLevelType.h"25#include "llvm/Support/Error.h"26#include "llvm/Support/SaveAndRestore.h"27#include <deque>28#include <list>29#include <map>30#include <memory>31#include <optional>32#include <set>33#include <string>34#include <vector>3536namespace llvm {3738class raw_ostream;39class Record;40class SMLoc;41class CodeGenRegisterClass;4243// Use a namespace to avoid conflicts because there's some fairly generic names44// in there (e.g. Matcher).45namespace gi {46class MatchTable;47class Matcher;48class OperandMatcher;49class MatchAction;50class PredicateMatcher;51class InstructionMatcher;5253enum {54GISF_IgnoreCopies = 0x1,55};5657using GISelFlags = std::uint16_t;5859//===- Helper functions ---------------------------------------------------===//6061void emitEncodingMacrosDef(raw_ostream &OS);62void emitEncodingMacrosUndef(raw_ostream &OS);6364std::string getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset,65int HwModeIdx);6667/// Takes a sequence of \p Rules and group them based on the predicates68/// they share. \p MatcherStorage is used as a memory container69/// for the group that are created as part of this process.70///71/// What this optimization does looks like if GroupT = GroupMatcher:72/// Output without optimization:73/// \verbatim74/// # R175/// # predicate A76/// # predicate B77/// ...78/// # R279/// # predicate A // <-- effectively this is going to be checked twice.80/// // Once in R1 and once in R2.81/// # predicate C82/// \endverbatim83/// Output with optimization:84/// \verbatim85/// # Group1_286/// # predicate A // <-- Check is now shared.87/// # R188/// # predicate B89/// # R290/// # predicate C91/// \endverbatim92template <class GroupT>93std::vector<Matcher *>94optimizeRules(ArrayRef<Matcher *> Rules,95std::vector<std::unique_ptr<Matcher>> &MatcherStorage);9697/// A record to be stored in a MatchTable.98///99/// This class represents any and all output that may be required to emit the100/// MatchTable. Instances are most often configured to represent an opcode or101/// value that will be emitted to the table with some formatting but it can also102/// represent commas, comments, and other formatting instructions.103struct MatchTableRecord {104enum RecordFlagsBits {105MTRF_None = 0x0,106/// Causes EmitStr to be formatted as comment when emitted.107MTRF_Comment = 0x1,108/// Causes the record value to be followed by a comma when emitted.109MTRF_CommaFollows = 0x2,110/// Causes the record value to be followed by a line break when emitted.111MTRF_LineBreakFollows = 0x4,112/// Indicates that the record defines a label and causes an additional113/// comment to be emitted containing the index of the label.114MTRF_Label = 0x8,115/// Causes the record to be emitted as the index of the label specified by116/// LabelID along with a comment indicating where that label is.117MTRF_JumpTarget = 0x10,118/// Causes the formatter to add a level of indentation before emitting the119/// record.120MTRF_Indent = 0x20,121/// Causes the formatter to remove a level of indentation after emitting the122/// record.123MTRF_Outdent = 0x40,124/// Causes the formatter to not use encoding macros to emit this multi-byte125/// value.126MTRF_PreEncoded = 0x80,127};128129/// When MTRF_Label or MTRF_JumpTarget is used, indicates a label id to130/// reference or define.131unsigned LabelID;132/// The string to emit. Depending on the MTRF_* flags it may be a comment, a133/// value, a label name.134std::string EmitStr;135136private:137/// The number of MatchTable elements described by this record. Comments are 0138/// while values are typically 1. Values >1 may occur when we need to emit139/// values that exceed the size of a MatchTable element.140unsigned NumElements;141142public:143/// A bitfield of RecordFlagsBits flags.144unsigned Flags;145146/// The actual run-time value, if known147int64_t RawValue;148149MatchTableRecord(std::optional<unsigned> LabelID_, StringRef EmitStr,150unsigned NumElements, unsigned Flags,151int64_t RawValue = std::numeric_limits<int64_t>::min())152: LabelID(LabelID_.value_or(~0u)), EmitStr(EmitStr),153NumElements(NumElements), Flags(Flags), RawValue(RawValue) {154assert((!LabelID_ || LabelID != ~0u) &&155"This value is reserved for non-labels");156}157MatchTableRecord(const MatchTableRecord &Other) = default;158MatchTableRecord(MatchTableRecord &&Other) = default;159160/// Useful if a Match Table Record gets optimized out161void turnIntoComment() {162Flags |= MTRF_Comment;163Flags &= ~MTRF_CommaFollows;164NumElements = 0;165}166167/// For Jump Table generation purposes168bool operator<(const MatchTableRecord &Other) const {169return RawValue < Other.RawValue;170}171int64_t getRawValue() const { return RawValue; }172173void emit(raw_ostream &OS, bool LineBreakNextAfterThis,174const MatchTable &Table) const;175unsigned size() const { return NumElements; }176};177178/// Holds the contents of a generated MatchTable to enable formatting and the179/// necessary index tracking needed to support GIM_Try.180class MatchTable {181/// An unique identifier for the table. The generated table will be named182/// MatchTable${ID}.183unsigned ID;184/// The records that make up the table. Also includes comments describing the185/// values being emitted and line breaks to format it.186std::vector<MatchTableRecord> Contents;187/// The currently defined labels.188DenseMap<unsigned, unsigned> LabelMap;189/// Tracks the sum of MatchTableRecord::NumElements as the table is built.190unsigned CurrentSize = 0;191/// A unique identifier for a MatchTable label.192unsigned CurrentLabelID = 0;193/// Determines if the table should be instrumented for rule coverage tracking.194bool IsWithCoverage;195/// Whether this table is for the GISel combiner.196bool IsCombinerTable;197198public:199static MatchTableRecord LineBreak;200static MatchTableRecord Comment(StringRef Comment);201static MatchTableRecord Opcode(StringRef Opcode, int IndentAdjust = 0);202static MatchTableRecord NamedValue(unsigned NumBytes, StringRef NamedValue);203static MatchTableRecord NamedValue(unsigned NumBytes, StringRef NamedValue,204int64_t RawValue);205static MatchTableRecord NamedValue(unsigned NumBytes, StringRef Namespace,206StringRef NamedValue);207static MatchTableRecord NamedValue(unsigned NumBytes, StringRef Namespace,208StringRef NamedValue, int64_t RawValue);209static MatchTableRecord IntValue(unsigned NumBytes, int64_t IntValue);210static MatchTableRecord ULEB128Value(uint64_t IntValue);211static MatchTableRecord Label(unsigned LabelID);212static MatchTableRecord JumpTarget(unsigned LabelID);213214static MatchTable buildTable(ArrayRef<Matcher *> Rules, bool WithCoverage,215bool IsCombiner = false);216217MatchTable(bool WithCoverage, bool IsCombinerTable, unsigned ID = 0)218: ID(ID), IsWithCoverage(WithCoverage), IsCombinerTable(IsCombinerTable) {219}220221bool isWithCoverage() const { return IsWithCoverage; }222bool isCombiner() const { return IsCombinerTable; }223224void push_back(const MatchTableRecord &Value) {225if (Value.Flags & MatchTableRecord::MTRF_Label)226defineLabel(Value.LabelID);227Contents.push_back(Value);228CurrentSize += Value.size();229}230231unsigned allocateLabelID() { return CurrentLabelID++; }232233void defineLabel(unsigned LabelID) {234LabelMap.insert(std::pair(LabelID, CurrentSize));235}236237unsigned getLabelIndex(unsigned LabelID) const {238const auto I = LabelMap.find(LabelID);239assert(I != LabelMap.end() && "Use of undeclared label");240return I->second;241}242243void emitUse(raw_ostream &OS) const;244void emitDeclaration(raw_ostream &OS) const;245};246247inline MatchTable &operator<<(MatchTable &Table,248const MatchTableRecord &Value) {249Table.push_back(Value);250return Table;251}252253/// This class stands in for LLT wherever we want to tablegen-erate an254/// equivalent at compiler run-time.255class LLTCodeGen {256private:257LLT Ty;258259public:260LLTCodeGen() = default;261LLTCodeGen(const LLT &Ty) : Ty(Ty) {}262263std::string getCxxEnumValue() const;264265void emitCxxEnumValue(raw_ostream &OS) const;266void emitCxxConstructorCall(raw_ostream &OS) const;267268const LLT &get() const { return Ty; }269270/// This ordering is used for std::unique() and llvm::sort(). There's no271/// particular logic behind the order but either A < B or B < A must be272/// true if A != B.273bool operator<(const LLTCodeGen &Other) const;274bool operator==(const LLTCodeGen &B) const { return Ty == B.Ty; }275};276277// Track all types that are used so we can emit the corresponding enum.278extern std::set<LLTCodeGen> KnownTypes;279280/// Convert an MVT to an equivalent LLT if possible, or the invalid LLT() for281/// MVTs that don't map cleanly to an LLT (e.g., iPTR, *any, ...).282std::optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT);283284using TempTypeIdx = int64_t;285class LLTCodeGenOrTempType {286public:287LLTCodeGenOrTempType(const LLTCodeGen &LLT) : Data(LLT) {}288LLTCodeGenOrTempType(TempTypeIdx TempTy) : Data(TempTy) {}289290bool isLLTCodeGen() const { return std::holds_alternative<LLTCodeGen>(Data); }291bool isTempTypeIdx() const {292return std::holds_alternative<TempTypeIdx>(Data);293}294295const LLTCodeGen &getLLTCodeGen() const {296assert(isLLTCodeGen());297return std::get<LLTCodeGen>(Data);298}299300TempTypeIdx getTempTypeIdx() const {301assert(isTempTypeIdx());302return std::get<TempTypeIdx>(Data);303}304305private:306std::variant<LLTCodeGen, TempTypeIdx> Data;307};308309inline MatchTable &operator<<(MatchTable &Table,310const LLTCodeGenOrTempType &Ty) {311if (Ty.isLLTCodeGen())312Table << MatchTable::NamedValue(1, Ty.getLLTCodeGen().getCxxEnumValue());313else314Table << MatchTable::IntValue(1, Ty.getTempTypeIdx());315return Table;316}317318//===- Matchers -----------------------------------------------------------===//319class Matcher {320public:321virtual ~Matcher();322virtual void optimize();323virtual void emit(MatchTable &Table) = 0;324325virtual bool hasFirstCondition() const = 0;326virtual const PredicateMatcher &getFirstCondition() const = 0;327virtual std::unique_ptr<PredicateMatcher> popFirstCondition() = 0;328};329330class GroupMatcher final : public Matcher {331/// Conditions that form a common prefix of all the matchers contained.332SmallVector<std::unique_ptr<PredicateMatcher>, 1> Conditions;333334/// All the nested matchers, sharing a common prefix.335std::vector<Matcher *> Matchers;336337/// An owning collection for any auxiliary matchers created while optimizing338/// nested matchers contained.339std::vector<std::unique_ptr<Matcher>> MatcherStorage;340341public:342/// Add a matcher to the collection of nested matchers if it meets the343/// requirements, and return true. If it doesn't, do nothing and return false.344///345/// Expected to preserve its argument, so it could be moved out later on.346bool addMatcher(Matcher &Candidate);347348/// Mark the matcher as fully-built and ensure any invariants expected by both349/// optimize() and emit(...) methods. Generally, both sequences of calls350/// are expected to lead to a sensible result:351///352/// addMatcher(...)*; finalize(); optimize(); emit(...); and353/// addMatcher(...)*; finalize(); emit(...);354///355/// or generally356///357/// addMatcher(...)*; finalize(); { optimize()*; emit(...); }*358///359/// Multiple calls to optimize() are expected to be handled gracefully, though360/// optimize() is not expected to be idempotent. Multiple calls to finalize()361/// aren't generally supported. emit(...) is expected to be non-mutating and362/// producing the exact same results upon repeated calls.363///364/// addMatcher() calls after the finalize() call are not supported.365///366/// finalize() and optimize() are both allowed to mutate the contained367/// matchers, so moving them out after finalize() is not supported.368void finalize();369void optimize() override;370void emit(MatchTable &Table) override;371372/// Could be used to move out the matchers added previously, unless finalize()373/// has been already called. If any of the matchers are moved out, the group374/// becomes safe to destroy, but not safe to re-use for anything else.375iterator_range<std::vector<Matcher *>::iterator> matchers() {376return make_range(Matchers.begin(), Matchers.end());377}378size_t size() const { return Matchers.size(); }379bool empty() const { return Matchers.empty(); }380381std::unique_ptr<PredicateMatcher> popFirstCondition() override {382assert(!Conditions.empty() &&383"Trying to pop a condition from a condition-less group");384std::unique_ptr<PredicateMatcher> P = std::move(Conditions.front());385Conditions.erase(Conditions.begin());386return P;387}388const PredicateMatcher &getFirstCondition() const override {389assert(!Conditions.empty() &&390"Trying to get a condition from a condition-less group");391return *Conditions.front();392}393bool hasFirstCondition() const override { return !Conditions.empty(); }394395private:396/// See if a candidate matcher could be added to this group solely by397/// analyzing its first condition.398bool candidateConditionMatches(const PredicateMatcher &Predicate) const;399};400401class SwitchMatcher : public Matcher {402/// All the nested matchers, representing distinct switch-cases. The first403/// conditions (as Matcher::getFirstCondition() reports) of all the nested404/// matchers must share the same type and path to a value they check, in other405/// words, be isIdenticalDownToValue, but have different values they check406/// against.407std::vector<Matcher *> Matchers;408409/// The representative condition, with a type and a path (InsnVarID and OpIdx410/// in most cases) shared by all the matchers contained.411std::unique_ptr<PredicateMatcher> Condition = nullptr;412413/// Temporary set used to check that the case values don't repeat within the414/// same switch.415std::set<MatchTableRecord> Values;416417/// An owning collection for any auxiliary matchers created while optimizing418/// nested matchers contained.419std::vector<std::unique_ptr<Matcher>> MatcherStorage;420421public:422bool addMatcher(Matcher &Candidate);423424void finalize();425void emit(MatchTable &Table) override;426427iterator_range<std::vector<Matcher *>::iterator> matchers() {428return make_range(Matchers.begin(), Matchers.end());429}430size_t size() const { return Matchers.size(); }431bool empty() const { return Matchers.empty(); }432433std::unique_ptr<PredicateMatcher> popFirstCondition() override {434// SwitchMatcher doesn't have a common first condition for its cases, as all435// the cases only share a kind of a value (a type and a path to it) they436// match, but deliberately differ in the actual value they match.437llvm_unreachable("Trying to pop a condition from a condition-less group");438}439440const PredicateMatcher &getFirstCondition() const override {441llvm_unreachable("Trying to pop a condition from a condition-less group");442}443444bool hasFirstCondition() const override { return false; }445446private:447/// See if the predicate type has a Switch-implementation for it.448static bool isSupportedPredicateType(const PredicateMatcher &Predicate);449450bool candidateConditionMatches(const PredicateMatcher &Predicate) const;451452/// emit()-helper453static void emitPredicateSpecificOpcodes(const PredicateMatcher &P,454MatchTable &Table);455};456457/// Generates code to check that a match rule matches.458class RuleMatcher : public Matcher {459public:460using ActionList = std::list<std::unique_ptr<MatchAction>>;461using action_iterator = ActionList::iterator;462463protected:464/// A list of matchers that all need to succeed for the current rule to match.465/// FIXME: This currently supports a single match position but could be466/// extended to support multiple positions to support div/rem fusion or467/// load-multiple instructions.468using MatchersTy = std::vector<std::unique_ptr<InstructionMatcher>>;469MatchersTy Matchers;470471/// A list of actions that need to be taken when all predicates in this rule472/// have succeeded.473ActionList Actions;474475/// Combiners can sometimes just run C++ code to finish matching a rule &476/// mutate instructions instead of relying on MatchActions. Empty if unused.477std::string CustomCXXAction;478479using DefinedInsnVariablesMap = std::map<InstructionMatcher *, unsigned>;480481/// A map of instruction matchers to the local variables482DefinedInsnVariablesMap InsnVariableIDs;483484using MutatableInsnSet = SmallPtrSet<InstructionMatcher *, 4>;485486// The set of instruction matchers that have not yet been claimed for mutation487// by a BuildMI.488MutatableInsnSet MutatableInsns;489490/// A map of named operands defined by the matchers that may be referenced by491/// the renderers.492StringMap<OperandMatcher *> DefinedOperands;493494/// A map of anonymous physical register operands defined by the matchers that495/// may be referenced by the renderers.496DenseMap<Record *, OperandMatcher *> PhysRegOperands;497498/// ID for the next instruction variable defined with499/// implicitlyDefineInsnVar()500unsigned NextInsnVarID;501502/// ID for the next output instruction allocated with allocateOutputInsnID()503unsigned NextOutputInsnID;504505/// ID for the next temporary register ID allocated with allocateTempRegID()506unsigned NextTempRegID;507508/// ID for the next recorded type. Starts at -1 and counts down.509TempTypeIdx NextTempTypeIdx = -1;510511// HwMode predicate index for this rule. -1 if no HwMode.512int HwModeIdx = -1;513514/// Current GISelFlags515GISelFlags Flags = 0;516517std::vector<std::string> RequiredSimplePredicates;518std::vector<Record *> RequiredFeatures;519std::vector<std::unique_ptr<PredicateMatcher>> EpilogueMatchers;520521DenseSet<unsigned> ErasedInsnIDs;522523ArrayRef<SMLoc> SrcLoc;524525typedef std::tuple<Record *, unsigned, unsigned>526DefinedComplexPatternSubOperand;527typedef StringMap<DefinedComplexPatternSubOperand>528DefinedComplexPatternSubOperandMap;529/// A map of Symbolic Names to ComplexPattern sub-operands.530DefinedComplexPatternSubOperandMap ComplexSubOperands;531/// A map used to for multiple referenced error check of ComplexSubOperand.532/// ComplexSubOperand can't be referenced multiple from different operands,533/// however multiple references from same operand are allowed since that is534/// how 'same operand checks' are generated.535StringMap<std::string> ComplexSubOperandsParentName;536537uint64_t RuleID;538static uint64_t NextRuleID;539540GISelFlags updateGISelFlag(GISelFlags CurFlags, const Record *R,541StringRef FlagName, GISelFlags FlagBit);542543public:544RuleMatcher(ArrayRef<SMLoc> SrcLoc)545: NextInsnVarID(0), NextOutputInsnID(0), NextTempRegID(0), SrcLoc(SrcLoc),546RuleID(NextRuleID++) {}547RuleMatcher(RuleMatcher &&Other) = default;548RuleMatcher &operator=(RuleMatcher &&Other) = default;549550TempTypeIdx getNextTempTypeIdx() { return NextTempTypeIdx--; }551552uint64_t getRuleID() const { return RuleID; }553554InstructionMatcher &addInstructionMatcher(StringRef SymbolicName);555void addRequiredFeature(Record *Feature);556const std::vector<Record *> &getRequiredFeatures() const;557558void addHwModeIdx(unsigned Idx) { HwModeIdx = Idx; }559int getHwModeIdx() const { return HwModeIdx; }560561void addRequiredSimplePredicate(StringRef PredName);562const std::vector<std::string> &getRequiredSimplePredicates();563564/// Attempts to mark \p ID as erased (GIR_EraseFromParent called on it).565/// If \p ID has already been erased, returns false and GIR_EraseFromParent566/// should NOT be emitted.567bool tryEraseInsnID(unsigned ID) { return ErasedInsnIDs.insert(ID).second; }568569void setCustomCXXAction(StringRef FnEnumName) {570CustomCXXAction = FnEnumName.str();571}572573// Emplaces an action of the specified Kind at the end of the action list.574//575// Returns a reference to the newly created action.576//577// Like std::vector::emplace_back(), may invalidate all iterators if the new578// size exceeds the capacity. Otherwise, only invalidates the past-the-end579// iterator.580template <class Kind, class... Args> Kind &addAction(Args &&...args) {581Actions.emplace_back(std::make_unique<Kind>(std::forward<Args>(args)...));582return *static_cast<Kind *>(Actions.back().get());583}584585// Emplaces an action of the specified Kind before the given insertion point.586//587// Returns an iterator pointing at the newly created instruction.588//589// Like std::vector::insert(), may invalidate all iterators if the new size590// exceeds the capacity. Otherwise, only invalidates the iterators from the591// insertion point onwards.592template <class Kind, class... Args>593action_iterator insertAction(action_iterator InsertPt, Args &&...args) {594return Actions.emplace(InsertPt,595std::make_unique<Kind>(std::forward<Args>(args)...));596}597598void setPermanentGISelFlags(GISelFlags V) { Flags = V; }599600// Update the active GISelFlags based on the GISelFlags Record R.601// A SaveAndRestore object is returned so the old GISelFlags are restored602// at the end of the scope.603SaveAndRestore<GISelFlags> setGISelFlags(const Record *R);604GISelFlags getGISelFlags() const { return Flags; }605606/// Define an instruction without emitting any code to do so.607unsigned implicitlyDefineInsnVar(InstructionMatcher &Matcher);608609unsigned getInsnVarID(InstructionMatcher &InsnMatcher) const;610DefinedInsnVariablesMap::const_iterator defined_insn_vars_begin() const {611return InsnVariableIDs.begin();612}613DefinedInsnVariablesMap::const_iterator defined_insn_vars_end() const {614return InsnVariableIDs.end();615}616iterator_range<typename DefinedInsnVariablesMap::const_iterator>617defined_insn_vars() const {618return make_range(defined_insn_vars_begin(), defined_insn_vars_end());619}620621MutatableInsnSet::const_iterator mutatable_insns_begin() const {622return MutatableInsns.begin();623}624MutatableInsnSet::const_iterator mutatable_insns_end() const {625return MutatableInsns.end();626}627iterator_range<typename MutatableInsnSet::const_iterator>628mutatable_insns() const {629return make_range(mutatable_insns_begin(), mutatable_insns_end());630}631void reserveInsnMatcherForMutation(InstructionMatcher *InsnMatcher) {632bool R = MutatableInsns.erase(InsnMatcher);633assert(R && "Reserving a mutatable insn that isn't available");634(void)R;635}636637action_iterator actions_begin() { return Actions.begin(); }638action_iterator actions_end() { return Actions.end(); }639iterator_range<action_iterator> actions() {640return make_range(actions_begin(), actions_end());641}642643void defineOperand(StringRef SymbolicName, OperandMatcher &OM);644645void definePhysRegOperand(Record *Reg, OperandMatcher &OM);646647Error defineComplexSubOperand(StringRef SymbolicName, Record *ComplexPattern,648unsigned RendererID, unsigned SubOperandID,649StringRef ParentSymbolicName);650651std::optional<DefinedComplexPatternSubOperand>652getComplexSubOperand(StringRef SymbolicName) const {653const auto &I = ComplexSubOperands.find(SymbolicName);654if (I == ComplexSubOperands.end())655return std::nullopt;656return I->second;657}658659InstructionMatcher &getInstructionMatcher(StringRef SymbolicName) const;660OperandMatcher &getOperandMatcher(StringRef Name);661const OperandMatcher &getOperandMatcher(StringRef Name) const;662const OperandMatcher &getPhysRegOperandMatcher(Record *) const;663664void optimize() override;665void emit(MatchTable &Table) override;666667/// Compare the priority of this object and B.668///669/// Returns true if this object is more important than B.670bool isHigherPriorityThan(const RuleMatcher &B) const;671672/// Report the maximum number of temporary operands needed by the rule673/// matcher.674unsigned countRendererFns() const;675676std::unique_ptr<PredicateMatcher> popFirstCondition() override;677const PredicateMatcher &getFirstCondition() const override;678LLTCodeGen getFirstConditionAsRootType();679bool hasFirstCondition() const override;680unsigned getNumOperands() const;681StringRef getOpcode() const;682683// FIXME: Remove this as soon as possible684InstructionMatcher &insnmatchers_front() const { return *Matchers.front(); }685686unsigned allocateOutputInsnID() { return NextOutputInsnID++; }687unsigned allocateTempRegID() { return NextTempRegID++; }688689iterator_range<MatchersTy::iterator> insnmatchers() {690return make_range(Matchers.begin(), Matchers.end());691}692bool insnmatchers_empty() const { return Matchers.empty(); }693void insnmatchers_pop_front() { Matchers.erase(Matchers.begin()); }694};695696template <class PredicateTy> class PredicateListMatcher {697private:698/// Template instantiations should specialize this to return a string to use699/// for the comment emitted when there are no predicates.700std::string getNoPredicateComment() const;701702protected:703using PredicatesTy = std::deque<std::unique_ptr<PredicateTy>>;704PredicatesTy Predicates;705706/// Track if the list of predicates was manipulated by one of the optimization707/// methods.708bool Optimized = false;709710public:711typename PredicatesTy::iterator predicates_begin() {712return Predicates.begin();713}714typename PredicatesTy::iterator predicates_end() { return Predicates.end(); }715iterator_range<typename PredicatesTy::iterator> predicates() {716return make_range(predicates_begin(), predicates_end());717}718typename PredicatesTy::size_type predicates_size() const {719return Predicates.size();720}721bool predicates_empty() const { return Predicates.empty(); }722723template <typename Ty> bool contains() const {724return any_of(Predicates, [&](auto &P) { return isa<Ty>(P.get()); });725}726727std::unique_ptr<PredicateTy> predicates_pop_front() {728std::unique_ptr<PredicateTy> Front = std::move(Predicates.front());729Predicates.pop_front();730Optimized = true;731return Front;732}733734void prependPredicate(std::unique_ptr<PredicateTy> &&Predicate) {735Predicates.push_front(std::move(Predicate));736}737738void eraseNullPredicates() {739const auto NewEnd =740std::stable_partition(Predicates.begin(), Predicates.end(),741std::logical_not<std::unique_ptr<PredicateTy>>());742if (NewEnd != Predicates.begin()) {743Predicates.erase(Predicates.begin(), NewEnd);744Optimized = true;745}746}747748/// Emit MatchTable opcodes that tests whether all the predicates are met.749template <class... Args>750void emitPredicateListOpcodes(MatchTable &Table, Args &&...args) {751if (Predicates.empty() && !Optimized) {752Table << MatchTable::Comment(getNoPredicateComment())753<< MatchTable::LineBreak;754return;755}756757for (const auto &Predicate : predicates())758Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...);759}760761/// Provide a function to avoid emitting certain predicates. This is used to762/// defer some predicate checks until after others763using PredicateFilterFunc = std::function<bool(const PredicateTy &)>;764765/// Emit MatchTable opcodes for predicates which satisfy \p766/// ShouldEmitPredicate. This should be called multiple times to ensure all767/// predicates are eventually added to the match table.768template <class... Args>769void emitFilteredPredicateListOpcodes(PredicateFilterFunc ShouldEmitPredicate,770MatchTable &Table, Args &&...args) {771if (Predicates.empty() && !Optimized) {772Table << MatchTable::Comment(getNoPredicateComment())773<< MatchTable::LineBreak;774return;775}776777for (const auto &Predicate : predicates()) {778if (ShouldEmitPredicate(*Predicate))779Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...);780}781}782};783784class PredicateMatcher {785public:786/// This enum is used for RTTI and also defines the priority that is given to787/// the predicate when generating the matcher code. Kinds with higher priority788/// must be tested first.789///790/// The relative priority of OPM_LLT, OPM_RegBank, and OPM_MBB do not matter791/// but OPM_Int must have priority over OPM_RegBank since constant integers792/// are represented by a virtual register defined by a G_CONSTANT instruction.793///794/// Note: The relative priority between IPM_ and OPM_ does not matter, they795/// are currently not compared between each other.796enum PredicateKind {797IPM_Opcode,798IPM_NumOperands,799IPM_ImmPredicate,800IPM_Imm,801IPM_AtomicOrderingMMO,802IPM_MemoryLLTSize,803IPM_MemoryVsLLTSize,804IPM_MemoryAddressSpace,805IPM_MemoryAlignment,806IPM_VectorSplatImm,807IPM_NoUse,808IPM_OneUse,809IPM_GenericPredicate,810IPM_MIFlags,811OPM_SameOperand,812OPM_ComplexPattern,813OPM_IntrinsicID,814OPM_CmpPredicate,815OPM_Instruction,816OPM_Int,817OPM_LiteralInt,818OPM_LLT,819OPM_PointerToAny,820OPM_RegBank,821OPM_MBB,822OPM_RecordNamedOperand,823OPM_RecordRegType,824};825826protected:827PredicateKind Kind;828unsigned InsnVarID;829unsigned OpIdx;830831public:832PredicateMatcher(PredicateKind Kind, unsigned InsnVarID, unsigned OpIdx = ~0)833: Kind(Kind), InsnVarID(InsnVarID), OpIdx(OpIdx) {}834virtual ~PredicateMatcher();835836unsigned getInsnVarID() const { return InsnVarID; }837unsigned getOpIdx() const { return OpIdx; }838839/// Emit MatchTable opcodes that check the predicate for the given operand.840virtual void emitPredicateOpcodes(MatchTable &Table,841RuleMatcher &Rule) const = 0;842843PredicateKind getKind() const { return Kind; }844845bool dependsOnOperands() const {846// Custom predicates really depend on the context pattern of the847// instruction, not just the individual instruction. This therefore848// implicitly depends on all other pattern constraints.849return Kind == IPM_GenericPredicate;850}851852virtual bool isIdentical(const PredicateMatcher &B) const {853return B.getKind() == getKind() && InsnVarID == B.InsnVarID &&854OpIdx == B.OpIdx;855}856857virtual bool isIdenticalDownToValue(const PredicateMatcher &B) const {858return hasValue() && PredicateMatcher::isIdentical(B);859}860861virtual MatchTableRecord getValue() const {862assert(hasValue() && "Can not get a value of a value-less predicate!");863llvm_unreachable("Not implemented yet");864}865virtual bool hasValue() const { return false; }866867/// Report the maximum number of temporary operands needed by the predicate868/// matcher.869virtual unsigned countRendererFns() const { return 0; }870};871872/// Generates code to check a predicate of an operand.873///874/// Typical predicates include:875/// * Operand is a particular register.876/// * Operand is assigned a particular register bank.877/// * Operand is an MBB.878class OperandPredicateMatcher : public PredicateMatcher {879public:880OperandPredicateMatcher(PredicateKind Kind, unsigned InsnVarID,881unsigned OpIdx)882: PredicateMatcher(Kind, InsnVarID, OpIdx) {}883virtual ~OperandPredicateMatcher();884885/// Compare the priority of this object and B.886///887/// Returns true if this object is more important than B.888virtual bool isHigherPriorityThan(const OperandPredicateMatcher &B) const;889};890891template <>892inline std::string893PredicateListMatcher<OperandPredicateMatcher>::getNoPredicateComment() const {894return "No operand predicates";895}896897/// Generates code to check that a register operand is defined by the same exact898/// one as another.899class SameOperandMatcher : public OperandPredicateMatcher {900std::string MatchingName;901unsigned OrigOpIdx;902903GISelFlags Flags;904905public:906SameOperandMatcher(unsigned InsnVarID, unsigned OpIdx, StringRef MatchingName,907unsigned OrigOpIdx, GISelFlags Flags)908: OperandPredicateMatcher(OPM_SameOperand, InsnVarID, OpIdx),909MatchingName(MatchingName), OrigOpIdx(OrigOpIdx), Flags(Flags) {}910911static bool classof(const PredicateMatcher *P) {912return P->getKind() == OPM_SameOperand;913}914915void emitPredicateOpcodes(MatchTable &Table,916RuleMatcher &Rule) const override;917918bool isIdentical(const PredicateMatcher &B) const override {919return OperandPredicateMatcher::isIdentical(B) &&920OrigOpIdx == cast<SameOperandMatcher>(&B)->OrigOpIdx &&921MatchingName == cast<SameOperandMatcher>(&B)->MatchingName;922}923};924925/// Generates code to check that an operand is a particular LLT.926class LLTOperandMatcher : public OperandPredicateMatcher {927protected:928LLTCodeGen Ty;929930public:931static std::map<LLTCodeGen, unsigned> TypeIDValues;932933static void initTypeIDValuesMap() {934TypeIDValues.clear();935936unsigned ID = 0;937for (const LLTCodeGen &LLTy : KnownTypes)938TypeIDValues[LLTy] = ID++;939}940941LLTOperandMatcher(unsigned InsnVarID, unsigned OpIdx, const LLTCodeGen &Ty)942: OperandPredicateMatcher(OPM_LLT, InsnVarID, OpIdx), Ty(Ty) {943KnownTypes.insert(Ty);944}945946static bool classof(const PredicateMatcher *P) {947return P->getKind() == OPM_LLT;948}949950bool isIdentical(const PredicateMatcher &B) const override {951return OperandPredicateMatcher::isIdentical(B) &&952Ty == cast<LLTOperandMatcher>(&B)->Ty;953}954955MatchTableRecord getValue() const override;956bool hasValue() const override;957958LLTCodeGen getTy() const { return Ty; }959960void emitPredicateOpcodes(MatchTable &Table,961RuleMatcher &Rule) const override;962};963964/// Generates code to check that an operand is a pointer to any address space.965///966/// In SelectionDAG, the types did not describe pointers or address spaces. As a967/// result, iN is used to describe a pointer of N bits to any address space and968/// PatFrag predicates are typically used to constrain the address space.969/// There's no reliable means to derive the missing type information from the970/// pattern so imported rules must test the components of a pointer separately.971///972/// If SizeInBits is zero, then the pointer size will be obtained from the973/// subtarget.974class PointerToAnyOperandMatcher : public OperandPredicateMatcher {975protected:976unsigned SizeInBits;977978public:979PointerToAnyOperandMatcher(unsigned InsnVarID, unsigned OpIdx,980unsigned SizeInBits)981: OperandPredicateMatcher(OPM_PointerToAny, InsnVarID, OpIdx),982SizeInBits(SizeInBits) {}983984static bool classof(const PredicateMatcher *P) {985return P->getKind() == OPM_PointerToAny;986}987988bool isIdentical(const PredicateMatcher &B) const override {989return OperandPredicateMatcher::isIdentical(B) &&990SizeInBits == cast<PointerToAnyOperandMatcher>(&B)->SizeInBits;991}992993void emitPredicateOpcodes(MatchTable &Table,994RuleMatcher &Rule) const override;995};996997/// Generates code to record named operand in RecordedOperands list at StoreIdx.998/// Predicates with 'let PredicateCodeUsesOperands = 1' get RecordedOperands as999/// an argument to predicate's c++ code once all operands have been matched.1000class RecordNamedOperandMatcher : public OperandPredicateMatcher {1001protected:1002unsigned StoreIdx;1003std::string Name;10041005public:1006RecordNamedOperandMatcher(unsigned InsnVarID, unsigned OpIdx,1007unsigned StoreIdx, StringRef Name)1008: OperandPredicateMatcher(OPM_RecordNamedOperand, InsnVarID, OpIdx),1009StoreIdx(StoreIdx), Name(Name) {}10101011static bool classof(const PredicateMatcher *P) {1012return P->getKind() == OPM_RecordNamedOperand;1013}10141015bool isIdentical(const PredicateMatcher &B) const override {1016return OperandPredicateMatcher::isIdentical(B) &&1017StoreIdx == cast<RecordNamedOperandMatcher>(&B)->StoreIdx &&1018Name == cast<RecordNamedOperandMatcher>(&B)->Name;1019}10201021void emitPredicateOpcodes(MatchTable &Table,1022RuleMatcher &Rule) const override;1023};10241025/// Generates code to store a register operand's type into the set of temporary1026/// LLTs.1027class RecordRegisterType : public OperandPredicateMatcher {1028protected:1029TempTypeIdx Idx;10301031public:1032RecordRegisterType(unsigned InsnVarID, unsigned OpIdx, TempTypeIdx Idx)1033: OperandPredicateMatcher(OPM_RecordRegType, InsnVarID, OpIdx), Idx(Idx) {1034}10351036static bool classof(const PredicateMatcher *P) {1037return P->getKind() == OPM_RecordRegType;1038}10391040bool isIdentical(const PredicateMatcher &B) const override {1041return OperandPredicateMatcher::isIdentical(B) &&1042Idx == cast<RecordRegisterType>(&B)->Idx;1043}10441045void emitPredicateOpcodes(MatchTable &Table,1046RuleMatcher &Rule) const override;1047};10481049/// Generates code to check that an operand is a particular target constant.1050class ComplexPatternOperandMatcher : public OperandPredicateMatcher {1051protected:1052const OperandMatcher &Operand;1053const Record &TheDef;10541055unsigned getAllocatedTemporariesBaseID() const;10561057public:1058bool isIdentical(const PredicateMatcher &B) const override { return false; }10591060ComplexPatternOperandMatcher(unsigned InsnVarID, unsigned OpIdx,1061const OperandMatcher &Operand,1062const Record &TheDef)1063: OperandPredicateMatcher(OPM_ComplexPattern, InsnVarID, OpIdx),1064Operand(Operand), TheDef(TheDef) {}10651066static bool classof(const PredicateMatcher *P) {1067return P->getKind() == OPM_ComplexPattern;1068}10691070void emitPredicateOpcodes(MatchTable &Table,1071RuleMatcher &Rule) const override;1072unsigned countRendererFns() const override { return 1; }1073};10741075/// Generates code to check that an operand is in a particular register bank.1076class RegisterBankOperandMatcher : public OperandPredicateMatcher {1077protected:1078const CodeGenRegisterClass &RC;10791080public:1081RegisterBankOperandMatcher(unsigned InsnVarID, unsigned OpIdx,1082const CodeGenRegisterClass &RC)1083: OperandPredicateMatcher(OPM_RegBank, InsnVarID, OpIdx), RC(RC) {}10841085bool isIdentical(const PredicateMatcher &B) const override;10861087static bool classof(const PredicateMatcher *P) {1088return P->getKind() == OPM_RegBank;1089}10901091void emitPredicateOpcodes(MatchTable &Table,1092RuleMatcher &Rule) const override;1093};10941095/// Generates code to check that an operand is a basic block.1096class MBBOperandMatcher : public OperandPredicateMatcher {1097public:1098MBBOperandMatcher(unsigned InsnVarID, unsigned OpIdx)1099: OperandPredicateMatcher(OPM_MBB, InsnVarID, OpIdx) {}11001101static bool classof(const PredicateMatcher *P) {1102return P->getKind() == OPM_MBB;1103}11041105void emitPredicateOpcodes(MatchTable &Table,1106RuleMatcher &Rule) const override;1107};11081109class ImmOperandMatcher : public OperandPredicateMatcher {1110public:1111ImmOperandMatcher(unsigned InsnVarID, unsigned OpIdx)1112: OperandPredicateMatcher(IPM_Imm, InsnVarID, OpIdx) {}11131114static bool classof(const PredicateMatcher *P) {1115return P->getKind() == IPM_Imm;1116}11171118void emitPredicateOpcodes(MatchTable &Table,1119RuleMatcher &Rule) const override;1120};11211122/// Generates code to check that an operand is a G_CONSTANT with a particular1123/// int.1124class ConstantIntOperandMatcher : public OperandPredicateMatcher {1125protected:1126int64_t Value;11271128public:1129ConstantIntOperandMatcher(unsigned InsnVarID, unsigned OpIdx, int64_t Value)1130: OperandPredicateMatcher(OPM_Int, InsnVarID, OpIdx), Value(Value) {}11311132bool isIdentical(const PredicateMatcher &B) const override {1133return OperandPredicateMatcher::isIdentical(B) &&1134Value == cast<ConstantIntOperandMatcher>(&B)->Value;1135}11361137static bool classof(const PredicateMatcher *P) {1138return P->getKind() == OPM_Int;1139}11401141void emitPredicateOpcodes(MatchTable &Table,1142RuleMatcher &Rule) const override;1143};11441145/// Generates code to check that an operand is a raw int (where MO.isImm() or1146/// MO.isCImm() is true).1147class LiteralIntOperandMatcher : public OperandPredicateMatcher {1148protected:1149int64_t Value;11501151public:1152LiteralIntOperandMatcher(unsigned InsnVarID, unsigned OpIdx, int64_t Value)1153: OperandPredicateMatcher(OPM_LiteralInt, InsnVarID, OpIdx),1154Value(Value) {}11551156bool isIdentical(const PredicateMatcher &B) const override {1157return OperandPredicateMatcher::isIdentical(B) &&1158Value == cast<LiteralIntOperandMatcher>(&B)->Value;1159}11601161static bool classof(const PredicateMatcher *P) {1162return P->getKind() == OPM_LiteralInt;1163}11641165void emitPredicateOpcodes(MatchTable &Table,1166RuleMatcher &Rule) const override;1167};11681169/// Generates code to check that an operand is an CmpInst predicate1170class CmpPredicateOperandMatcher : public OperandPredicateMatcher {1171protected:1172std::string PredName;11731174public:1175CmpPredicateOperandMatcher(unsigned InsnVarID, unsigned OpIdx, std::string P)1176: OperandPredicateMatcher(OPM_CmpPredicate, InsnVarID, OpIdx),1177PredName(std::move(P)) {}11781179bool isIdentical(const PredicateMatcher &B) const override {1180return OperandPredicateMatcher::isIdentical(B) &&1181PredName == cast<CmpPredicateOperandMatcher>(&B)->PredName;1182}11831184static bool classof(const PredicateMatcher *P) {1185return P->getKind() == OPM_CmpPredicate;1186}11871188void emitPredicateOpcodes(MatchTable &Table,1189RuleMatcher &Rule) const override;1190};11911192/// Generates code to check that an operand is an intrinsic ID.1193class IntrinsicIDOperandMatcher : public OperandPredicateMatcher {1194protected:1195const CodeGenIntrinsic *II;11961197public:1198IntrinsicIDOperandMatcher(unsigned InsnVarID, unsigned OpIdx,1199const CodeGenIntrinsic *II)1200: OperandPredicateMatcher(OPM_IntrinsicID, InsnVarID, OpIdx), II(II) {}12011202bool isIdentical(const PredicateMatcher &B) const override {1203return OperandPredicateMatcher::isIdentical(B) &&1204II == cast<IntrinsicIDOperandMatcher>(&B)->II;1205}12061207static bool classof(const PredicateMatcher *P) {1208return P->getKind() == OPM_IntrinsicID;1209}12101211void emitPredicateOpcodes(MatchTable &Table,1212RuleMatcher &Rule) const override;1213};12141215/// Generates code to check that this operand is an immediate whose value meets1216/// an immediate predicate.1217class OperandImmPredicateMatcher : public OperandPredicateMatcher {1218protected:1219TreePredicateFn Predicate;12201221public:1222OperandImmPredicateMatcher(unsigned InsnVarID, unsigned OpIdx,1223const TreePredicateFn &Predicate)1224: OperandPredicateMatcher(IPM_ImmPredicate, InsnVarID, OpIdx),1225Predicate(Predicate) {}12261227bool isIdentical(const PredicateMatcher &B) const override {1228return OperandPredicateMatcher::isIdentical(B) &&1229Predicate.getOrigPatFragRecord() ==1230cast<OperandImmPredicateMatcher>(&B)1231->Predicate.getOrigPatFragRecord();1232}12331234static bool classof(const PredicateMatcher *P) {1235return P->getKind() == IPM_ImmPredicate;1236}12371238void emitPredicateOpcodes(MatchTable &Table,1239RuleMatcher &Rule) const override;1240};12411242/// Generates code to check that a set of predicates match for a particular1243/// operand.1244class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher> {1245protected:1246InstructionMatcher &Insn;1247unsigned OpIdx;1248std::string SymbolicName;12491250/// The index of the first temporary variable allocated to this operand. The1251/// number of allocated temporaries can be found with1252/// countRendererFns().1253unsigned AllocatedTemporariesBaseID;12541255TempTypeIdx TTIdx = 0;12561257public:1258OperandMatcher(InstructionMatcher &Insn, unsigned OpIdx,1259const std::string &SymbolicName,1260unsigned AllocatedTemporariesBaseID)1261: Insn(Insn), OpIdx(OpIdx), SymbolicName(SymbolicName),1262AllocatedTemporariesBaseID(AllocatedTemporariesBaseID) {}12631264bool hasSymbolicName() const { return !SymbolicName.empty(); }1265StringRef getSymbolicName() const { return SymbolicName; }1266void setSymbolicName(StringRef Name) {1267assert(SymbolicName.empty() && "Operand already has a symbolic name");1268SymbolicName = std::string(Name);1269}12701271/// Construct a new operand predicate and add it to the matcher.1272template <class Kind, class... Args>1273std::optional<Kind *> addPredicate(Args &&...args) {1274if (isSameAsAnotherOperand())1275return std::nullopt;1276Predicates.emplace_back(std::make_unique<Kind>(1277getInsnVarID(), getOpIdx(), std::forward<Args>(args)...));1278return static_cast<Kind *>(Predicates.back().get());1279}12801281unsigned getOpIdx() const { return OpIdx; }1282unsigned getInsnVarID() const;12831284/// If this OperandMatcher has not been assigned a TempTypeIdx yet, assigns it1285/// one and adds a `RecordRegisterType` predicate to this matcher. If one has1286/// already been assigned, simply returns it.1287TempTypeIdx getTempTypeIdx(RuleMatcher &Rule);12881289std::string getOperandExpr(unsigned InsnVarID) const;12901291InstructionMatcher &getInstructionMatcher() const { return Insn; }12921293Error addTypeCheckPredicate(const TypeSetByHwMode &VTy,1294bool OperandIsAPointer);12951296/// Emit MatchTable opcodes that test whether the instruction named in1297/// InsnVarID matches all the predicates and all the operands.1298void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule);12991300/// Compare the priority of this object and B.1301///1302/// Returns true if this object is more important than B.1303bool isHigherPriorityThan(OperandMatcher &B);13041305/// Report the maximum number of temporary operands needed by the operand1306/// matcher.1307unsigned countRendererFns();13081309unsigned getAllocatedTemporariesBaseID() const {1310return AllocatedTemporariesBaseID;1311}13121313bool isSameAsAnotherOperand() {1314for (const auto &Predicate : predicates())1315if (isa<SameOperandMatcher>(Predicate))1316return true;1317return false;1318}1319};13201321/// Generates code to check a predicate on an instruction.1322///1323/// Typical predicates include:1324/// * The opcode of the instruction is a particular value.1325/// * The nsw/nuw flag is/isn't set.1326class InstructionPredicateMatcher : public PredicateMatcher {1327public:1328InstructionPredicateMatcher(PredicateKind Kind, unsigned InsnVarID)1329: PredicateMatcher(Kind, InsnVarID) {}1330virtual ~InstructionPredicateMatcher() {}13311332/// Compare the priority of this object and B.1333///1334/// Returns true if this object is more important than B.1335virtual bool1336isHigherPriorityThan(const InstructionPredicateMatcher &B) const {1337return Kind < B.Kind;1338};1339};13401341template <>1342inline std::string1343PredicateListMatcher<PredicateMatcher>::getNoPredicateComment() const {1344return "No instruction predicates";1345}13461347/// Generates code to check the opcode of an instruction.1348class InstructionOpcodeMatcher : public InstructionPredicateMatcher {1349protected:1350// Allow matching one to several, similar opcodes that share properties. This1351// is to handle patterns where one SelectionDAG operation maps to multiple1352// GlobalISel ones (e.g. G_BUILD_VECTOR and G_BUILD_VECTOR_TRUNC). The first1353// is treated as the canonical opcode.1354SmallVector<const CodeGenInstruction *, 2> Insts;13551356static DenseMap<const CodeGenInstruction *, unsigned> OpcodeValues;13571358MatchTableRecord getInstValue(const CodeGenInstruction *I) const;13591360public:1361static void initOpcodeValuesMap(const CodeGenTarget &Target);13621363InstructionOpcodeMatcher(unsigned InsnVarID,1364ArrayRef<const CodeGenInstruction *> I)1365: InstructionPredicateMatcher(IPM_Opcode, InsnVarID),1366Insts(I.begin(), I.end()) {1367assert((Insts.size() == 1 || Insts.size() == 2) &&1368"unexpected number of opcode alternatives");1369}13701371static bool classof(const PredicateMatcher *P) {1372return P->getKind() == IPM_Opcode;1373}13741375bool isIdentical(const PredicateMatcher &B) const override {1376return InstructionPredicateMatcher::isIdentical(B) &&1377Insts == cast<InstructionOpcodeMatcher>(&B)->Insts;1378}13791380bool hasValue() const override {1381return Insts.size() == 1 && OpcodeValues.count(Insts[0]);1382}13831384// TODO: This is used for the SwitchMatcher optimization. We should be able to1385// return a list of the opcodes to match.1386MatchTableRecord getValue() const override;13871388void emitPredicateOpcodes(MatchTable &Table,1389RuleMatcher &Rule) const override;13901391/// Compare the priority of this object and B.1392///1393/// Returns true if this object is more important than B.1394bool1395isHigherPriorityThan(const InstructionPredicateMatcher &B) const override;13961397bool isConstantInstruction() const;13981399// The first opcode is the canonical opcode, and later are alternatives.1400StringRef getOpcode() const;1401ArrayRef<const CodeGenInstruction *> getAlternativeOpcodes() { return Insts; }1402bool isVariadicNumOperands() const;1403StringRef getOperandType(unsigned OpIdx) const;1404};14051406class InstructionNumOperandsMatcher final : public InstructionPredicateMatcher {1407unsigned NumOperands = 0;14081409public:1410InstructionNumOperandsMatcher(unsigned InsnVarID, unsigned NumOperands)1411: InstructionPredicateMatcher(IPM_NumOperands, InsnVarID),1412NumOperands(NumOperands) {}14131414static bool classof(const PredicateMatcher *P) {1415return P->getKind() == IPM_NumOperands;1416}14171418bool isIdentical(const PredicateMatcher &B) const override {1419return InstructionPredicateMatcher::isIdentical(B) &&1420NumOperands == cast<InstructionNumOperandsMatcher>(&B)->NumOperands;1421}14221423void emitPredicateOpcodes(MatchTable &Table,1424RuleMatcher &Rule) const override;1425};14261427/// Generates code to check that this instruction is a constant whose value1428/// meets an immediate predicate.1429///1430/// Immediates are slightly odd since they are typically used like an operand1431/// but are represented as an operator internally. We typically write simm8:$src1432/// in a tablegen pattern, but this is just syntactic sugar for1433/// (imm:i32)<<P:Predicate_simm8>>:$imm which more directly describes the nodes1434/// that will be matched and the predicate (which is attached to the imm1435/// operator) that will be tested. In SelectionDAG this describes a1436/// ConstantSDNode whose internal value will be tested using the simm81437/// predicate.1438///1439/// The corresponding GlobalISel representation is %1 = G_CONSTANT iN Value. In1440/// this representation, the immediate could be tested with an1441/// InstructionMatcher, InstructionOpcodeMatcher, OperandMatcher, and a1442/// OperandPredicateMatcher-subclass to check the Value meets the predicate but1443/// there are two implementation issues with producing that matcher1444/// configuration from the SelectionDAG pattern:1445/// * ImmLeaf is a PatFrag whose root is an InstructionMatcher. This means that1446/// were we to sink the immediate predicate to the operand we would have to1447/// have two partial implementations of PatFrag support, one for immediates1448/// and one for non-immediates.1449/// * At the point we handle the predicate, the OperandMatcher hasn't been1450/// created yet. If we were to sink the predicate to the OperandMatcher we1451/// would also have to complicate (or duplicate) the code that descends and1452/// creates matchers for the subtree.1453/// Overall, it's simpler to handle it in the place it was found.1454class InstructionImmPredicateMatcher : public InstructionPredicateMatcher {1455protected:1456TreePredicateFn Predicate;14571458public:1459InstructionImmPredicateMatcher(unsigned InsnVarID,1460const TreePredicateFn &Predicate)1461: InstructionPredicateMatcher(IPM_ImmPredicate, InsnVarID),1462Predicate(Predicate) {}14631464bool isIdentical(const PredicateMatcher &B) const override;14651466static bool classof(const PredicateMatcher *P) {1467return P->getKind() == IPM_ImmPredicate;1468}14691470void emitPredicateOpcodes(MatchTable &Table,1471RuleMatcher &Rule) const override;1472};14731474/// Generates code to check that a memory instruction has a atomic ordering1475/// MachineMemoryOperand.1476class AtomicOrderingMMOPredicateMatcher : public InstructionPredicateMatcher {1477public:1478enum AOComparator {1479AO_Exactly,1480AO_OrStronger,1481AO_WeakerThan,1482};14831484protected:1485StringRef Order;1486AOComparator Comparator;14871488public:1489AtomicOrderingMMOPredicateMatcher(unsigned InsnVarID, StringRef Order,1490AOComparator Comparator = AO_Exactly)1491: InstructionPredicateMatcher(IPM_AtomicOrderingMMO, InsnVarID),1492Order(Order), Comparator(Comparator) {}14931494static bool classof(const PredicateMatcher *P) {1495return P->getKind() == IPM_AtomicOrderingMMO;1496}14971498bool isIdentical(const PredicateMatcher &B) const override;14991500void emitPredicateOpcodes(MatchTable &Table,1501RuleMatcher &Rule) const override;1502};15031504/// Generates code to check that the size of an MMO is exactly N bytes.1505class MemorySizePredicateMatcher : public InstructionPredicateMatcher {1506protected:1507unsigned MMOIdx;1508uint64_t Size;15091510public:1511MemorySizePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx, unsigned Size)1512: InstructionPredicateMatcher(IPM_MemoryLLTSize, InsnVarID),1513MMOIdx(MMOIdx), Size(Size) {}15141515static bool classof(const PredicateMatcher *P) {1516return P->getKind() == IPM_MemoryLLTSize;1517}1518bool isIdentical(const PredicateMatcher &B) const override {1519return InstructionPredicateMatcher::isIdentical(B) &&1520MMOIdx == cast<MemorySizePredicateMatcher>(&B)->MMOIdx &&1521Size == cast<MemorySizePredicateMatcher>(&B)->Size;1522}15231524void emitPredicateOpcodes(MatchTable &Table,1525RuleMatcher &Rule) const override;1526};15271528class MemoryAddressSpacePredicateMatcher : public InstructionPredicateMatcher {1529protected:1530unsigned MMOIdx;1531SmallVector<unsigned, 4> AddrSpaces;15321533public:1534MemoryAddressSpacePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx,1535ArrayRef<unsigned> AddrSpaces)1536: InstructionPredicateMatcher(IPM_MemoryAddressSpace, InsnVarID),1537MMOIdx(MMOIdx), AddrSpaces(AddrSpaces.begin(), AddrSpaces.end()) {}15381539static bool classof(const PredicateMatcher *P) {1540return P->getKind() == IPM_MemoryAddressSpace;1541}15421543bool isIdentical(const PredicateMatcher &B) const override;15441545void emitPredicateOpcodes(MatchTable &Table,1546RuleMatcher &Rule) const override;1547};15481549class MemoryAlignmentPredicateMatcher : public InstructionPredicateMatcher {1550protected:1551unsigned MMOIdx;1552int MinAlign;15531554public:1555MemoryAlignmentPredicateMatcher(unsigned InsnVarID, unsigned MMOIdx,1556int MinAlign)1557: InstructionPredicateMatcher(IPM_MemoryAlignment, InsnVarID),1558MMOIdx(MMOIdx), MinAlign(MinAlign) {1559assert(MinAlign > 0);1560}15611562static bool classof(const PredicateMatcher *P) {1563return P->getKind() == IPM_MemoryAlignment;1564}15651566bool isIdentical(const PredicateMatcher &B) const override;15671568void emitPredicateOpcodes(MatchTable &Table,1569RuleMatcher &Rule) const override;1570};15711572/// Generates code to check that the size of an MMO is less-than, equal-to, or1573/// greater than a given LLT.1574class MemoryVsLLTSizePredicateMatcher : public InstructionPredicateMatcher {1575public:1576enum RelationKind {1577GreaterThan,1578EqualTo,1579LessThan,1580};15811582protected:1583unsigned MMOIdx;1584RelationKind Relation;1585unsigned OpIdx;15861587public:1588MemoryVsLLTSizePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx,1589enum RelationKind Relation, unsigned OpIdx)1590: InstructionPredicateMatcher(IPM_MemoryVsLLTSize, InsnVarID),1591MMOIdx(MMOIdx), Relation(Relation), OpIdx(OpIdx) {}15921593static bool classof(const PredicateMatcher *P) {1594return P->getKind() == IPM_MemoryVsLLTSize;1595}1596bool isIdentical(const PredicateMatcher &B) const override;15971598void emitPredicateOpcodes(MatchTable &Table,1599RuleMatcher &Rule) const override;1600};16011602// Matcher for immAllOnesV/immAllZerosV1603class VectorSplatImmPredicateMatcher : public InstructionPredicateMatcher {1604public:1605enum SplatKind { AllZeros, AllOnes };16061607private:1608SplatKind Kind;16091610public:1611VectorSplatImmPredicateMatcher(unsigned InsnVarID, SplatKind K)1612: InstructionPredicateMatcher(IPM_VectorSplatImm, InsnVarID), Kind(K) {}16131614static bool classof(const PredicateMatcher *P) {1615return P->getKind() == IPM_VectorSplatImm;1616}16171618bool isIdentical(const PredicateMatcher &B) const override {1619return InstructionPredicateMatcher::isIdentical(B) &&1620Kind == static_cast<const VectorSplatImmPredicateMatcher &>(B).Kind;1621}16221623void emitPredicateOpcodes(MatchTable &Table,1624RuleMatcher &Rule) const override;1625};16261627/// Generates code to check an arbitrary C++ instruction predicate.1628class GenericInstructionPredicateMatcher : public InstructionPredicateMatcher {1629protected:1630std::string EnumVal;16311632public:1633GenericInstructionPredicateMatcher(unsigned InsnVarID,1634TreePredicateFn Predicate);16351636GenericInstructionPredicateMatcher(unsigned InsnVarID,1637const std::string &EnumVal)1638: InstructionPredicateMatcher(IPM_GenericPredicate, InsnVarID),1639EnumVal(EnumVal) {}16401641static bool classof(const InstructionPredicateMatcher *P) {1642return P->getKind() == IPM_GenericPredicate;1643}1644bool isIdentical(const PredicateMatcher &B) const override;1645void emitPredicateOpcodes(MatchTable &Table,1646RuleMatcher &Rule) const override;1647};16481649class MIFlagsInstructionPredicateMatcher : public InstructionPredicateMatcher {1650SmallVector<StringRef, 2> Flags;1651bool CheckNot; // false = GIM_MIFlags, true = GIM_MIFlagsNot16521653public:1654MIFlagsInstructionPredicateMatcher(unsigned InsnVarID,1655ArrayRef<StringRef> FlagsToCheck,1656bool CheckNot = false)1657: InstructionPredicateMatcher(IPM_MIFlags, InsnVarID),1658Flags(FlagsToCheck), CheckNot(CheckNot) {1659sort(Flags);1660}16611662static bool classof(const InstructionPredicateMatcher *P) {1663return P->getKind() == IPM_MIFlags;1664}16651666bool isIdentical(const PredicateMatcher &B) const override;1667void emitPredicateOpcodes(MatchTable &Table,1668RuleMatcher &Rule) const override;1669};16701671/// Generates code to check for the absence of use of the result.1672// TODO? Generalize this to support checking for one use.1673class NoUsePredicateMatcher : public InstructionPredicateMatcher {1674public:1675NoUsePredicateMatcher(unsigned InsnVarID)1676: InstructionPredicateMatcher(IPM_NoUse, InsnVarID) {}16771678static bool classof(const PredicateMatcher *P) {1679return P->getKind() == IPM_NoUse;1680}16811682bool isIdentical(const PredicateMatcher &B) const override {1683return InstructionPredicateMatcher::isIdentical(B);1684}16851686void emitPredicateOpcodes(MatchTable &Table,1687RuleMatcher &Rule) const override {1688Table << MatchTable::Opcode("GIM_CheckHasNoUse")1689<< MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)1690<< MatchTable::LineBreak;1691}1692};16931694/// Generates code to check that the first result has only one use.1695class OneUsePredicateMatcher : public InstructionPredicateMatcher {1696public:1697OneUsePredicateMatcher(unsigned InsnVarID)1698: InstructionPredicateMatcher(IPM_OneUse, InsnVarID) {}16991700static bool classof(const PredicateMatcher *P) {1701return P->getKind() == IPM_OneUse;1702}17031704bool isIdentical(const PredicateMatcher &B) const override {1705return InstructionPredicateMatcher::isIdentical(B);1706}17071708void emitPredicateOpcodes(MatchTable &Table,1709RuleMatcher &Rule) const override {1710Table << MatchTable::Opcode("GIM_CheckHasOneUse")1711<< MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID)1712<< MatchTable::LineBreak;1713}1714};17151716/// Generates code to check that a set of predicates and operands match for a1717/// particular instruction.1718///1719/// Typical predicates include:1720/// * Has a specific opcode.1721/// * Has an nsw/nuw flag or doesn't.1722class InstructionMatcher final : public PredicateListMatcher<PredicateMatcher> {1723protected:1724typedef std::vector<std::unique_ptr<OperandMatcher>> OperandVec;17251726RuleMatcher &Rule;17271728/// The operands to match. All rendered operands must be present even if the1729/// condition is always true.1730OperandVec Operands;1731bool NumOperandsCheck = true;17321733std::string SymbolicName;1734unsigned InsnVarID;17351736/// PhysRegInputs - List list has an entry for each explicitly specified1737/// physreg input to the pattern. The first elt is the Register node, the1738/// second is the recorded slot number the input pattern match saved it in.1739SmallVector<std::pair<Record *, unsigned>, 2> PhysRegInputs;17401741public:1742InstructionMatcher(RuleMatcher &Rule, StringRef SymbolicName,1743bool NumOpsCheck = true)1744: Rule(Rule), NumOperandsCheck(NumOpsCheck), SymbolicName(SymbolicName) {1745// We create a new instruction matcher.1746// Get a new ID for that instruction.1747InsnVarID = Rule.implicitlyDefineInsnVar(*this);1748}17491750/// Construct a new instruction predicate and add it to the matcher.1751template <class Kind, class... Args>1752std::optional<Kind *> addPredicate(Args &&...args) {1753Predicates.emplace_back(1754std::make_unique<Kind>(getInsnVarID(), std::forward<Args>(args)...));1755return static_cast<Kind *>(Predicates.back().get());1756}17571758RuleMatcher &getRuleMatcher() const { return Rule; }17591760unsigned getInsnVarID() const { return InsnVarID; }17611762/// Add an operand to the matcher.1763OperandMatcher &addOperand(unsigned OpIdx, const std::string &SymbolicName,1764unsigned AllocatedTemporariesBaseID);1765OperandMatcher &getOperand(unsigned OpIdx);1766OperandMatcher &addPhysRegInput(Record *Reg, unsigned OpIdx,1767unsigned TempOpIdx);17681769ArrayRef<std::pair<Record *, unsigned>> getPhysRegInputs() const {1770return PhysRegInputs;1771}17721773StringRef getSymbolicName() const { return SymbolicName; }1774unsigned getNumOperands() const { return Operands.size(); }1775OperandVec::iterator operands_begin() { return Operands.begin(); }1776OperandVec::iterator operands_end() { return Operands.end(); }1777iterator_range<OperandVec::iterator> operands() {1778return make_range(operands_begin(), operands_end());1779}1780OperandVec::const_iterator operands_begin() const { return Operands.begin(); }1781OperandVec::const_iterator operands_end() const { return Operands.end(); }1782iterator_range<OperandVec::const_iterator> operands() const {1783return make_range(operands_begin(), operands_end());1784}1785bool operands_empty() const { return Operands.empty(); }17861787void pop_front() { Operands.erase(Operands.begin()); }17881789void optimize();17901791/// Emit MatchTable opcodes that test whether the instruction named in1792/// InsnVarName matches all the predicates and all the operands.1793void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule);17941795/// Compare the priority of this object and B.1796///1797/// Returns true if this object is more important than B.1798bool isHigherPriorityThan(InstructionMatcher &B);17991800/// Report the maximum number of temporary operands needed by the instruction1801/// matcher.1802unsigned countRendererFns();18031804InstructionOpcodeMatcher &getOpcodeMatcher() {1805for (auto &P : predicates())1806if (auto *OpMatcher = dyn_cast<InstructionOpcodeMatcher>(P.get()))1807return *OpMatcher;1808llvm_unreachable("Didn't find an opcode matcher");1809}18101811bool isConstantInstruction() {1812return getOpcodeMatcher().isConstantInstruction();1813}18141815StringRef getOpcode() { return getOpcodeMatcher().getOpcode(); }1816};18171818/// Generates code to check that the operand is a register defined by an1819/// instruction that matches the given instruction matcher.1820///1821/// For example, the pattern:1822/// (set $dst, (G_MUL (G_ADD $src1, $src2), $src3))1823/// would use an InstructionOperandMatcher for operand 1 of the G_MUL to match1824/// the:1825/// (G_ADD $src1, $src2)1826/// subpattern.1827class InstructionOperandMatcher : public OperandPredicateMatcher {1828protected:1829std::unique_ptr<InstructionMatcher> InsnMatcher;18301831GISelFlags Flags;18321833public:1834InstructionOperandMatcher(unsigned InsnVarID, unsigned OpIdx,1835RuleMatcher &Rule, StringRef SymbolicName,1836bool NumOpsCheck = true)1837: OperandPredicateMatcher(OPM_Instruction, InsnVarID, OpIdx),1838InsnMatcher(new InstructionMatcher(Rule, SymbolicName, NumOpsCheck)),1839Flags(Rule.getGISelFlags()) {}18401841static bool classof(const PredicateMatcher *P) {1842return P->getKind() == OPM_Instruction;1843}18441845InstructionMatcher &getInsnMatcher() const { return *InsnMatcher; }18461847void emitCaptureOpcodes(MatchTable &Table, RuleMatcher &Rule) const;1848void emitPredicateOpcodes(MatchTable &Table,1849RuleMatcher &Rule) const override {1850emitCaptureOpcodes(Table, Rule);1851InsnMatcher->emitPredicateOpcodes(Table, Rule);1852}18531854bool isHigherPriorityThan(const OperandPredicateMatcher &B) const override;18551856/// Report the maximum number of temporary operands needed by the predicate1857/// matcher.1858unsigned countRendererFns() const override {1859return InsnMatcher->countRendererFns();1860}1861};18621863//===- Actions ------------------------------------------------------------===//1864class OperandRenderer {1865public:1866enum RendererKind {1867OR_Copy,1868OR_CopyOrAddZeroReg,1869OR_CopySubReg,1870OR_CopyPhysReg,1871OR_CopyConstantAsImm,1872OR_CopyFConstantAsFPImm,1873OR_Imm,1874OR_SubRegIndex,1875OR_Register,1876OR_TempRegister,1877OR_ComplexPattern,1878OR_Intrinsic,1879OR_Custom,1880OR_CustomOperand1881};18821883protected:1884RendererKind Kind;18851886public:1887OperandRenderer(RendererKind Kind) : Kind(Kind) {}1888virtual ~OperandRenderer();18891890RendererKind getKind() const { return Kind; }18911892virtual void emitRenderOpcodes(MatchTable &Table,1893RuleMatcher &Rule) const = 0;1894};18951896/// A CopyRenderer emits code to copy a single operand from an existing1897/// instruction to the one being built.1898class CopyRenderer : public OperandRenderer {1899protected:1900unsigned NewInsnID;1901/// The name of the operand.1902const StringRef SymbolicName;19031904public:1905CopyRenderer(unsigned NewInsnID, StringRef SymbolicName)1906: OperandRenderer(OR_Copy), NewInsnID(NewInsnID),1907SymbolicName(SymbolicName) {1908assert(!SymbolicName.empty() && "Cannot copy from an unspecified source");1909}19101911static bool classof(const OperandRenderer *R) {1912return R->getKind() == OR_Copy;1913}19141915StringRef getSymbolicName() const { return SymbolicName; }19161917static void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule,1918unsigned NewInsnID, unsigned OldInsnID,1919unsigned OpIdx, StringRef Name);19201921void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;1922};19231924/// A CopyRenderer emits code to copy a virtual register to a specific physical1925/// register.1926class CopyPhysRegRenderer : public OperandRenderer {1927protected:1928unsigned NewInsnID;1929Record *PhysReg;19301931public:1932CopyPhysRegRenderer(unsigned NewInsnID, Record *Reg)1933: OperandRenderer(OR_CopyPhysReg), NewInsnID(NewInsnID), PhysReg(Reg) {1934assert(PhysReg);1935}19361937static bool classof(const OperandRenderer *R) {1938return R->getKind() == OR_CopyPhysReg;1939}19401941Record *getPhysReg() const { return PhysReg; }19421943void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;1944};19451946/// A CopyOrAddZeroRegRenderer emits code to copy a single operand from an1947/// existing instruction to the one being built. If the operand turns out to be1948/// a 'G_CONSTANT 0' then it replaces the operand with a zero register.1949class CopyOrAddZeroRegRenderer : public OperandRenderer {1950protected:1951unsigned NewInsnID;1952/// The name of the operand.1953const StringRef SymbolicName;1954const Record *ZeroRegisterDef;19551956public:1957CopyOrAddZeroRegRenderer(unsigned NewInsnID, StringRef SymbolicName,1958Record *ZeroRegisterDef)1959: OperandRenderer(OR_CopyOrAddZeroReg), NewInsnID(NewInsnID),1960SymbolicName(SymbolicName), ZeroRegisterDef(ZeroRegisterDef) {1961assert(!SymbolicName.empty() && "Cannot copy from an unspecified source");1962}19631964static bool classof(const OperandRenderer *R) {1965return R->getKind() == OR_CopyOrAddZeroReg;1966}19671968StringRef getSymbolicName() const { return SymbolicName; }19691970void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;1971};19721973/// A CopyConstantAsImmRenderer emits code to render a G_CONSTANT instruction to1974/// an extended immediate operand.1975class CopyConstantAsImmRenderer : public OperandRenderer {1976protected:1977unsigned NewInsnID;1978/// The name of the operand.1979const std::string SymbolicName;1980bool Signed;19811982public:1983CopyConstantAsImmRenderer(unsigned NewInsnID, StringRef SymbolicName)1984: OperandRenderer(OR_CopyConstantAsImm), NewInsnID(NewInsnID),1985SymbolicName(SymbolicName), Signed(true) {}19861987static bool classof(const OperandRenderer *R) {1988return R->getKind() == OR_CopyConstantAsImm;1989}19901991StringRef getSymbolicName() const { return SymbolicName; }19921993void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;1994};19951996/// A CopyFConstantAsFPImmRenderer emits code to render a G_FCONSTANT1997/// instruction to an extended immediate operand.1998class CopyFConstantAsFPImmRenderer : public OperandRenderer {1999protected:2000unsigned NewInsnID;2001/// The name of the operand.2002const std::string SymbolicName;20032004public:2005CopyFConstantAsFPImmRenderer(unsigned NewInsnID, StringRef SymbolicName)2006: OperandRenderer(OR_CopyFConstantAsFPImm), NewInsnID(NewInsnID),2007SymbolicName(SymbolicName) {}20082009static bool classof(const OperandRenderer *R) {2010return R->getKind() == OR_CopyFConstantAsFPImm;2011}20122013StringRef getSymbolicName() const { return SymbolicName; }20142015void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2016};20172018/// A CopySubRegRenderer emits code to copy a single register operand from an2019/// existing instruction to the one being built and indicate that only a2020/// subregister should be copied.2021class CopySubRegRenderer : public OperandRenderer {2022protected:2023unsigned NewInsnID;2024/// The name of the operand.2025const StringRef SymbolicName;2026/// The subregister to extract.2027const CodeGenSubRegIndex *SubReg;20282029public:2030CopySubRegRenderer(unsigned NewInsnID, StringRef SymbolicName,2031const CodeGenSubRegIndex *SubReg)2032: OperandRenderer(OR_CopySubReg), NewInsnID(NewInsnID),2033SymbolicName(SymbolicName), SubReg(SubReg) {}20342035static bool classof(const OperandRenderer *R) {2036return R->getKind() == OR_CopySubReg;2037}20382039StringRef getSymbolicName() const { return SymbolicName; }20402041void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2042};20432044/// Adds a specific physical register to the instruction being built.2045/// This is typically useful for WZR/XZR on AArch64.2046class AddRegisterRenderer : public OperandRenderer {2047protected:2048unsigned InsnID;2049const Record *RegisterDef;2050bool IsDef;2051const CodeGenTarget &Target;20522053public:2054AddRegisterRenderer(unsigned InsnID, const CodeGenTarget &Target,2055const Record *RegisterDef, bool IsDef = false)2056: OperandRenderer(OR_Register), InsnID(InsnID), RegisterDef(RegisterDef),2057IsDef(IsDef), Target(Target) {}20582059static bool classof(const OperandRenderer *R) {2060return R->getKind() == OR_Register;2061}20622063void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2064};20652066/// Adds a specific temporary virtual register to the instruction being built.2067/// This is used to chain instructions together when emitting multiple2068/// instructions.2069class TempRegRenderer : public OperandRenderer {2070protected:2071unsigned InsnID;2072unsigned TempRegID;2073const CodeGenSubRegIndex *SubRegIdx;2074bool IsDef;2075bool IsDead;20762077public:2078TempRegRenderer(unsigned InsnID, unsigned TempRegID, bool IsDef = false,2079const CodeGenSubRegIndex *SubReg = nullptr,2080bool IsDead = false)2081: OperandRenderer(OR_Register), InsnID(InsnID), TempRegID(TempRegID),2082SubRegIdx(SubReg), IsDef(IsDef), IsDead(IsDead) {}20832084static bool classof(const OperandRenderer *R) {2085return R->getKind() == OR_TempRegister;2086}20872088void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2089};20902091/// Adds a specific immediate to the instruction being built.2092/// If a LLT is passed, a ConstantInt immediate is created instead.2093class ImmRenderer : public OperandRenderer {2094protected:2095unsigned InsnID;2096int64_t Imm;2097std::optional<LLTCodeGenOrTempType> CImmLLT;20982099public:2100ImmRenderer(unsigned InsnID, int64_t Imm)2101: OperandRenderer(OR_Imm), InsnID(InsnID), Imm(Imm) {}21022103ImmRenderer(unsigned InsnID, int64_t Imm, const LLTCodeGenOrTempType &CImmLLT)2104: OperandRenderer(OR_Imm), InsnID(InsnID), Imm(Imm), CImmLLT(CImmLLT) {2105if (CImmLLT.isLLTCodeGen())2106KnownTypes.insert(CImmLLT.getLLTCodeGen());2107}21082109static bool classof(const OperandRenderer *R) {2110return R->getKind() == OR_Imm;2111}21122113static void emitAddImm(MatchTable &Table, RuleMatcher &RM, unsigned InsnID,2114int64_t Imm, StringRef ImmName = "Imm");21152116void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2117};21182119/// Adds an enum value for a subreg index to the instruction being built.2120class SubRegIndexRenderer : public OperandRenderer {2121protected:2122unsigned InsnID;2123const CodeGenSubRegIndex *SubRegIdx;21242125public:2126SubRegIndexRenderer(unsigned InsnID, const CodeGenSubRegIndex *SRI)2127: OperandRenderer(OR_SubRegIndex), InsnID(InsnID), SubRegIdx(SRI) {}21282129static bool classof(const OperandRenderer *R) {2130return R->getKind() == OR_SubRegIndex;2131}21322133void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2134};21352136/// Adds operands by calling a renderer function supplied by the ComplexPattern2137/// matcher function.2138class RenderComplexPatternOperand : public OperandRenderer {2139private:2140unsigned InsnID;2141const Record &TheDef;2142/// The name of the operand.2143const StringRef SymbolicName;2144/// The renderer number. This must be unique within a rule since it's used to2145/// identify a temporary variable to hold the renderer function.2146unsigned RendererID;2147/// When provided, this is the suboperand of the ComplexPattern operand to2148/// render. Otherwise all the suboperands will be rendered.2149std::optional<unsigned> SubOperand;2150/// The subregister to extract. Render the whole register if not specified.2151const CodeGenSubRegIndex *SubReg;21522153unsigned getNumOperands() const {2154return TheDef.getValueAsDag("Operands")->getNumArgs();2155}21562157public:2158RenderComplexPatternOperand(unsigned InsnID, const Record &TheDef,2159StringRef SymbolicName, unsigned RendererID,2160std::optional<unsigned> SubOperand = std::nullopt,2161const CodeGenSubRegIndex *SubReg = nullptr)2162: OperandRenderer(OR_ComplexPattern), InsnID(InsnID), TheDef(TheDef),2163SymbolicName(SymbolicName), RendererID(RendererID),2164SubOperand(SubOperand), SubReg(SubReg) {}21652166static bool classof(const OperandRenderer *R) {2167return R->getKind() == OR_ComplexPattern;2168}21692170void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2171};21722173/// Adds an intrinsic ID operand to the instruction being built.2174class IntrinsicIDRenderer : public OperandRenderer {2175protected:2176unsigned InsnID;2177const CodeGenIntrinsic *II;21782179public:2180IntrinsicIDRenderer(unsigned InsnID, const CodeGenIntrinsic *II)2181: OperandRenderer(OR_Intrinsic), InsnID(InsnID), II(II) {}21822183static bool classof(const OperandRenderer *R) {2184return R->getKind() == OR_Intrinsic;2185}21862187void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2188};21892190class CustomRenderer : public OperandRenderer {2191protected:2192unsigned InsnID;2193const Record &Renderer;2194/// The name of the operand.2195const std::string SymbolicName;21962197public:2198CustomRenderer(unsigned InsnID, const Record &Renderer,2199StringRef SymbolicName)2200: OperandRenderer(OR_Custom), InsnID(InsnID), Renderer(Renderer),2201SymbolicName(SymbolicName) {}22022203static bool classof(const OperandRenderer *R) {2204return R->getKind() == OR_Custom;2205}22062207void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2208};22092210class CustomOperandRenderer : public OperandRenderer {2211protected:2212unsigned InsnID;2213const Record &Renderer;2214/// The name of the operand.2215const std::string SymbolicName;22162217public:2218CustomOperandRenderer(unsigned InsnID, const Record &Renderer,2219StringRef SymbolicName)2220: OperandRenderer(OR_CustomOperand), InsnID(InsnID), Renderer(Renderer),2221SymbolicName(SymbolicName) {}22222223static bool classof(const OperandRenderer *R) {2224return R->getKind() == OR_CustomOperand;2225}22262227void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2228};22292230/// An action taken when all Matcher predicates succeeded for a parent rule.2231///2232/// Typical actions include:2233/// * Changing the opcode of an instruction.2234/// * Adding an operand to an instruction.2235class MatchAction {2236public:2237enum ActionKind {2238AK_DebugComment,2239AK_BuildMI,2240AK_BuildConstantMI,2241AK_EraseInst,2242AK_ReplaceReg,2243AK_ConstraintOpsToDef,2244AK_ConstraintOpsToRC,2245AK_MakeTempReg,2246};22472248MatchAction(ActionKind K) : Kind(K) {}22492250ActionKind getKind() const { return Kind; }22512252virtual ~MatchAction() {}22532254// Some actions may need to add extra predicates to ensure they can run.2255virtual void emitAdditionalPredicates(MatchTable &Table,2256RuleMatcher &Rule) const {}22572258/// Emit the MatchTable opcodes to implement the action.2259virtual void emitActionOpcodes(MatchTable &Table,2260RuleMatcher &Rule) const = 0;22612262/// If this opcode has an overload that can call GIR_Done directly, emit that2263/// instead of the usual opcode and return "true". Return "false" if GIR_Done2264/// still needs to be emitted.2265virtual bool emitActionOpcodesAndDone(MatchTable &Table,2266RuleMatcher &Rule) const {2267emitActionOpcodes(Table, Rule);2268return false;2269}22702271private:2272ActionKind Kind;2273};22742275/// Generates a comment describing the matched rule being acted upon.2276class DebugCommentAction : public MatchAction {2277private:2278std::string S;22792280public:2281DebugCommentAction(StringRef S)2282: MatchAction(AK_DebugComment), S(std::string(S)) {}22832284static bool classof(const MatchAction *A) {2285return A->getKind() == AK_DebugComment;2286}22872288void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {2289Table << MatchTable::Comment(S) << MatchTable::LineBreak;2290}2291};22922293/// Generates code to build an instruction or mutate an existing instruction2294/// into the desired instruction when this is possible.2295class BuildMIAction : public MatchAction {2296private:2297unsigned InsnID;2298const CodeGenInstruction *I;2299InstructionMatcher *Matched;2300std::vector<std::unique_ptr<OperandRenderer>> OperandRenderers;2301SmallPtrSet<Record *, 4> DeadImplicitDefs;23022303std::vector<const InstructionMatcher *> CopiedFlags;2304std::vector<StringRef> SetFlags;2305std::vector<StringRef> UnsetFlags;23062307/// True if the instruction can be built solely by mutating the opcode.2308bool canMutate(RuleMatcher &Rule, const InstructionMatcher *Insn) const;23092310public:2311BuildMIAction(unsigned InsnID, const CodeGenInstruction *I)2312: MatchAction(AK_BuildMI), InsnID(InsnID), I(I), Matched(nullptr) {}23132314static bool classof(const MatchAction *A) {2315return A->getKind() == AK_BuildMI;2316}23172318unsigned getInsnID() const { return InsnID; }2319const CodeGenInstruction *getCGI() const { return I; }23202321void addSetMIFlags(StringRef Flag) { SetFlags.push_back(Flag); }2322void addUnsetMIFlags(StringRef Flag) { UnsetFlags.push_back(Flag); }2323void addCopiedMIFlags(const InstructionMatcher &IM) {2324CopiedFlags.push_back(&IM);2325}23262327void chooseInsnToMutate(RuleMatcher &Rule);23282329void setDeadImplicitDef(Record *R) { DeadImplicitDefs.insert(R); }23302331template <class Kind, class... Args> Kind &addRenderer(Args &&...args) {2332OperandRenderers.emplace_back(2333std::make_unique<Kind>(InsnID, std::forward<Args>(args)...));2334return *static_cast<Kind *>(OperandRenderers.back().get());2335}23362337void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2338};23392340/// Generates code to create a constant that defines a TempReg.2341/// The instruction created is usually a G_CONSTANT but it could also be a2342/// G_BUILD_VECTOR for vector types.2343class BuildConstantAction : public MatchAction {2344unsigned TempRegID;2345int64_t Val;23462347public:2348BuildConstantAction(unsigned TempRegID, int64_t Val)2349: MatchAction(AK_BuildConstantMI), TempRegID(TempRegID), Val(Val) {}23502351static bool classof(const MatchAction *A) {2352return A->getKind() == AK_BuildConstantMI;2353}23542355void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2356};23572358class EraseInstAction : public MatchAction {2359unsigned InsnID;23602361public:2362EraseInstAction(unsigned InsnID)2363: MatchAction(AK_EraseInst), InsnID(InsnID) {}23642365unsigned getInsnID() const { return InsnID; }23662367static bool classof(const MatchAction *A) {2368return A->getKind() == AK_EraseInst;2369}23702371void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2372bool emitActionOpcodesAndDone(MatchTable &Table,2373RuleMatcher &Rule) const override;2374};23752376class ReplaceRegAction : public MatchAction {2377unsigned OldInsnID, OldOpIdx;2378unsigned NewInsnId = -1, NewOpIdx;2379unsigned TempRegID = -1;23802381public:2382ReplaceRegAction(unsigned OldInsnID, unsigned OldOpIdx, unsigned NewInsnId,2383unsigned NewOpIdx)2384: MatchAction(AK_ReplaceReg), OldInsnID(OldInsnID), OldOpIdx(OldOpIdx),2385NewInsnId(NewInsnId), NewOpIdx(NewOpIdx) {}23862387ReplaceRegAction(unsigned OldInsnID, unsigned OldOpIdx, unsigned TempRegID)2388: MatchAction(AK_ReplaceReg), OldInsnID(OldInsnID), OldOpIdx(OldOpIdx),2389TempRegID(TempRegID) {}23902391static bool classof(const MatchAction *A) {2392return A->getKind() == AK_ReplaceReg;2393}23942395void emitAdditionalPredicates(MatchTable &Table,2396RuleMatcher &Rule) const override;2397void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2398};23992400/// Generates code to constrain the operands of an output instruction to the2401/// register classes specified by the definition of that instruction.2402class ConstrainOperandsToDefinitionAction : public MatchAction {2403unsigned InsnID;24042405public:2406ConstrainOperandsToDefinitionAction(unsigned InsnID)2407: MatchAction(AK_ConstraintOpsToDef), InsnID(InsnID) {}24082409static bool classof(const MatchAction *A) {2410return A->getKind() == AK_ConstraintOpsToDef;2411}24122413void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {2414if (InsnID == 0) {2415Table << MatchTable::Opcode("GIR_RootConstrainSelectedInstOperands")2416<< MatchTable::LineBreak;2417} else {2418Table << MatchTable::Opcode("GIR_ConstrainSelectedInstOperands")2419<< MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID)2420<< MatchTable::LineBreak;2421}2422}2423};24242425/// Generates code to constrain the specified operand of an output instruction2426/// to the specified register class.2427class ConstrainOperandToRegClassAction : public MatchAction {2428unsigned InsnID;2429unsigned OpIdx;2430const CodeGenRegisterClass &RC;24312432public:2433ConstrainOperandToRegClassAction(unsigned InsnID, unsigned OpIdx,2434const CodeGenRegisterClass &RC)2435: MatchAction(AK_ConstraintOpsToRC), InsnID(InsnID), OpIdx(OpIdx),2436RC(RC) {}24372438static bool classof(const MatchAction *A) {2439return A->getKind() == AK_ConstraintOpsToRC;2440}24412442void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2443};24442445/// Generates code to create a temporary register which can be used to chain2446/// instructions together.2447class MakeTempRegisterAction : public MatchAction {2448private:2449LLTCodeGenOrTempType Ty;2450unsigned TempRegID;24512452public:2453MakeTempRegisterAction(const LLTCodeGenOrTempType &Ty, unsigned TempRegID)2454: MatchAction(AK_MakeTempReg), Ty(Ty), TempRegID(TempRegID) {2455if (Ty.isLLTCodeGen())2456KnownTypes.insert(Ty.getLLTCodeGen());2457}24582459static bool classof(const MatchAction *A) {2460return A->getKind() == AK_MakeTempReg;2461}24622463void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override;2464};24652466} // namespace gi2467} // namespace llvm24682469#endif247024712472