1*0fca6ea1SDimitry Andric //===- GlobalISelMatchTable.h ---------------------------------------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric /// \file 10*0fca6ea1SDimitry Andric /// This file contains the code related to the GlobalISel Match Table emitted by 11*0fca6ea1SDimitry Andric /// GlobalISelEmitter.cpp. The generated match table is interpreted at runtime 12*0fca6ea1SDimitry Andric /// by `GIMatchTableExecutorImpl.h` to match & apply ISel patterns. 13*0fca6ea1SDimitry Andric /// 14*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 15*0fca6ea1SDimitry Andric 16*0fca6ea1SDimitry Andric #ifndef LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLE_H 17*0fca6ea1SDimitry Andric #define LLVM_UTILS_TABLEGEN_GLOBALISELMATCHTABLE_H 18*0fca6ea1SDimitry Andric 19*0fca6ea1SDimitry Andric #include "Common/CodeGenDAGPatterns.h" 20*0fca6ea1SDimitry Andric #include "llvm/ADT/ArrayRef.h" 21*0fca6ea1SDimitry Andric #include "llvm/ADT/DenseMap.h" 22*0fca6ea1SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 23*0fca6ea1SDimitry Andric #include "llvm/ADT/StringMap.h" 24*0fca6ea1SDimitry Andric #include "llvm/ADT/StringRef.h" 25*0fca6ea1SDimitry Andric #include "llvm/CodeGenTypes/LowLevelType.h" 26*0fca6ea1SDimitry Andric #include "llvm/Support/Error.h" 27*0fca6ea1SDimitry Andric #include "llvm/Support/SaveAndRestore.h" 28*0fca6ea1SDimitry Andric #include <deque> 29*0fca6ea1SDimitry Andric #include <list> 30*0fca6ea1SDimitry Andric #include <map> 31*0fca6ea1SDimitry Andric #include <memory> 32*0fca6ea1SDimitry Andric #include <optional> 33*0fca6ea1SDimitry Andric #include <set> 34*0fca6ea1SDimitry Andric #include <string> 35*0fca6ea1SDimitry Andric #include <vector> 36*0fca6ea1SDimitry Andric 37*0fca6ea1SDimitry Andric namespace llvm { 38*0fca6ea1SDimitry Andric 39*0fca6ea1SDimitry Andric class raw_ostream; 40*0fca6ea1SDimitry Andric class Record; 41*0fca6ea1SDimitry Andric class SMLoc; 42*0fca6ea1SDimitry Andric class CodeGenRegisterClass; 43*0fca6ea1SDimitry Andric 44*0fca6ea1SDimitry Andric // Use a namespace to avoid conflicts because there's some fairly generic names 45*0fca6ea1SDimitry Andric // in there (e.g. Matcher). 46*0fca6ea1SDimitry Andric namespace gi { 47*0fca6ea1SDimitry Andric class MatchTable; 48*0fca6ea1SDimitry Andric class Matcher; 49*0fca6ea1SDimitry Andric class OperandMatcher; 50*0fca6ea1SDimitry Andric class MatchAction; 51*0fca6ea1SDimitry Andric class PredicateMatcher; 52*0fca6ea1SDimitry Andric class InstructionMatcher; 53*0fca6ea1SDimitry Andric 54*0fca6ea1SDimitry Andric enum { 55*0fca6ea1SDimitry Andric GISF_IgnoreCopies = 0x1, 56*0fca6ea1SDimitry Andric }; 57*0fca6ea1SDimitry Andric 58*0fca6ea1SDimitry Andric using GISelFlags = std::uint16_t; 59*0fca6ea1SDimitry Andric 60*0fca6ea1SDimitry Andric //===- Helper functions ---------------------------------------------------===// 61*0fca6ea1SDimitry Andric 62*0fca6ea1SDimitry Andric void emitEncodingMacrosDef(raw_ostream &OS); 63*0fca6ea1SDimitry Andric void emitEncodingMacrosUndef(raw_ostream &OS); 64*0fca6ea1SDimitry Andric 65*0fca6ea1SDimitry Andric std::string getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset, 66*0fca6ea1SDimitry Andric int HwModeIdx); 67*0fca6ea1SDimitry Andric 68*0fca6ea1SDimitry Andric /// Takes a sequence of \p Rules and group them based on the predicates 69*0fca6ea1SDimitry Andric /// they share. \p MatcherStorage is used as a memory container 70*0fca6ea1SDimitry Andric /// for the group that are created as part of this process. 71*0fca6ea1SDimitry Andric /// 72*0fca6ea1SDimitry Andric /// What this optimization does looks like if GroupT = GroupMatcher: 73*0fca6ea1SDimitry Andric /// Output without optimization: 74*0fca6ea1SDimitry Andric /// \verbatim 75*0fca6ea1SDimitry Andric /// # R1 76*0fca6ea1SDimitry Andric /// # predicate A 77*0fca6ea1SDimitry Andric /// # predicate B 78*0fca6ea1SDimitry Andric /// ... 79*0fca6ea1SDimitry Andric /// # R2 80*0fca6ea1SDimitry Andric /// # predicate A // <-- effectively this is going to be checked twice. 81*0fca6ea1SDimitry Andric /// // Once in R1 and once in R2. 82*0fca6ea1SDimitry Andric /// # predicate C 83*0fca6ea1SDimitry Andric /// \endverbatim 84*0fca6ea1SDimitry Andric /// Output with optimization: 85*0fca6ea1SDimitry Andric /// \verbatim 86*0fca6ea1SDimitry Andric /// # Group1_2 87*0fca6ea1SDimitry Andric /// # predicate A // <-- Check is now shared. 88*0fca6ea1SDimitry Andric /// # R1 89*0fca6ea1SDimitry Andric /// # predicate B 90*0fca6ea1SDimitry Andric /// # R2 91*0fca6ea1SDimitry Andric /// # predicate C 92*0fca6ea1SDimitry Andric /// \endverbatim 93*0fca6ea1SDimitry Andric template <class GroupT> 94*0fca6ea1SDimitry Andric std::vector<Matcher *> 95*0fca6ea1SDimitry Andric optimizeRules(ArrayRef<Matcher *> Rules, 96*0fca6ea1SDimitry Andric std::vector<std::unique_ptr<Matcher>> &MatcherStorage); 97*0fca6ea1SDimitry Andric 98*0fca6ea1SDimitry Andric /// A record to be stored in a MatchTable. 99*0fca6ea1SDimitry Andric /// 100*0fca6ea1SDimitry Andric /// This class represents any and all output that may be required to emit the 101*0fca6ea1SDimitry Andric /// MatchTable. Instances are most often configured to represent an opcode or 102*0fca6ea1SDimitry Andric /// value that will be emitted to the table with some formatting but it can also 103*0fca6ea1SDimitry Andric /// represent commas, comments, and other formatting instructions. 104*0fca6ea1SDimitry Andric struct MatchTableRecord { 105*0fca6ea1SDimitry Andric enum RecordFlagsBits { 106*0fca6ea1SDimitry Andric MTRF_None = 0x0, 107*0fca6ea1SDimitry Andric /// Causes EmitStr to be formatted as comment when emitted. 108*0fca6ea1SDimitry Andric MTRF_Comment = 0x1, 109*0fca6ea1SDimitry Andric /// Causes the record value to be followed by a comma when emitted. 110*0fca6ea1SDimitry Andric MTRF_CommaFollows = 0x2, 111*0fca6ea1SDimitry Andric /// Causes the record value to be followed by a line break when emitted. 112*0fca6ea1SDimitry Andric MTRF_LineBreakFollows = 0x4, 113*0fca6ea1SDimitry Andric /// Indicates that the record defines a label and causes an additional 114*0fca6ea1SDimitry Andric /// comment to be emitted containing the index of the label. 115*0fca6ea1SDimitry Andric MTRF_Label = 0x8, 116*0fca6ea1SDimitry Andric /// Causes the record to be emitted as the index of the label specified by 117*0fca6ea1SDimitry Andric /// LabelID along with a comment indicating where that label is. 118*0fca6ea1SDimitry Andric MTRF_JumpTarget = 0x10, 119*0fca6ea1SDimitry Andric /// Causes the formatter to add a level of indentation before emitting the 120*0fca6ea1SDimitry Andric /// record. 121*0fca6ea1SDimitry Andric MTRF_Indent = 0x20, 122*0fca6ea1SDimitry Andric /// Causes the formatter to remove a level of indentation after emitting the 123*0fca6ea1SDimitry Andric /// record. 124*0fca6ea1SDimitry Andric MTRF_Outdent = 0x40, 125*0fca6ea1SDimitry Andric /// Causes the formatter to not use encoding macros to emit this multi-byte 126*0fca6ea1SDimitry Andric /// value. 127*0fca6ea1SDimitry Andric MTRF_PreEncoded = 0x80, 128*0fca6ea1SDimitry Andric }; 129*0fca6ea1SDimitry Andric 130*0fca6ea1SDimitry Andric /// When MTRF_Label or MTRF_JumpTarget is used, indicates a label id to 131*0fca6ea1SDimitry Andric /// reference or define. 132*0fca6ea1SDimitry Andric unsigned LabelID; 133*0fca6ea1SDimitry Andric /// The string to emit. Depending on the MTRF_* flags it may be a comment, a 134*0fca6ea1SDimitry Andric /// value, a label name. 135*0fca6ea1SDimitry Andric std::string EmitStr; 136*0fca6ea1SDimitry Andric 137*0fca6ea1SDimitry Andric private: 138*0fca6ea1SDimitry Andric /// The number of MatchTable elements described by this record. Comments are 0 139*0fca6ea1SDimitry Andric /// while values are typically 1. Values >1 may occur when we need to emit 140*0fca6ea1SDimitry Andric /// values that exceed the size of a MatchTable element. 141*0fca6ea1SDimitry Andric unsigned NumElements; 142*0fca6ea1SDimitry Andric 143*0fca6ea1SDimitry Andric public: 144*0fca6ea1SDimitry Andric /// A bitfield of RecordFlagsBits flags. 145*0fca6ea1SDimitry Andric unsigned Flags; 146*0fca6ea1SDimitry Andric 147*0fca6ea1SDimitry Andric /// The actual run-time value, if known 148*0fca6ea1SDimitry Andric int64_t RawValue; 149*0fca6ea1SDimitry Andric 150*0fca6ea1SDimitry Andric MatchTableRecord(std::optional<unsigned> LabelID_, StringRef EmitStr, 151*0fca6ea1SDimitry Andric unsigned NumElements, unsigned Flags, 152*0fca6ea1SDimitry Andric int64_t RawValue = std::numeric_limits<int64_t>::min()) 153*0fca6ea1SDimitry Andric : LabelID(LabelID_.value_or(~0u)), EmitStr(EmitStr), 154*0fca6ea1SDimitry Andric NumElements(NumElements), Flags(Flags), RawValue(RawValue) { 155*0fca6ea1SDimitry Andric assert((!LabelID_ || LabelID != ~0u) && 156*0fca6ea1SDimitry Andric "This value is reserved for non-labels"); 157*0fca6ea1SDimitry Andric } 158*0fca6ea1SDimitry Andric MatchTableRecord(const MatchTableRecord &Other) = default; 159*0fca6ea1SDimitry Andric MatchTableRecord(MatchTableRecord &&Other) = default; 160*0fca6ea1SDimitry Andric 161*0fca6ea1SDimitry Andric /// Useful if a Match Table Record gets optimized out 162*0fca6ea1SDimitry Andric void turnIntoComment() { 163*0fca6ea1SDimitry Andric Flags |= MTRF_Comment; 164*0fca6ea1SDimitry Andric Flags &= ~MTRF_CommaFollows; 165*0fca6ea1SDimitry Andric NumElements = 0; 166*0fca6ea1SDimitry Andric } 167*0fca6ea1SDimitry Andric 168*0fca6ea1SDimitry Andric /// For Jump Table generation purposes 169*0fca6ea1SDimitry Andric bool operator<(const MatchTableRecord &Other) const { 170*0fca6ea1SDimitry Andric return RawValue < Other.RawValue; 171*0fca6ea1SDimitry Andric } 172*0fca6ea1SDimitry Andric int64_t getRawValue() const { return RawValue; } 173*0fca6ea1SDimitry Andric 174*0fca6ea1SDimitry Andric void emit(raw_ostream &OS, bool LineBreakNextAfterThis, 175*0fca6ea1SDimitry Andric const MatchTable &Table) const; 176*0fca6ea1SDimitry Andric unsigned size() const { return NumElements; } 177*0fca6ea1SDimitry Andric }; 178*0fca6ea1SDimitry Andric 179*0fca6ea1SDimitry Andric /// Holds the contents of a generated MatchTable to enable formatting and the 180*0fca6ea1SDimitry Andric /// necessary index tracking needed to support GIM_Try. 181*0fca6ea1SDimitry Andric class MatchTable { 182*0fca6ea1SDimitry Andric /// An unique identifier for the table. The generated table will be named 183*0fca6ea1SDimitry Andric /// MatchTable${ID}. 184*0fca6ea1SDimitry Andric unsigned ID; 185*0fca6ea1SDimitry Andric /// The records that make up the table. Also includes comments describing the 186*0fca6ea1SDimitry Andric /// values being emitted and line breaks to format it. 187*0fca6ea1SDimitry Andric std::vector<MatchTableRecord> Contents; 188*0fca6ea1SDimitry Andric /// The currently defined labels. 189*0fca6ea1SDimitry Andric DenseMap<unsigned, unsigned> LabelMap; 190*0fca6ea1SDimitry Andric /// Tracks the sum of MatchTableRecord::NumElements as the table is built. 191*0fca6ea1SDimitry Andric unsigned CurrentSize = 0; 192*0fca6ea1SDimitry Andric /// A unique identifier for a MatchTable label. 193*0fca6ea1SDimitry Andric unsigned CurrentLabelID = 0; 194*0fca6ea1SDimitry Andric /// Determines if the table should be instrumented for rule coverage tracking. 195*0fca6ea1SDimitry Andric bool IsWithCoverage; 196*0fca6ea1SDimitry Andric /// Whether this table is for the GISel combiner. 197*0fca6ea1SDimitry Andric bool IsCombinerTable; 198*0fca6ea1SDimitry Andric 199*0fca6ea1SDimitry Andric public: 200*0fca6ea1SDimitry Andric static MatchTableRecord LineBreak; 201*0fca6ea1SDimitry Andric static MatchTableRecord Comment(StringRef Comment); 202*0fca6ea1SDimitry Andric static MatchTableRecord Opcode(StringRef Opcode, int IndentAdjust = 0); 203*0fca6ea1SDimitry Andric static MatchTableRecord NamedValue(unsigned NumBytes, StringRef NamedValue); 204*0fca6ea1SDimitry Andric static MatchTableRecord NamedValue(unsigned NumBytes, StringRef NamedValue, 205*0fca6ea1SDimitry Andric int64_t RawValue); 206*0fca6ea1SDimitry Andric static MatchTableRecord NamedValue(unsigned NumBytes, StringRef Namespace, 207*0fca6ea1SDimitry Andric StringRef NamedValue); 208*0fca6ea1SDimitry Andric static MatchTableRecord NamedValue(unsigned NumBytes, StringRef Namespace, 209*0fca6ea1SDimitry Andric StringRef NamedValue, int64_t RawValue); 210*0fca6ea1SDimitry Andric static MatchTableRecord IntValue(unsigned NumBytes, int64_t IntValue); 211*0fca6ea1SDimitry Andric static MatchTableRecord ULEB128Value(uint64_t IntValue); 212*0fca6ea1SDimitry Andric static MatchTableRecord Label(unsigned LabelID); 213*0fca6ea1SDimitry Andric static MatchTableRecord JumpTarget(unsigned LabelID); 214*0fca6ea1SDimitry Andric 215*0fca6ea1SDimitry Andric static MatchTable buildTable(ArrayRef<Matcher *> Rules, bool WithCoverage, 216*0fca6ea1SDimitry Andric bool IsCombiner = false); 217*0fca6ea1SDimitry Andric 218*0fca6ea1SDimitry Andric MatchTable(bool WithCoverage, bool IsCombinerTable, unsigned ID = 0) 219*0fca6ea1SDimitry Andric : ID(ID), IsWithCoverage(WithCoverage), IsCombinerTable(IsCombinerTable) { 220*0fca6ea1SDimitry Andric } 221*0fca6ea1SDimitry Andric 222*0fca6ea1SDimitry Andric bool isWithCoverage() const { return IsWithCoverage; } 223*0fca6ea1SDimitry Andric bool isCombiner() const { return IsCombinerTable; } 224*0fca6ea1SDimitry Andric 225*0fca6ea1SDimitry Andric void push_back(const MatchTableRecord &Value) { 226*0fca6ea1SDimitry Andric if (Value.Flags & MatchTableRecord::MTRF_Label) 227*0fca6ea1SDimitry Andric defineLabel(Value.LabelID); 228*0fca6ea1SDimitry Andric Contents.push_back(Value); 229*0fca6ea1SDimitry Andric CurrentSize += Value.size(); 230*0fca6ea1SDimitry Andric } 231*0fca6ea1SDimitry Andric 232*0fca6ea1SDimitry Andric unsigned allocateLabelID() { return CurrentLabelID++; } 233*0fca6ea1SDimitry Andric 234*0fca6ea1SDimitry Andric void defineLabel(unsigned LabelID) { 235*0fca6ea1SDimitry Andric LabelMap.insert(std::pair(LabelID, CurrentSize)); 236*0fca6ea1SDimitry Andric } 237*0fca6ea1SDimitry Andric 238*0fca6ea1SDimitry Andric unsigned getLabelIndex(unsigned LabelID) const { 239*0fca6ea1SDimitry Andric const auto I = LabelMap.find(LabelID); 240*0fca6ea1SDimitry Andric assert(I != LabelMap.end() && "Use of undeclared label"); 241*0fca6ea1SDimitry Andric return I->second; 242*0fca6ea1SDimitry Andric } 243*0fca6ea1SDimitry Andric 244*0fca6ea1SDimitry Andric void emitUse(raw_ostream &OS) const; 245*0fca6ea1SDimitry Andric void emitDeclaration(raw_ostream &OS) const; 246*0fca6ea1SDimitry Andric }; 247*0fca6ea1SDimitry Andric 248*0fca6ea1SDimitry Andric inline MatchTable &operator<<(MatchTable &Table, 249*0fca6ea1SDimitry Andric const MatchTableRecord &Value) { 250*0fca6ea1SDimitry Andric Table.push_back(Value); 251*0fca6ea1SDimitry Andric return Table; 252*0fca6ea1SDimitry Andric } 253*0fca6ea1SDimitry Andric 254*0fca6ea1SDimitry Andric /// This class stands in for LLT wherever we want to tablegen-erate an 255*0fca6ea1SDimitry Andric /// equivalent at compiler run-time. 256*0fca6ea1SDimitry Andric class LLTCodeGen { 257*0fca6ea1SDimitry Andric private: 258*0fca6ea1SDimitry Andric LLT Ty; 259*0fca6ea1SDimitry Andric 260*0fca6ea1SDimitry Andric public: 261*0fca6ea1SDimitry Andric LLTCodeGen() = default; 262*0fca6ea1SDimitry Andric LLTCodeGen(const LLT &Ty) : Ty(Ty) {} 263*0fca6ea1SDimitry Andric 264*0fca6ea1SDimitry Andric std::string getCxxEnumValue() const; 265*0fca6ea1SDimitry Andric 266*0fca6ea1SDimitry Andric void emitCxxEnumValue(raw_ostream &OS) const; 267*0fca6ea1SDimitry Andric void emitCxxConstructorCall(raw_ostream &OS) const; 268*0fca6ea1SDimitry Andric 269*0fca6ea1SDimitry Andric const LLT &get() const { return Ty; } 270*0fca6ea1SDimitry Andric 271*0fca6ea1SDimitry Andric /// This ordering is used for std::unique() and llvm::sort(). There's no 272*0fca6ea1SDimitry Andric /// particular logic behind the order but either A < B or B < A must be 273*0fca6ea1SDimitry Andric /// true if A != B. 274*0fca6ea1SDimitry Andric bool operator<(const LLTCodeGen &Other) const; 275*0fca6ea1SDimitry Andric bool operator==(const LLTCodeGen &B) const { return Ty == B.Ty; } 276*0fca6ea1SDimitry Andric }; 277*0fca6ea1SDimitry Andric 278*0fca6ea1SDimitry Andric // Track all types that are used so we can emit the corresponding enum. 279*0fca6ea1SDimitry Andric extern std::set<LLTCodeGen> KnownTypes; 280*0fca6ea1SDimitry Andric 281*0fca6ea1SDimitry Andric /// Convert an MVT to an equivalent LLT if possible, or the invalid LLT() for 282*0fca6ea1SDimitry Andric /// MVTs that don't map cleanly to an LLT (e.g., iPTR, *any, ...). 283*0fca6ea1SDimitry Andric std::optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT); 284*0fca6ea1SDimitry Andric 285*0fca6ea1SDimitry Andric using TempTypeIdx = int64_t; 286*0fca6ea1SDimitry Andric class LLTCodeGenOrTempType { 287*0fca6ea1SDimitry Andric public: 288*0fca6ea1SDimitry Andric LLTCodeGenOrTempType(const LLTCodeGen &LLT) : Data(LLT) {} 289*0fca6ea1SDimitry Andric LLTCodeGenOrTempType(TempTypeIdx TempTy) : Data(TempTy) {} 290*0fca6ea1SDimitry Andric 291*0fca6ea1SDimitry Andric bool isLLTCodeGen() const { return std::holds_alternative<LLTCodeGen>(Data); } 292*0fca6ea1SDimitry Andric bool isTempTypeIdx() const { 293*0fca6ea1SDimitry Andric return std::holds_alternative<TempTypeIdx>(Data); 294*0fca6ea1SDimitry Andric } 295*0fca6ea1SDimitry Andric 296*0fca6ea1SDimitry Andric const LLTCodeGen &getLLTCodeGen() const { 297*0fca6ea1SDimitry Andric assert(isLLTCodeGen()); 298*0fca6ea1SDimitry Andric return std::get<LLTCodeGen>(Data); 299*0fca6ea1SDimitry Andric } 300*0fca6ea1SDimitry Andric 301*0fca6ea1SDimitry Andric TempTypeIdx getTempTypeIdx() const { 302*0fca6ea1SDimitry Andric assert(isTempTypeIdx()); 303*0fca6ea1SDimitry Andric return std::get<TempTypeIdx>(Data); 304*0fca6ea1SDimitry Andric } 305*0fca6ea1SDimitry Andric 306*0fca6ea1SDimitry Andric private: 307*0fca6ea1SDimitry Andric std::variant<LLTCodeGen, TempTypeIdx> Data; 308*0fca6ea1SDimitry Andric }; 309*0fca6ea1SDimitry Andric 310*0fca6ea1SDimitry Andric inline MatchTable &operator<<(MatchTable &Table, 311*0fca6ea1SDimitry Andric const LLTCodeGenOrTempType &Ty) { 312*0fca6ea1SDimitry Andric if (Ty.isLLTCodeGen()) 313*0fca6ea1SDimitry Andric Table << MatchTable::NamedValue(1, Ty.getLLTCodeGen().getCxxEnumValue()); 314*0fca6ea1SDimitry Andric else 315*0fca6ea1SDimitry Andric Table << MatchTable::IntValue(1, Ty.getTempTypeIdx()); 316*0fca6ea1SDimitry Andric return Table; 317*0fca6ea1SDimitry Andric } 318*0fca6ea1SDimitry Andric 319*0fca6ea1SDimitry Andric //===- Matchers -----------------------------------------------------------===// 320*0fca6ea1SDimitry Andric class Matcher { 321*0fca6ea1SDimitry Andric public: 322*0fca6ea1SDimitry Andric virtual ~Matcher(); 323*0fca6ea1SDimitry Andric virtual void optimize(); 324*0fca6ea1SDimitry Andric virtual void emit(MatchTable &Table) = 0; 325*0fca6ea1SDimitry Andric 326*0fca6ea1SDimitry Andric virtual bool hasFirstCondition() const = 0; 327*0fca6ea1SDimitry Andric virtual const PredicateMatcher &getFirstCondition() const = 0; 328*0fca6ea1SDimitry Andric virtual std::unique_ptr<PredicateMatcher> popFirstCondition() = 0; 329*0fca6ea1SDimitry Andric }; 330*0fca6ea1SDimitry Andric 331*0fca6ea1SDimitry Andric class GroupMatcher final : public Matcher { 332*0fca6ea1SDimitry Andric /// Conditions that form a common prefix of all the matchers contained. 333*0fca6ea1SDimitry Andric SmallVector<std::unique_ptr<PredicateMatcher>, 1> Conditions; 334*0fca6ea1SDimitry Andric 335*0fca6ea1SDimitry Andric /// All the nested matchers, sharing a common prefix. 336*0fca6ea1SDimitry Andric std::vector<Matcher *> Matchers; 337*0fca6ea1SDimitry Andric 338*0fca6ea1SDimitry Andric /// An owning collection for any auxiliary matchers created while optimizing 339*0fca6ea1SDimitry Andric /// nested matchers contained. 340*0fca6ea1SDimitry Andric std::vector<std::unique_ptr<Matcher>> MatcherStorage; 341*0fca6ea1SDimitry Andric 342*0fca6ea1SDimitry Andric public: 343*0fca6ea1SDimitry Andric /// Add a matcher to the collection of nested matchers if it meets the 344*0fca6ea1SDimitry Andric /// requirements, and return true. If it doesn't, do nothing and return false. 345*0fca6ea1SDimitry Andric /// 346*0fca6ea1SDimitry Andric /// Expected to preserve its argument, so it could be moved out later on. 347*0fca6ea1SDimitry Andric bool addMatcher(Matcher &Candidate); 348*0fca6ea1SDimitry Andric 349*0fca6ea1SDimitry Andric /// Mark the matcher as fully-built and ensure any invariants expected by both 350*0fca6ea1SDimitry Andric /// optimize() and emit(...) methods. Generally, both sequences of calls 351*0fca6ea1SDimitry Andric /// are expected to lead to a sensible result: 352*0fca6ea1SDimitry Andric /// 353*0fca6ea1SDimitry Andric /// addMatcher(...)*; finalize(); optimize(); emit(...); and 354*0fca6ea1SDimitry Andric /// addMatcher(...)*; finalize(); emit(...); 355*0fca6ea1SDimitry Andric /// 356*0fca6ea1SDimitry Andric /// or generally 357*0fca6ea1SDimitry Andric /// 358*0fca6ea1SDimitry Andric /// addMatcher(...)*; finalize(); { optimize()*; emit(...); }* 359*0fca6ea1SDimitry Andric /// 360*0fca6ea1SDimitry Andric /// Multiple calls to optimize() are expected to be handled gracefully, though 361*0fca6ea1SDimitry Andric /// optimize() is not expected to be idempotent. Multiple calls to finalize() 362*0fca6ea1SDimitry Andric /// aren't generally supported. emit(...) is expected to be non-mutating and 363*0fca6ea1SDimitry Andric /// producing the exact same results upon repeated calls. 364*0fca6ea1SDimitry Andric /// 365*0fca6ea1SDimitry Andric /// addMatcher() calls after the finalize() call are not supported. 366*0fca6ea1SDimitry Andric /// 367*0fca6ea1SDimitry Andric /// finalize() and optimize() are both allowed to mutate the contained 368*0fca6ea1SDimitry Andric /// matchers, so moving them out after finalize() is not supported. 369*0fca6ea1SDimitry Andric void finalize(); 370*0fca6ea1SDimitry Andric void optimize() override; 371*0fca6ea1SDimitry Andric void emit(MatchTable &Table) override; 372*0fca6ea1SDimitry Andric 373*0fca6ea1SDimitry Andric /// Could be used to move out the matchers added previously, unless finalize() 374*0fca6ea1SDimitry Andric /// has been already called. If any of the matchers are moved out, the group 375*0fca6ea1SDimitry Andric /// becomes safe to destroy, but not safe to re-use for anything else. 376*0fca6ea1SDimitry Andric iterator_range<std::vector<Matcher *>::iterator> matchers() { 377*0fca6ea1SDimitry Andric return make_range(Matchers.begin(), Matchers.end()); 378*0fca6ea1SDimitry Andric } 379*0fca6ea1SDimitry Andric size_t size() const { return Matchers.size(); } 380*0fca6ea1SDimitry Andric bool empty() const { return Matchers.empty(); } 381*0fca6ea1SDimitry Andric 382*0fca6ea1SDimitry Andric std::unique_ptr<PredicateMatcher> popFirstCondition() override { 383*0fca6ea1SDimitry Andric assert(!Conditions.empty() && 384*0fca6ea1SDimitry Andric "Trying to pop a condition from a condition-less group"); 385*0fca6ea1SDimitry Andric std::unique_ptr<PredicateMatcher> P = std::move(Conditions.front()); 386*0fca6ea1SDimitry Andric Conditions.erase(Conditions.begin()); 387*0fca6ea1SDimitry Andric return P; 388*0fca6ea1SDimitry Andric } 389*0fca6ea1SDimitry Andric const PredicateMatcher &getFirstCondition() const override { 390*0fca6ea1SDimitry Andric assert(!Conditions.empty() && 391*0fca6ea1SDimitry Andric "Trying to get a condition from a condition-less group"); 392*0fca6ea1SDimitry Andric return *Conditions.front(); 393*0fca6ea1SDimitry Andric } 394*0fca6ea1SDimitry Andric bool hasFirstCondition() const override { return !Conditions.empty(); } 395*0fca6ea1SDimitry Andric 396*0fca6ea1SDimitry Andric private: 397*0fca6ea1SDimitry Andric /// See if a candidate matcher could be added to this group solely by 398*0fca6ea1SDimitry Andric /// analyzing its first condition. 399*0fca6ea1SDimitry Andric bool candidateConditionMatches(const PredicateMatcher &Predicate) const; 400*0fca6ea1SDimitry Andric }; 401*0fca6ea1SDimitry Andric 402*0fca6ea1SDimitry Andric class SwitchMatcher : public Matcher { 403*0fca6ea1SDimitry Andric /// All the nested matchers, representing distinct switch-cases. The first 404*0fca6ea1SDimitry Andric /// conditions (as Matcher::getFirstCondition() reports) of all the nested 405*0fca6ea1SDimitry Andric /// matchers must share the same type and path to a value they check, in other 406*0fca6ea1SDimitry Andric /// words, be isIdenticalDownToValue, but have different values they check 407*0fca6ea1SDimitry Andric /// against. 408*0fca6ea1SDimitry Andric std::vector<Matcher *> Matchers; 409*0fca6ea1SDimitry Andric 410*0fca6ea1SDimitry Andric /// The representative condition, with a type and a path (InsnVarID and OpIdx 411*0fca6ea1SDimitry Andric /// in most cases) shared by all the matchers contained. 412*0fca6ea1SDimitry Andric std::unique_ptr<PredicateMatcher> Condition = nullptr; 413*0fca6ea1SDimitry Andric 414*0fca6ea1SDimitry Andric /// Temporary set used to check that the case values don't repeat within the 415*0fca6ea1SDimitry Andric /// same switch. 416*0fca6ea1SDimitry Andric std::set<MatchTableRecord> Values; 417*0fca6ea1SDimitry Andric 418*0fca6ea1SDimitry Andric /// An owning collection for any auxiliary matchers created while optimizing 419*0fca6ea1SDimitry Andric /// nested matchers contained. 420*0fca6ea1SDimitry Andric std::vector<std::unique_ptr<Matcher>> MatcherStorage; 421*0fca6ea1SDimitry Andric 422*0fca6ea1SDimitry Andric public: 423*0fca6ea1SDimitry Andric bool addMatcher(Matcher &Candidate); 424*0fca6ea1SDimitry Andric 425*0fca6ea1SDimitry Andric void finalize(); 426*0fca6ea1SDimitry Andric void emit(MatchTable &Table) override; 427*0fca6ea1SDimitry Andric 428*0fca6ea1SDimitry Andric iterator_range<std::vector<Matcher *>::iterator> matchers() { 429*0fca6ea1SDimitry Andric return make_range(Matchers.begin(), Matchers.end()); 430*0fca6ea1SDimitry Andric } 431*0fca6ea1SDimitry Andric size_t size() const { return Matchers.size(); } 432*0fca6ea1SDimitry Andric bool empty() const { return Matchers.empty(); } 433*0fca6ea1SDimitry Andric 434*0fca6ea1SDimitry Andric std::unique_ptr<PredicateMatcher> popFirstCondition() override { 435*0fca6ea1SDimitry Andric // SwitchMatcher doesn't have a common first condition for its cases, as all 436*0fca6ea1SDimitry Andric // the cases only share a kind of a value (a type and a path to it) they 437*0fca6ea1SDimitry Andric // match, but deliberately differ in the actual value they match. 438*0fca6ea1SDimitry Andric llvm_unreachable("Trying to pop a condition from a condition-less group"); 439*0fca6ea1SDimitry Andric } 440*0fca6ea1SDimitry Andric 441*0fca6ea1SDimitry Andric const PredicateMatcher &getFirstCondition() const override { 442*0fca6ea1SDimitry Andric llvm_unreachable("Trying to pop a condition from a condition-less group"); 443*0fca6ea1SDimitry Andric } 444*0fca6ea1SDimitry Andric 445*0fca6ea1SDimitry Andric bool hasFirstCondition() const override { return false; } 446*0fca6ea1SDimitry Andric 447*0fca6ea1SDimitry Andric private: 448*0fca6ea1SDimitry Andric /// See if the predicate type has a Switch-implementation for it. 449*0fca6ea1SDimitry Andric static bool isSupportedPredicateType(const PredicateMatcher &Predicate); 450*0fca6ea1SDimitry Andric 451*0fca6ea1SDimitry Andric bool candidateConditionMatches(const PredicateMatcher &Predicate) const; 452*0fca6ea1SDimitry Andric 453*0fca6ea1SDimitry Andric /// emit()-helper 454*0fca6ea1SDimitry Andric static void emitPredicateSpecificOpcodes(const PredicateMatcher &P, 455*0fca6ea1SDimitry Andric MatchTable &Table); 456*0fca6ea1SDimitry Andric }; 457*0fca6ea1SDimitry Andric 458*0fca6ea1SDimitry Andric /// Generates code to check that a match rule matches. 459*0fca6ea1SDimitry Andric class RuleMatcher : public Matcher { 460*0fca6ea1SDimitry Andric public: 461*0fca6ea1SDimitry Andric using ActionList = std::list<std::unique_ptr<MatchAction>>; 462*0fca6ea1SDimitry Andric using action_iterator = ActionList::iterator; 463*0fca6ea1SDimitry Andric 464*0fca6ea1SDimitry Andric protected: 465*0fca6ea1SDimitry Andric /// A list of matchers that all need to succeed for the current rule to match. 466*0fca6ea1SDimitry Andric /// FIXME: This currently supports a single match position but could be 467*0fca6ea1SDimitry Andric /// extended to support multiple positions to support div/rem fusion or 468*0fca6ea1SDimitry Andric /// load-multiple instructions. 469*0fca6ea1SDimitry Andric using MatchersTy = std::vector<std::unique_ptr<InstructionMatcher>>; 470*0fca6ea1SDimitry Andric MatchersTy Matchers; 471*0fca6ea1SDimitry Andric 472*0fca6ea1SDimitry Andric /// A list of actions that need to be taken when all predicates in this rule 473*0fca6ea1SDimitry Andric /// have succeeded. 474*0fca6ea1SDimitry Andric ActionList Actions; 475*0fca6ea1SDimitry Andric 476*0fca6ea1SDimitry Andric /// Combiners can sometimes just run C++ code to finish matching a rule & 477*0fca6ea1SDimitry Andric /// mutate instructions instead of relying on MatchActions. Empty if unused. 478*0fca6ea1SDimitry Andric std::string CustomCXXAction; 479*0fca6ea1SDimitry Andric 480*0fca6ea1SDimitry Andric using DefinedInsnVariablesMap = std::map<InstructionMatcher *, unsigned>; 481*0fca6ea1SDimitry Andric 482*0fca6ea1SDimitry Andric /// A map of instruction matchers to the local variables 483*0fca6ea1SDimitry Andric DefinedInsnVariablesMap InsnVariableIDs; 484*0fca6ea1SDimitry Andric 485*0fca6ea1SDimitry Andric using MutatableInsnSet = SmallPtrSet<InstructionMatcher *, 4>; 486*0fca6ea1SDimitry Andric 487*0fca6ea1SDimitry Andric // The set of instruction matchers that have not yet been claimed for mutation 488*0fca6ea1SDimitry Andric // by a BuildMI. 489*0fca6ea1SDimitry Andric MutatableInsnSet MutatableInsns; 490*0fca6ea1SDimitry Andric 491*0fca6ea1SDimitry Andric /// A map of named operands defined by the matchers that may be referenced by 492*0fca6ea1SDimitry Andric /// the renderers. 493*0fca6ea1SDimitry Andric StringMap<OperandMatcher *> DefinedOperands; 494*0fca6ea1SDimitry Andric 495*0fca6ea1SDimitry Andric /// A map of anonymous physical register operands defined by the matchers that 496*0fca6ea1SDimitry Andric /// may be referenced by the renderers. 497*0fca6ea1SDimitry Andric DenseMap<Record *, OperandMatcher *> PhysRegOperands; 498*0fca6ea1SDimitry Andric 499*0fca6ea1SDimitry Andric /// ID for the next instruction variable defined with 500*0fca6ea1SDimitry Andric /// implicitlyDefineInsnVar() 501*0fca6ea1SDimitry Andric unsigned NextInsnVarID; 502*0fca6ea1SDimitry Andric 503*0fca6ea1SDimitry Andric /// ID for the next output instruction allocated with allocateOutputInsnID() 504*0fca6ea1SDimitry Andric unsigned NextOutputInsnID; 505*0fca6ea1SDimitry Andric 506*0fca6ea1SDimitry Andric /// ID for the next temporary register ID allocated with allocateTempRegID() 507*0fca6ea1SDimitry Andric unsigned NextTempRegID; 508*0fca6ea1SDimitry Andric 509*0fca6ea1SDimitry Andric /// ID for the next recorded type. Starts at -1 and counts down. 510*0fca6ea1SDimitry Andric TempTypeIdx NextTempTypeIdx = -1; 511*0fca6ea1SDimitry Andric 512*0fca6ea1SDimitry Andric // HwMode predicate index for this rule. -1 if no HwMode. 513*0fca6ea1SDimitry Andric int HwModeIdx = -1; 514*0fca6ea1SDimitry Andric 515*0fca6ea1SDimitry Andric /// Current GISelFlags 516*0fca6ea1SDimitry Andric GISelFlags Flags = 0; 517*0fca6ea1SDimitry Andric 518*0fca6ea1SDimitry Andric std::vector<std::string> RequiredSimplePredicates; 519*0fca6ea1SDimitry Andric std::vector<Record *> RequiredFeatures; 520*0fca6ea1SDimitry Andric std::vector<std::unique_ptr<PredicateMatcher>> EpilogueMatchers; 521*0fca6ea1SDimitry Andric 522*0fca6ea1SDimitry Andric DenseSet<unsigned> ErasedInsnIDs; 523*0fca6ea1SDimitry Andric 524*0fca6ea1SDimitry Andric ArrayRef<SMLoc> SrcLoc; 525*0fca6ea1SDimitry Andric 526*0fca6ea1SDimitry Andric typedef std::tuple<Record *, unsigned, unsigned> 527*0fca6ea1SDimitry Andric DefinedComplexPatternSubOperand; 528*0fca6ea1SDimitry Andric typedef StringMap<DefinedComplexPatternSubOperand> 529*0fca6ea1SDimitry Andric DefinedComplexPatternSubOperandMap; 530*0fca6ea1SDimitry Andric /// A map of Symbolic Names to ComplexPattern sub-operands. 531*0fca6ea1SDimitry Andric DefinedComplexPatternSubOperandMap ComplexSubOperands; 532*0fca6ea1SDimitry Andric /// A map used to for multiple referenced error check of ComplexSubOperand. 533*0fca6ea1SDimitry Andric /// ComplexSubOperand can't be referenced multiple from different operands, 534*0fca6ea1SDimitry Andric /// however multiple references from same operand are allowed since that is 535*0fca6ea1SDimitry Andric /// how 'same operand checks' are generated. 536*0fca6ea1SDimitry Andric StringMap<std::string> ComplexSubOperandsParentName; 537*0fca6ea1SDimitry Andric 538*0fca6ea1SDimitry Andric uint64_t RuleID; 539*0fca6ea1SDimitry Andric static uint64_t NextRuleID; 540*0fca6ea1SDimitry Andric 541*0fca6ea1SDimitry Andric GISelFlags updateGISelFlag(GISelFlags CurFlags, const Record *R, 542*0fca6ea1SDimitry Andric StringRef FlagName, GISelFlags FlagBit); 543*0fca6ea1SDimitry Andric 544*0fca6ea1SDimitry Andric public: 545*0fca6ea1SDimitry Andric RuleMatcher(ArrayRef<SMLoc> SrcLoc) 546*0fca6ea1SDimitry Andric : NextInsnVarID(0), NextOutputInsnID(0), NextTempRegID(0), SrcLoc(SrcLoc), 547*0fca6ea1SDimitry Andric RuleID(NextRuleID++) {} 548*0fca6ea1SDimitry Andric RuleMatcher(RuleMatcher &&Other) = default; 549*0fca6ea1SDimitry Andric RuleMatcher &operator=(RuleMatcher &&Other) = default; 550*0fca6ea1SDimitry Andric 551*0fca6ea1SDimitry Andric TempTypeIdx getNextTempTypeIdx() { return NextTempTypeIdx--; } 552*0fca6ea1SDimitry Andric 553*0fca6ea1SDimitry Andric uint64_t getRuleID() const { return RuleID; } 554*0fca6ea1SDimitry Andric 555*0fca6ea1SDimitry Andric InstructionMatcher &addInstructionMatcher(StringRef SymbolicName); 556*0fca6ea1SDimitry Andric void addRequiredFeature(Record *Feature); 557*0fca6ea1SDimitry Andric const std::vector<Record *> &getRequiredFeatures() const; 558*0fca6ea1SDimitry Andric 559*0fca6ea1SDimitry Andric void addHwModeIdx(unsigned Idx) { HwModeIdx = Idx; } 560*0fca6ea1SDimitry Andric int getHwModeIdx() const { return HwModeIdx; } 561*0fca6ea1SDimitry Andric 562*0fca6ea1SDimitry Andric void addRequiredSimplePredicate(StringRef PredName); 563*0fca6ea1SDimitry Andric const std::vector<std::string> &getRequiredSimplePredicates(); 564*0fca6ea1SDimitry Andric 565*0fca6ea1SDimitry Andric /// Attempts to mark \p ID as erased (GIR_EraseFromParent called on it). 566*0fca6ea1SDimitry Andric /// If \p ID has already been erased, returns false and GIR_EraseFromParent 567*0fca6ea1SDimitry Andric /// should NOT be emitted. 568*0fca6ea1SDimitry Andric bool tryEraseInsnID(unsigned ID) { return ErasedInsnIDs.insert(ID).second; } 569*0fca6ea1SDimitry Andric 570*0fca6ea1SDimitry Andric void setCustomCXXAction(StringRef FnEnumName) { 571*0fca6ea1SDimitry Andric CustomCXXAction = FnEnumName.str(); 572*0fca6ea1SDimitry Andric } 573*0fca6ea1SDimitry Andric 574*0fca6ea1SDimitry Andric // Emplaces an action of the specified Kind at the end of the action list. 575*0fca6ea1SDimitry Andric // 576*0fca6ea1SDimitry Andric // Returns a reference to the newly created action. 577*0fca6ea1SDimitry Andric // 578*0fca6ea1SDimitry Andric // Like std::vector::emplace_back(), may invalidate all iterators if the new 579*0fca6ea1SDimitry Andric // size exceeds the capacity. Otherwise, only invalidates the past-the-end 580*0fca6ea1SDimitry Andric // iterator. 581*0fca6ea1SDimitry Andric template <class Kind, class... Args> Kind &addAction(Args &&...args) { 582*0fca6ea1SDimitry Andric Actions.emplace_back(std::make_unique<Kind>(std::forward<Args>(args)...)); 583*0fca6ea1SDimitry Andric return *static_cast<Kind *>(Actions.back().get()); 584*0fca6ea1SDimitry Andric } 585*0fca6ea1SDimitry Andric 586*0fca6ea1SDimitry Andric // Emplaces an action of the specified Kind before the given insertion point. 587*0fca6ea1SDimitry Andric // 588*0fca6ea1SDimitry Andric // Returns an iterator pointing at the newly created instruction. 589*0fca6ea1SDimitry Andric // 590*0fca6ea1SDimitry Andric // Like std::vector::insert(), may invalidate all iterators if the new size 591*0fca6ea1SDimitry Andric // exceeds the capacity. Otherwise, only invalidates the iterators from the 592*0fca6ea1SDimitry Andric // insertion point onwards. 593*0fca6ea1SDimitry Andric template <class Kind, class... Args> 594*0fca6ea1SDimitry Andric action_iterator insertAction(action_iterator InsertPt, Args &&...args) { 595*0fca6ea1SDimitry Andric return Actions.emplace(InsertPt, 596*0fca6ea1SDimitry Andric std::make_unique<Kind>(std::forward<Args>(args)...)); 597*0fca6ea1SDimitry Andric } 598*0fca6ea1SDimitry Andric 599*0fca6ea1SDimitry Andric void setPermanentGISelFlags(GISelFlags V) { Flags = V; } 600*0fca6ea1SDimitry Andric 601*0fca6ea1SDimitry Andric // Update the active GISelFlags based on the GISelFlags Record R. 602*0fca6ea1SDimitry Andric // A SaveAndRestore object is returned so the old GISelFlags are restored 603*0fca6ea1SDimitry Andric // at the end of the scope. 604*0fca6ea1SDimitry Andric SaveAndRestore<GISelFlags> setGISelFlags(const Record *R); 605*0fca6ea1SDimitry Andric GISelFlags getGISelFlags() const { return Flags; } 606*0fca6ea1SDimitry Andric 607*0fca6ea1SDimitry Andric /// Define an instruction without emitting any code to do so. 608*0fca6ea1SDimitry Andric unsigned implicitlyDefineInsnVar(InstructionMatcher &Matcher); 609*0fca6ea1SDimitry Andric 610*0fca6ea1SDimitry Andric unsigned getInsnVarID(InstructionMatcher &InsnMatcher) const; 611*0fca6ea1SDimitry Andric DefinedInsnVariablesMap::const_iterator defined_insn_vars_begin() const { 612*0fca6ea1SDimitry Andric return InsnVariableIDs.begin(); 613*0fca6ea1SDimitry Andric } 614*0fca6ea1SDimitry Andric DefinedInsnVariablesMap::const_iterator defined_insn_vars_end() const { 615*0fca6ea1SDimitry Andric return InsnVariableIDs.end(); 616*0fca6ea1SDimitry Andric } 617*0fca6ea1SDimitry Andric iterator_range<typename DefinedInsnVariablesMap::const_iterator> 618*0fca6ea1SDimitry Andric defined_insn_vars() const { 619*0fca6ea1SDimitry Andric return make_range(defined_insn_vars_begin(), defined_insn_vars_end()); 620*0fca6ea1SDimitry Andric } 621*0fca6ea1SDimitry Andric 622*0fca6ea1SDimitry Andric MutatableInsnSet::const_iterator mutatable_insns_begin() const { 623*0fca6ea1SDimitry Andric return MutatableInsns.begin(); 624*0fca6ea1SDimitry Andric } 625*0fca6ea1SDimitry Andric MutatableInsnSet::const_iterator mutatable_insns_end() const { 626*0fca6ea1SDimitry Andric return MutatableInsns.end(); 627*0fca6ea1SDimitry Andric } 628*0fca6ea1SDimitry Andric iterator_range<typename MutatableInsnSet::const_iterator> 629*0fca6ea1SDimitry Andric mutatable_insns() const { 630*0fca6ea1SDimitry Andric return make_range(mutatable_insns_begin(), mutatable_insns_end()); 631*0fca6ea1SDimitry Andric } 632*0fca6ea1SDimitry Andric void reserveInsnMatcherForMutation(InstructionMatcher *InsnMatcher) { 633*0fca6ea1SDimitry Andric bool R = MutatableInsns.erase(InsnMatcher); 634*0fca6ea1SDimitry Andric assert(R && "Reserving a mutatable insn that isn't available"); 635*0fca6ea1SDimitry Andric (void)R; 636*0fca6ea1SDimitry Andric } 637*0fca6ea1SDimitry Andric 638*0fca6ea1SDimitry Andric action_iterator actions_begin() { return Actions.begin(); } 639*0fca6ea1SDimitry Andric action_iterator actions_end() { return Actions.end(); } 640*0fca6ea1SDimitry Andric iterator_range<action_iterator> actions() { 641*0fca6ea1SDimitry Andric return make_range(actions_begin(), actions_end()); 642*0fca6ea1SDimitry Andric } 643*0fca6ea1SDimitry Andric 644*0fca6ea1SDimitry Andric void defineOperand(StringRef SymbolicName, OperandMatcher &OM); 645*0fca6ea1SDimitry Andric 646*0fca6ea1SDimitry Andric void definePhysRegOperand(Record *Reg, OperandMatcher &OM); 647*0fca6ea1SDimitry Andric 648*0fca6ea1SDimitry Andric Error defineComplexSubOperand(StringRef SymbolicName, Record *ComplexPattern, 649*0fca6ea1SDimitry Andric unsigned RendererID, unsigned SubOperandID, 650*0fca6ea1SDimitry Andric StringRef ParentSymbolicName); 651*0fca6ea1SDimitry Andric 652*0fca6ea1SDimitry Andric std::optional<DefinedComplexPatternSubOperand> 653*0fca6ea1SDimitry Andric getComplexSubOperand(StringRef SymbolicName) const { 654*0fca6ea1SDimitry Andric const auto &I = ComplexSubOperands.find(SymbolicName); 655*0fca6ea1SDimitry Andric if (I == ComplexSubOperands.end()) 656*0fca6ea1SDimitry Andric return std::nullopt; 657*0fca6ea1SDimitry Andric return I->second; 658*0fca6ea1SDimitry Andric } 659*0fca6ea1SDimitry Andric 660*0fca6ea1SDimitry Andric InstructionMatcher &getInstructionMatcher(StringRef SymbolicName) const; 661*0fca6ea1SDimitry Andric OperandMatcher &getOperandMatcher(StringRef Name); 662*0fca6ea1SDimitry Andric const OperandMatcher &getOperandMatcher(StringRef Name) const; 663*0fca6ea1SDimitry Andric const OperandMatcher &getPhysRegOperandMatcher(Record *) const; 664*0fca6ea1SDimitry Andric 665*0fca6ea1SDimitry Andric void optimize() override; 666*0fca6ea1SDimitry Andric void emit(MatchTable &Table) override; 667*0fca6ea1SDimitry Andric 668*0fca6ea1SDimitry Andric /// Compare the priority of this object and B. 669*0fca6ea1SDimitry Andric /// 670*0fca6ea1SDimitry Andric /// Returns true if this object is more important than B. 671*0fca6ea1SDimitry Andric bool isHigherPriorityThan(const RuleMatcher &B) const; 672*0fca6ea1SDimitry Andric 673*0fca6ea1SDimitry Andric /// Report the maximum number of temporary operands needed by the rule 674*0fca6ea1SDimitry Andric /// matcher. 675*0fca6ea1SDimitry Andric unsigned countRendererFns() const; 676*0fca6ea1SDimitry Andric 677*0fca6ea1SDimitry Andric std::unique_ptr<PredicateMatcher> popFirstCondition() override; 678*0fca6ea1SDimitry Andric const PredicateMatcher &getFirstCondition() const override; 679*0fca6ea1SDimitry Andric LLTCodeGen getFirstConditionAsRootType(); 680*0fca6ea1SDimitry Andric bool hasFirstCondition() const override; 681*0fca6ea1SDimitry Andric unsigned getNumOperands() const; 682*0fca6ea1SDimitry Andric StringRef getOpcode() const; 683*0fca6ea1SDimitry Andric 684*0fca6ea1SDimitry Andric // FIXME: Remove this as soon as possible 685*0fca6ea1SDimitry Andric InstructionMatcher &insnmatchers_front() const { return *Matchers.front(); } 686*0fca6ea1SDimitry Andric 687*0fca6ea1SDimitry Andric unsigned allocateOutputInsnID() { return NextOutputInsnID++; } 688*0fca6ea1SDimitry Andric unsigned allocateTempRegID() { return NextTempRegID++; } 689*0fca6ea1SDimitry Andric 690*0fca6ea1SDimitry Andric iterator_range<MatchersTy::iterator> insnmatchers() { 691*0fca6ea1SDimitry Andric return make_range(Matchers.begin(), Matchers.end()); 692*0fca6ea1SDimitry Andric } 693*0fca6ea1SDimitry Andric bool insnmatchers_empty() const { return Matchers.empty(); } 694*0fca6ea1SDimitry Andric void insnmatchers_pop_front() { Matchers.erase(Matchers.begin()); } 695*0fca6ea1SDimitry Andric }; 696*0fca6ea1SDimitry Andric 697*0fca6ea1SDimitry Andric template <class PredicateTy> class PredicateListMatcher { 698*0fca6ea1SDimitry Andric private: 699*0fca6ea1SDimitry Andric /// Template instantiations should specialize this to return a string to use 700*0fca6ea1SDimitry Andric /// for the comment emitted when there are no predicates. 701*0fca6ea1SDimitry Andric std::string getNoPredicateComment() const; 702*0fca6ea1SDimitry Andric 703*0fca6ea1SDimitry Andric protected: 704*0fca6ea1SDimitry Andric using PredicatesTy = std::deque<std::unique_ptr<PredicateTy>>; 705*0fca6ea1SDimitry Andric PredicatesTy Predicates; 706*0fca6ea1SDimitry Andric 707*0fca6ea1SDimitry Andric /// Track if the list of predicates was manipulated by one of the optimization 708*0fca6ea1SDimitry Andric /// methods. 709*0fca6ea1SDimitry Andric bool Optimized = false; 710*0fca6ea1SDimitry Andric 711*0fca6ea1SDimitry Andric public: 712*0fca6ea1SDimitry Andric typename PredicatesTy::iterator predicates_begin() { 713*0fca6ea1SDimitry Andric return Predicates.begin(); 714*0fca6ea1SDimitry Andric } 715*0fca6ea1SDimitry Andric typename PredicatesTy::iterator predicates_end() { return Predicates.end(); } 716*0fca6ea1SDimitry Andric iterator_range<typename PredicatesTy::iterator> predicates() { 717*0fca6ea1SDimitry Andric return make_range(predicates_begin(), predicates_end()); 718*0fca6ea1SDimitry Andric } 719*0fca6ea1SDimitry Andric typename PredicatesTy::size_type predicates_size() const { 720*0fca6ea1SDimitry Andric return Predicates.size(); 721*0fca6ea1SDimitry Andric } 722*0fca6ea1SDimitry Andric bool predicates_empty() const { return Predicates.empty(); } 723*0fca6ea1SDimitry Andric 724*0fca6ea1SDimitry Andric template <typename Ty> bool contains() const { 725*0fca6ea1SDimitry Andric return any_of(Predicates, [&](auto &P) { return isa<Ty>(P.get()); }); 726*0fca6ea1SDimitry Andric } 727*0fca6ea1SDimitry Andric 728*0fca6ea1SDimitry Andric std::unique_ptr<PredicateTy> predicates_pop_front() { 729*0fca6ea1SDimitry Andric std::unique_ptr<PredicateTy> Front = std::move(Predicates.front()); 730*0fca6ea1SDimitry Andric Predicates.pop_front(); 731*0fca6ea1SDimitry Andric Optimized = true; 732*0fca6ea1SDimitry Andric return Front; 733*0fca6ea1SDimitry Andric } 734*0fca6ea1SDimitry Andric 735*0fca6ea1SDimitry Andric void prependPredicate(std::unique_ptr<PredicateTy> &&Predicate) { 736*0fca6ea1SDimitry Andric Predicates.push_front(std::move(Predicate)); 737*0fca6ea1SDimitry Andric } 738*0fca6ea1SDimitry Andric 739*0fca6ea1SDimitry Andric void eraseNullPredicates() { 740*0fca6ea1SDimitry Andric const auto NewEnd = 741*0fca6ea1SDimitry Andric std::stable_partition(Predicates.begin(), Predicates.end(), 742*0fca6ea1SDimitry Andric std::logical_not<std::unique_ptr<PredicateTy>>()); 743*0fca6ea1SDimitry Andric if (NewEnd != Predicates.begin()) { 744*0fca6ea1SDimitry Andric Predicates.erase(Predicates.begin(), NewEnd); 745*0fca6ea1SDimitry Andric Optimized = true; 746*0fca6ea1SDimitry Andric } 747*0fca6ea1SDimitry Andric } 748*0fca6ea1SDimitry Andric 749*0fca6ea1SDimitry Andric /// Emit MatchTable opcodes that tests whether all the predicates are met. 750*0fca6ea1SDimitry Andric template <class... Args> 751*0fca6ea1SDimitry Andric void emitPredicateListOpcodes(MatchTable &Table, Args &&...args) { 752*0fca6ea1SDimitry Andric if (Predicates.empty() && !Optimized) { 753*0fca6ea1SDimitry Andric Table << MatchTable::Comment(getNoPredicateComment()) 754*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 755*0fca6ea1SDimitry Andric return; 756*0fca6ea1SDimitry Andric } 757*0fca6ea1SDimitry Andric 758*0fca6ea1SDimitry Andric for (const auto &Predicate : predicates()) 759*0fca6ea1SDimitry Andric Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...); 760*0fca6ea1SDimitry Andric } 761*0fca6ea1SDimitry Andric 762*0fca6ea1SDimitry Andric /// Provide a function to avoid emitting certain predicates. This is used to 763*0fca6ea1SDimitry Andric /// defer some predicate checks until after others 764*0fca6ea1SDimitry Andric using PredicateFilterFunc = std::function<bool(const PredicateTy &)>; 765*0fca6ea1SDimitry Andric 766*0fca6ea1SDimitry Andric /// Emit MatchTable opcodes for predicates which satisfy \p 767*0fca6ea1SDimitry Andric /// ShouldEmitPredicate. This should be called multiple times to ensure all 768*0fca6ea1SDimitry Andric /// predicates are eventually added to the match table. 769*0fca6ea1SDimitry Andric template <class... Args> 770*0fca6ea1SDimitry Andric void emitFilteredPredicateListOpcodes(PredicateFilterFunc ShouldEmitPredicate, 771*0fca6ea1SDimitry Andric MatchTable &Table, Args &&...args) { 772*0fca6ea1SDimitry Andric if (Predicates.empty() && !Optimized) { 773*0fca6ea1SDimitry Andric Table << MatchTable::Comment(getNoPredicateComment()) 774*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 775*0fca6ea1SDimitry Andric return; 776*0fca6ea1SDimitry Andric } 777*0fca6ea1SDimitry Andric 778*0fca6ea1SDimitry Andric for (const auto &Predicate : predicates()) { 779*0fca6ea1SDimitry Andric if (ShouldEmitPredicate(*Predicate)) 780*0fca6ea1SDimitry Andric Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...); 781*0fca6ea1SDimitry Andric } 782*0fca6ea1SDimitry Andric } 783*0fca6ea1SDimitry Andric }; 784*0fca6ea1SDimitry Andric 785*0fca6ea1SDimitry Andric class PredicateMatcher { 786*0fca6ea1SDimitry Andric public: 787*0fca6ea1SDimitry Andric /// This enum is used for RTTI and also defines the priority that is given to 788*0fca6ea1SDimitry Andric /// the predicate when generating the matcher code. Kinds with higher priority 789*0fca6ea1SDimitry Andric /// must be tested first. 790*0fca6ea1SDimitry Andric /// 791*0fca6ea1SDimitry Andric /// The relative priority of OPM_LLT, OPM_RegBank, and OPM_MBB do not matter 792*0fca6ea1SDimitry Andric /// but OPM_Int must have priority over OPM_RegBank since constant integers 793*0fca6ea1SDimitry Andric /// are represented by a virtual register defined by a G_CONSTANT instruction. 794*0fca6ea1SDimitry Andric /// 795*0fca6ea1SDimitry Andric /// Note: The relative priority between IPM_ and OPM_ does not matter, they 796*0fca6ea1SDimitry Andric /// are currently not compared between each other. 797*0fca6ea1SDimitry Andric enum PredicateKind { 798*0fca6ea1SDimitry Andric IPM_Opcode, 799*0fca6ea1SDimitry Andric IPM_NumOperands, 800*0fca6ea1SDimitry Andric IPM_ImmPredicate, 801*0fca6ea1SDimitry Andric IPM_Imm, 802*0fca6ea1SDimitry Andric IPM_AtomicOrderingMMO, 803*0fca6ea1SDimitry Andric IPM_MemoryLLTSize, 804*0fca6ea1SDimitry Andric IPM_MemoryVsLLTSize, 805*0fca6ea1SDimitry Andric IPM_MemoryAddressSpace, 806*0fca6ea1SDimitry Andric IPM_MemoryAlignment, 807*0fca6ea1SDimitry Andric IPM_VectorSplatImm, 808*0fca6ea1SDimitry Andric IPM_NoUse, 809*0fca6ea1SDimitry Andric IPM_OneUse, 810*0fca6ea1SDimitry Andric IPM_GenericPredicate, 811*0fca6ea1SDimitry Andric IPM_MIFlags, 812*0fca6ea1SDimitry Andric OPM_SameOperand, 813*0fca6ea1SDimitry Andric OPM_ComplexPattern, 814*0fca6ea1SDimitry Andric OPM_IntrinsicID, 815*0fca6ea1SDimitry Andric OPM_CmpPredicate, 816*0fca6ea1SDimitry Andric OPM_Instruction, 817*0fca6ea1SDimitry Andric OPM_Int, 818*0fca6ea1SDimitry Andric OPM_LiteralInt, 819*0fca6ea1SDimitry Andric OPM_LLT, 820*0fca6ea1SDimitry Andric OPM_PointerToAny, 821*0fca6ea1SDimitry Andric OPM_RegBank, 822*0fca6ea1SDimitry Andric OPM_MBB, 823*0fca6ea1SDimitry Andric OPM_RecordNamedOperand, 824*0fca6ea1SDimitry Andric OPM_RecordRegType, 825*0fca6ea1SDimitry Andric }; 826*0fca6ea1SDimitry Andric 827*0fca6ea1SDimitry Andric protected: 828*0fca6ea1SDimitry Andric PredicateKind Kind; 829*0fca6ea1SDimitry Andric unsigned InsnVarID; 830*0fca6ea1SDimitry Andric unsigned OpIdx; 831*0fca6ea1SDimitry Andric 832*0fca6ea1SDimitry Andric public: 833*0fca6ea1SDimitry Andric PredicateMatcher(PredicateKind Kind, unsigned InsnVarID, unsigned OpIdx = ~0) 834*0fca6ea1SDimitry Andric : Kind(Kind), InsnVarID(InsnVarID), OpIdx(OpIdx) {} 835*0fca6ea1SDimitry Andric virtual ~PredicateMatcher(); 836*0fca6ea1SDimitry Andric 837*0fca6ea1SDimitry Andric unsigned getInsnVarID() const { return InsnVarID; } 838*0fca6ea1SDimitry Andric unsigned getOpIdx() const { return OpIdx; } 839*0fca6ea1SDimitry Andric 840*0fca6ea1SDimitry Andric /// Emit MatchTable opcodes that check the predicate for the given operand. 841*0fca6ea1SDimitry Andric virtual void emitPredicateOpcodes(MatchTable &Table, 842*0fca6ea1SDimitry Andric RuleMatcher &Rule) const = 0; 843*0fca6ea1SDimitry Andric 844*0fca6ea1SDimitry Andric PredicateKind getKind() const { return Kind; } 845*0fca6ea1SDimitry Andric 846*0fca6ea1SDimitry Andric bool dependsOnOperands() const { 847*0fca6ea1SDimitry Andric // Custom predicates really depend on the context pattern of the 848*0fca6ea1SDimitry Andric // instruction, not just the individual instruction. This therefore 849*0fca6ea1SDimitry Andric // implicitly depends on all other pattern constraints. 850*0fca6ea1SDimitry Andric return Kind == IPM_GenericPredicate; 851*0fca6ea1SDimitry Andric } 852*0fca6ea1SDimitry Andric 853*0fca6ea1SDimitry Andric virtual bool isIdentical(const PredicateMatcher &B) const { 854*0fca6ea1SDimitry Andric return B.getKind() == getKind() && InsnVarID == B.InsnVarID && 855*0fca6ea1SDimitry Andric OpIdx == B.OpIdx; 856*0fca6ea1SDimitry Andric } 857*0fca6ea1SDimitry Andric 858*0fca6ea1SDimitry Andric virtual bool isIdenticalDownToValue(const PredicateMatcher &B) const { 859*0fca6ea1SDimitry Andric return hasValue() && PredicateMatcher::isIdentical(B); 860*0fca6ea1SDimitry Andric } 861*0fca6ea1SDimitry Andric 862*0fca6ea1SDimitry Andric virtual MatchTableRecord getValue() const { 863*0fca6ea1SDimitry Andric assert(hasValue() && "Can not get a value of a value-less predicate!"); 864*0fca6ea1SDimitry Andric llvm_unreachable("Not implemented yet"); 865*0fca6ea1SDimitry Andric } 866*0fca6ea1SDimitry Andric virtual bool hasValue() const { return false; } 867*0fca6ea1SDimitry Andric 868*0fca6ea1SDimitry Andric /// Report the maximum number of temporary operands needed by the predicate 869*0fca6ea1SDimitry Andric /// matcher. 870*0fca6ea1SDimitry Andric virtual unsigned countRendererFns() const { return 0; } 871*0fca6ea1SDimitry Andric }; 872*0fca6ea1SDimitry Andric 873*0fca6ea1SDimitry Andric /// Generates code to check a predicate of an operand. 874*0fca6ea1SDimitry Andric /// 875*0fca6ea1SDimitry Andric /// Typical predicates include: 876*0fca6ea1SDimitry Andric /// * Operand is a particular register. 877*0fca6ea1SDimitry Andric /// * Operand is assigned a particular register bank. 878*0fca6ea1SDimitry Andric /// * Operand is an MBB. 879*0fca6ea1SDimitry Andric class OperandPredicateMatcher : public PredicateMatcher { 880*0fca6ea1SDimitry Andric public: 881*0fca6ea1SDimitry Andric OperandPredicateMatcher(PredicateKind Kind, unsigned InsnVarID, 882*0fca6ea1SDimitry Andric unsigned OpIdx) 883*0fca6ea1SDimitry Andric : PredicateMatcher(Kind, InsnVarID, OpIdx) {} 884*0fca6ea1SDimitry Andric virtual ~OperandPredicateMatcher(); 885*0fca6ea1SDimitry Andric 886*0fca6ea1SDimitry Andric /// Compare the priority of this object and B. 887*0fca6ea1SDimitry Andric /// 888*0fca6ea1SDimitry Andric /// Returns true if this object is more important than B. 889*0fca6ea1SDimitry Andric virtual bool isHigherPriorityThan(const OperandPredicateMatcher &B) const; 890*0fca6ea1SDimitry Andric }; 891*0fca6ea1SDimitry Andric 892*0fca6ea1SDimitry Andric template <> 893*0fca6ea1SDimitry Andric inline std::string 894*0fca6ea1SDimitry Andric PredicateListMatcher<OperandPredicateMatcher>::getNoPredicateComment() const { 895*0fca6ea1SDimitry Andric return "No operand predicates"; 896*0fca6ea1SDimitry Andric } 897*0fca6ea1SDimitry Andric 898*0fca6ea1SDimitry Andric /// Generates code to check that a register operand is defined by the same exact 899*0fca6ea1SDimitry Andric /// one as another. 900*0fca6ea1SDimitry Andric class SameOperandMatcher : public OperandPredicateMatcher { 901*0fca6ea1SDimitry Andric std::string MatchingName; 902*0fca6ea1SDimitry Andric unsigned OrigOpIdx; 903*0fca6ea1SDimitry Andric 904*0fca6ea1SDimitry Andric GISelFlags Flags; 905*0fca6ea1SDimitry Andric 906*0fca6ea1SDimitry Andric public: 907*0fca6ea1SDimitry Andric SameOperandMatcher(unsigned InsnVarID, unsigned OpIdx, StringRef MatchingName, 908*0fca6ea1SDimitry Andric unsigned OrigOpIdx, GISelFlags Flags) 909*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_SameOperand, InsnVarID, OpIdx), 910*0fca6ea1SDimitry Andric MatchingName(MatchingName), OrigOpIdx(OrigOpIdx), Flags(Flags) {} 911*0fca6ea1SDimitry Andric 912*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 913*0fca6ea1SDimitry Andric return P->getKind() == OPM_SameOperand; 914*0fca6ea1SDimitry Andric } 915*0fca6ea1SDimitry Andric 916*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 917*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 918*0fca6ea1SDimitry Andric 919*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 920*0fca6ea1SDimitry Andric return OperandPredicateMatcher::isIdentical(B) && 921*0fca6ea1SDimitry Andric OrigOpIdx == cast<SameOperandMatcher>(&B)->OrigOpIdx && 922*0fca6ea1SDimitry Andric MatchingName == cast<SameOperandMatcher>(&B)->MatchingName; 923*0fca6ea1SDimitry Andric } 924*0fca6ea1SDimitry Andric }; 925*0fca6ea1SDimitry Andric 926*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a particular LLT. 927*0fca6ea1SDimitry Andric class LLTOperandMatcher : public OperandPredicateMatcher { 928*0fca6ea1SDimitry Andric protected: 929*0fca6ea1SDimitry Andric LLTCodeGen Ty; 930*0fca6ea1SDimitry Andric 931*0fca6ea1SDimitry Andric public: 932*0fca6ea1SDimitry Andric static std::map<LLTCodeGen, unsigned> TypeIDValues; 933*0fca6ea1SDimitry Andric 934*0fca6ea1SDimitry Andric static void initTypeIDValuesMap() { 935*0fca6ea1SDimitry Andric TypeIDValues.clear(); 936*0fca6ea1SDimitry Andric 937*0fca6ea1SDimitry Andric unsigned ID = 0; 938*0fca6ea1SDimitry Andric for (const LLTCodeGen &LLTy : KnownTypes) 939*0fca6ea1SDimitry Andric TypeIDValues[LLTy] = ID++; 940*0fca6ea1SDimitry Andric } 941*0fca6ea1SDimitry Andric 942*0fca6ea1SDimitry Andric LLTOperandMatcher(unsigned InsnVarID, unsigned OpIdx, const LLTCodeGen &Ty) 943*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_LLT, InsnVarID, OpIdx), Ty(Ty) { 944*0fca6ea1SDimitry Andric KnownTypes.insert(Ty); 945*0fca6ea1SDimitry Andric } 946*0fca6ea1SDimitry Andric 947*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 948*0fca6ea1SDimitry Andric return P->getKind() == OPM_LLT; 949*0fca6ea1SDimitry Andric } 950*0fca6ea1SDimitry Andric 951*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 952*0fca6ea1SDimitry Andric return OperandPredicateMatcher::isIdentical(B) && 953*0fca6ea1SDimitry Andric Ty == cast<LLTOperandMatcher>(&B)->Ty; 954*0fca6ea1SDimitry Andric } 955*0fca6ea1SDimitry Andric 956*0fca6ea1SDimitry Andric MatchTableRecord getValue() const override; 957*0fca6ea1SDimitry Andric bool hasValue() const override; 958*0fca6ea1SDimitry Andric 959*0fca6ea1SDimitry Andric LLTCodeGen getTy() const { return Ty; } 960*0fca6ea1SDimitry Andric 961*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 962*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 963*0fca6ea1SDimitry Andric }; 964*0fca6ea1SDimitry Andric 965*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a pointer to any address space. 966*0fca6ea1SDimitry Andric /// 967*0fca6ea1SDimitry Andric /// In SelectionDAG, the types did not describe pointers or address spaces. As a 968*0fca6ea1SDimitry Andric /// result, iN is used to describe a pointer of N bits to any address space and 969*0fca6ea1SDimitry Andric /// PatFrag predicates are typically used to constrain the address space. 970*0fca6ea1SDimitry Andric /// There's no reliable means to derive the missing type information from the 971*0fca6ea1SDimitry Andric /// pattern so imported rules must test the components of a pointer separately. 972*0fca6ea1SDimitry Andric /// 973*0fca6ea1SDimitry Andric /// If SizeInBits is zero, then the pointer size will be obtained from the 974*0fca6ea1SDimitry Andric /// subtarget. 975*0fca6ea1SDimitry Andric class PointerToAnyOperandMatcher : public OperandPredicateMatcher { 976*0fca6ea1SDimitry Andric protected: 977*0fca6ea1SDimitry Andric unsigned SizeInBits; 978*0fca6ea1SDimitry Andric 979*0fca6ea1SDimitry Andric public: 980*0fca6ea1SDimitry Andric PointerToAnyOperandMatcher(unsigned InsnVarID, unsigned OpIdx, 981*0fca6ea1SDimitry Andric unsigned SizeInBits) 982*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_PointerToAny, InsnVarID, OpIdx), 983*0fca6ea1SDimitry Andric SizeInBits(SizeInBits) {} 984*0fca6ea1SDimitry Andric 985*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 986*0fca6ea1SDimitry Andric return P->getKind() == OPM_PointerToAny; 987*0fca6ea1SDimitry Andric } 988*0fca6ea1SDimitry Andric 989*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 990*0fca6ea1SDimitry Andric return OperandPredicateMatcher::isIdentical(B) && 991*0fca6ea1SDimitry Andric SizeInBits == cast<PointerToAnyOperandMatcher>(&B)->SizeInBits; 992*0fca6ea1SDimitry Andric } 993*0fca6ea1SDimitry Andric 994*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 995*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 996*0fca6ea1SDimitry Andric }; 997*0fca6ea1SDimitry Andric 998*0fca6ea1SDimitry Andric /// Generates code to record named operand in RecordedOperands list at StoreIdx. 999*0fca6ea1SDimitry Andric /// Predicates with 'let PredicateCodeUsesOperands = 1' get RecordedOperands as 1000*0fca6ea1SDimitry Andric /// an argument to predicate's c++ code once all operands have been matched. 1001*0fca6ea1SDimitry Andric class RecordNamedOperandMatcher : public OperandPredicateMatcher { 1002*0fca6ea1SDimitry Andric protected: 1003*0fca6ea1SDimitry Andric unsigned StoreIdx; 1004*0fca6ea1SDimitry Andric std::string Name; 1005*0fca6ea1SDimitry Andric 1006*0fca6ea1SDimitry Andric public: 1007*0fca6ea1SDimitry Andric RecordNamedOperandMatcher(unsigned InsnVarID, unsigned OpIdx, 1008*0fca6ea1SDimitry Andric unsigned StoreIdx, StringRef Name) 1009*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_RecordNamedOperand, InsnVarID, OpIdx), 1010*0fca6ea1SDimitry Andric StoreIdx(StoreIdx), Name(Name) {} 1011*0fca6ea1SDimitry Andric 1012*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1013*0fca6ea1SDimitry Andric return P->getKind() == OPM_RecordNamedOperand; 1014*0fca6ea1SDimitry Andric } 1015*0fca6ea1SDimitry Andric 1016*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1017*0fca6ea1SDimitry Andric return OperandPredicateMatcher::isIdentical(B) && 1018*0fca6ea1SDimitry Andric StoreIdx == cast<RecordNamedOperandMatcher>(&B)->StoreIdx && 1019*0fca6ea1SDimitry Andric Name == cast<RecordNamedOperandMatcher>(&B)->Name; 1020*0fca6ea1SDimitry Andric } 1021*0fca6ea1SDimitry Andric 1022*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1023*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1024*0fca6ea1SDimitry Andric }; 1025*0fca6ea1SDimitry Andric 1026*0fca6ea1SDimitry Andric /// Generates code to store a register operand's type into the set of temporary 1027*0fca6ea1SDimitry Andric /// LLTs. 1028*0fca6ea1SDimitry Andric class RecordRegisterType : public OperandPredicateMatcher { 1029*0fca6ea1SDimitry Andric protected: 1030*0fca6ea1SDimitry Andric TempTypeIdx Idx; 1031*0fca6ea1SDimitry Andric 1032*0fca6ea1SDimitry Andric public: 1033*0fca6ea1SDimitry Andric RecordRegisterType(unsigned InsnVarID, unsigned OpIdx, TempTypeIdx Idx) 1034*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_RecordRegType, InsnVarID, OpIdx), Idx(Idx) { 1035*0fca6ea1SDimitry Andric } 1036*0fca6ea1SDimitry Andric 1037*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1038*0fca6ea1SDimitry Andric return P->getKind() == OPM_RecordRegType; 1039*0fca6ea1SDimitry Andric } 1040*0fca6ea1SDimitry Andric 1041*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1042*0fca6ea1SDimitry Andric return OperandPredicateMatcher::isIdentical(B) && 1043*0fca6ea1SDimitry Andric Idx == cast<RecordRegisterType>(&B)->Idx; 1044*0fca6ea1SDimitry Andric } 1045*0fca6ea1SDimitry Andric 1046*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1047*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1048*0fca6ea1SDimitry Andric }; 1049*0fca6ea1SDimitry Andric 1050*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a particular target constant. 1051*0fca6ea1SDimitry Andric class ComplexPatternOperandMatcher : public OperandPredicateMatcher { 1052*0fca6ea1SDimitry Andric protected: 1053*0fca6ea1SDimitry Andric const OperandMatcher &Operand; 1054*0fca6ea1SDimitry Andric const Record &TheDef; 1055*0fca6ea1SDimitry Andric 1056*0fca6ea1SDimitry Andric unsigned getAllocatedTemporariesBaseID() const; 1057*0fca6ea1SDimitry Andric 1058*0fca6ea1SDimitry Andric public: 1059*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { return false; } 1060*0fca6ea1SDimitry Andric 1061*0fca6ea1SDimitry Andric ComplexPatternOperandMatcher(unsigned InsnVarID, unsigned OpIdx, 1062*0fca6ea1SDimitry Andric const OperandMatcher &Operand, 1063*0fca6ea1SDimitry Andric const Record &TheDef) 1064*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_ComplexPattern, InsnVarID, OpIdx), 1065*0fca6ea1SDimitry Andric Operand(Operand), TheDef(TheDef) {} 1066*0fca6ea1SDimitry Andric 1067*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1068*0fca6ea1SDimitry Andric return P->getKind() == OPM_ComplexPattern; 1069*0fca6ea1SDimitry Andric } 1070*0fca6ea1SDimitry Andric 1071*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1072*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1073*0fca6ea1SDimitry Andric unsigned countRendererFns() const override { return 1; } 1074*0fca6ea1SDimitry Andric }; 1075*0fca6ea1SDimitry Andric 1076*0fca6ea1SDimitry Andric /// Generates code to check that an operand is in a particular register bank. 1077*0fca6ea1SDimitry Andric class RegisterBankOperandMatcher : public OperandPredicateMatcher { 1078*0fca6ea1SDimitry Andric protected: 1079*0fca6ea1SDimitry Andric const CodeGenRegisterClass &RC; 1080*0fca6ea1SDimitry Andric 1081*0fca6ea1SDimitry Andric public: 1082*0fca6ea1SDimitry Andric RegisterBankOperandMatcher(unsigned InsnVarID, unsigned OpIdx, 1083*0fca6ea1SDimitry Andric const CodeGenRegisterClass &RC) 1084*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_RegBank, InsnVarID, OpIdx), RC(RC) {} 1085*0fca6ea1SDimitry Andric 1086*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override; 1087*0fca6ea1SDimitry Andric 1088*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1089*0fca6ea1SDimitry Andric return P->getKind() == OPM_RegBank; 1090*0fca6ea1SDimitry Andric } 1091*0fca6ea1SDimitry Andric 1092*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1093*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1094*0fca6ea1SDimitry Andric }; 1095*0fca6ea1SDimitry Andric 1096*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a basic block. 1097*0fca6ea1SDimitry Andric class MBBOperandMatcher : public OperandPredicateMatcher { 1098*0fca6ea1SDimitry Andric public: 1099*0fca6ea1SDimitry Andric MBBOperandMatcher(unsigned InsnVarID, unsigned OpIdx) 1100*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_MBB, InsnVarID, OpIdx) {} 1101*0fca6ea1SDimitry Andric 1102*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1103*0fca6ea1SDimitry Andric return P->getKind() == OPM_MBB; 1104*0fca6ea1SDimitry Andric } 1105*0fca6ea1SDimitry Andric 1106*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1107*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1108*0fca6ea1SDimitry Andric }; 1109*0fca6ea1SDimitry Andric 1110*0fca6ea1SDimitry Andric class ImmOperandMatcher : public OperandPredicateMatcher { 1111*0fca6ea1SDimitry Andric public: 1112*0fca6ea1SDimitry Andric ImmOperandMatcher(unsigned InsnVarID, unsigned OpIdx) 1113*0fca6ea1SDimitry Andric : OperandPredicateMatcher(IPM_Imm, InsnVarID, OpIdx) {} 1114*0fca6ea1SDimitry Andric 1115*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1116*0fca6ea1SDimitry Andric return P->getKind() == IPM_Imm; 1117*0fca6ea1SDimitry Andric } 1118*0fca6ea1SDimitry Andric 1119*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1120*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1121*0fca6ea1SDimitry Andric }; 1122*0fca6ea1SDimitry Andric 1123*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a G_CONSTANT with a particular 1124*0fca6ea1SDimitry Andric /// int. 1125*0fca6ea1SDimitry Andric class ConstantIntOperandMatcher : public OperandPredicateMatcher { 1126*0fca6ea1SDimitry Andric protected: 1127*0fca6ea1SDimitry Andric int64_t Value; 1128*0fca6ea1SDimitry Andric 1129*0fca6ea1SDimitry Andric public: 1130*0fca6ea1SDimitry Andric ConstantIntOperandMatcher(unsigned InsnVarID, unsigned OpIdx, int64_t Value) 1131*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_Int, InsnVarID, OpIdx), Value(Value) {} 1132*0fca6ea1SDimitry Andric 1133*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1134*0fca6ea1SDimitry Andric return OperandPredicateMatcher::isIdentical(B) && 1135*0fca6ea1SDimitry Andric Value == cast<ConstantIntOperandMatcher>(&B)->Value; 1136*0fca6ea1SDimitry Andric } 1137*0fca6ea1SDimitry Andric 1138*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1139*0fca6ea1SDimitry Andric return P->getKind() == OPM_Int; 1140*0fca6ea1SDimitry Andric } 1141*0fca6ea1SDimitry Andric 1142*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1143*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1144*0fca6ea1SDimitry Andric }; 1145*0fca6ea1SDimitry Andric 1146*0fca6ea1SDimitry Andric /// Generates code to check that an operand is a raw int (where MO.isImm() or 1147*0fca6ea1SDimitry Andric /// MO.isCImm() is true). 1148*0fca6ea1SDimitry Andric class LiteralIntOperandMatcher : public OperandPredicateMatcher { 1149*0fca6ea1SDimitry Andric protected: 1150*0fca6ea1SDimitry Andric int64_t Value; 1151*0fca6ea1SDimitry Andric 1152*0fca6ea1SDimitry Andric public: 1153*0fca6ea1SDimitry Andric LiteralIntOperandMatcher(unsigned InsnVarID, unsigned OpIdx, int64_t Value) 1154*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_LiteralInt, InsnVarID, OpIdx), 1155*0fca6ea1SDimitry Andric Value(Value) {} 1156*0fca6ea1SDimitry Andric 1157*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1158*0fca6ea1SDimitry Andric return OperandPredicateMatcher::isIdentical(B) && 1159*0fca6ea1SDimitry Andric Value == cast<LiteralIntOperandMatcher>(&B)->Value; 1160*0fca6ea1SDimitry Andric } 1161*0fca6ea1SDimitry Andric 1162*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1163*0fca6ea1SDimitry Andric return P->getKind() == OPM_LiteralInt; 1164*0fca6ea1SDimitry Andric } 1165*0fca6ea1SDimitry Andric 1166*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1167*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1168*0fca6ea1SDimitry Andric }; 1169*0fca6ea1SDimitry Andric 1170*0fca6ea1SDimitry Andric /// Generates code to check that an operand is an CmpInst predicate 1171*0fca6ea1SDimitry Andric class CmpPredicateOperandMatcher : public OperandPredicateMatcher { 1172*0fca6ea1SDimitry Andric protected: 1173*0fca6ea1SDimitry Andric std::string PredName; 1174*0fca6ea1SDimitry Andric 1175*0fca6ea1SDimitry Andric public: 1176*0fca6ea1SDimitry Andric CmpPredicateOperandMatcher(unsigned InsnVarID, unsigned OpIdx, std::string P) 1177*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_CmpPredicate, InsnVarID, OpIdx), 1178*0fca6ea1SDimitry Andric PredName(std::move(P)) {} 1179*0fca6ea1SDimitry Andric 1180*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1181*0fca6ea1SDimitry Andric return OperandPredicateMatcher::isIdentical(B) && 1182*0fca6ea1SDimitry Andric PredName == cast<CmpPredicateOperandMatcher>(&B)->PredName; 1183*0fca6ea1SDimitry Andric } 1184*0fca6ea1SDimitry Andric 1185*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1186*0fca6ea1SDimitry Andric return P->getKind() == OPM_CmpPredicate; 1187*0fca6ea1SDimitry Andric } 1188*0fca6ea1SDimitry Andric 1189*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1190*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1191*0fca6ea1SDimitry Andric }; 1192*0fca6ea1SDimitry Andric 1193*0fca6ea1SDimitry Andric /// Generates code to check that an operand is an intrinsic ID. 1194*0fca6ea1SDimitry Andric class IntrinsicIDOperandMatcher : public OperandPredicateMatcher { 1195*0fca6ea1SDimitry Andric protected: 1196*0fca6ea1SDimitry Andric const CodeGenIntrinsic *II; 1197*0fca6ea1SDimitry Andric 1198*0fca6ea1SDimitry Andric public: 1199*0fca6ea1SDimitry Andric IntrinsicIDOperandMatcher(unsigned InsnVarID, unsigned OpIdx, 1200*0fca6ea1SDimitry Andric const CodeGenIntrinsic *II) 1201*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_IntrinsicID, InsnVarID, OpIdx), II(II) {} 1202*0fca6ea1SDimitry Andric 1203*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1204*0fca6ea1SDimitry Andric return OperandPredicateMatcher::isIdentical(B) && 1205*0fca6ea1SDimitry Andric II == cast<IntrinsicIDOperandMatcher>(&B)->II; 1206*0fca6ea1SDimitry Andric } 1207*0fca6ea1SDimitry Andric 1208*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1209*0fca6ea1SDimitry Andric return P->getKind() == OPM_IntrinsicID; 1210*0fca6ea1SDimitry Andric } 1211*0fca6ea1SDimitry Andric 1212*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1213*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1214*0fca6ea1SDimitry Andric }; 1215*0fca6ea1SDimitry Andric 1216*0fca6ea1SDimitry Andric /// Generates code to check that this operand is an immediate whose value meets 1217*0fca6ea1SDimitry Andric /// an immediate predicate. 1218*0fca6ea1SDimitry Andric class OperandImmPredicateMatcher : public OperandPredicateMatcher { 1219*0fca6ea1SDimitry Andric protected: 1220*0fca6ea1SDimitry Andric TreePredicateFn Predicate; 1221*0fca6ea1SDimitry Andric 1222*0fca6ea1SDimitry Andric public: 1223*0fca6ea1SDimitry Andric OperandImmPredicateMatcher(unsigned InsnVarID, unsigned OpIdx, 1224*0fca6ea1SDimitry Andric const TreePredicateFn &Predicate) 1225*0fca6ea1SDimitry Andric : OperandPredicateMatcher(IPM_ImmPredicate, InsnVarID, OpIdx), 1226*0fca6ea1SDimitry Andric Predicate(Predicate) {} 1227*0fca6ea1SDimitry Andric 1228*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1229*0fca6ea1SDimitry Andric return OperandPredicateMatcher::isIdentical(B) && 1230*0fca6ea1SDimitry Andric Predicate.getOrigPatFragRecord() == 1231*0fca6ea1SDimitry Andric cast<OperandImmPredicateMatcher>(&B) 1232*0fca6ea1SDimitry Andric ->Predicate.getOrigPatFragRecord(); 1233*0fca6ea1SDimitry Andric } 1234*0fca6ea1SDimitry Andric 1235*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1236*0fca6ea1SDimitry Andric return P->getKind() == IPM_ImmPredicate; 1237*0fca6ea1SDimitry Andric } 1238*0fca6ea1SDimitry Andric 1239*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1240*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1241*0fca6ea1SDimitry Andric }; 1242*0fca6ea1SDimitry Andric 1243*0fca6ea1SDimitry Andric /// Generates code to check that a set of predicates match for a particular 1244*0fca6ea1SDimitry Andric /// operand. 1245*0fca6ea1SDimitry Andric class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher> { 1246*0fca6ea1SDimitry Andric protected: 1247*0fca6ea1SDimitry Andric InstructionMatcher &Insn; 1248*0fca6ea1SDimitry Andric unsigned OpIdx; 1249*0fca6ea1SDimitry Andric std::string SymbolicName; 1250*0fca6ea1SDimitry Andric 1251*0fca6ea1SDimitry Andric /// The index of the first temporary variable allocated to this operand. The 1252*0fca6ea1SDimitry Andric /// number of allocated temporaries can be found with 1253*0fca6ea1SDimitry Andric /// countRendererFns(). 1254*0fca6ea1SDimitry Andric unsigned AllocatedTemporariesBaseID; 1255*0fca6ea1SDimitry Andric 1256*0fca6ea1SDimitry Andric TempTypeIdx TTIdx = 0; 1257*0fca6ea1SDimitry Andric 1258*0fca6ea1SDimitry Andric public: 1259*0fca6ea1SDimitry Andric OperandMatcher(InstructionMatcher &Insn, unsigned OpIdx, 1260*0fca6ea1SDimitry Andric const std::string &SymbolicName, 1261*0fca6ea1SDimitry Andric unsigned AllocatedTemporariesBaseID) 1262*0fca6ea1SDimitry Andric : Insn(Insn), OpIdx(OpIdx), SymbolicName(SymbolicName), 1263*0fca6ea1SDimitry Andric AllocatedTemporariesBaseID(AllocatedTemporariesBaseID) {} 1264*0fca6ea1SDimitry Andric 1265*0fca6ea1SDimitry Andric bool hasSymbolicName() const { return !SymbolicName.empty(); } 1266*0fca6ea1SDimitry Andric StringRef getSymbolicName() const { return SymbolicName; } 1267*0fca6ea1SDimitry Andric void setSymbolicName(StringRef Name) { 1268*0fca6ea1SDimitry Andric assert(SymbolicName.empty() && "Operand already has a symbolic name"); 1269*0fca6ea1SDimitry Andric SymbolicName = std::string(Name); 1270*0fca6ea1SDimitry Andric } 1271*0fca6ea1SDimitry Andric 1272*0fca6ea1SDimitry Andric /// Construct a new operand predicate and add it to the matcher. 1273*0fca6ea1SDimitry Andric template <class Kind, class... Args> 1274*0fca6ea1SDimitry Andric std::optional<Kind *> addPredicate(Args &&...args) { 1275*0fca6ea1SDimitry Andric if (isSameAsAnotherOperand()) 1276*0fca6ea1SDimitry Andric return std::nullopt; 1277*0fca6ea1SDimitry Andric Predicates.emplace_back(std::make_unique<Kind>( 1278*0fca6ea1SDimitry Andric getInsnVarID(), getOpIdx(), std::forward<Args>(args)...)); 1279*0fca6ea1SDimitry Andric return static_cast<Kind *>(Predicates.back().get()); 1280*0fca6ea1SDimitry Andric } 1281*0fca6ea1SDimitry Andric 1282*0fca6ea1SDimitry Andric unsigned getOpIdx() const { return OpIdx; } 1283*0fca6ea1SDimitry Andric unsigned getInsnVarID() const; 1284*0fca6ea1SDimitry Andric 1285*0fca6ea1SDimitry Andric /// If this OperandMatcher has not been assigned a TempTypeIdx yet, assigns it 1286*0fca6ea1SDimitry Andric /// one and adds a `RecordRegisterType` predicate to this matcher. If one has 1287*0fca6ea1SDimitry Andric /// already been assigned, simply returns it. 1288*0fca6ea1SDimitry Andric TempTypeIdx getTempTypeIdx(RuleMatcher &Rule); 1289*0fca6ea1SDimitry Andric 1290*0fca6ea1SDimitry Andric std::string getOperandExpr(unsigned InsnVarID) const; 1291*0fca6ea1SDimitry Andric 1292*0fca6ea1SDimitry Andric InstructionMatcher &getInstructionMatcher() const { return Insn; } 1293*0fca6ea1SDimitry Andric 1294*0fca6ea1SDimitry Andric Error addTypeCheckPredicate(const TypeSetByHwMode &VTy, 1295*0fca6ea1SDimitry Andric bool OperandIsAPointer); 1296*0fca6ea1SDimitry Andric 1297*0fca6ea1SDimitry Andric /// Emit MatchTable opcodes that test whether the instruction named in 1298*0fca6ea1SDimitry Andric /// InsnVarID matches all the predicates and all the operands. 1299*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule); 1300*0fca6ea1SDimitry Andric 1301*0fca6ea1SDimitry Andric /// Compare the priority of this object and B. 1302*0fca6ea1SDimitry Andric /// 1303*0fca6ea1SDimitry Andric /// Returns true if this object is more important than B. 1304*0fca6ea1SDimitry Andric bool isHigherPriorityThan(OperandMatcher &B); 1305*0fca6ea1SDimitry Andric 1306*0fca6ea1SDimitry Andric /// Report the maximum number of temporary operands needed by the operand 1307*0fca6ea1SDimitry Andric /// matcher. 1308*0fca6ea1SDimitry Andric unsigned countRendererFns(); 1309*0fca6ea1SDimitry Andric 1310*0fca6ea1SDimitry Andric unsigned getAllocatedTemporariesBaseID() const { 1311*0fca6ea1SDimitry Andric return AllocatedTemporariesBaseID; 1312*0fca6ea1SDimitry Andric } 1313*0fca6ea1SDimitry Andric 1314*0fca6ea1SDimitry Andric bool isSameAsAnotherOperand() { 1315*0fca6ea1SDimitry Andric for (const auto &Predicate : predicates()) 1316*0fca6ea1SDimitry Andric if (isa<SameOperandMatcher>(Predicate)) 1317*0fca6ea1SDimitry Andric return true; 1318*0fca6ea1SDimitry Andric return false; 1319*0fca6ea1SDimitry Andric } 1320*0fca6ea1SDimitry Andric }; 1321*0fca6ea1SDimitry Andric 1322*0fca6ea1SDimitry Andric /// Generates code to check a predicate on an instruction. 1323*0fca6ea1SDimitry Andric /// 1324*0fca6ea1SDimitry Andric /// Typical predicates include: 1325*0fca6ea1SDimitry Andric /// * The opcode of the instruction is a particular value. 1326*0fca6ea1SDimitry Andric /// * The nsw/nuw flag is/isn't set. 1327*0fca6ea1SDimitry Andric class InstructionPredicateMatcher : public PredicateMatcher { 1328*0fca6ea1SDimitry Andric public: 1329*0fca6ea1SDimitry Andric InstructionPredicateMatcher(PredicateKind Kind, unsigned InsnVarID) 1330*0fca6ea1SDimitry Andric : PredicateMatcher(Kind, InsnVarID) {} 1331*0fca6ea1SDimitry Andric virtual ~InstructionPredicateMatcher() {} 1332*0fca6ea1SDimitry Andric 1333*0fca6ea1SDimitry Andric /// Compare the priority of this object and B. 1334*0fca6ea1SDimitry Andric /// 1335*0fca6ea1SDimitry Andric /// Returns true if this object is more important than B. 1336*0fca6ea1SDimitry Andric virtual bool 1337*0fca6ea1SDimitry Andric isHigherPriorityThan(const InstructionPredicateMatcher &B) const { 1338*0fca6ea1SDimitry Andric return Kind < B.Kind; 1339*0fca6ea1SDimitry Andric }; 1340*0fca6ea1SDimitry Andric }; 1341*0fca6ea1SDimitry Andric 1342*0fca6ea1SDimitry Andric template <> 1343*0fca6ea1SDimitry Andric inline std::string 1344*0fca6ea1SDimitry Andric PredicateListMatcher<PredicateMatcher>::getNoPredicateComment() const { 1345*0fca6ea1SDimitry Andric return "No instruction predicates"; 1346*0fca6ea1SDimitry Andric } 1347*0fca6ea1SDimitry Andric 1348*0fca6ea1SDimitry Andric /// Generates code to check the opcode of an instruction. 1349*0fca6ea1SDimitry Andric class InstructionOpcodeMatcher : public InstructionPredicateMatcher { 1350*0fca6ea1SDimitry Andric protected: 1351*0fca6ea1SDimitry Andric // Allow matching one to several, similar opcodes that share properties. This 1352*0fca6ea1SDimitry Andric // is to handle patterns where one SelectionDAG operation maps to multiple 1353*0fca6ea1SDimitry Andric // GlobalISel ones (e.g. G_BUILD_VECTOR and G_BUILD_VECTOR_TRUNC). The first 1354*0fca6ea1SDimitry Andric // is treated as the canonical opcode. 1355*0fca6ea1SDimitry Andric SmallVector<const CodeGenInstruction *, 2> Insts; 1356*0fca6ea1SDimitry Andric 1357*0fca6ea1SDimitry Andric static DenseMap<const CodeGenInstruction *, unsigned> OpcodeValues; 1358*0fca6ea1SDimitry Andric 1359*0fca6ea1SDimitry Andric MatchTableRecord getInstValue(const CodeGenInstruction *I) const; 1360*0fca6ea1SDimitry Andric 1361*0fca6ea1SDimitry Andric public: 1362*0fca6ea1SDimitry Andric static void initOpcodeValuesMap(const CodeGenTarget &Target); 1363*0fca6ea1SDimitry Andric 1364*0fca6ea1SDimitry Andric InstructionOpcodeMatcher(unsigned InsnVarID, 1365*0fca6ea1SDimitry Andric ArrayRef<const CodeGenInstruction *> I) 1366*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_Opcode, InsnVarID), 1367*0fca6ea1SDimitry Andric Insts(I.begin(), I.end()) { 1368*0fca6ea1SDimitry Andric assert((Insts.size() == 1 || Insts.size() == 2) && 1369*0fca6ea1SDimitry Andric "unexpected number of opcode alternatives"); 1370*0fca6ea1SDimitry Andric } 1371*0fca6ea1SDimitry Andric 1372*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1373*0fca6ea1SDimitry Andric return P->getKind() == IPM_Opcode; 1374*0fca6ea1SDimitry Andric } 1375*0fca6ea1SDimitry Andric 1376*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1377*0fca6ea1SDimitry Andric return InstructionPredicateMatcher::isIdentical(B) && 1378*0fca6ea1SDimitry Andric Insts == cast<InstructionOpcodeMatcher>(&B)->Insts; 1379*0fca6ea1SDimitry Andric } 1380*0fca6ea1SDimitry Andric 1381*0fca6ea1SDimitry Andric bool hasValue() const override { 1382*0fca6ea1SDimitry Andric return Insts.size() == 1 && OpcodeValues.count(Insts[0]); 1383*0fca6ea1SDimitry Andric } 1384*0fca6ea1SDimitry Andric 1385*0fca6ea1SDimitry Andric // TODO: This is used for the SwitchMatcher optimization. We should be able to 1386*0fca6ea1SDimitry Andric // return a list of the opcodes to match. 1387*0fca6ea1SDimitry Andric MatchTableRecord getValue() const override; 1388*0fca6ea1SDimitry Andric 1389*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1390*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1391*0fca6ea1SDimitry Andric 1392*0fca6ea1SDimitry Andric /// Compare the priority of this object and B. 1393*0fca6ea1SDimitry Andric /// 1394*0fca6ea1SDimitry Andric /// Returns true if this object is more important than B. 1395*0fca6ea1SDimitry Andric bool 1396*0fca6ea1SDimitry Andric isHigherPriorityThan(const InstructionPredicateMatcher &B) const override; 1397*0fca6ea1SDimitry Andric 1398*0fca6ea1SDimitry Andric bool isConstantInstruction() const; 1399*0fca6ea1SDimitry Andric 1400*0fca6ea1SDimitry Andric // The first opcode is the canonical opcode, and later are alternatives. 1401*0fca6ea1SDimitry Andric StringRef getOpcode() const; 1402*0fca6ea1SDimitry Andric ArrayRef<const CodeGenInstruction *> getAlternativeOpcodes() { return Insts; } 1403*0fca6ea1SDimitry Andric bool isVariadicNumOperands() const; 1404*0fca6ea1SDimitry Andric StringRef getOperandType(unsigned OpIdx) const; 1405*0fca6ea1SDimitry Andric }; 1406*0fca6ea1SDimitry Andric 1407*0fca6ea1SDimitry Andric class InstructionNumOperandsMatcher final : public InstructionPredicateMatcher { 1408*0fca6ea1SDimitry Andric unsigned NumOperands = 0; 1409*0fca6ea1SDimitry Andric 1410*0fca6ea1SDimitry Andric public: 1411*0fca6ea1SDimitry Andric InstructionNumOperandsMatcher(unsigned InsnVarID, unsigned NumOperands) 1412*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_NumOperands, InsnVarID), 1413*0fca6ea1SDimitry Andric NumOperands(NumOperands) {} 1414*0fca6ea1SDimitry Andric 1415*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1416*0fca6ea1SDimitry Andric return P->getKind() == IPM_NumOperands; 1417*0fca6ea1SDimitry Andric } 1418*0fca6ea1SDimitry Andric 1419*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1420*0fca6ea1SDimitry Andric return InstructionPredicateMatcher::isIdentical(B) && 1421*0fca6ea1SDimitry Andric NumOperands == cast<InstructionNumOperandsMatcher>(&B)->NumOperands; 1422*0fca6ea1SDimitry Andric } 1423*0fca6ea1SDimitry Andric 1424*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1425*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1426*0fca6ea1SDimitry Andric }; 1427*0fca6ea1SDimitry Andric 1428*0fca6ea1SDimitry Andric /// Generates code to check that this instruction is a constant whose value 1429*0fca6ea1SDimitry Andric /// meets an immediate predicate. 1430*0fca6ea1SDimitry Andric /// 1431*0fca6ea1SDimitry Andric /// Immediates are slightly odd since they are typically used like an operand 1432*0fca6ea1SDimitry Andric /// but are represented as an operator internally. We typically write simm8:$src 1433*0fca6ea1SDimitry Andric /// in a tablegen pattern, but this is just syntactic sugar for 1434*0fca6ea1SDimitry Andric /// (imm:i32)<<P:Predicate_simm8>>:$imm which more directly describes the nodes 1435*0fca6ea1SDimitry Andric /// that will be matched and the predicate (which is attached to the imm 1436*0fca6ea1SDimitry Andric /// operator) that will be tested. In SelectionDAG this describes a 1437*0fca6ea1SDimitry Andric /// ConstantSDNode whose internal value will be tested using the simm8 1438*0fca6ea1SDimitry Andric /// predicate. 1439*0fca6ea1SDimitry Andric /// 1440*0fca6ea1SDimitry Andric /// The corresponding GlobalISel representation is %1 = G_CONSTANT iN Value. In 1441*0fca6ea1SDimitry Andric /// this representation, the immediate could be tested with an 1442*0fca6ea1SDimitry Andric /// InstructionMatcher, InstructionOpcodeMatcher, OperandMatcher, and a 1443*0fca6ea1SDimitry Andric /// OperandPredicateMatcher-subclass to check the Value meets the predicate but 1444*0fca6ea1SDimitry Andric /// there are two implementation issues with producing that matcher 1445*0fca6ea1SDimitry Andric /// configuration from the SelectionDAG pattern: 1446*0fca6ea1SDimitry Andric /// * ImmLeaf is a PatFrag whose root is an InstructionMatcher. This means that 1447*0fca6ea1SDimitry Andric /// were we to sink the immediate predicate to the operand we would have to 1448*0fca6ea1SDimitry Andric /// have two partial implementations of PatFrag support, one for immediates 1449*0fca6ea1SDimitry Andric /// and one for non-immediates. 1450*0fca6ea1SDimitry Andric /// * At the point we handle the predicate, the OperandMatcher hasn't been 1451*0fca6ea1SDimitry Andric /// created yet. If we were to sink the predicate to the OperandMatcher we 1452*0fca6ea1SDimitry Andric /// would also have to complicate (or duplicate) the code that descends and 1453*0fca6ea1SDimitry Andric /// creates matchers for the subtree. 1454*0fca6ea1SDimitry Andric /// Overall, it's simpler to handle it in the place it was found. 1455*0fca6ea1SDimitry Andric class InstructionImmPredicateMatcher : public InstructionPredicateMatcher { 1456*0fca6ea1SDimitry Andric protected: 1457*0fca6ea1SDimitry Andric TreePredicateFn Predicate; 1458*0fca6ea1SDimitry Andric 1459*0fca6ea1SDimitry Andric public: 1460*0fca6ea1SDimitry Andric InstructionImmPredicateMatcher(unsigned InsnVarID, 1461*0fca6ea1SDimitry Andric const TreePredicateFn &Predicate) 1462*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_ImmPredicate, InsnVarID), 1463*0fca6ea1SDimitry Andric Predicate(Predicate) {} 1464*0fca6ea1SDimitry Andric 1465*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override; 1466*0fca6ea1SDimitry Andric 1467*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1468*0fca6ea1SDimitry Andric return P->getKind() == IPM_ImmPredicate; 1469*0fca6ea1SDimitry Andric } 1470*0fca6ea1SDimitry Andric 1471*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1472*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1473*0fca6ea1SDimitry Andric }; 1474*0fca6ea1SDimitry Andric 1475*0fca6ea1SDimitry Andric /// Generates code to check that a memory instruction has a atomic ordering 1476*0fca6ea1SDimitry Andric /// MachineMemoryOperand. 1477*0fca6ea1SDimitry Andric class AtomicOrderingMMOPredicateMatcher : public InstructionPredicateMatcher { 1478*0fca6ea1SDimitry Andric public: 1479*0fca6ea1SDimitry Andric enum AOComparator { 1480*0fca6ea1SDimitry Andric AO_Exactly, 1481*0fca6ea1SDimitry Andric AO_OrStronger, 1482*0fca6ea1SDimitry Andric AO_WeakerThan, 1483*0fca6ea1SDimitry Andric }; 1484*0fca6ea1SDimitry Andric 1485*0fca6ea1SDimitry Andric protected: 1486*0fca6ea1SDimitry Andric StringRef Order; 1487*0fca6ea1SDimitry Andric AOComparator Comparator; 1488*0fca6ea1SDimitry Andric 1489*0fca6ea1SDimitry Andric public: 1490*0fca6ea1SDimitry Andric AtomicOrderingMMOPredicateMatcher(unsigned InsnVarID, StringRef Order, 1491*0fca6ea1SDimitry Andric AOComparator Comparator = AO_Exactly) 1492*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_AtomicOrderingMMO, InsnVarID), 1493*0fca6ea1SDimitry Andric Order(Order), Comparator(Comparator) {} 1494*0fca6ea1SDimitry Andric 1495*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1496*0fca6ea1SDimitry Andric return P->getKind() == IPM_AtomicOrderingMMO; 1497*0fca6ea1SDimitry Andric } 1498*0fca6ea1SDimitry Andric 1499*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override; 1500*0fca6ea1SDimitry Andric 1501*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1502*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1503*0fca6ea1SDimitry Andric }; 1504*0fca6ea1SDimitry Andric 1505*0fca6ea1SDimitry Andric /// Generates code to check that the size of an MMO is exactly N bytes. 1506*0fca6ea1SDimitry Andric class MemorySizePredicateMatcher : public InstructionPredicateMatcher { 1507*0fca6ea1SDimitry Andric protected: 1508*0fca6ea1SDimitry Andric unsigned MMOIdx; 1509*0fca6ea1SDimitry Andric uint64_t Size; 1510*0fca6ea1SDimitry Andric 1511*0fca6ea1SDimitry Andric public: 1512*0fca6ea1SDimitry Andric MemorySizePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx, unsigned Size) 1513*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_MemoryLLTSize, InsnVarID), 1514*0fca6ea1SDimitry Andric MMOIdx(MMOIdx), Size(Size) {} 1515*0fca6ea1SDimitry Andric 1516*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1517*0fca6ea1SDimitry Andric return P->getKind() == IPM_MemoryLLTSize; 1518*0fca6ea1SDimitry Andric } 1519*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1520*0fca6ea1SDimitry Andric return InstructionPredicateMatcher::isIdentical(B) && 1521*0fca6ea1SDimitry Andric MMOIdx == cast<MemorySizePredicateMatcher>(&B)->MMOIdx && 1522*0fca6ea1SDimitry Andric Size == cast<MemorySizePredicateMatcher>(&B)->Size; 1523*0fca6ea1SDimitry Andric } 1524*0fca6ea1SDimitry Andric 1525*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1526*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1527*0fca6ea1SDimitry Andric }; 1528*0fca6ea1SDimitry Andric 1529*0fca6ea1SDimitry Andric class MemoryAddressSpacePredicateMatcher : public InstructionPredicateMatcher { 1530*0fca6ea1SDimitry Andric protected: 1531*0fca6ea1SDimitry Andric unsigned MMOIdx; 1532*0fca6ea1SDimitry Andric SmallVector<unsigned, 4> AddrSpaces; 1533*0fca6ea1SDimitry Andric 1534*0fca6ea1SDimitry Andric public: 1535*0fca6ea1SDimitry Andric MemoryAddressSpacePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx, 1536*0fca6ea1SDimitry Andric ArrayRef<unsigned> AddrSpaces) 1537*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_MemoryAddressSpace, InsnVarID), 1538*0fca6ea1SDimitry Andric MMOIdx(MMOIdx), AddrSpaces(AddrSpaces.begin(), AddrSpaces.end()) {} 1539*0fca6ea1SDimitry Andric 1540*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1541*0fca6ea1SDimitry Andric return P->getKind() == IPM_MemoryAddressSpace; 1542*0fca6ea1SDimitry Andric } 1543*0fca6ea1SDimitry Andric 1544*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override; 1545*0fca6ea1SDimitry Andric 1546*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1547*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1548*0fca6ea1SDimitry Andric }; 1549*0fca6ea1SDimitry Andric 1550*0fca6ea1SDimitry Andric class MemoryAlignmentPredicateMatcher : public InstructionPredicateMatcher { 1551*0fca6ea1SDimitry Andric protected: 1552*0fca6ea1SDimitry Andric unsigned MMOIdx; 1553*0fca6ea1SDimitry Andric int MinAlign; 1554*0fca6ea1SDimitry Andric 1555*0fca6ea1SDimitry Andric public: 1556*0fca6ea1SDimitry Andric MemoryAlignmentPredicateMatcher(unsigned InsnVarID, unsigned MMOIdx, 1557*0fca6ea1SDimitry Andric int MinAlign) 1558*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_MemoryAlignment, InsnVarID), 1559*0fca6ea1SDimitry Andric MMOIdx(MMOIdx), MinAlign(MinAlign) { 1560*0fca6ea1SDimitry Andric assert(MinAlign > 0); 1561*0fca6ea1SDimitry Andric } 1562*0fca6ea1SDimitry Andric 1563*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1564*0fca6ea1SDimitry Andric return P->getKind() == IPM_MemoryAlignment; 1565*0fca6ea1SDimitry Andric } 1566*0fca6ea1SDimitry Andric 1567*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override; 1568*0fca6ea1SDimitry Andric 1569*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1570*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1571*0fca6ea1SDimitry Andric }; 1572*0fca6ea1SDimitry Andric 1573*0fca6ea1SDimitry Andric /// Generates code to check that the size of an MMO is less-than, equal-to, or 1574*0fca6ea1SDimitry Andric /// greater than a given LLT. 1575*0fca6ea1SDimitry Andric class MemoryVsLLTSizePredicateMatcher : public InstructionPredicateMatcher { 1576*0fca6ea1SDimitry Andric public: 1577*0fca6ea1SDimitry Andric enum RelationKind { 1578*0fca6ea1SDimitry Andric GreaterThan, 1579*0fca6ea1SDimitry Andric EqualTo, 1580*0fca6ea1SDimitry Andric LessThan, 1581*0fca6ea1SDimitry Andric }; 1582*0fca6ea1SDimitry Andric 1583*0fca6ea1SDimitry Andric protected: 1584*0fca6ea1SDimitry Andric unsigned MMOIdx; 1585*0fca6ea1SDimitry Andric RelationKind Relation; 1586*0fca6ea1SDimitry Andric unsigned OpIdx; 1587*0fca6ea1SDimitry Andric 1588*0fca6ea1SDimitry Andric public: 1589*0fca6ea1SDimitry Andric MemoryVsLLTSizePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx, 1590*0fca6ea1SDimitry Andric enum RelationKind Relation, unsigned OpIdx) 1591*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_MemoryVsLLTSize, InsnVarID), 1592*0fca6ea1SDimitry Andric MMOIdx(MMOIdx), Relation(Relation), OpIdx(OpIdx) {} 1593*0fca6ea1SDimitry Andric 1594*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1595*0fca6ea1SDimitry Andric return P->getKind() == IPM_MemoryVsLLTSize; 1596*0fca6ea1SDimitry Andric } 1597*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override; 1598*0fca6ea1SDimitry Andric 1599*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1600*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1601*0fca6ea1SDimitry Andric }; 1602*0fca6ea1SDimitry Andric 1603*0fca6ea1SDimitry Andric // Matcher for immAllOnesV/immAllZerosV 1604*0fca6ea1SDimitry Andric class VectorSplatImmPredicateMatcher : public InstructionPredicateMatcher { 1605*0fca6ea1SDimitry Andric public: 1606*0fca6ea1SDimitry Andric enum SplatKind { AllZeros, AllOnes }; 1607*0fca6ea1SDimitry Andric 1608*0fca6ea1SDimitry Andric private: 1609*0fca6ea1SDimitry Andric SplatKind Kind; 1610*0fca6ea1SDimitry Andric 1611*0fca6ea1SDimitry Andric public: 1612*0fca6ea1SDimitry Andric VectorSplatImmPredicateMatcher(unsigned InsnVarID, SplatKind K) 1613*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_VectorSplatImm, InsnVarID), Kind(K) {} 1614*0fca6ea1SDimitry Andric 1615*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1616*0fca6ea1SDimitry Andric return P->getKind() == IPM_VectorSplatImm; 1617*0fca6ea1SDimitry Andric } 1618*0fca6ea1SDimitry Andric 1619*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1620*0fca6ea1SDimitry Andric return InstructionPredicateMatcher::isIdentical(B) && 1621*0fca6ea1SDimitry Andric Kind == static_cast<const VectorSplatImmPredicateMatcher &>(B).Kind; 1622*0fca6ea1SDimitry Andric } 1623*0fca6ea1SDimitry Andric 1624*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1625*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1626*0fca6ea1SDimitry Andric }; 1627*0fca6ea1SDimitry Andric 1628*0fca6ea1SDimitry Andric /// Generates code to check an arbitrary C++ instruction predicate. 1629*0fca6ea1SDimitry Andric class GenericInstructionPredicateMatcher : public InstructionPredicateMatcher { 1630*0fca6ea1SDimitry Andric protected: 1631*0fca6ea1SDimitry Andric std::string EnumVal; 1632*0fca6ea1SDimitry Andric 1633*0fca6ea1SDimitry Andric public: 1634*0fca6ea1SDimitry Andric GenericInstructionPredicateMatcher(unsigned InsnVarID, 1635*0fca6ea1SDimitry Andric TreePredicateFn Predicate); 1636*0fca6ea1SDimitry Andric 1637*0fca6ea1SDimitry Andric GenericInstructionPredicateMatcher(unsigned InsnVarID, 1638*0fca6ea1SDimitry Andric const std::string &EnumVal) 1639*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_GenericPredicate, InsnVarID), 1640*0fca6ea1SDimitry Andric EnumVal(EnumVal) {} 1641*0fca6ea1SDimitry Andric 1642*0fca6ea1SDimitry Andric static bool classof(const InstructionPredicateMatcher *P) { 1643*0fca6ea1SDimitry Andric return P->getKind() == IPM_GenericPredicate; 1644*0fca6ea1SDimitry Andric } 1645*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override; 1646*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1647*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1648*0fca6ea1SDimitry Andric }; 1649*0fca6ea1SDimitry Andric 1650*0fca6ea1SDimitry Andric class MIFlagsInstructionPredicateMatcher : public InstructionPredicateMatcher { 1651*0fca6ea1SDimitry Andric SmallVector<StringRef, 2> Flags; 1652*0fca6ea1SDimitry Andric bool CheckNot; // false = GIM_MIFlags, true = GIM_MIFlagsNot 1653*0fca6ea1SDimitry Andric 1654*0fca6ea1SDimitry Andric public: 1655*0fca6ea1SDimitry Andric MIFlagsInstructionPredicateMatcher(unsigned InsnVarID, 1656*0fca6ea1SDimitry Andric ArrayRef<StringRef> FlagsToCheck, 1657*0fca6ea1SDimitry Andric bool CheckNot = false) 1658*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_MIFlags, InsnVarID), 1659*0fca6ea1SDimitry Andric Flags(FlagsToCheck), CheckNot(CheckNot) { 1660*0fca6ea1SDimitry Andric sort(Flags); 1661*0fca6ea1SDimitry Andric } 1662*0fca6ea1SDimitry Andric 1663*0fca6ea1SDimitry Andric static bool classof(const InstructionPredicateMatcher *P) { 1664*0fca6ea1SDimitry Andric return P->getKind() == IPM_MIFlags; 1665*0fca6ea1SDimitry Andric } 1666*0fca6ea1SDimitry Andric 1667*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override; 1668*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1669*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 1670*0fca6ea1SDimitry Andric }; 1671*0fca6ea1SDimitry Andric 1672*0fca6ea1SDimitry Andric /// Generates code to check for the absence of use of the result. 1673*0fca6ea1SDimitry Andric // TODO? Generalize this to support checking for one use. 1674*0fca6ea1SDimitry Andric class NoUsePredicateMatcher : public InstructionPredicateMatcher { 1675*0fca6ea1SDimitry Andric public: 1676*0fca6ea1SDimitry Andric NoUsePredicateMatcher(unsigned InsnVarID) 1677*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_NoUse, InsnVarID) {} 1678*0fca6ea1SDimitry Andric 1679*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1680*0fca6ea1SDimitry Andric return P->getKind() == IPM_NoUse; 1681*0fca6ea1SDimitry Andric } 1682*0fca6ea1SDimitry Andric 1683*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1684*0fca6ea1SDimitry Andric return InstructionPredicateMatcher::isIdentical(B); 1685*0fca6ea1SDimitry Andric } 1686*0fca6ea1SDimitry Andric 1687*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1688*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override { 1689*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckHasNoUse") 1690*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1691*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1692*0fca6ea1SDimitry Andric } 1693*0fca6ea1SDimitry Andric }; 1694*0fca6ea1SDimitry Andric 1695*0fca6ea1SDimitry Andric /// Generates code to check that the first result has only one use. 1696*0fca6ea1SDimitry Andric class OneUsePredicateMatcher : public InstructionPredicateMatcher { 1697*0fca6ea1SDimitry Andric public: 1698*0fca6ea1SDimitry Andric OneUsePredicateMatcher(unsigned InsnVarID) 1699*0fca6ea1SDimitry Andric : InstructionPredicateMatcher(IPM_OneUse, InsnVarID) {} 1700*0fca6ea1SDimitry Andric 1701*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1702*0fca6ea1SDimitry Andric return P->getKind() == IPM_OneUse; 1703*0fca6ea1SDimitry Andric } 1704*0fca6ea1SDimitry Andric 1705*0fca6ea1SDimitry Andric bool isIdentical(const PredicateMatcher &B) const override { 1706*0fca6ea1SDimitry Andric return InstructionPredicateMatcher::isIdentical(B); 1707*0fca6ea1SDimitry Andric } 1708*0fca6ea1SDimitry Andric 1709*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1710*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override { 1711*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIM_CheckHasOneUse") 1712*0fca6ea1SDimitry Andric << MatchTable::Comment("MI") << MatchTable::ULEB128Value(InsnVarID) 1713*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 1714*0fca6ea1SDimitry Andric } 1715*0fca6ea1SDimitry Andric }; 1716*0fca6ea1SDimitry Andric 1717*0fca6ea1SDimitry Andric /// Generates code to check that a set of predicates and operands match for a 1718*0fca6ea1SDimitry Andric /// particular instruction. 1719*0fca6ea1SDimitry Andric /// 1720*0fca6ea1SDimitry Andric /// Typical predicates include: 1721*0fca6ea1SDimitry Andric /// * Has a specific opcode. 1722*0fca6ea1SDimitry Andric /// * Has an nsw/nuw flag or doesn't. 1723*0fca6ea1SDimitry Andric class InstructionMatcher final : public PredicateListMatcher<PredicateMatcher> { 1724*0fca6ea1SDimitry Andric protected: 1725*0fca6ea1SDimitry Andric typedef std::vector<std::unique_ptr<OperandMatcher>> OperandVec; 1726*0fca6ea1SDimitry Andric 1727*0fca6ea1SDimitry Andric RuleMatcher &Rule; 1728*0fca6ea1SDimitry Andric 1729*0fca6ea1SDimitry Andric /// The operands to match. All rendered operands must be present even if the 1730*0fca6ea1SDimitry Andric /// condition is always true. 1731*0fca6ea1SDimitry Andric OperandVec Operands; 1732*0fca6ea1SDimitry Andric bool NumOperandsCheck = true; 1733*0fca6ea1SDimitry Andric 1734*0fca6ea1SDimitry Andric std::string SymbolicName; 1735*0fca6ea1SDimitry Andric unsigned InsnVarID; 1736*0fca6ea1SDimitry Andric 1737*0fca6ea1SDimitry Andric /// PhysRegInputs - List list has an entry for each explicitly specified 1738*0fca6ea1SDimitry Andric /// physreg input to the pattern. The first elt is the Register node, the 1739*0fca6ea1SDimitry Andric /// second is the recorded slot number the input pattern match saved it in. 1740*0fca6ea1SDimitry Andric SmallVector<std::pair<Record *, unsigned>, 2> PhysRegInputs; 1741*0fca6ea1SDimitry Andric 1742*0fca6ea1SDimitry Andric public: 1743*0fca6ea1SDimitry Andric InstructionMatcher(RuleMatcher &Rule, StringRef SymbolicName, 1744*0fca6ea1SDimitry Andric bool NumOpsCheck = true) 1745*0fca6ea1SDimitry Andric : Rule(Rule), NumOperandsCheck(NumOpsCheck), SymbolicName(SymbolicName) { 1746*0fca6ea1SDimitry Andric // We create a new instruction matcher. 1747*0fca6ea1SDimitry Andric // Get a new ID for that instruction. 1748*0fca6ea1SDimitry Andric InsnVarID = Rule.implicitlyDefineInsnVar(*this); 1749*0fca6ea1SDimitry Andric } 1750*0fca6ea1SDimitry Andric 1751*0fca6ea1SDimitry Andric /// Construct a new instruction predicate and add it to the matcher. 1752*0fca6ea1SDimitry Andric template <class Kind, class... Args> 1753*0fca6ea1SDimitry Andric std::optional<Kind *> addPredicate(Args &&...args) { 1754*0fca6ea1SDimitry Andric Predicates.emplace_back( 1755*0fca6ea1SDimitry Andric std::make_unique<Kind>(getInsnVarID(), std::forward<Args>(args)...)); 1756*0fca6ea1SDimitry Andric return static_cast<Kind *>(Predicates.back().get()); 1757*0fca6ea1SDimitry Andric } 1758*0fca6ea1SDimitry Andric 1759*0fca6ea1SDimitry Andric RuleMatcher &getRuleMatcher() const { return Rule; } 1760*0fca6ea1SDimitry Andric 1761*0fca6ea1SDimitry Andric unsigned getInsnVarID() const { return InsnVarID; } 1762*0fca6ea1SDimitry Andric 1763*0fca6ea1SDimitry Andric /// Add an operand to the matcher. 1764*0fca6ea1SDimitry Andric OperandMatcher &addOperand(unsigned OpIdx, const std::string &SymbolicName, 1765*0fca6ea1SDimitry Andric unsigned AllocatedTemporariesBaseID); 1766*0fca6ea1SDimitry Andric OperandMatcher &getOperand(unsigned OpIdx); 1767*0fca6ea1SDimitry Andric OperandMatcher &addPhysRegInput(Record *Reg, unsigned OpIdx, 1768*0fca6ea1SDimitry Andric unsigned TempOpIdx); 1769*0fca6ea1SDimitry Andric 1770*0fca6ea1SDimitry Andric ArrayRef<std::pair<Record *, unsigned>> getPhysRegInputs() const { 1771*0fca6ea1SDimitry Andric return PhysRegInputs; 1772*0fca6ea1SDimitry Andric } 1773*0fca6ea1SDimitry Andric 1774*0fca6ea1SDimitry Andric StringRef getSymbolicName() const { return SymbolicName; } 1775*0fca6ea1SDimitry Andric unsigned getNumOperands() const { return Operands.size(); } 1776*0fca6ea1SDimitry Andric OperandVec::iterator operands_begin() { return Operands.begin(); } 1777*0fca6ea1SDimitry Andric OperandVec::iterator operands_end() { return Operands.end(); } 1778*0fca6ea1SDimitry Andric iterator_range<OperandVec::iterator> operands() { 1779*0fca6ea1SDimitry Andric return make_range(operands_begin(), operands_end()); 1780*0fca6ea1SDimitry Andric } 1781*0fca6ea1SDimitry Andric OperandVec::const_iterator operands_begin() const { return Operands.begin(); } 1782*0fca6ea1SDimitry Andric OperandVec::const_iterator operands_end() const { return Operands.end(); } 1783*0fca6ea1SDimitry Andric iterator_range<OperandVec::const_iterator> operands() const { 1784*0fca6ea1SDimitry Andric return make_range(operands_begin(), operands_end()); 1785*0fca6ea1SDimitry Andric } 1786*0fca6ea1SDimitry Andric bool operands_empty() const { return Operands.empty(); } 1787*0fca6ea1SDimitry Andric 1788*0fca6ea1SDimitry Andric void pop_front() { Operands.erase(Operands.begin()); } 1789*0fca6ea1SDimitry Andric 1790*0fca6ea1SDimitry Andric void optimize(); 1791*0fca6ea1SDimitry Andric 1792*0fca6ea1SDimitry Andric /// Emit MatchTable opcodes that test whether the instruction named in 1793*0fca6ea1SDimitry Andric /// InsnVarName matches all the predicates and all the operands. 1794*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule); 1795*0fca6ea1SDimitry Andric 1796*0fca6ea1SDimitry Andric /// Compare the priority of this object and B. 1797*0fca6ea1SDimitry Andric /// 1798*0fca6ea1SDimitry Andric /// Returns true if this object is more important than B. 1799*0fca6ea1SDimitry Andric bool isHigherPriorityThan(InstructionMatcher &B); 1800*0fca6ea1SDimitry Andric 1801*0fca6ea1SDimitry Andric /// Report the maximum number of temporary operands needed by the instruction 1802*0fca6ea1SDimitry Andric /// matcher. 1803*0fca6ea1SDimitry Andric unsigned countRendererFns(); 1804*0fca6ea1SDimitry Andric 1805*0fca6ea1SDimitry Andric InstructionOpcodeMatcher &getOpcodeMatcher() { 1806*0fca6ea1SDimitry Andric for (auto &P : predicates()) 1807*0fca6ea1SDimitry Andric if (auto *OpMatcher = dyn_cast<InstructionOpcodeMatcher>(P.get())) 1808*0fca6ea1SDimitry Andric return *OpMatcher; 1809*0fca6ea1SDimitry Andric llvm_unreachable("Didn't find an opcode matcher"); 1810*0fca6ea1SDimitry Andric } 1811*0fca6ea1SDimitry Andric 1812*0fca6ea1SDimitry Andric bool isConstantInstruction() { 1813*0fca6ea1SDimitry Andric return getOpcodeMatcher().isConstantInstruction(); 1814*0fca6ea1SDimitry Andric } 1815*0fca6ea1SDimitry Andric 1816*0fca6ea1SDimitry Andric StringRef getOpcode() { return getOpcodeMatcher().getOpcode(); } 1817*0fca6ea1SDimitry Andric }; 1818*0fca6ea1SDimitry Andric 1819*0fca6ea1SDimitry Andric /// Generates code to check that the operand is a register defined by an 1820*0fca6ea1SDimitry Andric /// instruction that matches the given instruction matcher. 1821*0fca6ea1SDimitry Andric /// 1822*0fca6ea1SDimitry Andric /// For example, the pattern: 1823*0fca6ea1SDimitry Andric /// (set $dst, (G_MUL (G_ADD $src1, $src2), $src3)) 1824*0fca6ea1SDimitry Andric /// would use an InstructionOperandMatcher for operand 1 of the G_MUL to match 1825*0fca6ea1SDimitry Andric /// the: 1826*0fca6ea1SDimitry Andric /// (G_ADD $src1, $src2) 1827*0fca6ea1SDimitry Andric /// subpattern. 1828*0fca6ea1SDimitry Andric class InstructionOperandMatcher : public OperandPredicateMatcher { 1829*0fca6ea1SDimitry Andric protected: 1830*0fca6ea1SDimitry Andric std::unique_ptr<InstructionMatcher> InsnMatcher; 1831*0fca6ea1SDimitry Andric 1832*0fca6ea1SDimitry Andric GISelFlags Flags; 1833*0fca6ea1SDimitry Andric 1834*0fca6ea1SDimitry Andric public: 1835*0fca6ea1SDimitry Andric InstructionOperandMatcher(unsigned InsnVarID, unsigned OpIdx, 1836*0fca6ea1SDimitry Andric RuleMatcher &Rule, StringRef SymbolicName, 1837*0fca6ea1SDimitry Andric bool NumOpsCheck = true) 1838*0fca6ea1SDimitry Andric : OperandPredicateMatcher(OPM_Instruction, InsnVarID, OpIdx), 1839*0fca6ea1SDimitry Andric InsnMatcher(new InstructionMatcher(Rule, SymbolicName, NumOpsCheck)), 1840*0fca6ea1SDimitry Andric Flags(Rule.getGISelFlags()) {} 1841*0fca6ea1SDimitry Andric 1842*0fca6ea1SDimitry Andric static bool classof(const PredicateMatcher *P) { 1843*0fca6ea1SDimitry Andric return P->getKind() == OPM_Instruction; 1844*0fca6ea1SDimitry Andric } 1845*0fca6ea1SDimitry Andric 1846*0fca6ea1SDimitry Andric InstructionMatcher &getInsnMatcher() const { return *InsnMatcher; } 1847*0fca6ea1SDimitry Andric 1848*0fca6ea1SDimitry Andric void emitCaptureOpcodes(MatchTable &Table, RuleMatcher &Rule) const; 1849*0fca6ea1SDimitry Andric void emitPredicateOpcodes(MatchTable &Table, 1850*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override { 1851*0fca6ea1SDimitry Andric emitCaptureOpcodes(Table, Rule); 1852*0fca6ea1SDimitry Andric InsnMatcher->emitPredicateOpcodes(Table, Rule); 1853*0fca6ea1SDimitry Andric } 1854*0fca6ea1SDimitry Andric 1855*0fca6ea1SDimitry Andric bool isHigherPriorityThan(const OperandPredicateMatcher &B) const override; 1856*0fca6ea1SDimitry Andric 1857*0fca6ea1SDimitry Andric /// Report the maximum number of temporary operands needed by the predicate 1858*0fca6ea1SDimitry Andric /// matcher. 1859*0fca6ea1SDimitry Andric unsigned countRendererFns() const override { 1860*0fca6ea1SDimitry Andric return InsnMatcher->countRendererFns(); 1861*0fca6ea1SDimitry Andric } 1862*0fca6ea1SDimitry Andric }; 1863*0fca6ea1SDimitry Andric 1864*0fca6ea1SDimitry Andric //===- Actions ------------------------------------------------------------===// 1865*0fca6ea1SDimitry Andric class OperandRenderer { 1866*0fca6ea1SDimitry Andric public: 1867*0fca6ea1SDimitry Andric enum RendererKind { 1868*0fca6ea1SDimitry Andric OR_Copy, 1869*0fca6ea1SDimitry Andric OR_CopyOrAddZeroReg, 1870*0fca6ea1SDimitry Andric OR_CopySubReg, 1871*0fca6ea1SDimitry Andric OR_CopyPhysReg, 1872*0fca6ea1SDimitry Andric OR_CopyConstantAsImm, 1873*0fca6ea1SDimitry Andric OR_CopyFConstantAsFPImm, 1874*0fca6ea1SDimitry Andric OR_Imm, 1875*0fca6ea1SDimitry Andric OR_SubRegIndex, 1876*0fca6ea1SDimitry Andric OR_Register, 1877*0fca6ea1SDimitry Andric OR_TempRegister, 1878*0fca6ea1SDimitry Andric OR_ComplexPattern, 1879*0fca6ea1SDimitry Andric OR_Intrinsic, 1880*0fca6ea1SDimitry Andric OR_Custom, 1881*0fca6ea1SDimitry Andric OR_CustomOperand 1882*0fca6ea1SDimitry Andric }; 1883*0fca6ea1SDimitry Andric 1884*0fca6ea1SDimitry Andric protected: 1885*0fca6ea1SDimitry Andric RendererKind Kind; 1886*0fca6ea1SDimitry Andric 1887*0fca6ea1SDimitry Andric public: 1888*0fca6ea1SDimitry Andric OperandRenderer(RendererKind Kind) : Kind(Kind) {} 1889*0fca6ea1SDimitry Andric virtual ~OperandRenderer(); 1890*0fca6ea1SDimitry Andric 1891*0fca6ea1SDimitry Andric RendererKind getKind() const { return Kind; } 1892*0fca6ea1SDimitry Andric 1893*0fca6ea1SDimitry Andric virtual void emitRenderOpcodes(MatchTable &Table, 1894*0fca6ea1SDimitry Andric RuleMatcher &Rule) const = 0; 1895*0fca6ea1SDimitry Andric }; 1896*0fca6ea1SDimitry Andric 1897*0fca6ea1SDimitry Andric /// A CopyRenderer emits code to copy a single operand from an existing 1898*0fca6ea1SDimitry Andric /// instruction to the one being built. 1899*0fca6ea1SDimitry Andric class CopyRenderer : public OperandRenderer { 1900*0fca6ea1SDimitry Andric protected: 1901*0fca6ea1SDimitry Andric unsigned NewInsnID; 1902*0fca6ea1SDimitry Andric /// The name of the operand. 1903*0fca6ea1SDimitry Andric const StringRef SymbolicName; 1904*0fca6ea1SDimitry Andric 1905*0fca6ea1SDimitry Andric public: 1906*0fca6ea1SDimitry Andric CopyRenderer(unsigned NewInsnID, StringRef SymbolicName) 1907*0fca6ea1SDimitry Andric : OperandRenderer(OR_Copy), NewInsnID(NewInsnID), 1908*0fca6ea1SDimitry Andric SymbolicName(SymbolicName) { 1909*0fca6ea1SDimitry Andric assert(!SymbolicName.empty() && "Cannot copy from an unspecified source"); 1910*0fca6ea1SDimitry Andric } 1911*0fca6ea1SDimitry Andric 1912*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 1913*0fca6ea1SDimitry Andric return R->getKind() == OR_Copy; 1914*0fca6ea1SDimitry Andric } 1915*0fca6ea1SDimitry Andric 1916*0fca6ea1SDimitry Andric StringRef getSymbolicName() const { return SymbolicName; } 1917*0fca6ea1SDimitry Andric 1918*0fca6ea1SDimitry Andric static void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule, 1919*0fca6ea1SDimitry Andric unsigned NewInsnID, unsigned OldInsnID, 1920*0fca6ea1SDimitry Andric unsigned OpIdx, StringRef Name); 1921*0fca6ea1SDimitry Andric 1922*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 1923*0fca6ea1SDimitry Andric }; 1924*0fca6ea1SDimitry Andric 1925*0fca6ea1SDimitry Andric /// A CopyRenderer emits code to copy a virtual register to a specific physical 1926*0fca6ea1SDimitry Andric /// register. 1927*0fca6ea1SDimitry Andric class CopyPhysRegRenderer : public OperandRenderer { 1928*0fca6ea1SDimitry Andric protected: 1929*0fca6ea1SDimitry Andric unsigned NewInsnID; 1930*0fca6ea1SDimitry Andric Record *PhysReg; 1931*0fca6ea1SDimitry Andric 1932*0fca6ea1SDimitry Andric public: 1933*0fca6ea1SDimitry Andric CopyPhysRegRenderer(unsigned NewInsnID, Record *Reg) 1934*0fca6ea1SDimitry Andric : OperandRenderer(OR_CopyPhysReg), NewInsnID(NewInsnID), PhysReg(Reg) { 1935*0fca6ea1SDimitry Andric assert(PhysReg); 1936*0fca6ea1SDimitry Andric } 1937*0fca6ea1SDimitry Andric 1938*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 1939*0fca6ea1SDimitry Andric return R->getKind() == OR_CopyPhysReg; 1940*0fca6ea1SDimitry Andric } 1941*0fca6ea1SDimitry Andric 1942*0fca6ea1SDimitry Andric Record *getPhysReg() const { return PhysReg; } 1943*0fca6ea1SDimitry Andric 1944*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 1945*0fca6ea1SDimitry Andric }; 1946*0fca6ea1SDimitry Andric 1947*0fca6ea1SDimitry Andric /// A CopyOrAddZeroRegRenderer emits code to copy a single operand from an 1948*0fca6ea1SDimitry Andric /// existing instruction to the one being built. If the operand turns out to be 1949*0fca6ea1SDimitry Andric /// a 'G_CONSTANT 0' then it replaces the operand with a zero register. 1950*0fca6ea1SDimitry Andric class CopyOrAddZeroRegRenderer : public OperandRenderer { 1951*0fca6ea1SDimitry Andric protected: 1952*0fca6ea1SDimitry Andric unsigned NewInsnID; 1953*0fca6ea1SDimitry Andric /// The name of the operand. 1954*0fca6ea1SDimitry Andric const StringRef SymbolicName; 1955*0fca6ea1SDimitry Andric const Record *ZeroRegisterDef; 1956*0fca6ea1SDimitry Andric 1957*0fca6ea1SDimitry Andric public: 1958*0fca6ea1SDimitry Andric CopyOrAddZeroRegRenderer(unsigned NewInsnID, StringRef SymbolicName, 1959*0fca6ea1SDimitry Andric Record *ZeroRegisterDef) 1960*0fca6ea1SDimitry Andric : OperandRenderer(OR_CopyOrAddZeroReg), NewInsnID(NewInsnID), 1961*0fca6ea1SDimitry Andric SymbolicName(SymbolicName), ZeroRegisterDef(ZeroRegisterDef) { 1962*0fca6ea1SDimitry Andric assert(!SymbolicName.empty() && "Cannot copy from an unspecified source"); 1963*0fca6ea1SDimitry Andric } 1964*0fca6ea1SDimitry Andric 1965*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 1966*0fca6ea1SDimitry Andric return R->getKind() == OR_CopyOrAddZeroReg; 1967*0fca6ea1SDimitry Andric } 1968*0fca6ea1SDimitry Andric 1969*0fca6ea1SDimitry Andric StringRef getSymbolicName() const { return SymbolicName; } 1970*0fca6ea1SDimitry Andric 1971*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 1972*0fca6ea1SDimitry Andric }; 1973*0fca6ea1SDimitry Andric 1974*0fca6ea1SDimitry Andric /// A CopyConstantAsImmRenderer emits code to render a G_CONSTANT instruction to 1975*0fca6ea1SDimitry Andric /// an extended immediate operand. 1976*0fca6ea1SDimitry Andric class CopyConstantAsImmRenderer : public OperandRenderer { 1977*0fca6ea1SDimitry Andric protected: 1978*0fca6ea1SDimitry Andric unsigned NewInsnID; 1979*0fca6ea1SDimitry Andric /// The name of the operand. 1980*0fca6ea1SDimitry Andric const std::string SymbolicName; 1981*0fca6ea1SDimitry Andric bool Signed; 1982*0fca6ea1SDimitry Andric 1983*0fca6ea1SDimitry Andric public: 1984*0fca6ea1SDimitry Andric CopyConstantAsImmRenderer(unsigned NewInsnID, StringRef SymbolicName) 1985*0fca6ea1SDimitry Andric : OperandRenderer(OR_CopyConstantAsImm), NewInsnID(NewInsnID), 1986*0fca6ea1SDimitry Andric SymbolicName(SymbolicName), Signed(true) {} 1987*0fca6ea1SDimitry Andric 1988*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 1989*0fca6ea1SDimitry Andric return R->getKind() == OR_CopyConstantAsImm; 1990*0fca6ea1SDimitry Andric } 1991*0fca6ea1SDimitry Andric 1992*0fca6ea1SDimitry Andric StringRef getSymbolicName() const { return SymbolicName; } 1993*0fca6ea1SDimitry Andric 1994*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 1995*0fca6ea1SDimitry Andric }; 1996*0fca6ea1SDimitry Andric 1997*0fca6ea1SDimitry Andric /// A CopyFConstantAsFPImmRenderer emits code to render a G_FCONSTANT 1998*0fca6ea1SDimitry Andric /// instruction to an extended immediate operand. 1999*0fca6ea1SDimitry Andric class CopyFConstantAsFPImmRenderer : public OperandRenderer { 2000*0fca6ea1SDimitry Andric protected: 2001*0fca6ea1SDimitry Andric unsigned NewInsnID; 2002*0fca6ea1SDimitry Andric /// The name of the operand. 2003*0fca6ea1SDimitry Andric const std::string SymbolicName; 2004*0fca6ea1SDimitry Andric 2005*0fca6ea1SDimitry Andric public: 2006*0fca6ea1SDimitry Andric CopyFConstantAsFPImmRenderer(unsigned NewInsnID, StringRef SymbolicName) 2007*0fca6ea1SDimitry Andric : OperandRenderer(OR_CopyFConstantAsFPImm), NewInsnID(NewInsnID), 2008*0fca6ea1SDimitry Andric SymbolicName(SymbolicName) {} 2009*0fca6ea1SDimitry Andric 2010*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 2011*0fca6ea1SDimitry Andric return R->getKind() == OR_CopyFConstantAsFPImm; 2012*0fca6ea1SDimitry Andric } 2013*0fca6ea1SDimitry Andric 2014*0fca6ea1SDimitry Andric StringRef getSymbolicName() const { return SymbolicName; } 2015*0fca6ea1SDimitry Andric 2016*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2017*0fca6ea1SDimitry Andric }; 2018*0fca6ea1SDimitry Andric 2019*0fca6ea1SDimitry Andric /// A CopySubRegRenderer emits code to copy a single register operand from an 2020*0fca6ea1SDimitry Andric /// existing instruction to the one being built and indicate that only a 2021*0fca6ea1SDimitry Andric /// subregister should be copied. 2022*0fca6ea1SDimitry Andric class CopySubRegRenderer : public OperandRenderer { 2023*0fca6ea1SDimitry Andric protected: 2024*0fca6ea1SDimitry Andric unsigned NewInsnID; 2025*0fca6ea1SDimitry Andric /// The name of the operand. 2026*0fca6ea1SDimitry Andric const StringRef SymbolicName; 2027*0fca6ea1SDimitry Andric /// The subregister to extract. 2028*0fca6ea1SDimitry Andric const CodeGenSubRegIndex *SubReg; 2029*0fca6ea1SDimitry Andric 2030*0fca6ea1SDimitry Andric public: 2031*0fca6ea1SDimitry Andric CopySubRegRenderer(unsigned NewInsnID, StringRef SymbolicName, 2032*0fca6ea1SDimitry Andric const CodeGenSubRegIndex *SubReg) 2033*0fca6ea1SDimitry Andric : OperandRenderer(OR_CopySubReg), NewInsnID(NewInsnID), 2034*0fca6ea1SDimitry Andric SymbolicName(SymbolicName), SubReg(SubReg) {} 2035*0fca6ea1SDimitry Andric 2036*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 2037*0fca6ea1SDimitry Andric return R->getKind() == OR_CopySubReg; 2038*0fca6ea1SDimitry Andric } 2039*0fca6ea1SDimitry Andric 2040*0fca6ea1SDimitry Andric StringRef getSymbolicName() const { return SymbolicName; } 2041*0fca6ea1SDimitry Andric 2042*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2043*0fca6ea1SDimitry Andric }; 2044*0fca6ea1SDimitry Andric 2045*0fca6ea1SDimitry Andric /// Adds a specific physical register to the instruction being built. 2046*0fca6ea1SDimitry Andric /// This is typically useful for WZR/XZR on AArch64. 2047*0fca6ea1SDimitry Andric class AddRegisterRenderer : public OperandRenderer { 2048*0fca6ea1SDimitry Andric protected: 2049*0fca6ea1SDimitry Andric unsigned InsnID; 2050*0fca6ea1SDimitry Andric const Record *RegisterDef; 2051*0fca6ea1SDimitry Andric bool IsDef; 2052*0fca6ea1SDimitry Andric const CodeGenTarget &Target; 2053*0fca6ea1SDimitry Andric 2054*0fca6ea1SDimitry Andric public: 2055*0fca6ea1SDimitry Andric AddRegisterRenderer(unsigned InsnID, const CodeGenTarget &Target, 2056*0fca6ea1SDimitry Andric const Record *RegisterDef, bool IsDef = false) 2057*0fca6ea1SDimitry Andric : OperandRenderer(OR_Register), InsnID(InsnID), RegisterDef(RegisterDef), 2058*0fca6ea1SDimitry Andric IsDef(IsDef), Target(Target) {} 2059*0fca6ea1SDimitry Andric 2060*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 2061*0fca6ea1SDimitry Andric return R->getKind() == OR_Register; 2062*0fca6ea1SDimitry Andric } 2063*0fca6ea1SDimitry Andric 2064*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2065*0fca6ea1SDimitry Andric }; 2066*0fca6ea1SDimitry Andric 2067*0fca6ea1SDimitry Andric /// Adds a specific temporary virtual register to the instruction being built. 2068*0fca6ea1SDimitry Andric /// This is used to chain instructions together when emitting multiple 2069*0fca6ea1SDimitry Andric /// instructions. 2070*0fca6ea1SDimitry Andric class TempRegRenderer : public OperandRenderer { 2071*0fca6ea1SDimitry Andric protected: 2072*0fca6ea1SDimitry Andric unsigned InsnID; 2073*0fca6ea1SDimitry Andric unsigned TempRegID; 2074*0fca6ea1SDimitry Andric const CodeGenSubRegIndex *SubRegIdx; 2075*0fca6ea1SDimitry Andric bool IsDef; 2076*0fca6ea1SDimitry Andric bool IsDead; 2077*0fca6ea1SDimitry Andric 2078*0fca6ea1SDimitry Andric public: 2079*0fca6ea1SDimitry Andric TempRegRenderer(unsigned InsnID, unsigned TempRegID, bool IsDef = false, 2080*0fca6ea1SDimitry Andric const CodeGenSubRegIndex *SubReg = nullptr, 2081*0fca6ea1SDimitry Andric bool IsDead = false) 2082*0fca6ea1SDimitry Andric : OperandRenderer(OR_Register), InsnID(InsnID), TempRegID(TempRegID), 2083*0fca6ea1SDimitry Andric SubRegIdx(SubReg), IsDef(IsDef), IsDead(IsDead) {} 2084*0fca6ea1SDimitry Andric 2085*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 2086*0fca6ea1SDimitry Andric return R->getKind() == OR_TempRegister; 2087*0fca6ea1SDimitry Andric } 2088*0fca6ea1SDimitry Andric 2089*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2090*0fca6ea1SDimitry Andric }; 2091*0fca6ea1SDimitry Andric 2092*0fca6ea1SDimitry Andric /// Adds a specific immediate to the instruction being built. 2093*0fca6ea1SDimitry Andric /// If a LLT is passed, a ConstantInt immediate is created instead. 2094*0fca6ea1SDimitry Andric class ImmRenderer : public OperandRenderer { 2095*0fca6ea1SDimitry Andric protected: 2096*0fca6ea1SDimitry Andric unsigned InsnID; 2097*0fca6ea1SDimitry Andric int64_t Imm; 2098*0fca6ea1SDimitry Andric std::optional<LLTCodeGenOrTempType> CImmLLT; 2099*0fca6ea1SDimitry Andric 2100*0fca6ea1SDimitry Andric public: 2101*0fca6ea1SDimitry Andric ImmRenderer(unsigned InsnID, int64_t Imm) 2102*0fca6ea1SDimitry Andric : OperandRenderer(OR_Imm), InsnID(InsnID), Imm(Imm) {} 2103*0fca6ea1SDimitry Andric 2104*0fca6ea1SDimitry Andric ImmRenderer(unsigned InsnID, int64_t Imm, const LLTCodeGenOrTempType &CImmLLT) 2105*0fca6ea1SDimitry Andric : OperandRenderer(OR_Imm), InsnID(InsnID), Imm(Imm), CImmLLT(CImmLLT) { 2106*0fca6ea1SDimitry Andric if (CImmLLT.isLLTCodeGen()) 2107*0fca6ea1SDimitry Andric KnownTypes.insert(CImmLLT.getLLTCodeGen()); 2108*0fca6ea1SDimitry Andric } 2109*0fca6ea1SDimitry Andric 2110*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 2111*0fca6ea1SDimitry Andric return R->getKind() == OR_Imm; 2112*0fca6ea1SDimitry Andric } 2113*0fca6ea1SDimitry Andric 2114*0fca6ea1SDimitry Andric static void emitAddImm(MatchTable &Table, RuleMatcher &RM, unsigned InsnID, 2115*0fca6ea1SDimitry Andric int64_t Imm, StringRef ImmName = "Imm"); 2116*0fca6ea1SDimitry Andric 2117*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2118*0fca6ea1SDimitry Andric }; 2119*0fca6ea1SDimitry Andric 2120*0fca6ea1SDimitry Andric /// Adds an enum value for a subreg index to the instruction being built. 2121*0fca6ea1SDimitry Andric class SubRegIndexRenderer : public OperandRenderer { 2122*0fca6ea1SDimitry Andric protected: 2123*0fca6ea1SDimitry Andric unsigned InsnID; 2124*0fca6ea1SDimitry Andric const CodeGenSubRegIndex *SubRegIdx; 2125*0fca6ea1SDimitry Andric 2126*0fca6ea1SDimitry Andric public: 2127*0fca6ea1SDimitry Andric SubRegIndexRenderer(unsigned InsnID, const CodeGenSubRegIndex *SRI) 2128*0fca6ea1SDimitry Andric : OperandRenderer(OR_SubRegIndex), InsnID(InsnID), SubRegIdx(SRI) {} 2129*0fca6ea1SDimitry Andric 2130*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 2131*0fca6ea1SDimitry Andric return R->getKind() == OR_SubRegIndex; 2132*0fca6ea1SDimitry Andric } 2133*0fca6ea1SDimitry Andric 2134*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2135*0fca6ea1SDimitry Andric }; 2136*0fca6ea1SDimitry Andric 2137*0fca6ea1SDimitry Andric /// Adds operands by calling a renderer function supplied by the ComplexPattern 2138*0fca6ea1SDimitry Andric /// matcher function. 2139*0fca6ea1SDimitry Andric class RenderComplexPatternOperand : public OperandRenderer { 2140*0fca6ea1SDimitry Andric private: 2141*0fca6ea1SDimitry Andric unsigned InsnID; 2142*0fca6ea1SDimitry Andric const Record &TheDef; 2143*0fca6ea1SDimitry Andric /// The name of the operand. 2144*0fca6ea1SDimitry Andric const StringRef SymbolicName; 2145*0fca6ea1SDimitry Andric /// The renderer number. This must be unique within a rule since it's used to 2146*0fca6ea1SDimitry Andric /// identify a temporary variable to hold the renderer function. 2147*0fca6ea1SDimitry Andric unsigned RendererID; 2148*0fca6ea1SDimitry Andric /// When provided, this is the suboperand of the ComplexPattern operand to 2149*0fca6ea1SDimitry Andric /// render. Otherwise all the suboperands will be rendered. 2150*0fca6ea1SDimitry Andric std::optional<unsigned> SubOperand; 2151*0fca6ea1SDimitry Andric /// The subregister to extract. Render the whole register if not specified. 2152*0fca6ea1SDimitry Andric const CodeGenSubRegIndex *SubReg; 2153*0fca6ea1SDimitry Andric 2154*0fca6ea1SDimitry Andric unsigned getNumOperands() const { 2155*0fca6ea1SDimitry Andric return TheDef.getValueAsDag("Operands")->getNumArgs(); 2156*0fca6ea1SDimitry Andric } 2157*0fca6ea1SDimitry Andric 2158*0fca6ea1SDimitry Andric public: 2159*0fca6ea1SDimitry Andric RenderComplexPatternOperand(unsigned InsnID, const Record &TheDef, 2160*0fca6ea1SDimitry Andric StringRef SymbolicName, unsigned RendererID, 2161*0fca6ea1SDimitry Andric std::optional<unsigned> SubOperand = std::nullopt, 2162*0fca6ea1SDimitry Andric const CodeGenSubRegIndex *SubReg = nullptr) 2163*0fca6ea1SDimitry Andric : OperandRenderer(OR_ComplexPattern), InsnID(InsnID), TheDef(TheDef), 2164*0fca6ea1SDimitry Andric SymbolicName(SymbolicName), RendererID(RendererID), 2165*0fca6ea1SDimitry Andric SubOperand(SubOperand), SubReg(SubReg) {} 2166*0fca6ea1SDimitry Andric 2167*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 2168*0fca6ea1SDimitry Andric return R->getKind() == OR_ComplexPattern; 2169*0fca6ea1SDimitry Andric } 2170*0fca6ea1SDimitry Andric 2171*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2172*0fca6ea1SDimitry Andric }; 2173*0fca6ea1SDimitry Andric 2174*0fca6ea1SDimitry Andric /// Adds an intrinsic ID operand to the instruction being built. 2175*0fca6ea1SDimitry Andric class IntrinsicIDRenderer : public OperandRenderer { 2176*0fca6ea1SDimitry Andric protected: 2177*0fca6ea1SDimitry Andric unsigned InsnID; 2178*0fca6ea1SDimitry Andric const CodeGenIntrinsic *II; 2179*0fca6ea1SDimitry Andric 2180*0fca6ea1SDimitry Andric public: 2181*0fca6ea1SDimitry Andric IntrinsicIDRenderer(unsigned InsnID, const CodeGenIntrinsic *II) 2182*0fca6ea1SDimitry Andric : OperandRenderer(OR_Intrinsic), InsnID(InsnID), II(II) {} 2183*0fca6ea1SDimitry Andric 2184*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 2185*0fca6ea1SDimitry Andric return R->getKind() == OR_Intrinsic; 2186*0fca6ea1SDimitry Andric } 2187*0fca6ea1SDimitry Andric 2188*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2189*0fca6ea1SDimitry Andric }; 2190*0fca6ea1SDimitry Andric 2191*0fca6ea1SDimitry Andric class CustomRenderer : public OperandRenderer { 2192*0fca6ea1SDimitry Andric protected: 2193*0fca6ea1SDimitry Andric unsigned InsnID; 2194*0fca6ea1SDimitry Andric const Record &Renderer; 2195*0fca6ea1SDimitry Andric /// The name of the operand. 2196*0fca6ea1SDimitry Andric const std::string SymbolicName; 2197*0fca6ea1SDimitry Andric 2198*0fca6ea1SDimitry Andric public: 2199*0fca6ea1SDimitry Andric CustomRenderer(unsigned InsnID, const Record &Renderer, 2200*0fca6ea1SDimitry Andric StringRef SymbolicName) 2201*0fca6ea1SDimitry Andric : OperandRenderer(OR_Custom), InsnID(InsnID), Renderer(Renderer), 2202*0fca6ea1SDimitry Andric SymbolicName(SymbolicName) {} 2203*0fca6ea1SDimitry Andric 2204*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 2205*0fca6ea1SDimitry Andric return R->getKind() == OR_Custom; 2206*0fca6ea1SDimitry Andric } 2207*0fca6ea1SDimitry Andric 2208*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2209*0fca6ea1SDimitry Andric }; 2210*0fca6ea1SDimitry Andric 2211*0fca6ea1SDimitry Andric class CustomOperandRenderer : public OperandRenderer { 2212*0fca6ea1SDimitry Andric protected: 2213*0fca6ea1SDimitry Andric unsigned InsnID; 2214*0fca6ea1SDimitry Andric const Record &Renderer; 2215*0fca6ea1SDimitry Andric /// The name of the operand. 2216*0fca6ea1SDimitry Andric const std::string SymbolicName; 2217*0fca6ea1SDimitry Andric 2218*0fca6ea1SDimitry Andric public: 2219*0fca6ea1SDimitry Andric CustomOperandRenderer(unsigned InsnID, const Record &Renderer, 2220*0fca6ea1SDimitry Andric StringRef SymbolicName) 2221*0fca6ea1SDimitry Andric : OperandRenderer(OR_CustomOperand), InsnID(InsnID), Renderer(Renderer), 2222*0fca6ea1SDimitry Andric SymbolicName(SymbolicName) {} 2223*0fca6ea1SDimitry Andric 2224*0fca6ea1SDimitry Andric static bool classof(const OperandRenderer *R) { 2225*0fca6ea1SDimitry Andric return R->getKind() == OR_CustomOperand; 2226*0fca6ea1SDimitry Andric } 2227*0fca6ea1SDimitry Andric 2228*0fca6ea1SDimitry Andric void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2229*0fca6ea1SDimitry Andric }; 2230*0fca6ea1SDimitry Andric 2231*0fca6ea1SDimitry Andric /// An action taken when all Matcher predicates succeeded for a parent rule. 2232*0fca6ea1SDimitry Andric /// 2233*0fca6ea1SDimitry Andric /// Typical actions include: 2234*0fca6ea1SDimitry Andric /// * Changing the opcode of an instruction. 2235*0fca6ea1SDimitry Andric /// * Adding an operand to an instruction. 2236*0fca6ea1SDimitry Andric class MatchAction { 2237*0fca6ea1SDimitry Andric public: 2238*0fca6ea1SDimitry Andric enum ActionKind { 2239*0fca6ea1SDimitry Andric AK_DebugComment, 2240*0fca6ea1SDimitry Andric AK_BuildMI, 2241*0fca6ea1SDimitry Andric AK_BuildConstantMI, 2242*0fca6ea1SDimitry Andric AK_EraseInst, 2243*0fca6ea1SDimitry Andric AK_ReplaceReg, 2244*0fca6ea1SDimitry Andric AK_ConstraintOpsToDef, 2245*0fca6ea1SDimitry Andric AK_ConstraintOpsToRC, 2246*0fca6ea1SDimitry Andric AK_MakeTempReg, 2247*0fca6ea1SDimitry Andric }; 2248*0fca6ea1SDimitry Andric 2249*0fca6ea1SDimitry Andric MatchAction(ActionKind K) : Kind(K) {} 2250*0fca6ea1SDimitry Andric 2251*0fca6ea1SDimitry Andric ActionKind getKind() const { return Kind; } 2252*0fca6ea1SDimitry Andric 2253*0fca6ea1SDimitry Andric virtual ~MatchAction() {} 2254*0fca6ea1SDimitry Andric 2255*0fca6ea1SDimitry Andric // Some actions may need to add extra predicates to ensure they can run. 2256*0fca6ea1SDimitry Andric virtual void emitAdditionalPredicates(MatchTable &Table, 2257*0fca6ea1SDimitry Andric RuleMatcher &Rule) const {} 2258*0fca6ea1SDimitry Andric 2259*0fca6ea1SDimitry Andric /// Emit the MatchTable opcodes to implement the action. 2260*0fca6ea1SDimitry Andric virtual void emitActionOpcodes(MatchTable &Table, 2261*0fca6ea1SDimitry Andric RuleMatcher &Rule) const = 0; 2262*0fca6ea1SDimitry Andric 2263*0fca6ea1SDimitry Andric /// If this opcode has an overload that can call GIR_Done directly, emit that 2264*0fca6ea1SDimitry Andric /// instead of the usual opcode and return "true". Return "false" if GIR_Done 2265*0fca6ea1SDimitry Andric /// still needs to be emitted. 2266*0fca6ea1SDimitry Andric virtual bool emitActionOpcodesAndDone(MatchTable &Table, 2267*0fca6ea1SDimitry Andric RuleMatcher &Rule) const { 2268*0fca6ea1SDimitry Andric emitActionOpcodes(Table, Rule); 2269*0fca6ea1SDimitry Andric return false; 2270*0fca6ea1SDimitry Andric } 2271*0fca6ea1SDimitry Andric 2272*0fca6ea1SDimitry Andric private: 2273*0fca6ea1SDimitry Andric ActionKind Kind; 2274*0fca6ea1SDimitry Andric }; 2275*0fca6ea1SDimitry Andric 2276*0fca6ea1SDimitry Andric /// Generates a comment describing the matched rule being acted upon. 2277*0fca6ea1SDimitry Andric class DebugCommentAction : public MatchAction { 2278*0fca6ea1SDimitry Andric private: 2279*0fca6ea1SDimitry Andric std::string S; 2280*0fca6ea1SDimitry Andric 2281*0fca6ea1SDimitry Andric public: 2282*0fca6ea1SDimitry Andric DebugCommentAction(StringRef S) 2283*0fca6ea1SDimitry Andric : MatchAction(AK_DebugComment), S(std::string(S)) {} 2284*0fca6ea1SDimitry Andric 2285*0fca6ea1SDimitry Andric static bool classof(const MatchAction *A) { 2286*0fca6ea1SDimitry Andric return A->getKind() == AK_DebugComment; 2287*0fca6ea1SDimitry Andric } 2288*0fca6ea1SDimitry Andric 2289*0fca6ea1SDimitry Andric void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override { 2290*0fca6ea1SDimitry Andric Table << MatchTable::Comment(S) << MatchTable::LineBreak; 2291*0fca6ea1SDimitry Andric } 2292*0fca6ea1SDimitry Andric }; 2293*0fca6ea1SDimitry Andric 2294*0fca6ea1SDimitry Andric /// Generates code to build an instruction or mutate an existing instruction 2295*0fca6ea1SDimitry Andric /// into the desired instruction when this is possible. 2296*0fca6ea1SDimitry Andric class BuildMIAction : public MatchAction { 2297*0fca6ea1SDimitry Andric private: 2298*0fca6ea1SDimitry Andric unsigned InsnID; 2299*0fca6ea1SDimitry Andric const CodeGenInstruction *I; 2300*0fca6ea1SDimitry Andric InstructionMatcher *Matched; 2301*0fca6ea1SDimitry Andric std::vector<std::unique_ptr<OperandRenderer>> OperandRenderers; 2302*0fca6ea1SDimitry Andric SmallPtrSet<Record *, 4> DeadImplicitDefs; 2303*0fca6ea1SDimitry Andric 2304*0fca6ea1SDimitry Andric std::vector<const InstructionMatcher *> CopiedFlags; 2305*0fca6ea1SDimitry Andric std::vector<StringRef> SetFlags; 2306*0fca6ea1SDimitry Andric std::vector<StringRef> UnsetFlags; 2307*0fca6ea1SDimitry Andric 2308*0fca6ea1SDimitry Andric /// True if the instruction can be built solely by mutating the opcode. 2309*0fca6ea1SDimitry Andric bool canMutate(RuleMatcher &Rule, const InstructionMatcher *Insn) const; 2310*0fca6ea1SDimitry Andric 2311*0fca6ea1SDimitry Andric public: 2312*0fca6ea1SDimitry Andric BuildMIAction(unsigned InsnID, const CodeGenInstruction *I) 2313*0fca6ea1SDimitry Andric : MatchAction(AK_BuildMI), InsnID(InsnID), I(I), Matched(nullptr) {} 2314*0fca6ea1SDimitry Andric 2315*0fca6ea1SDimitry Andric static bool classof(const MatchAction *A) { 2316*0fca6ea1SDimitry Andric return A->getKind() == AK_BuildMI; 2317*0fca6ea1SDimitry Andric } 2318*0fca6ea1SDimitry Andric 2319*0fca6ea1SDimitry Andric unsigned getInsnID() const { return InsnID; } 2320*0fca6ea1SDimitry Andric const CodeGenInstruction *getCGI() const { return I; } 2321*0fca6ea1SDimitry Andric 2322*0fca6ea1SDimitry Andric void addSetMIFlags(StringRef Flag) { SetFlags.push_back(Flag); } 2323*0fca6ea1SDimitry Andric void addUnsetMIFlags(StringRef Flag) { UnsetFlags.push_back(Flag); } 2324*0fca6ea1SDimitry Andric void addCopiedMIFlags(const InstructionMatcher &IM) { 2325*0fca6ea1SDimitry Andric CopiedFlags.push_back(&IM); 2326*0fca6ea1SDimitry Andric } 2327*0fca6ea1SDimitry Andric 2328*0fca6ea1SDimitry Andric void chooseInsnToMutate(RuleMatcher &Rule); 2329*0fca6ea1SDimitry Andric 2330*0fca6ea1SDimitry Andric void setDeadImplicitDef(Record *R) { DeadImplicitDefs.insert(R); } 2331*0fca6ea1SDimitry Andric 2332*0fca6ea1SDimitry Andric template <class Kind, class... Args> Kind &addRenderer(Args &&...args) { 2333*0fca6ea1SDimitry Andric OperandRenderers.emplace_back( 2334*0fca6ea1SDimitry Andric std::make_unique<Kind>(InsnID, std::forward<Args>(args)...)); 2335*0fca6ea1SDimitry Andric return *static_cast<Kind *>(OperandRenderers.back().get()); 2336*0fca6ea1SDimitry Andric } 2337*0fca6ea1SDimitry Andric 2338*0fca6ea1SDimitry Andric void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2339*0fca6ea1SDimitry Andric }; 2340*0fca6ea1SDimitry Andric 2341*0fca6ea1SDimitry Andric /// Generates code to create a constant that defines a TempReg. 2342*0fca6ea1SDimitry Andric /// The instruction created is usually a G_CONSTANT but it could also be a 2343*0fca6ea1SDimitry Andric /// G_BUILD_VECTOR for vector types. 2344*0fca6ea1SDimitry Andric class BuildConstantAction : public MatchAction { 2345*0fca6ea1SDimitry Andric unsigned TempRegID; 2346*0fca6ea1SDimitry Andric int64_t Val; 2347*0fca6ea1SDimitry Andric 2348*0fca6ea1SDimitry Andric public: 2349*0fca6ea1SDimitry Andric BuildConstantAction(unsigned TempRegID, int64_t Val) 2350*0fca6ea1SDimitry Andric : MatchAction(AK_BuildConstantMI), TempRegID(TempRegID), Val(Val) {} 2351*0fca6ea1SDimitry Andric 2352*0fca6ea1SDimitry Andric static bool classof(const MatchAction *A) { 2353*0fca6ea1SDimitry Andric return A->getKind() == AK_BuildConstantMI; 2354*0fca6ea1SDimitry Andric } 2355*0fca6ea1SDimitry Andric 2356*0fca6ea1SDimitry Andric void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2357*0fca6ea1SDimitry Andric }; 2358*0fca6ea1SDimitry Andric 2359*0fca6ea1SDimitry Andric class EraseInstAction : public MatchAction { 2360*0fca6ea1SDimitry Andric unsigned InsnID; 2361*0fca6ea1SDimitry Andric 2362*0fca6ea1SDimitry Andric public: 2363*0fca6ea1SDimitry Andric EraseInstAction(unsigned InsnID) 2364*0fca6ea1SDimitry Andric : MatchAction(AK_EraseInst), InsnID(InsnID) {} 2365*0fca6ea1SDimitry Andric 2366*0fca6ea1SDimitry Andric unsigned getInsnID() const { return InsnID; } 2367*0fca6ea1SDimitry Andric 2368*0fca6ea1SDimitry Andric static bool classof(const MatchAction *A) { 2369*0fca6ea1SDimitry Andric return A->getKind() == AK_EraseInst; 2370*0fca6ea1SDimitry Andric } 2371*0fca6ea1SDimitry Andric 2372*0fca6ea1SDimitry Andric void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2373*0fca6ea1SDimitry Andric bool emitActionOpcodesAndDone(MatchTable &Table, 2374*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 2375*0fca6ea1SDimitry Andric }; 2376*0fca6ea1SDimitry Andric 2377*0fca6ea1SDimitry Andric class ReplaceRegAction : public MatchAction { 2378*0fca6ea1SDimitry Andric unsigned OldInsnID, OldOpIdx; 2379*0fca6ea1SDimitry Andric unsigned NewInsnId = -1, NewOpIdx; 2380*0fca6ea1SDimitry Andric unsigned TempRegID = -1; 2381*0fca6ea1SDimitry Andric 2382*0fca6ea1SDimitry Andric public: 2383*0fca6ea1SDimitry Andric ReplaceRegAction(unsigned OldInsnID, unsigned OldOpIdx, unsigned NewInsnId, 2384*0fca6ea1SDimitry Andric unsigned NewOpIdx) 2385*0fca6ea1SDimitry Andric : MatchAction(AK_ReplaceReg), OldInsnID(OldInsnID), OldOpIdx(OldOpIdx), 2386*0fca6ea1SDimitry Andric NewInsnId(NewInsnId), NewOpIdx(NewOpIdx) {} 2387*0fca6ea1SDimitry Andric 2388*0fca6ea1SDimitry Andric ReplaceRegAction(unsigned OldInsnID, unsigned OldOpIdx, unsigned TempRegID) 2389*0fca6ea1SDimitry Andric : MatchAction(AK_ReplaceReg), OldInsnID(OldInsnID), OldOpIdx(OldOpIdx), 2390*0fca6ea1SDimitry Andric TempRegID(TempRegID) {} 2391*0fca6ea1SDimitry Andric 2392*0fca6ea1SDimitry Andric static bool classof(const MatchAction *A) { 2393*0fca6ea1SDimitry Andric return A->getKind() == AK_ReplaceReg; 2394*0fca6ea1SDimitry Andric } 2395*0fca6ea1SDimitry Andric 2396*0fca6ea1SDimitry Andric void emitAdditionalPredicates(MatchTable &Table, 2397*0fca6ea1SDimitry Andric RuleMatcher &Rule) const override; 2398*0fca6ea1SDimitry Andric void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2399*0fca6ea1SDimitry Andric }; 2400*0fca6ea1SDimitry Andric 2401*0fca6ea1SDimitry Andric /// Generates code to constrain the operands of an output instruction to the 2402*0fca6ea1SDimitry Andric /// register classes specified by the definition of that instruction. 2403*0fca6ea1SDimitry Andric class ConstrainOperandsToDefinitionAction : public MatchAction { 2404*0fca6ea1SDimitry Andric unsigned InsnID; 2405*0fca6ea1SDimitry Andric 2406*0fca6ea1SDimitry Andric public: 2407*0fca6ea1SDimitry Andric ConstrainOperandsToDefinitionAction(unsigned InsnID) 2408*0fca6ea1SDimitry Andric : MatchAction(AK_ConstraintOpsToDef), InsnID(InsnID) {} 2409*0fca6ea1SDimitry Andric 2410*0fca6ea1SDimitry Andric static bool classof(const MatchAction *A) { 2411*0fca6ea1SDimitry Andric return A->getKind() == AK_ConstraintOpsToDef; 2412*0fca6ea1SDimitry Andric } 2413*0fca6ea1SDimitry Andric 2414*0fca6ea1SDimitry Andric void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override { 2415*0fca6ea1SDimitry Andric if (InsnID == 0) { 2416*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_RootConstrainSelectedInstOperands") 2417*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2418*0fca6ea1SDimitry Andric } else { 2419*0fca6ea1SDimitry Andric Table << MatchTable::Opcode("GIR_ConstrainSelectedInstOperands") 2420*0fca6ea1SDimitry Andric << MatchTable::Comment("InsnID") << MatchTable::ULEB128Value(InsnID) 2421*0fca6ea1SDimitry Andric << MatchTable::LineBreak; 2422*0fca6ea1SDimitry Andric } 2423*0fca6ea1SDimitry Andric } 2424*0fca6ea1SDimitry Andric }; 2425*0fca6ea1SDimitry Andric 2426*0fca6ea1SDimitry Andric /// Generates code to constrain the specified operand of an output instruction 2427*0fca6ea1SDimitry Andric /// to the specified register class. 2428*0fca6ea1SDimitry Andric class ConstrainOperandToRegClassAction : public MatchAction { 2429*0fca6ea1SDimitry Andric unsigned InsnID; 2430*0fca6ea1SDimitry Andric unsigned OpIdx; 2431*0fca6ea1SDimitry Andric const CodeGenRegisterClass &RC; 2432*0fca6ea1SDimitry Andric 2433*0fca6ea1SDimitry Andric public: 2434*0fca6ea1SDimitry Andric ConstrainOperandToRegClassAction(unsigned InsnID, unsigned OpIdx, 2435*0fca6ea1SDimitry Andric const CodeGenRegisterClass &RC) 2436*0fca6ea1SDimitry Andric : MatchAction(AK_ConstraintOpsToRC), InsnID(InsnID), OpIdx(OpIdx), 2437*0fca6ea1SDimitry Andric RC(RC) {} 2438*0fca6ea1SDimitry Andric 2439*0fca6ea1SDimitry Andric static bool classof(const MatchAction *A) { 2440*0fca6ea1SDimitry Andric return A->getKind() == AK_ConstraintOpsToRC; 2441*0fca6ea1SDimitry Andric } 2442*0fca6ea1SDimitry Andric 2443*0fca6ea1SDimitry Andric void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2444*0fca6ea1SDimitry Andric }; 2445*0fca6ea1SDimitry Andric 2446*0fca6ea1SDimitry Andric /// Generates code to create a temporary register which can be used to chain 2447*0fca6ea1SDimitry Andric /// instructions together. 2448*0fca6ea1SDimitry Andric class MakeTempRegisterAction : public MatchAction { 2449*0fca6ea1SDimitry Andric private: 2450*0fca6ea1SDimitry Andric LLTCodeGenOrTempType Ty; 2451*0fca6ea1SDimitry Andric unsigned TempRegID; 2452*0fca6ea1SDimitry Andric 2453*0fca6ea1SDimitry Andric public: 2454*0fca6ea1SDimitry Andric MakeTempRegisterAction(const LLTCodeGenOrTempType &Ty, unsigned TempRegID) 2455*0fca6ea1SDimitry Andric : MatchAction(AK_MakeTempReg), Ty(Ty), TempRegID(TempRegID) { 2456*0fca6ea1SDimitry Andric if (Ty.isLLTCodeGen()) 2457*0fca6ea1SDimitry Andric KnownTypes.insert(Ty.getLLTCodeGen()); 2458*0fca6ea1SDimitry Andric } 2459*0fca6ea1SDimitry Andric 2460*0fca6ea1SDimitry Andric static bool classof(const MatchAction *A) { 2461*0fca6ea1SDimitry Andric return A->getKind() == AK_MakeTempReg; 2462*0fca6ea1SDimitry Andric } 2463*0fca6ea1SDimitry Andric 2464*0fca6ea1SDimitry Andric void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; 2465*0fca6ea1SDimitry Andric }; 2466*0fca6ea1SDimitry Andric 2467*0fca6ea1SDimitry Andric } // namespace gi 2468*0fca6ea1SDimitry Andric } // namespace llvm 2469*0fca6ea1SDimitry Andric 2470*0fca6ea1SDimitry Andric #endif 2471