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