1fa3d789dSPierre van Houtryve //===- CodeGenDAGPatterns.h - Read DAG patterns from .td file ---*- C++ -*-===// 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 // This file declares the CodeGenDAGPatterns class, which is used to read and 10fa3d789dSPierre van Houtryve // represent the patterns present in a .td file for instructions. 11fa3d789dSPierre van Houtryve // 12fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===// 13fa3d789dSPierre van Houtryve 148a61bfcfSRahul Joshi #ifndef LLVM_UTILS_TABLEGEN_COMMON_CODEGENDAGPATTERNS_H 158a61bfcfSRahul Joshi #define LLVM_UTILS_TABLEGEN_COMMON_CODEGENDAGPATTERNS_H 16fa3d789dSPierre van Houtryve 17fa3d789dSPierre van Houtryve #include "Basic/CodeGenIntrinsics.h" 18fa3d789dSPierre van Houtryve #include "Basic/SDNodeProperties.h" 19fa3d789dSPierre van Houtryve #include "CodeGenTarget.h" 20fa3d789dSPierre van Houtryve #include "llvm/ADT/IntrusiveRefCntPtr.h" 21fa3d789dSPierre van Houtryve #include "llvm/ADT/MapVector.h" 22fa3d789dSPierre van Houtryve #include "llvm/ADT/PointerUnion.h" 23fa3d789dSPierre van Houtryve #include "llvm/ADT/SmallVector.h" 24fa3d789dSPierre van Houtryve #include "llvm/ADT/StringMap.h" 25fa3d789dSPierre van Houtryve #include "llvm/ADT/StringSet.h" 26fa3d789dSPierre van Houtryve #include "llvm/ADT/Twine.h" 27fa3d789dSPierre van Houtryve #include "llvm/Support/ErrorHandling.h" 28fa3d789dSPierre van Houtryve #include "llvm/Support/MathExtras.h" 29fa3d789dSPierre van Houtryve #include "llvm/TableGen/Record.h" 30fa3d789dSPierre van Houtryve #include <algorithm> 31fa3d789dSPierre van Houtryve #include <array> 32fa3d789dSPierre van Houtryve #include <functional> 33fa3d789dSPierre van Houtryve #include <map> 34fa3d789dSPierre van Houtryve #include <numeric> 35fa3d789dSPierre van Houtryve #include <vector> 36fa3d789dSPierre van Houtryve 37fa3d789dSPierre van Houtryve namespace llvm { 38fa3d789dSPierre van Houtryve 39fa3d789dSPierre van Houtryve class Init; 40fa3d789dSPierre van Houtryve class ListInit; 41fa3d789dSPierre van Houtryve class DagInit; 42fa3d789dSPierre van Houtryve class SDNodeInfo; 43fa3d789dSPierre van Houtryve class TreePattern; 44fa3d789dSPierre van Houtryve class TreePatternNode; 45fa3d789dSPierre van Houtryve class CodeGenDAGPatterns; 46fa3d789dSPierre van Houtryve 47fa3d789dSPierre van Houtryve /// Shared pointer for TreePatternNode. 48fa3d789dSPierre van Houtryve using TreePatternNodePtr = IntrusiveRefCntPtr<TreePatternNode>; 49fa3d789dSPierre van Houtryve 50fa3d789dSPierre van Houtryve /// This represents a set of MVTs. Since the underlying type for the MVT 51a4c6ebebSBrandon Wu /// is uint16_t, there are at most 65536 values. To reduce the number of memory 52fa3d789dSPierre van Houtryve /// allocations and deallocations, represent the set as a sequence of bits. 53fa3d789dSPierre van Houtryve /// To reduce the allocations even further, make MachineValueTypeSet own 54fa3d789dSPierre van Houtryve /// the storage and use std::array as the bit container. 55fa3d789dSPierre van Houtryve struct MachineValueTypeSet { 56e2c74aa5SCraig Topper static unsigned constexpr Capacity = 512; 57fa3d789dSPierre van Houtryve using WordType = uint64_t; 58fa3d789dSPierre van Houtryve static unsigned constexpr WordWidth = CHAR_BIT * sizeof(WordType); 59fa3d789dSPierre van Houtryve static unsigned constexpr NumWords = Capacity / WordWidth; 60fa3d789dSPierre van Houtryve static_assert(NumWords * WordWidth == Capacity, 61fa3d789dSPierre van Houtryve "Capacity should be a multiple of WordWidth"); 62fa3d789dSPierre van Houtryve 63fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 64fa3d789dSPierre van Houtryve MachineValueTypeSet() { clear(); } 65fa3d789dSPierre van Houtryve 66fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 67fa3d789dSPierre van Houtryve unsigned size() const { 68fa3d789dSPierre van Houtryve unsigned Count = 0; 69fa3d789dSPierre van Houtryve for (WordType W : Words) 70fa3d789dSPierre van Houtryve Count += llvm::popcount(W); 71fa3d789dSPierre van Houtryve return Count; 72fa3d789dSPierre van Houtryve } 73fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 74fa3d789dSPierre van Houtryve void clear() { std::memset(Words.data(), 0, NumWords * sizeof(WordType)); } 75fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 76fa3d789dSPierre van Houtryve bool empty() const { 77fa3d789dSPierre van Houtryve for (WordType W : Words) 78fa3d789dSPierre van Houtryve if (W != 0) 79fa3d789dSPierre van Houtryve return false; 80fa3d789dSPierre van Houtryve return true; 81fa3d789dSPierre van Houtryve } 82fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 83fa3d789dSPierre van Houtryve unsigned count(MVT T) const { 84e2c74aa5SCraig Topper assert(T.SimpleTy < Capacity && "Capacity needs to be enlarged"); 85fa3d789dSPierre van Houtryve return (Words[T.SimpleTy / WordWidth] >> (T.SimpleTy % WordWidth)) & 1; 86fa3d789dSPierre van Houtryve } 87fa3d789dSPierre van Houtryve std::pair<MachineValueTypeSet &, bool> insert(MVT T) { 88e2c74aa5SCraig Topper assert(T.SimpleTy < Capacity && "Capacity needs to be enlarged"); 89fa3d789dSPierre van Houtryve bool V = count(T.SimpleTy); 90fa3d789dSPierre van Houtryve Words[T.SimpleTy / WordWidth] |= WordType(1) << (T.SimpleTy % WordWidth); 91fa3d789dSPierre van Houtryve return {*this, V}; 92fa3d789dSPierre van Houtryve } 93fa3d789dSPierre van Houtryve MachineValueTypeSet &insert(const MachineValueTypeSet &S) { 94fa3d789dSPierre van Houtryve for (unsigned i = 0; i != NumWords; ++i) 95fa3d789dSPierre van Houtryve Words[i] |= S.Words[i]; 96fa3d789dSPierre van Houtryve return *this; 97fa3d789dSPierre van Houtryve } 98fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 99fa3d789dSPierre van Houtryve void erase(MVT T) { 100e2c74aa5SCraig Topper assert(T.SimpleTy < Capacity && "Capacity needs to be enlarged"); 101fa3d789dSPierre van Houtryve Words[T.SimpleTy / WordWidth] &= ~(WordType(1) << (T.SimpleTy % WordWidth)); 102fa3d789dSPierre van Houtryve } 103fa3d789dSPierre van Houtryve 104fa3d789dSPierre van Houtryve void writeToStream(raw_ostream &OS) const; 105fa3d789dSPierre van Houtryve 106fa3d789dSPierre van Houtryve struct const_iterator { 107fa3d789dSPierre van Houtryve // Some implementations of the C++ library require these traits to be 108fa3d789dSPierre van Houtryve // defined. 109fa3d789dSPierre van Houtryve using iterator_category = std::forward_iterator_tag; 110fa3d789dSPierre van Houtryve using value_type = MVT; 111fa3d789dSPierre van Houtryve using difference_type = ptrdiff_t; 112fa3d789dSPierre van Houtryve using pointer = const MVT *; 113fa3d789dSPierre van Houtryve using reference = const MVT &; 114fa3d789dSPierre van Houtryve 115fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 116fa3d789dSPierre van Houtryve MVT operator*() const { 117fa3d789dSPierre van Houtryve assert(Pos != Capacity); 118fa3d789dSPierre van Houtryve return MVT::SimpleValueType(Pos); 119fa3d789dSPierre van Houtryve } 120fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 121fa3d789dSPierre van Houtryve const_iterator(const MachineValueTypeSet *S, bool End) : Set(S) { 122fa3d789dSPierre van Houtryve Pos = End ? Capacity : find_from_pos(0); 123fa3d789dSPierre van Houtryve } 124fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 125fa3d789dSPierre van Houtryve const_iterator &operator++() { 126fa3d789dSPierre van Houtryve assert(Pos != Capacity); 127fa3d789dSPierre van Houtryve Pos = find_from_pos(Pos + 1); 128fa3d789dSPierre van Houtryve return *this; 129fa3d789dSPierre van Houtryve } 130fa3d789dSPierre van Houtryve 131fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 132fa3d789dSPierre van Houtryve bool operator==(const const_iterator &It) const { 133fa3d789dSPierre van Houtryve return Set == It.Set && Pos == It.Pos; 134fa3d789dSPierre van Houtryve } 135fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 136fa3d789dSPierre van Houtryve bool operator!=(const const_iterator &It) const { return !operator==(It); } 137fa3d789dSPierre van Houtryve 138fa3d789dSPierre van Houtryve private: 139fa3d789dSPierre van Houtryve unsigned find_from_pos(unsigned P) const { 140fa3d789dSPierre van Houtryve unsigned SkipWords = P / WordWidth; 141fa3d789dSPierre van Houtryve unsigned SkipBits = P % WordWidth; 142fa3d789dSPierre van Houtryve unsigned Count = SkipWords * WordWidth; 143fa3d789dSPierre van Houtryve 144fa3d789dSPierre van Houtryve // If P is in the middle of a word, process it manually here, because 145fa3d789dSPierre van Houtryve // the trailing bits need to be masked off to use findFirstSet. 146fa3d789dSPierre van Houtryve if (SkipBits != 0) { 147fa3d789dSPierre van Houtryve WordType W = Set->Words[SkipWords]; 148fa3d789dSPierre van Houtryve W &= maskLeadingOnes<WordType>(WordWidth - SkipBits); 149fa3d789dSPierre van Houtryve if (W != 0) 150fa3d789dSPierre van Houtryve return Count + llvm::countr_zero(W); 151fa3d789dSPierre van Houtryve Count += WordWidth; 152fa3d789dSPierre van Houtryve SkipWords++; 153fa3d789dSPierre van Houtryve } 154fa3d789dSPierre van Houtryve 155fa3d789dSPierre van Houtryve for (unsigned i = SkipWords; i != NumWords; ++i) { 156fa3d789dSPierre van Houtryve WordType W = Set->Words[i]; 157fa3d789dSPierre van Houtryve if (W != 0) 158fa3d789dSPierre van Houtryve return Count + llvm::countr_zero(W); 159fa3d789dSPierre van Houtryve Count += WordWidth; 160fa3d789dSPierre van Houtryve } 161fa3d789dSPierre van Houtryve return Capacity; 162fa3d789dSPierre van Houtryve } 163fa3d789dSPierre van Houtryve 164fa3d789dSPierre van Houtryve const MachineValueTypeSet *Set; 165fa3d789dSPierre van Houtryve unsigned Pos; 166fa3d789dSPierre van Houtryve }; 167fa3d789dSPierre van Houtryve 168fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 169fa3d789dSPierre van Houtryve const_iterator begin() const { return const_iterator(this, false); } 170fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 171fa3d789dSPierre van Houtryve const_iterator end() const { return const_iterator(this, true); } 172fa3d789dSPierre van Houtryve 173fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 174fa3d789dSPierre van Houtryve bool operator==(const MachineValueTypeSet &S) const { 175fa3d789dSPierre van Houtryve return Words == S.Words; 176fa3d789dSPierre van Houtryve } 177fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 178fa3d789dSPierre van Houtryve bool operator!=(const MachineValueTypeSet &S) const { return !operator==(S); } 179fa3d789dSPierre van Houtryve 180fa3d789dSPierre van Houtryve private: 181fa3d789dSPierre van Houtryve friend struct const_iterator; 182fa3d789dSPierre van Houtryve std::array<WordType, NumWords> Words; 183fa3d789dSPierre van Houtryve }; 184fa3d789dSPierre van Houtryve 185fa3d789dSPierre van Houtryve raw_ostream &operator<<(raw_ostream &OS, const MachineValueTypeSet &T); 186fa3d789dSPierre van Houtryve 187fa3d789dSPierre van Houtryve struct TypeSetByHwMode : public InfoByHwMode<MachineValueTypeSet> { 188fa3d789dSPierre van Houtryve using SetType = MachineValueTypeSet; 189fa3d789dSPierre van Houtryve unsigned AddrSpace = std::numeric_limits<unsigned>::max(); 190fa3d789dSPierre van Houtryve 191fa3d789dSPierre van Houtryve TypeSetByHwMode() = default; 192fa3d789dSPierre van Houtryve TypeSetByHwMode(const TypeSetByHwMode &VTS) = default; 193fa3d789dSPierre van Houtryve TypeSetByHwMode &operator=(const TypeSetByHwMode &) = default; 194fa3d789dSPierre van Houtryve TypeSetByHwMode(MVT::SimpleValueType VT) 195fa3d789dSPierre van Houtryve : TypeSetByHwMode(ValueTypeByHwMode(VT)) {} 196fa3d789dSPierre van Houtryve TypeSetByHwMode(ArrayRef<ValueTypeByHwMode> VTList); 197fa3d789dSPierre van Houtryve 198fa3d789dSPierre van Houtryve SetType &getOrCreate(unsigned Mode) { return Map[Mode]; } 199fa3d789dSPierre van Houtryve 200fa3d789dSPierre van Houtryve bool isValueTypeByHwMode(bool AllowEmpty) const; 201fa3d789dSPierre van Houtryve ValueTypeByHwMode getValueTypeByHwMode() const; 202fa3d789dSPierre van Houtryve 203fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 204fa3d789dSPierre van Houtryve bool isMachineValueType() const { 205fa3d789dSPierre van Houtryve return isSimple() && getSimple().size() == 1; 206fa3d789dSPierre van Houtryve } 207fa3d789dSPierre van Houtryve 208fa3d789dSPierre van Houtryve LLVM_ATTRIBUTE_ALWAYS_INLINE 209fa3d789dSPierre van Houtryve MVT getMachineValueType() const { 210fa3d789dSPierre van Houtryve assert(isMachineValueType()); 211fa3d789dSPierre van Houtryve return *getSimple().begin(); 212fa3d789dSPierre van Houtryve } 213fa3d789dSPierre van Houtryve 214fa3d789dSPierre van Houtryve bool isPossible() const; 215fa3d789dSPierre van Houtryve 216fa3d789dSPierre van Houtryve bool isPointer() const { return getValueTypeByHwMode().isPointer(); } 217fa3d789dSPierre van Houtryve 218fa3d789dSPierre van Houtryve unsigned getPtrAddrSpace() const { 219fa3d789dSPierre van Houtryve assert(isPointer()); 220fa3d789dSPierre van Houtryve return getValueTypeByHwMode().PtrAddrSpace; 221fa3d789dSPierre van Houtryve } 222fa3d789dSPierre van Houtryve 223fa3d789dSPierre van Houtryve bool insert(const ValueTypeByHwMode &VVT); 224fa3d789dSPierre van Houtryve bool constrain(const TypeSetByHwMode &VTS); 225fa3d789dSPierre van Houtryve template <typename Predicate> bool constrain(Predicate P); 226fa3d789dSPierre van Houtryve template <typename Predicate> 227fa3d789dSPierre van Houtryve bool assign_if(const TypeSetByHwMode &VTS, Predicate P); 228fa3d789dSPierre van Houtryve 229fa3d789dSPierre van Houtryve void writeToStream(raw_ostream &OS) const; 230fa3d789dSPierre van Houtryve 231fa3d789dSPierre van Houtryve bool operator==(const TypeSetByHwMode &VTS) const; 232fa3d789dSPierre van Houtryve bool operator!=(const TypeSetByHwMode &VTS) const { return !(*this == VTS); } 233fa3d789dSPierre van Houtryve 234fa3d789dSPierre van Houtryve void dump() const; 235fa3d789dSPierre van Houtryve bool validate() const; 236fa3d789dSPierre van Houtryve 237fa3d789dSPierre van Houtryve private: 238fa3d789dSPierre van Houtryve unsigned PtrAddrSpace = std::numeric_limits<unsigned>::max(); 239fa3d789dSPierre van Houtryve /// Intersect two sets. Return true if anything has changed. 240fa3d789dSPierre van Houtryve bool intersect(SetType &Out, const SetType &In); 241fa3d789dSPierre van Houtryve }; 242fa3d789dSPierre van Houtryve 243fa3d789dSPierre van Houtryve raw_ostream &operator<<(raw_ostream &OS, const TypeSetByHwMode &T); 244fa3d789dSPierre van Houtryve 245fa3d789dSPierre van Houtryve struct TypeInfer { 246fa3d789dSPierre van Houtryve TypeInfer(TreePattern &T) : TP(T) {} 247fa3d789dSPierre van Houtryve 248fa3d789dSPierre van Houtryve bool isConcrete(const TypeSetByHwMode &VTS, bool AllowEmpty) const { 249fa3d789dSPierre van Houtryve return VTS.isValueTypeByHwMode(AllowEmpty); 250fa3d789dSPierre van Houtryve } 251fa3d789dSPierre van Houtryve ValueTypeByHwMode getConcrete(const TypeSetByHwMode &VTS, 252fa3d789dSPierre van Houtryve bool AllowEmpty) const { 253fa3d789dSPierre van Houtryve assert(VTS.isValueTypeByHwMode(AllowEmpty)); 254fa3d789dSPierre van Houtryve return VTS.getValueTypeByHwMode(); 255fa3d789dSPierre van Houtryve } 256fa3d789dSPierre van Houtryve 257fa3d789dSPierre van Houtryve /// The protocol in the following functions (Merge*, force*, Enforce*, 258fa3d789dSPierre van Houtryve /// expand*) is to return "true" if a change has been made, "false" 259fa3d789dSPierre van Houtryve /// otherwise. 260fa3d789dSPierre van Houtryve 261fa3d789dSPierre van Houtryve bool MergeInTypeInfo(TypeSetByHwMode &Out, const TypeSetByHwMode &In) const; 262fa3d789dSPierre van Houtryve bool MergeInTypeInfo(TypeSetByHwMode &Out, MVT::SimpleValueType InVT) const { 263fa3d789dSPierre van Houtryve return MergeInTypeInfo(Out, TypeSetByHwMode(InVT)); 264fa3d789dSPierre van Houtryve } 265c2dc46cdSCraig Topper bool MergeInTypeInfo(TypeSetByHwMode &Out, 266c2dc46cdSCraig Topper const ValueTypeByHwMode &InVT) const { 267fa3d789dSPierre van Houtryve return MergeInTypeInfo(Out, TypeSetByHwMode(InVT)); 268fa3d789dSPierre van Houtryve } 269fa3d789dSPierre van Houtryve 270fa3d789dSPierre van Houtryve /// Reduce the set \p Out to have at most one element for each mode. 271fa3d789dSPierre van Houtryve bool forceArbitrary(TypeSetByHwMode &Out); 272fa3d789dSPierre van Houtryve 273fa3d789dSPierre van Houtryve /// The following four functions ensure that upon return the set \p Out 274fa3d789dSPierre van Houtryve /// will only contain types of the specified kind: integer, floating-point, 275fa3d789dSPierre van Houtryve /// scalar, or vector. 276fa3d789dSPierre van Houtryve /// If \p Out is empty, all legal types of the specified kind will be added 277fa3d789dSPierre van Houtryve /// to it. Otherwise, all types that are not of the specified kind will be 278fa3d789dSPierre van Houtryve /// removed from \p Out. 279fa3d789dSPierre van Houtryve bool EnforceInteger(TypeSetByHwMode &Out); 280fa3d789dSPierre van Houtryve bool EnforceFloatingPoint(TypeSetByHwMode &Out); 281fa3d789dSPierre van Houtryve bool EnforceScalar(TypeSetByHwMode &Out); 282fa3d789dSPierre van Houtryve bool EnforceVector(TypeSetByHwMode &Out); 283fa3d789dSPierre van Houtryve 284fa3d789dSPierre van Houtryve /// If \p Out is empty, fill it with all legal types. Otherwise, leave it 285fa3d789dSPierre van Houtryve /// unchanged. 286fa3d789dSPierre van Houtryve bool EnforceAny(TypeSetByHwMode &Out); 287fa3d789dSPierre van Houtryve /// Make sure that for each type in \p Small, there exists a larger type 288fa3d789dSPierre van Houtryve /// in \p Big. \p SmallIsVT indicates that this is being called for 289fa3d789dSPierre van Houtryve /// SDTCisVTSmallerThanOp. In that case the TypeSetByHwMode is re-created for 290fa3d789dSPierre van Houtryve /// each call and needs special consideration in how we detect changes. 291fa3d789dSPierre van Houtryve bool EnforceSmallerThan(TypeSetByHwMode &Small, TypeSetByHwMode &Big, 292fa3d789dSPierre van Houtryve bool SmallIsVT = false); 293fa3d789dSPierre van Houtryve /// 1. Ensure that for each type T in \p Vec, T is a vector type, and that 294fa3d789dSPierre van Houtryve /// for each type U in \p Elem, U is a scalar type. 295fa3d789dSPierre van Houtryve /// 2. Ensure that for each (scalar) type U in \p Elem, there exists a 296fa3d789dSPierre van Houtryve /// (vector) type T in \p Vec, such that U is the element type of T. 297fa3d789dSPierre van Houtryve bool EnforceVectorEltTypeIs(TypeSetByHwMode &Vec, TypeSetByHwMode &Elem); 298fa3d789dSPierre van Houtryve bool EnforceVectorEltTypeIs(TypeSetByHwMode &Vec, 299fa3d789dSPierre van Houtryve const ValueTypeByHwMode &VVT); 300fa3d789dSPierre van Houtryve /// Ensure that for each type T in \p Sub, T is a vector type, and there 301fa3d789dSPierre van Houtryve /// exists a type U in \p Vec such that U is a vector type with the same 302fa3d789dSPierre van Houtryve /// element type as T and at least as many elements as T. 303fa3d789dSPierre van Houtryve bool EnforceVectorSubVectorTypeIs(TypeSetByHwMode &Vec, TypeSetByHwMode &Sub); 304fa3d789dSPierre van Houtryve /// 1. Ensure that \p V has a scalar type iff \p W has a scalar type. 305fa3d789dSPierre van Houtryve /// 2. Ensure that for each vector type T in \p V, there exists a vector 306fa3d789dSPierre van Houtryve /// type U in \p W, such that T and U have the same number of elements. 307fa3d789dSPierre van Houtryve /// 3. Ensure that for each vector type U in \p W, there exists a vector 308fa3d789dSPierre van Houtryve /// type T in \p V, such that T and U have the same number of elements 309fa3d789dSPierre van Houtryve /// (reverse of 2). 310fa3d789dSPierre van Houtryve bool EnforceSameNumElts(TypeSetByHwMode &V, TypeSetByHwMode &W); 311fa3d789dSPierre van Houtryve /// 1. Ensure that for each type T in \p A, there exists a type U in \p B, 312fa3d789dSPierre van Houtryve /// such that T and U have equal size in bits. 313fa3d789dSPierre van Houtryve /// 2. Ensure that for each type U in \p B, there exists a type T in \p A 314fa3d789dSPierre van Houtryve /// such that T and U have equal size in bits (reverse of 1). 315fa3d789dSPierre van Houtryve bool EnforceSameSize(TypeSetByHwMode &A, TypeSetByHwMode &B); 316fa3d789dSPierre van Houtryve 317fa3d789dSPierre van Houtryve /// For each overloaded type (i.e. of form *Any), replace it with the 318fa3d789dSPierre van Houtryve /// corresponding subset of legal, specific types. 319fa3d789dSPierre van Houtryve void expandOverloads(TypeSetByHwMode &VTS) const; 320fa3d789dSPierre van Houtryve void expandOverloads(TypeSetByHwMode::SetType &Out, 321fa3d789dSPierre van Houtryve const TypeSetByHwMode::SetType &Legal) const; 322fa3d789dSPierre van Houtryve 323fa3d789dSPierre van Houtryve struct ValidateOnExit { 324fa3d789dSPierre van Houtryve ValidateOnExit(const TypeSetByHwMode &T, const TypeInfer &TI) 325fa3d789dSPierre van Houtryve : Infer(TI), VTS(T) {} 326fa3d789dSPierre van Houtryve ~ValidateOnExit(); 327fa3d789dSPierre van Houtryve const TypeInfer &Infer; 328fa3d789dSPierre van Houtryve const TypeSetByHwMode &VTS; 329fa3d789dSPierre van Houtryve }; 330fa3d789dSPierre van Houtryve 331fa3d789dSPierre van Houtryve struct SuppressValidation { 332fa3d789dSPierre van Houtryve SuppressValidation(TypeInfer &TI) : Infer(TI), SavedValidate(TI.Validate) { 333fa3d789dSPierre van Houtryve Infer.Validate = false; 334fa3d789dSPierre van Houtryve } 335fa3d789dSPierre van Houtryve ~SuppressValidation() { Infer.Validate = SavedValidate; } 336fa3d789dSPierre van Houtryve TypeInfer &Infer; 337fa3d789dSPierre van Houtryve bool SavedValidate; 338fa3d789dSPierre van Houtryve }; 339fa3d789dSPierre van Houtryve 340fa3d789dSPierre van Houtryve TreePattern &TP; 341fa3d789dSPierre van Houtryve bool Validate = true; // Indicate whether to validate types. 342fa3d789dSPierre van Houtryve 343fa3d789dSPierre van Houtryve private: 344fa3d789dSPierre van Houtryve const TypeSetByHwMode &getLegalTypes() const; 345fa3d789dSPierre van Houtryve 346fa3d789dSPierre van Houtryve /// Cached legal types (in default mode). 347fa3d789dSPierre van Houtryve mutable bool LegalTypesCached = false; 348fa3d789dSPierre van Houtryve mutable TypeSetByHwMode LegalCache; 349fa3d789dSPierre van Houtryve }; 350fa3d789dSPierre van Houtryve 351fa3d789dSPierre van Houtryve /// Set type used to track multiply used variables in patterns 352fa3d789dSPierre van Houtryve typedef StringSet<> MultipleUseVarSet; 353fa3d789dSPierre van Houtryve 354fa3d789dSPierre van Houtryve /// SDTypeConstraint - This is a discriminated union of constraints, 355fa3d789dSPierre van Houtryve /// corresponding to the SDTypeConstraint tablegen class in Target.td. 356fa3d789dSPierre van Houtryve struct SDTypeConstraint { 357*6aeffcdbSSergei Barannikov SDTypeConstraint() = default; 35887e8b530SRahul Joshi SDTypeConstraint(const Record *R, const CodeGenHwModes &CGH); 359fa3d789dSPierre van Houtryve 360fa3d789dSPierre van Houtryve unsigned OperandNo; // The operand # this constraint applies to. 361*6aeffcdbSSergei Barannikov enum KindTy { 362fa3d789dSPierre van Houtryve SDTCisVT, 363fa3d789dSPierre van Houtryve SDTCisPtrTy, 364fa3d789dSPierre van Houtryve SDTCisInt, 365fa3d789dSPierre van Houtryve SDTCisFP, 366fa3d789dSPierre van Houtryve SDTCisVec, 367fa3d789dSPierre van Houtryve SDTCisSameAs, 368fa3d789dSPierre van Houtryve SDTCisVTSmallerThanOp, 369fa3d789dSPierre van Houtryve SDTCisOpSmallerThanOp, 370fa3d789dSPierre van Houtryve SDTCisEltOfVec, 371fa3d789dSPierre van Houtryve SDTCisSubVecOfVec, 372fa3d789dSPierre van Houtryve SDTCVecEltisVT, 373fa3d789dSPierre van Houtryve SDTCisSameNumEltsAs, 374fa3d789dSPierre van Houtryve SDTCisSameSizeAs 375fa3d789dSPierre van Houtryve } ConstraintType; 376fa3d789dSPierre van Houtryve 377*6aeffcdbSSergei Barannikov unsigned OtherOperandNo; 378fa3d789dSPierre van Houtryve 379fa3d789dSPierre van Houtryve // The VT for SDTCisVT and SDTCVecEltisVT. 380fa3d789dSPierre van Houtryve // Must not be in the union because it has a non-trivial destructor. 381fa3d789dSPierre van Houtryve ValueTypeByHwMode VVT; 382fa3d789dSPierre van Houtryve 383fa3d789dSPierre van Houtryve /// ApplyTypeConstraint - Given a node in a pattern, apply this type 384fa3d789dSPierre van Houtryve /// constraint to the nodes operands. This returns true if it makes a 385fa3d789dSPierre van Houtryve /// change, false otherwise. If a type contradiction is found, an error 386fa3d789dSPierre van Houtryve /// is flagged. 387fa3d789dSPierre van Houtryve bool ApplyTypeConstraint(TreePatternNode &N, const SDNodeInfo &NodeInfo, 388fa3d789dSPierre van Houtryve TreePattern &TP) const; 389*6aeffcdbSSergei Barannikov 390*6aeffcdbSSergei Barannikov friend bool operator==(const SDTypeConstraint &LHS, 391*6aeffcdbSSergei Barannikov const SDTypeConstraint &RHS); 392*6aeffcdbSSergei Barannikov friend bool operator<(const SDTypeConstraint &LHS, 393*6aeffcdbSSergei Barannikov const SDTypeConstraint &RHS); 394fa3d789dSPierre van Houtryve }; 395fa3d789dSPierre van Houtryve 396fa3d789dSPierre van Houtryve /// ScopedName - A name of a node associated with a "scope" that indicates 397fa3d789dSPierre van Houtryve /// the context (e.g. instance of Pattern or PatFrag) in which the name was 398fa3d789dSPierre van Houtryve /// used. This enables substitution of pattern fragments while keeping track 399fa3d789dSPierre van Houtryve /// of what name(s) were originally given to various nodes in the tree. 400fa3d789dSPierre van Houtryve class ScopedName { 401fa3d789dSPierre van Houtryve unsigned Scope; 402fa3d789dSPierre van Houtryve std::string Identifier; 403fa3d789dSPierre van Houtryve 404fa3d789dSPierre van Houtryve public: 405fa3d789dSPierre van Houtryve ScopedName(unsigned Scope, StringRef Identifier) 406fa3d789dSPierre van Houtryve : Scope(Scope), Identifier(std::string(Identifier)) { 407fa3d789dSPierre van Houtryve assert(Scope != 0 && 408fa3d789dSPierre van Houtryve "Scope == 0 is used to indicate predicates without arguments"); 409fa3d789dSPierre van Houtryve } 410fa3d789dSPierre van Houtryve 411fa3d789dSPierre van Houtryve unsigned getScope() const { return Scope; } 412fa3d789dSPierre van Houtryve const std::string &getIdentifier() const { return Identifier; } 413fa3d789dSPierre van Houtryve 414fa3d789dSPierre van Houtryve bool operator==(const ScopedName &o) const; 415fa3d789dSPierre van Houtryve bool operator!=(const ScopedName &o) const; 416fa3d789dSPierre van Houtryve }; 417fa3d789dSPierre van Houtryve 418fa3d789dSPierre van Houtryve /// SDNodeInfo - One of these records is created for each SDNode instance in 419fa3d789dSPierre van Houtryve /// the target .td file. This represents the various dag nodes we will be 420fa3d789dSPierre van Houtryve /// processing. 421fa3d789dSPierre van Houtryve class SDNodeInfo { 42287e8b530SRahul Joshi const Record *Def; 423fa3d789dSPierre van Houtryve StringRef EnumName; 424fa3d789dSPierre van Houtryve StringRef SDClassName; 425fa3d789dSPierre van Houtryve unsigned NumResults; 426fa3d789dSPierre van Houtryve int NumOperands; 427*6aeffcdbSSergei Barannikov unsigned Properties; 428*6aeffcdbSSergei Barannikov bool IsStrictFP; 429*6aeffcdbSSergei Barannikov uint32_t TSFlags; 430fa3d789dSPierre van Houtryve std::vector<SDTypeConstraint> TypeConstraints; 431fa3d789dSPierre van Houtryve 432fa3d789dSPierre van Houtryve public: 433fa3d789dSPierre van Houtryve // Parse the specified record. 43487e8b530SRahul Joshi SDNodeInfo(const Record *R, const CodeGenHwModes &CGH); 435fa3d789dSPierre van Houtryve 436fa3d789dSPierre van Houtryve unsigned getNumResults() const { return NumResults; } 437fa3d789dSPierre van Houtryve 438fa3d789dSPierre van Houtryve /// getNumOperands - This is the number of operands required or -1 if 439fa3d789dSPierre van Houtryve /// variadic. 440fa3d789dSPierre van Houtryve int getNumOperands() const { return NumOperands; } 44187e8b530SRahul Joshi const Record *getRecord() const { return Def; } 442fa3d789dSPierre van Houtryve StringRef getEnumName() const { return EnumName; } 443fa3d789dSPierre van Houtryve StringRef getSDClassName() const { return SDClassName; } 444fa3d789dSPierre van Houtryve 445fa3d789dSPierre van Houtryve const std::vector<SDTypeConstraint> &getTypeConstraints() const { 446fa3d789dSPierre van Houtryve return TypeConstraints; 447fa3d789dSPierre van Houtryve } 448fa3d789dSPierre van Houtryve 449fa3d789dSPierre van Houtryve /// getKnownType - If the type constraints on this node imply a fixed type 450fa3d789dSPierre van Houtryve /// (e.g. all stores return void, etc), then return it as an 451fa3d789dSPierre van Houtryve /// MVT::SimpleValueType. Otherwise, return MVT::Other. 452fa3d789dSPierre van Houtryve MVT::SimpleValueType getKnownType(unsigned ResNo) const; 453fa3d789dSPierre van Houtryve 454*6aeffcdbSSergei Barannikov unsigned getProperties() const { return Properties; } 455*6aeffcdbSSergei Barannikov 456fa3d789dSPierre van Houtryve /// hasProperty - Return true if this node has the specified property. 457fa3d789dSPierre van Houtryve /// 458fa3d789dSPierre van Houtryve bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); } 459fa3d789dSPierre van Houtryve 460*6aeffcdbSSergei Barannikov bool isStrictFP() const { return IsStrictFP; } 461*6aeffcdbSSergei Barannikov 462*6aeffcdbSSergei Barannikov uint32_t getTSFlags() const { return TSFlags; } 463*6aeffcdbSSergei Barannikov 464fa3d789dSPierre van Houtryve /// ApplyTypeConstraints - Given a node in a pattern, apply the type 465fa3d789dSPierre van Houtryve /// constraints for this node to the operands of the node. This returns 466fa3d789dSPierre van Houtryve /// true if it makes a change, false otherwise. If a type contradiction is 467fa3d789dSPierre van Houtryve /// found, an error is flagged. 468fa3d789dSPierre van Houtryve bool ApplyTypeConstraints(TreePatternNode &N, TreePattern &TP) const; 469fa3d789dSPierre van Houtryve }; 470fa3d789dSPierre van Houtryve 471fa3d789dSPierre van Houtryve /// TreePredicateFn - This is an abstraction that represents the predicates on 472fa3d789dSPierre van Houtryve /// a PatFrag node. This is a simple one-word wrapper around a pointer to 473fa3d789dSPierre van Houtryve /// provide nice accessors. 474fa3d789dSPierre van Houtryve class TreePredicateFn { 475fa3d789dSPierre van Houtryve /// PatFragRec - This is the TreePattern for the PatFrag that we 476fa3d789dSPierre van Houtryve /// originally came from. 477fa3d789dSPierre van Houtryve TreePattern *PatFragRec; 478fa3d789dSPierre van Houtryve 479fa3d789dSPierre van Houtryve public: 480fa3d789dSPierre van Houtryve /// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag. 481fa3d789dSPierre van Houtryve TreePredicateFn(TreePattern *N); 482fa3d789dSPierre van Houtryve 483fa3d789dSPierre van Houtryve TreePattern *getOrigPatFragRecord() const { return PatFragRec; } 484fa3d789dSPierre van Houtryve 485fa3d789dSPierre van Houtryve /// isAlwaysTrue - Return true if this is a noop predicate. 486fa3d789dSPierre van Houtryve bool isAlwaysTrue() const; 487fa3d789dSPierre van Houtryve 488fa3d789dSPierre van Houtryve bool isImmediatePattern() const { return hasImmCode(); } 489fa3d789dSPierre van Houtryve 490fa3d789dSPierre van Houtryve /// getImmediatePredicateCode - Return the code that evaluates this pattern if 491fa3d789dSPierre van Houtryve /// this is an immediate predicate. It is an error to call this on a 492fa3d789dSPierre van Houtryve /// non-immediate pattern. 493fa3d789dSPierre van Houtryve std::string getImmediatePredicateCode() const { 494fa3d789dSPierre van Houtryve std::string Result = getImmCode(); 495fa3d789dSPierre van Houtryve assert(!Result.empty() && "Isn't an immediate pattern!"); 496fa3d789dSPierre van Houtryve return Result; 497fa3d789dSPierre van Houtryve } 498fa3d789dSPierre van Houtryve 499fa3d789dSPierre van Houtryve bool operator==(const TreePredicateFn &RHS) const { 500fa3d789dSPierre van Houtryve return PatFragRec == RHS.PatFragRec; 501fa3d789dSPierre van Houtryve } 502fa3d789dSPierre van Houtryve 503fa3d789dSPierre van Houtryve bool operator!=(const TreePredicateFn &RHS) const { return !(*this == RHS); } 504fa3d789dSPierre van Houtryve 505fa3d789dSPierre van Houtryve /// Return the name to use in the generated code to reference this, this is 506fa3d789dSPierre van Houtryve /// "Predicate_foo" if from a pattern fragment "foo". 507fa3d789dSPierre van Houtryve std::string getFnName() const; 508fa3d789dSPierre van Houtryve 509fa3d789dSPierre van Houtryve /// getCodeToRunOnSDNode - Return the code for the function body that 510fa3d789dSPierre van Houtryve /// evaluates this predicate. The argument is expected to be in "Node", 511fa3d789dSPierre van Houtryve /// not N. This handles casting and conversion to a concrete node type as 512fa3d789dSPierre van Houtryve /// appropriate. 513fa3d789dSPierre van Houtryve std::string getCodeToRunOnSDNode() const; 514fa3d789dSPierre van Houtryve 515fa3d789dSPierre van Houtryve /// Get the data type of the argument to getImmediatePredicateCode(). 516fa3d789dSPierre van Houtryve StringRef getImmType() const; 517fa3d789dSPierre van Houtryve 518fa3d789dSPierre van Houtryve /// Get a string that describes the type returned by getImmType() but is 519fa3d789dSPierre van Houtryve /// usable as part of an identifier. 520fa3d789dSPierre van Houtryve StringRef getImmTypeIdentifier() const; 521fa3d789dSPierre van Houtryve 522fa3d789dSPierre van Houtryve // Predicate code uses the PatFrag's captured operands. 523fa3d789dSPierre van Houtryve bool usesOperands() const; 524fa3d789dSPierre van Houtryve 525fa3d789dSPierre van Houtryve // Check if the HasNoUse predicate is set. 526fa3d789dSPierre van Houtryve bool hasNoUse() const; 527d0dc29c2Sjofrn // Check if the HasOneUse predicate is set. 528d0dc29c2Sjofrn bool hasOneUse() const; 529fa3d789dSPierre van Houtryve 530fa3d789dSPierre van Houtryve // Is the desired predefined predicate for a load? 531fa3d789dSPierre van Houtryve bool isLoad() const; 532fa3d789dSPierre van Houtryve // Is the desired predefined predicate for a store? 533fa3d789dSPierre van Houtryve bool isStore() const; 534fa3d789dSPierre van Houtryve // Is the desired predefined predicate for an atomic? 535fa3d789dSPierre van Houtryve bool isAtomic() const; 536fa3d789dSPierre van Houtryve 537fa3d789dSPierre van Houtryve /// Is this predicate the predefined unindexed load predicate? 538fa3d789dSPierre van Houtryve /// Is this predicate the predefined unindexed store predicate? 539fa3d789dSPierre van Houtryve bool isUnindexed() const; 540fa3d789dSPierre van Houtryve /// Is this predicate the predefined non-extending load predicate? 541fa3d789dSPierre van Houtryve bool isNonExtLoad() const; 542fa3d789dSPierre van Houtryve /// Is this predicate the predefined any-extend load predicate? 543fa3d789dSPierre van Houtryve bool isAnyExtLoad() const; 544fa3d789dSPierre van Houtryve /// Is this predicate the predefined sign-extend load predicate? 545fa3d789dSPierre van Houtryve bool isSignExtLoad() const; 546fa3d789dSPierre van Houtryve /// Is this predicate the predefined zero-extend load predicate? 547fa3d789dSPierre van Houtryve bool isZeroExtLoad() const; 548fa3d789dSPierre van Houtryve /// Is this predicate the predefined non-truncating store predicate? 549fa3d789dSPierre van Houtryve bool isNonTruncStore() const; 550fa3d789dSPierre van Houtryve /// Is this predicate the predefined truncating store predicate? 551fa3d789dSPierre van Houtryve bool isTruncStore() const; 552fa3d789dSPierre van Houtryve 553fa3d789dSPierre van Houtryve /// Is this predicate the predefined monotonic atomic predicate? 554fa3d789dSPierre van Houtryve bool isAtomicOrderingMonotonic() const; 555fa3d789dSPierre van Houtryve /// Is this predicate the predefined acquire atomic predicate? 556fa3d789dSPierre van Houtryve bool isAtomicOrderingAcquire() const; 557fa3d789dSPierre van Houtryve /// Is this predicate the predefined release atomic predicate? 558fa3d789dSPierre van Houtryve bool isAtomicOrderingRelease() const; 559fa3d789dSPierre van Houtryve /// Is this predicate the predefined acquire-release atomic predicate? 560fa3d789dSPierre van Houtryve bool isAtomicOrderingAcquireRelease() const; 561fa3d789dSPierre van Houtryve /// Is this predicate the predefined sequentially consistent atomic predicate? 562fa3d789dSPierre van Houtryve bool isAtomicOrderingSequentiallyConsistent() const; 563fa3d789dSPierre van Houtryve 564fa3d789dSPierre van Houtryve /// Is this predicate the predefined acquire-or-stronger atomic predicate? 565fa3d789dSPierre van Houtryve bool isAtomicOrderingAcquireOrStronger() const; 566fa3d789dSPierre van Houtryve /// Is this predicate the predefined weaker-than-acquire atomic predicate? 567fa3d789dSPierre van Houtryve bool isAtomicOrderingWeakerThanAcquire() const; 568fa3d789dSPierre van Houtryve 569fa3d789dSPierre van Houtryve /// Is this predicate the predefined release-or-stronger atomic predicate? 570fa3d789dSPierre van Houtryve bool isAtomicOrderingReleaseOrStronger() const; 571fa3d789dSPierre van Houtryve /// Is this predicate the predefined weaker-than-release atomic predicate? 572fa3d789dSPierre van Houtryve bool isAtomicOrderingWeakerThanRelease() const; 573fa3d789dSPierre van Houtryve 574fa3d789dSPierre van Houtryve /// If non-null, indicates that this predicate is a predefined memory VT 575fa3d789dSPierre van Houtryve /// predicate for a load/store and returns the ValueType record for the memory 576fa3d789dSPierre van Houtryve /// VT. 5773138eb50SRahul Joshi const Record *getMemoryVT() const; 578fa3d789dSPierre van Houtryve /// If non-null, indicates that this predicate is a predefined memory VT 579fa3d789dSPierre van Houtryve /// predicate (checking only the scalar type) for load/store and returns the 580fa3d789dSPierre van Houtryve /// ValueType record for the memory VT. 5813138eb50SRahul Joshi const Record *getScalarMemoryVT() const; 582fa3d789dSPierre van Houtryve 5833138eb50SRahul Joshi const ListInit *getAddressSpaces() const; 584fa3d789dSPierre van Houtryve int64_t getMinAlignment() const; 585fa3d789dSPierre van Houtryve 586fa3d789dSPierre van Houtryve // If true, indicates that GlobalISel-based C++ code was supplied. 587fa3d789dSPierre van Houtryve bool hasGISelPredicateCode() const; 588fa3d789dSPierre van Houtryve std::string getGISelPredicateCode() const; 589fa3d789dSPierre van Houtryve 590fa3d789dSPierre van Houtryve private: 591fa3d789dSPierre van Houtryve bool hasPredCode() const; 592fa3d789dSPierre van Houtryve bool hasImmCode() const; 593fa3d789dSPierre van Houtryve std::string getPredCode() const; 594fa3d789dSPierre van Houtryve std::string getImmCode() const; 595fa3d789dSPierre van Houtryve bool immCodeUsesAPInt() const; 596fa3d789dSPierre van Houtryve bool immCodeUsesAPFloat() const; 597fa3d789dSPierre van Houtryve 598fa3d789dSPierre van Houtryve bool isPredefinedPredicateEqualTo(StringRef Field, bool Value) const; 599fa3d789dSPierre van Houtryve }; 600fa3d789dSPierre van Houtryve 601fa3d789dSPierre van Houtryve struct TreePredicateCall { 602fa3d789dSPierre van Houtryve TreePredicateFn Fn; 603fa3d789dSPierre van Houtryve 604fa3d789dSPierre van Houtryve // Scope -- unique identifier for retrieving named arguments. 0 is used when 605fa3d789dSPierre van Houtryve // the predicate does not use named arguments. 606fa3d789dSPierre van Houtryve unsigned Scope; 607fa3d789dSPierre van Houtryve 608fa3d789dSPierre van Houtryve TreePredicateCall(const TreePredicateFn &Fn, unsigned Scope) 609fa3d789dSPierre van Houtryve : Fn(Fn), Scope(Scope) {} 610fa3d789dSPierre van Houtryve 611fa3d789dSPierre van Houtryve bool operator==(const TreePredicateCall &o) const { 612fa3d789dSPierre van Houtryve return Fn == o.Fn && Scope == o.Scope; 613fa3d789dSPierre van Houtryve } 614fa3d789dSPierre van Houtryve bool operator!=(const TreePredicateCall &o) const { return !(*this == o); } 615fa3d789dSPierre van Houtryve }; 616fa3d789dSPierre van Houtryve 617fa3d789dSPierre van Houtryve class TreePatternNode : public RefCountedBase<TreePatternNode> { 618fa3d789dSPierre van Houtryve /// The type of each node result. Before and during type inference, each 619fa3d789dSPierre van Houtryve /// result may be a set of possible types. After (successful) type inference, 620fa3d789dSPierre van Houtryve /// each is a single concrete type. 621fa3d789dSPierre van Houtryve std::vector<TypeSetByHwMode> Types; 622fa3d789dSPierre van Houtryve 623fa3d789dSPierre van Houtryve /// The index of each result in results of the pattern. 624fa3d789dSPierre van Houtryve std::vector<unsigned> ResultPerm; 625fa3d789dSPierre van Houtryve 626fa3d789dSPierre van Houtryve /// OperatorOrVal - The Record for the operator if this is an interior node 627fa3d789dSPierre van Houtryve /// (not a leaf) or the init value (e.g. the "GPRC" record, or "7") for a 628fa3d789dSPierre van Houtryve /// leaf. 6293138eb50SRahul Joshi PointerUnion<const Record *, const Init *> OperatorOrVal; 630fa3d789dSPierre van Houtryve 631fa3d789dSPierre van Houtryve /// Name - The name given to this node with the :$foo notation. 632fa3d789dSPierre van Houtryve /// 633fa3d789dSPierre van Houtryve std::string Name; 634fa3d789dSPierre van Houtryve 635fa3d789dSPierre van Houtryve std::vector<ScopedName> NamesAsPredicateArg; 636fa3d789dSPierre van Houtryve 637fa3d789dSPierre van Houtryve /// PredicateCalls - The predicate functions to execute on this node to check 638fa3d789dSPierre van Houtryve /// for a match. If this list is empty, no predicate is involved. 639fa3d789dSPierre van Houtryve std::vector<TreePredicateCall> PredicateCalls; 640fa3d789dSPierre van Houtryve 641fa3d789dSPierre van Houtryve /// TransformFn - The transformation function to execute on this node before 642fa3d789dSPierre van Houtryve /// it can be substituted into the resulting instruction on a pattern match. 6433138eb50SRahul Joshi const Record *TransformFn; 644fa3d789dSPierre van Houtryve 645fa3d789dSPierre van Houtryve std::vector<TreePatternNodePtr> Children; 646fa3d789dSPierre van Houtryve 647fa3d789dSPierre van Houtryve /// If this was instantiated from a PatFrag node, and the PatFrag was derived 648fa3d789dSPierre van Houtryve /// from "GISelFlags": the original Record derived from GISelFlags. 649fa3d789dSPierre van Houtryve const Record *GISelFlags = nullptr; 650fa3d789dSPierre van Houtryve 651fa3d789dSPierre van Houtryve public: 65237865681SRahul Joshi TreePatternNode(const Record *Op, std::vector<TreePatternNodePtr> Ch, 653fa3d789dSPierre van Houtryve unsigned NumResults) 654fa3d789dSPierre van Houtryve : OperatorOrVal(Op), TransformFn(nullptr), Children(std::move(Ch)) { 655fa3d789dSPierre van Houtryve Types.resize(NumResults); 656fa3d789dSPierre van Houtryve ResultPerm.resize(NumResults); 657fa3d789dSPierre van Houtryve std::iota(ResultPerm.begin(), ResultPerm.end(), 0); 658fa3d789dSPierre van Houtryve } 6593138eb50SRahul Joshi TreePatternNode(const Init *val, unsigned NumResults) // leaf ctor 660fa3d789dSPierre van Houtryve : OperatorOrVal(val), TransformFn(nullptr) { 661fa3d789dSPierre van Houtryve Types.resize(NumResults); 662fa3d789dSPierre van Houtryve ResultPerm.resize(NumResults); 663fa3d789dSPierre van Houtryve std::iota(ResultPerm.begin(), ResultPerm.end(), 0); 664fa3d789dSPierre van Houtryve } 665fa3d789dSPierre van Houtryve 666fa3d789dSPierre van Houtryve bool hasName() const { return !Name.empty(); } 667fa3d789dSPierre van Houtryve const std::string &getName() const { return Name; } 668fa3d789dSPierre van Houtryve void setName(StringRef N) { Name.assign(N.begin(), N.end()); } 669fa3d789dSPierre van Houtryve 670fa3d789dSPierre van Houtryve const std::vector<ScopedName> &getNamesAsPredicateArg() const { 671fa3d789dSPierre van Houtryve return NamesAsPredicateArg; 672fa3d789dSPierre van Houtryve } 673fa3d789dSPierre van Houtryve void setNamesAsPredicateArg(const std::vector<ScopedName> &Names) { 674fa3d789dSPierre van Houtryve NamesAsPredicateArg = Names; 675fa3d789dSPierre van Houtryve } 676fa3d789dSPierre van Houtryve void addNameAsPredicateArg(const ScopedName &N) { 677fa3d789dSPierre van Houtryve NamesAsPredicateArg.push_back(N); 678fa3d789dSPierre van Houtryve } 679fa3d789dSPierre van Houtryve 6803138eb50SRahul Joshi bool isLeaf() const { return isa<const Init *>(OperatorOrVal); } 681fa3d789dSPierre van Houtryve 682fa3d789dSPierre van Houtryve // Type accessors. 683fa3d789dSPierre van Houtryve unsigned getNumTypes() const { return Types.size(); } 684fa3d789dSPierre van Houtryve ValueTypeByHwMode getType(unsigned ResNo) const { 685fa3d789dSPierre van Houtryve return Types[ResNo].getValueTypeByHwMode(); 686fa3d789dSPierre van Houtryve } 687fa3d789dSPierre van Houtryve const std::vector<TypeSetByHwMode> &getExtTypes() const { return Types; } 688fa3d789dSPierre van Houtryve const TypeSetByHwMode &getExtType(unsigned ResNo) const { 689fa3d789dSPierre van Houtryve return Types[ResNo]; 690fa3d789dSPierre van Houtryve } 691fa3d789dSPierre van Houtryve TypeSetByHwMode &getExtType(unsigned ResNo) { return Types[ResNo]; } 692fa3d789dSPierre van Houtryve void setType(unsigned ResNo, const TypeSetByHwMode &T) { Types[ResNo] = T; } 693fa3d789dSPierre van Houtryve MVT::SimpleValueType getSimpleType(unsigned ResNo) const { 694fa3d789dSPierre van Houtryve return Types[ResNo].getMachineValueType().SimpleTy; 695fa3d789dSPierre van Houtryve } 696fa3d789dSPierre van Houtryve 697fa3d789dSPierre van Houtryve bool hasConcreteType(unsigned ResNo) const { 698fa3d789dSPierre van Houtryve return Types[ResNo].isValueTypeByHwMode(false); 699fa3d789dSPierre van Houtryve } 700fa3d789dSPierre van Houtryve bool isTypeCompletelyUnknown(unsigned ResNo, TreePattern &TP) const { 701fa3d789dSPierre van Houtryve return Types[ResNo].empty(); 702fa3d789dSPierre van Houtryve } 703fa3d789dSPierre van Houtryve 704fa3d789dSPierre van Houtryve unsigned getNumResults() const { return ResultPerm.size(); } 705fa3d789dSPierre van Houtryve unsigned getResultIndex(unsigned ResNo) const { return ResultPerm[ResNo]; } 706fa3d789dSPierre van Houtryve void setResultIndex(unsigned ResNo, unsigned RI) { ResultPerm[ResNo] = RI; } 707fa3d789dSPierre van Houtryve 7083138eb50SRahul Joshi const Init *getLeafValue() const { 709fa3d789dSPierre van Houtryve assert(isLeaf()); 7103138eb50SRahul Joshi return cast<const Init *>(OperatorOrVal); 711fa3d789dSPierre van Houtryve } 71237865681SRahul Joshi const Record *getOperator() const { 713fa3d789dSPierre van Houtryve assert(!isLeaf()); 71437865681SRahul Joshi return cast<const Record *>(OperatorOrVal); 715fa3d789dSPierre van Houtryve } 716fa3d789dSPierre van Houtryve 717d1f51c67SSergei Barannikov using child_iterator = pointee_iterator<decltype(Children)::iterator>; 718d1f51c67SSergei Barannikov using child_const_iterator = 719d1f51c67SSergei Barannikov pointee_iterator<decltype(Children)::const_iterator>; 720d1f51c67SSergei Barannikov 721d1f51c67SSergei Barannikov iterator_range<child_iterator> children() { 722d1f51c67SSergei Barannikov return make_pointee_range(Children); 723d1f51c67SSergei Barannikov } 724d1f51c67SSergei Barannikov 725d1f51c67SSergei Barannikov iterator_range<child_const_iterator> children() const { 726d1f51c67SSergei Barannikov return make_pointee_range(Children); 727d1f51c67SSergei Barannikov } 728d1f51c67SSergei Barannikov 729fa3d789dSPierre van Houtryve unsigned getNumChildren() const { return Children.size(); } 730fa3d789dSPierre van Houtryve const TreePatternNode &getChild(unsigned N) const { 731fa3d789dSPierre van Houtryve return *Children[N].get(); 732fa3d789dSPierre van Houtryve } 733fa3d789dSPierre van Houtryve TreePatternNode &getChild(unsigned N) { return *Children[N].get(); } 734fa3d789dSPierre van Houtryve const TreePatternNodePtr &getChildShared(unsigned N) const { 735fa3d789dSPierre van Houtryve return Children[N]; 736fa3d789dSPierre van Houtryve } 737fa3d789dSPierre van Houtryve TreePatternNodePtr &getChildSharedPtr(unsigned N) { return Children[N]; } 738fa3d789dSPierre van Houtryve void setChild(unsigned i, TreePatternNodePtr N) { Children[i] = N; } 739fa3d789dSPierre van Houtryve 740fa3d789dSPierre van Houtryve /// hasChild - Return true if N is any of our children. 741fa3d789dSPierre van Houtryve bool hasChild(const TreePatternNode *N) const { 742fa3d789dSPierre van Houtryve for (unsigned i = 0, e = Children.size(); i != e; ++i) 743fa3d789dSPierre van Houtryve if (Children[i].get() == N) 744fa3d789dSPierre van Houtryve return true; 745fa3d789dSPierre van Houtryve return false; 746fa3d789dSPierre van Houtryve } 747fa3d789dSPierre van Houtryve 748fa3d789dSPierre van Houtryve bool hasProperTypeByHwMode() const; 749fa3d789dSPierre van Houtryve bool hasPossibleType() const; 750fa3d789dSPierre van Houtryve bool setDefaultMode(unsigned Mode); 751fa3d789dSPierre van Houtryve 752fa3d789dSPierre van Houtryve bool hasAnyPredicate() const { return !PredicateCalls.empty(); } 753fa3d789dSPierre van Houtryve 754fa3d789dSPierre van Houtryve const std::vector<TreePredicateCall> &getPredicateCalls() const { 755fa3d789dSPierre van Houtryve return PredicateCalls; 756fa3d789dSPierre van Houtryve } 757fa3d789dSPierre van Houtryve void clearPredicateCalls() { PredicateCalls.clear(); } 758fa3d789dSPierre van Houtryve void setPredicateCalls(const std::vector<TreePredicateCall> &Calls) { 759fa3d789dSPierre van Houtryve assert(PredicateCalls.empty() && "Overwriting non-empty predicate list!"); 760fa3d789dSPierre van Houtryve PredicateCalls = Calls; 761fa3d789dSPierre van Houtryve } 762fa3d789dSPierre van Houtryve void addPredicateCall(const TreePredicateCall &Call) { 763fa3d789dSPierre van Houtryve assert(!Call.Fn.isAlwaysTrue() && "Empty predicate string!"); 764fa3d789dSPierre van Houtryve assert(!is_contained(PredicateCalls, Call) && 765fa3d789dSPierre van Houtryve "predicate applied recursively"); 766fa3d789dSPierre van Houtryve PredicateCalls.push_back(Call); 767fa3d789dSPierre van Houtryve } 768fa3d789dSPierre van Houtryve void addPredicateCall(const TreePredicateFn &Fn, unsigned Scope) { 769fa3d789dSPierre van Houtryve assert((Scope != 0) == Fn.usesOperands()); 770fa3d789dSPierre van Houtryve addPredicateCall(TreePredicateCall(Fn, Scope)); 771fa3d789dSPierre van Houtryve } 772fa3d789dSPierre van Houtryve 7733138eb50SRahul Joshi const Record *getTransformFn() const { return TransformFn; } 7743138eb50SRahul Joshi void setTransformFn(const Record *Fn) { TransformFn = Fn; } 775fa3d789dSPierre van Houtryve 776fa3d789dSPierre van Houtryve /// getIntrinsicInfo - If this node corresponds to an intrinsic, return the 777fa3d789dSPierre van Houtryve /// CodeGenIntrinsic information for it, otherwise return a null pointer. 778fa3d789dSPierre van Houtryve const CodeGenIntrinsic *getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const; 779fa3d789dSPierre van Houtryve 780fa3d789dSPierre van Houtryve /// getComplexPatternInfo - If this node corresponds to a ComplexPattern, 781fa3d789dSPierre van Houtryve /// return the ComplexPattern information, otherwise return null. 782fa3d789dSPierre van Houtryve const ComplexPattern * 783fa3d789dSPierre van Houtryve getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const; 784fa3d789dSPierre van Houtryve 785fa3d789dSPierre van Houtryve /// Returns the number of MachineInstr operands that would be produced by this 786fa3d789dSPierre van Houtryve /// node if it mapped directly to an output Instruction's 787fa3d789dSPierre van Houtryve /// operand. ComplexPattern specifies this explicitly; MIOperandInfo gives it 788fa3d789dSPierre van Houtryve /// for Operands; otherwise 1. 789fa3d789dSPierre van Houtryve unsigned getNumMIResults(const CodeGenDAGPatterns &CGP) const; 790fa3d789dSPierre van Houtryve 791fa3d789dSPierre van Houtryve /// NodeHasProperty - Return true if this node has the specified property. 792fa3d789dSPierre van Houtryve bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const; 793fa3d789dSPierre van Houtryve 794fa3d789dSPierre van Houtryve /// TreeHasProperty - Return true if any node in this tree has the specified 795fa3d789dSPierre van Houtryve /// property. 796fa3d789dSPierre van Houtryve bool TreeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const; 797fa3d789dSPierre van Houtryve 798fa3d789dSPierre van Houtryve /// isCommutativeIntrinsic - Return true if the node is an intrinsic which is 799fa3d789dSPierre van Houtryve /// marked isCommutative. 800fa3d789dSPierre van Houtryve bool isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const; 801fa3d789dSPierre van Houtryve 802fa3d789dSPierre van Houtryve void setGISelFlagsRecord(const Record *R) { GISelFlags = R; } 803fa3d789dSPierre van Houtryve const Record *getGISelFlagsRecord() const { return GISelFlags; } 804fa3d789dSPierre van Houtryve 805fa3d789dSPierre van Houtryve void print(raw_ostream &OS) const; 806fa3d789dSPierre van Houtryve void dump() const; 807fa3d789dSPierre van Houtryve 808fa3d789dSPierre van Houtryve public: // Higher level manipulation routines. 809fa3d789dSPierre van Houtryve /// clone - Return a new copy of this tree. 810fa3d789dSPierre van Houtryve /// 811fa3d789dSPierre van Houtryve TreePatternNodePtr clone() const; 812fa3d789dSPierre van Houtryve 813fa3d789dSPierre van Houtryve /// RemoveAllTypes - Recursively strip all the types of this tree. 814fa3d789dSPierre van Houtryve void RemoveAllTypes(); 815fa3d789dSPierre van Houtryve 816fa3d789dSPierre van Houtryve /// isIsomorphicTo - Return true if this node is recursively isomorphic to 817fa3d789dSPierre van Houtryve /// the specified node. For this comparison, all of the state of the node 818fa3d789dSPierre van Houtryve /// is considered, except for the assigned name. Nodes with differing names 819fa3d789dSPierre van Houtryve /// that are otherwise identical are considered isomorphic. 820fa3d789dSPierre van Houtryve bool isIsomorphicTo(const TreePatternNode &N, 821fa3d789dSPierre van Houtryve const MultipleUseVarSet &DepVars) const; 822fa3d789dSPierre van Houtryve 823fa3d789dSPierre van Houtryve /// SubstituteFormalArguments - Replace the formal arguments in this tree 824fa3d789dSPierre van Houtryve /// with actual values specified by ArgMap. 825fa3d789dSPierre van Houtryve void 826fa3d789dSPierre van Houtryve SubstituteFormalArguments(std::map<std::string, TreePatternNodePtr> &ArgMap); 827fa3d789dSPierre van Houtryve 828fa3d789dSPierre van Houtryve /// InlinePatternFragments - If \p T pattern refers to any pattern 829fa3d789dSPierre van Houtryve /// fragments, return the set of inlined versions (this can be more than 830fa3d789dSPierre van Houtryve /// one if a PatFrags record has multiple alternatives). 831fa3d789dSPierre van Houtryve void InlinePatternFragments(TreePattern &TP, 832fa3d789dSPierre van Houtryve std::vector<TreePatternNodePtr> &OutAlternatives); 833fa3d789dSPierre van Houtryve 834fa3d789dSPierre van Houtryve /// ApplyTypeConstraints - Apply all of the type constraints relevant to 835fa3d789dSPierre van Houtryve /// this node and its children in the tree. This returns true if it makes a 836fa3d789dSPierre van Houtryve /// change, false otherwise. If a type contradiction is found, flag an error. 837fa3d789dSPierre van Houtryve bool ApplyTypeConstraints(TreePattern &TP, bool NotRegisters); 838fa3d789dSPierre van Houtryve 839fa3d789dSPierre van Houtryve /// UpdateNodeType - Set the node type of N to VT if VT contains 840fa3d789dSPierre van Houtryve /// information. If N already contains a conflicting type, then flag an 841fa3d789dSPierre van Houtryve /// error. This returns true if any information was updated. 842fa3d789dSPierre van Houtryve /// 843fa3d789dSPierre van Houtryve bool UpdateNodeType(unsigned ResNo, const TypeSetByHwMode &InTy, 844fa3d789dSPierre van Houtryve TreePattern &TP); 845fa3d789dSPierre van Houtryve bool UpdateNodeType(unsigned ResNo, MVT::SimpleValueType InTy, 846fa3d789dSPierre van Houtryve TreePattern &TP); 847c2dc46cdSCraig Topper bool UpdateNodeType(unsigned ResNo, const ValueTypeByHwMode &InTy, 848c2dc46cdSCraig Topper TreePattern &TP); 849fa3d789dSPierre van Houtryve 850fa3d789dSPierre van Houtryve // Update node type with types inferred from an instruction operand or result 851fa3d789dSPierre van Houtryve // def from the ins/outs lists. 852fa3d789dSPierre van Houtryve // Return true if the type changed. 853bdf02249SRahul Joshi bool UpdateNodeTypeFromInst(unsigned ResNo, const Record *Operand, 854bdf02249SRahul Joshi TreePattern &TP); 855fa3d789dSPierre van Houtryve 856fa3d789dSPierre van Houtryve /// ContainsUnresolvedType - Return true if this tree contains any 857fa3d789dSPierre van Houtryve /// unresolved types. 858fa3d789dSPierre van Houtryve bool ContainsUnresolvedType(TreePattern &TP) const; 859fa3d789dSPierre van Houtryve 860fa3d789dSPierre van Houtryve /// canPatternMatch - If it is impossible for this pattern to match on this 861fa3d789dSPierre van Houtryve /// target, fill in Reason and return false. Otherwise, return true. 862d1f51c67SSergei Barannikov bool canPatternMatch(std::string &Reason, 863d1f51c67SSergei Barannikov const CodeGenDAGPatterns &CDP) const; 864fa3d789dSPierre van Houtryve }; 865fa3d789dSPierre van Houtryve 866fa3d789dSPierre van Houtryve inline raw_ostream &operator<<(raw_ostream &OS, const TreePatternNode &TPN) { 867fa3d789dSPierre van Houtryve TPN.print(OS); 868fa3d789dSPierre van Houtryve return OS; 869fa3d789dSPierre van Houtryve } 870fa3d789dSPierre van Houtryve 871fa3d789dSPierre van Houtryve /// TreePattern - Represent a pattern, used for instructions, pattern 872fa3d789dSPierre van Houtryve /// fragments, etc. 873fa3d789dSPierre van Houtryve /// 874fa3d789dSPierre van Houtryve class TreePattern { 875fa3d789dSPierre van Houtryve /// Trees - The list of pattern trees which corresponds to this pattern. 876fa3d789dSPierre van Houtryve /// Note that PatFrag's only have a single tree. 877fa3d789dSPierre van Houtryve /// 878fa3d789dSPierre van Houtryve std::vector<TreePatternNodePtr> Trees; 879fa3d789dSPierre van Houtryve 880fa3d789dSPierre van Houtryve /// NamedNodes - This is all of the nodes that have names in the trees in this 881fa3d789dSPierre van Houtryve /// pattern. 882fa3d789dSPierre van Houtryve StringMap<SmallVector<TreePatternNode *, 1>> NamedNodes; 883fa3d789dSPierre van Houtryve 884fa3d789dSPierre van Houtryve /// TheRecord - The actual TableGen record corresponding to this pattern. 885fa3d789dSPierre van Houtryve /// 88637865681SRahul Joshi const Record *TheRecord; 887fa3d789dSPierre van Houtryve 888fa3d789dSPierre van Houtryve /// Args - This is a list of all of the arguments to this pattern (for 889fa3d789dSPierre van Houtryve /// PatFrag patterns), which are the 'node' markers in this pattern. 890fa3d789dSPierre van Houtryve std::vector<std::string> Args; 891fa3d789dSPierre van Houtryve 892fa3d789dSPierre van Houtryve /// CDP - the top-level object coordinating this madness. 893fa3d789dSPierre van Houtryve /// 894fa3d789dSPierre van Houtryve CodeGenDAGPatterns &CDP; 895fa3d789dSPierre van Houtryve 896fa3d789dSPierre van Houtryve /// isInputPattern - True if this is an input pattern, something to match. 897fa3d789dSPierre van Houtryve /// False if this is an output pattern, something to emit. 898fa3d789dSPierre van Houtryve bool isInputPattern; 899fa3d789dSPierre van Houtryve 900fa3d789dSPierre van Houtryve /// hasError - True if the currently processed nodes have unresolvable types 901fa3d789dSPierre van Houtryve /// or other non-fatal errors 902fa3d789dSPierre van Houtryve bool HasError; 903fa3d789dSPierre van Houtryve 904fa3d789dSPierre van Houtryve /// It's important that the usage of operands in ComplexPatterns is 905fa3d789dSPierre van Houtryve /// consistent: each named operand can be defined by at most one 906fa3d789dSPierre van Houtryve /// ComplexPattern. This records the ComplexPattern instance and the operand 907fa3d789dSPierre van Houtryve /// number for each operand encountered in a ComplexPattern to aid in that 908fa3d789dSPierre van Houtryve /// check. 9093138eb50SRahul Joshi StringMap<std::pair<const Record *, unsigned>> ComplexPatternOperands; 910fa3d789dSPierre van Houtryve 911fa3d789dSPierre van Houtryve TypeInfer Infer; 912fa3d789dSPierre van Houtryve 913fa3d789dSPierre van Houtryve public: 914fa3d789dSPierre van Houtryve /// TreePattern constructor - Parse the specified DagInits into the 915fa3d789dSPierre van Houtryve /// current record. 9163138eb50SRahul Joshi TreePattern(const Record *TheRec, const ListInit *RawPat, bool isInput, 917fa3d789dSPierre van Houtryve CodeGenDAGPatterns &ise); 91862e2c7fbSRahul Joshi TreePattern(const Record *TheRec, const DagInit *Pat, bool isInput, 919fa3d789dSPierre van Houtryve CodeGenDAGPatterns &ise); 92037865681SRahul Joshi TreePattern(const Record *TheRec, TreePatternNodePtr Pat, bool isInput, 921fa3d789dSPierre van Houtryve CodeGenDAGPatterns &ise); 922fa3d789dSPierre van Houtryve 923fa3d789dSPierre van Houtryve /// getTrees - Return the tree patterns which corresponds to this pattern. 924fa3d789dSPierre van Houtryve /// 925fa3d789dSPierre van Houtryve const std::vector<TreePatternNodePtr> &getTrees() const { return Trees; } 926fa3d789dSPierre van Houtryve unsigned getNumTrees() const { return Trees.size(); } 927fa3d789dSPierre van Houtryve const TreePatternNodePtr &getTree(unsigned i) const { return Trees[i]; } 928fa3d789dSPierre van Houtryve void setTree(unsigned i, TreePatternNodePtr Tree) { Trees[i] = Tree; } 929fa3d789dSPierre van Houtryve const TreePatternNodePtr &getOnlyTree() const { 930fa3d789dSPierre van Houtryve assert(Trees.size() == 1 && "Doesn't have exactly one pattern!"); 931fa3d789dSPierre van Houtryve return Trees[0]; 932fa3d789dSPierre van Houtryve } 933fa3d789dSPierre van Houtryve 934fa3d789dSPierre van Houtryve const StringMap<SmallVector<TreePatternNode *, 1>> &getNamedNodesMap() { 935fa3d789dSPierre van Houtryve if (NamedNodes.empty()) 936fa3d789dSPierre van Houtryve ComputeNamedNodes(); 937fa3d789dSPierre van Houtryve return NamedNodes; 938fa3d789dSPierre van Houtryve } 939fa3d789dSPierre van Houtryve 940fa3d789dSPierre van Houtryve /// getRecord - Return the actual TableGen record corresponding to this 941fa3d789dSPierre van Houtryve /// pattern. 942fa3d789dSPierre van Houtryve /// 94337865681SRahul Joshi const Record *getRecord() const { return TheRecord; } 944fa3d789dSPierre van Houtryve 945fa3d789dSPierre van Houtryve unsigned getNumArgs() const { return Args.size(); } 946fa3d789dSPierre van Houtryve const std::string &getArgName(unsigned i) const { 947fa3d789dSPierre van Houtryve assert(i < Args.size() && "Argument reference out of range!"); 948fa3d789dSPierre van Houtryve return Args[i]; 949fa3d789dSPierre van Houtryve } 950fa3d789dSPierre van Houtryve std::vector<std::string> &getArgList() { return Args; } 951fa3d789dSPierre van Houtryve 952fa3d789dSPierre van Houtryve CodeGenDAGPatterns &getDAGPatterns() const { return CDP; } 953fa3d789dSPierre van Houtryve 954fa3d789dSPierre van Houtryve /// InlinePatternFragments - If this pattern refers to any pattern 955fa3d789dSPierre van Houtryve /// fragments, inline them into place, giving us a pattern without any 956fa3d789dSPierre van Houtryve /// PatFrags references. This may increase the number of trees in the 957fa3d789dSPierre van Houtryve /// pattern if a PatFrags has multiple alternatives. 958fa3d789dSPierre van Houtryve void InlinePatternFragments() { 959fa3d789dSPierre van Houtryve std::vector<TreePatternNodePtr> Copy; 960fa3d789dSPierre van Houtryve Trees.swap(Copy); 961fa3d789dSPierre van Houtryve for (const TreePatternNodePtr &C : Copy) 962fa3d789dSPierre van Houtryve C->InlinePatternFragments(*this, Trees); 963fa3d789dSPierre van Houtryve } 964fa3d789dSPierre van Houtryve 965fa3d789dSPierre van Houtryve /// InferAllTypes - Infer/propagate as many types throughout the expression 966fa3d789dSPierre van Houtryve /// patterns as possible. Return true if all types are inferred, false 967fa3d789dSPierre van Houtryve /// otherwise. Bail out if a type contradiction is found. 968fa3d789dSPierre van Houtryve bool InferAllTypes( 969fa3d789dSPierre van Houtryve const StringMap<SmallVector<TreePatternNode *, 1>> *NamedTypes = nullptr); 970fa3d789dSPierre van Houtryve 971fa3d789dSPierre van Houtryve /// error - If this is the first error in the current resolution step, 972fa3d789dSPierre van Houtryve /// print it and set the error flag. Otherwise, continue silently. 973fa3d789dSPierre van Houtryve void error(const Twine &Msg); 974fa3d789dSPierre van Houtryve bool hasError() const { return HasError; } 975fa3d789dSPierre van Houtryve void resetError() { HasError = false; } 976fa3d789dSPierre van Houtryve 977fa3d789dSPierre van Houtryve TypeInfer &getInfer() { return Infer; } 978fa3d789dSPierre van Houtryve 979fa3d789dSPierre van Houtryve void print(raw_ostream &OS) const; 980fa3d789dSPierre van Houtryve void dump() const; 981fa3d789dSPierre van Houtryve 982fa3d789dSPierre van Houtryve private: 98362e2c7fbSRahul Joshi TreePatternNodePtr ParseTreePattern(const Init *DI, StringRef OpName); 984fa3d789dSPierre van Houtryve void ComputeNamedNodes(); 985fa3d789dSPierre van Houtryve void ComputeNamedNodes(TreePatternNode &N); 986fa3d789dSPierre van Houtryve }; 987fa3d789dSPierre van Houtryve 988fa3d789dSPierre van Houtryve inline bool TreePatternNode::UpdateNodeType(unsigned ResNo, 989fa3d789dSPierre van Houtryve const TypeSetByHwMode &InTy, 990fa3d789dSPierre van Houtryve TreePattern &TP) { 991fa3d789dSPierre van Houtryve TypeSetByHwMode VTS(InTy); 992fa3d789dSPierre van Houtryve TP.getInfer().expandOverloads(VTS); 993fa3d789dSPierre van Houtryve return TP.getInfer().MergeInTypeInfo(Types[ResNo], VTS); 994fa3d789dSPierre van Houtryve } 995fa3d789dSPierre van Houtryve 996fa3d789dSPierre van Houtryve inline bool TreePatternNode::UpdateNodeType(unsigned ResNo, 997fa3d789dSPierre van Houtryve MVT::SimpleValueType InTy, 998fa3d789dSPierre van Houtryve TreePattern &TP) { 999fa3d789dSPierre van Houtryve TypeSetByHwMode VTS(InTy); 1000fa3d789dSPierre van Houtryve TP.getInfer().expandOverloads(VTS); 1001fa3d789dSPierre van Houtryve return TP.getInfer().MergeInTypeInfo(Types[ResNo], VTS); 1002fa3d789dSPierre van Houtryve } 1003fa3d789dSPierre van Houtryve 1004fa3d789dSPierre van Houtryve inline bool TreePatternNode::UpdateNodeType(unsigned ResNo, 1005c2dc46cdSCraig Topper const ValueTypeByHwMode &InTy, 1006fa3d789dSPierre van Houtryve TreePattern &TP) { 1007fa3d789dSPierre van Houtryve TypeSetByHwMode VTS(InTy); 1008fa3d789dSPierre van Houtryve TP.getInfer().expandOverloads(VTS); 1009fa3d789dSPierre van Houtryve return TP.getInfer().MergeInTypeInfo(Types[ResNo], VTS); 1010fa3d789dSPierre van Houtryve } 1011fa3d789dSPierre van Houtryve 1012fa3d789dSPierre van Houtryve /// DAGDefaultOperand - One of these is created for each OperandWithDefaultOps 1013fa3d789dSPierre van Houtryve /// that has a set ExecuteAlways / DefaultOps field. 1014fa3d789dSPierre van Houtryve struct DAGDefaultOperand { 1015fa3d789dSPierre van Houtryve std::vector<TreePatternNodePtr> DefaultOps; 1016fa3d789dSPierre van Houtryve }; 1017fa3d789dSPierre van Houtryve 1018fa3d789dSPierre van Houtryve class DAGInstruction { 1019bdf02249SRahul Joshi std::vector<const Record *> Results; 1020bdf02249SRahul Joshi std::vector<const Record *> Operands; 10213138eb50SRahul Joshi std::vector<const Record *> ImpResults; 1022fa3d789dSPierre van Houtryve TreePatternNodePtr SrcPattern; 1023fa3d789dSPierre van Houtryve TreePatternNodePtr ResultPattern; 1024fa3d789dSPierre van Houtryve 1025fa3d789dSPierre van Houtryve public: 10263138eb50SRahul Joshi DAGInstruction(std::vector<const Record *> &&Results, 10273138eb50SRahul Joshi std::vector<const Record *> &&Operands, 10283138eb50SRahul Joshi std::vector<const Record *> &&ImpResults, 10293138eb50SRahul Joshi TreePatternNodePtr SrcPattern = nullptr, 10303138eb50SRahul Joshi TreePatternNodePtr ResultPattern = nullptr) 10313138eb50SRahul Joshi : Results(std::move(Results)), Operands(std::move(Operands)), 10323138eb50SRahul Joshi ImpResults(std::move(ImpResults)), SrcPattern(SrcPattern), 10333138eb50SRahul Joshi ResultPattern(ResultPattern) {} 1034fa3d789dSPierre van Houtryve 1035fa3d789dSPierre van Houtryve unsigned getNumResults() const { return Results.size(); } 1036fa3d789dSPierre van Houtryve unsigned getNumOperands() const { return Operands.size(); } 1037fa3d789dSPierre van Houtryve unsigned getNumImpResults() const { return ImpResults.size(); } 10383138eb50SRahul Joshi ArrayRef<const Record *> getImpResults() const { return ImpResults; } 1039fa3d789dSPierre van Houtryve 1040bdf02249SRahul Joshi const Record *getResult(unsigned RN) const { 1041fa3d789dSPierre van Houtryve assert(RN < Results.size()); 1042fa3d789dSPierre van Houtryve return Results[RN]; 1043fa3d789dSPierre van Houtryve } 1044fa3d789dSPierre van Houtryve 1045bdf02249SRahul Joshi const Record *getOperand(unsigned ON) const { 1046fa3d789dSPierre van Houtryve assert(ON < Operands.size()); 1047fa3d789dSPierre van Houtryve return Operands[ON]; 1048fa3d789dSPierre van Houtryve } 1049fa3d789dSPierre van Houtryve 10503138eb50SRahul Joshi const Record *getImpResult(unsigned RN) const { 1051fa3d789dSPierre van Houtryve assert(RN < ImpResults.size()); 1052fa3d789dSPierre van Houtryve return ImpResults[RN]; 1053fa3d789dSPierre van Houtryve } 1054fa3d789dSPierre van Houtryve 1055fa3d789dSPierre van Houtryve TreePatternNodePtr getSrcPattern() const { return SrcPattern; } 1056fa3d789dSPierre van Houtryve TreePatternNodePtr getResultPattern() const { return ResultPattern; } 1057fa3d789dSPierre van Houtryve }; 1058fa3d789dSPierre van Houtryve 1059fa3d789dSPierre van Houtryve /// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns 1060fa3d789dSPierre van Houtryve /// processed to produce isel. 1061fa3d789dSPierre van Houtryve class PatternToMatch { 106237865681SRahul Joshi const Record *SrcRecord; // Originating Record for the pattern. 106362e2c7fbSRahul Joshi const ListInit *Predicates; // Top level predicate conditions to match. 1064fa3d789dSPierre van Houtryve TreePatternNodePtr SrcPattern; // Source pattern to match. 1065fa3d789dSPierre van Houtryve TreePatternNodePtr DstPattern; // Resulting pattern. 10663138eb50SRahul Joshi std::vector<const Record *> Dstregs; // Physical register defs being matched. 1067fa3d789dSPierre van Houtryve std::string HwModeFeatures; 1068fa3d789dSPierre van Houtryve int AddedComplexity; // Add to matching pattern complexity. 1069eae7554dSjofrn bool GISelShouldIgnore; // Should GlobalISel ignore importing this pattern. 1070fa3d789dSPierre van Houtryve unsigned ID; // Unique ID for the record. 1071fa3d789dSPierre van Houtryve 1072fa3d789dSPierre van Houtryve public: 107362e2c7fbSRahul Joshi PatternToMatch(const Record *srcrecord, const ListInit *preds, 107437865681SRahul Joshi TreePatternNodePtr src, TreePatternNodePtr dst, 10753138eb50SRahul Joshi ArrayRef<const Record *> dstregs, int complexity, unsigned uid, 107637865681SRahul Joshi bool ignore, const Twine &hwmodefeatures = "") 1077fa3d789dSPierre van Houtryve : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), 10783138eb50SRahul Joshi DstPattern(dst), Dstregs(dstregs), HwModeFeatures(hwmodefeatures.str()), 10793138eb50SRahul Joshi AddedComplexity(complexity), GISelShouldIgnore(ignore), ID(uid) {} 1080fa3d789dSPierre van Houtryve 108137865681SRahul Joshi const Record *getSrcRecord() const { return SrcRecord; } 108262e2c7fbSRahul Joshi const ListInit *getPredicates() const { return Predicates; } 1083fa3d789dSPierre van Houtryve TreePatternNode &getSrcPattern() const { return *SrcPattern; } 1084fa3d789dSPierre van Houtryve TreePatternNodePtr getSrcPatternShared() const { return SrcPattern; } 1085fa3d789dSPierre van Houtryve TreePatternNode &getDstPattern() const { return *DstPattern; } 1086fa3d789dSPierre van Houtryve TreePatternNodePtr getDstPatternShared() const { return DstPattern; } 10873138eb50SRahul Joshi ArrayRef<const Record *> getDstRegs() const { return Dstregs; } 1088fa3d789dSPierre van Houtryve StringRef getHwModeFeatures() const { return HwModeFeatures; } 1089fa3d789dSPierre van Houtryve int getAddedComplexity() const { return AddedComplexity; } 1090eae7554dSjofrn bool getGISelShouldIgnore() const { return GISelShouldIgnore; } 1091fa3d789dSPierre van Houtryve unsigned getID() const { return ID; } 1092fa3d789dSPierre van Houtryve 1093fa3d789dSPierre van Houtryve std::string getPredicateCheck() const; 10943138eb50SRahul Joshi void 10953138eb50SRahul Joshi getPredicateRecords(SmallVectorImpl<const Record *> &PredicateRecs) const; 1096fa3d789dSPierre van Houtryve 1097fa3d789dSPierre van Houtryve /// Compute the complexity metric for the input pattern. This roughly 1098fa3d789dSPierre van Houtryve /// corresponds to the number of nodes that are covered. 1099fa3d789dSPierre van Houtryve int getPatternComplexity(const CodeGenDAGPatterns &CGP) const; 1100fa3d789dSPierre van Houtryve }; 1101fa3d789dSPierre van Houtryve 1102fa3d789dSPierre van Houtryve class CodeGenDAGPatterns { 110387e8b530SRahul Joshi public: 110487e8b530SRahul Joshi using NodeXForm = std::pair<const Record *, std::string>; 110587e8b530SRahul Joshi 110687e8b530SRahul Joshi private: 110787e8b530SRahul Joshi const RecordKeeper &Records; 1108fa3d789dSPierre van Houtryve CodeGenTarget Target; 1109fa3d789dSPierre van Houtryve CodeGenIntrinsicTable Intrinsics; 1110fa3d789dSPierre van Houtryve 111137865681SRahul Joshi std::map<const Record *, SDNodeInfo, LessRecordByID> SDNodes; 111287e8b530SRahul Joshi 111387e8b530SRahul Joshi std::map<const Record *, NodeXForm, LessRecordByID> SDNodeXForms; 111437865681SRahul Joshi std::map<const Record *, ComplexPattern, LessRecordByID> ComplexPatterns; 111537865681SRahul Joshi std::map<const Record *, std::unique_ptr<TreePattern>, LessRecordByID> 1116fa3d789dSPierre van Houtryve PatternFragments; 1117bdf02249SRahul Joshi std::map<const Record *, DAGDefaultOperand, LessRecordByID> DefaultOperands; 111837865681SRahul Joshi std::map<const Record *, DAGInstruction, LessRecordByID> Instructions; 1119fa3d789dSPierre van Houtryve 1120fa3d789dSPierre van Houtryve // Specific SDNode definitions: 11213138eb50SRahul Joshi const Record *intrinsic_void_sdnode; 11223138eb50SRahul Joshi const Record *intrinsic_w_chain_sdnode, *intrinsic_wo_chain_sdnode; 1123fa3d789dSPierre van Houtryve 1124fa3d789dSPierre van Houtryve /// PatternsToMatch - All of the things we are matching on the DAG. The first 1125fa3d789dSPierre van Houtryve /// value is the pattern to match, the second pattern is the result to 1126fa3d789dSPierre van Houtryve /// emit. 1127fa3d789dSPierre van Houtryve std::vector<PatternToMatch> PatternsToMatch; 1128fa3d789dSPierre van Houtryve 1129fa3d789dSPierre van Houtryve TypeSetByHwMode LegalVTS; 1130fa3d789dSPierre van Houtryve 1131fa3d789dSPierre van Houtryve using PatternRewriterFn = std::function<void(TreePattern *)>; 1132fa3d789dSPierre van Houtryve PatternRewriterFn PatternRewriter; 1133fa3d789dSPierre van Houtryve 1134fa3d789dSPierre van Houtryve unsigned NumScopes = 0; 1135fa3d789dSPierre van Houtryve 1136fa3d789dSPierre van Houtryve public: 113787e8b530SRahul Joshi CodeGenDAGPatterns(const RecordKeeper &R, 1138fa3d789dSPierre van Houtryve PatternRewriterFn PatternRewriter = nullptr); 1139fa3d789dSPierre van Houtryve 1140fa3d789dSPierre van Houtryve CodeGenTarget &getTargetInfo() { return Target; } 1141fa3d789dSPierre van Houtryve const CodeGenTarget &getTargetInfo() const { return Target; } 1142fa3d789dSPierre van Houtryve const TypeSetByHwMode &getLegalTypes() const { return LegalVTS; } 1143fa3d789dSPierre van Houtryve 11443138eb50SRahul Joshi const Record *getSDNodeNamed(StringRef Name) const; 1145fa3d789dSPierre van Houtryve 114637865681SRahul Joshi const SDNodeInfo &getSDNodeInfo(const Record *R) const { 1147fa3d789dSPierre van Houtryve auto F = SDNodes.find(R); 1148fa3d789dSPierre van Houtryve assert(F != SDNodes.end() && "Unknown node!"); 1149fa3d789dSPierre van Houtryve return F->second; 1150fa3d789dSPierre van Houtryve } 1151fa3d789dSPierre van Houtryve 1152fa3d789dSPierre van Houtryve // Node transformation lookups. 115337865681SRahul Joshi const NodeXForm &getSDNodeTransform(const Record *R) const { 1154fa3d789dSPierre van Houtryve auto F = SDNodeXForms.find(R); 1155fa3d789dSPierre van Houtryve assert(F != SDNodeXForms.end() && "Invalid transform!"); 1156fa3d789dSPierre van Houtryve return F->second; 1157fa3d789dSPierre van Houtryve } 1158fa3d789dSPierre van Houtryve 115937865681SRahul Joshi const ComplexPattern &getComplexPattern(const Record *R) const { 1160fa3d789dSPierre van Houtryve auto F = ComplexPatterns.find(R); 1161fa3d789dSPierre van Houtryve assert(F != ComplexPatterns.end() && "Unknown addressing mode!"); 1162fa3d789dSPierre van Houtryve return F->second; 1163fa3d789dSPierre van Houtryve } 1164fa3d789dSPierre van Houtryve 116537865681SRahul Joshi const CodeGenIntrinsic &getIntrinsic(const Record *R) const { 1166fa3d789dSPierre van Houtryve for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i) 1167fa3d789dSPierre van Houtryve if (Intrinsics[i].TheDef == R) 1168fa3d789dSPierre van Houtryve return Intrinsics[i]; 1169fa3d789dSPierre van Houtryve llvm_unreachable("Unknown intrinsic!"); 1170fa3d789dSPierre van Houtryve } 1171fa3d789dSPierre van Houtryve 1172fa3d789dSPierre van Houtryve const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const { 1173fa3d789dSPierre van Houtryve if (IID - 1 < Intrinsics.size()) 1174fa3d789dSPierre van Houtryve return Intrinsics[IID - 1]; 1175fa3d789dSPierre van Houtryve llvm_unreachable("Bad intrinsic ID!"); 1176fa3d789dSPierre van Houtryve } 1177fa3d789dSPierre van Houtryve 11783138eb50SRahul Joshi unsigned getIntrinsicID(const Record *R) const { 1179fa3d789dSPierre van Houtryve for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i) 1180fa3d789dSPierre van Houtryve if (Intrinsics[i].TheDef == R) 1181fa3d789dSPierre van Houtryve return i; 1182fa3d789dSPierre van Houtryve llvm_unreachable("Unknown intrinsic!"); 1183fa3d789dSPierre van Houtryve } 1184fa3d789dSPierre van Houtryve 1185bdf02249SRahul Joshi const DAGDefaultOperand &getDefaultOperand(const Record *R) const { 1186fa3d789dSPierre van Houtryve auto F = DefaultOperands.find(R); 1187fa3d789dSPierre van Houtryve assert(F != DefaultOperands.end() && "Isn't an analyzed default operand!"); 1188fa3d789dSPierre van Houtryve return F->second; 1189fa3d789dSPierre van Houtryve } 1190fa3d789dSPierre van Houtryve 1191fa3d789dSPierre van Houtryve // Pattern Fragment information. 119237865681SRahul Joshi TreePattern *getPatternFragment(const Record *R) const { 1193fa3d789dSPierre van Houtryve auto F = PatternFragments.find(R); 1194fa3d789dSPierre van Houtryve assert(F != PatternFragments.end() && "Invalid pattern fragment request!"); 1195fa3d789dSPierre van Houtryve return F->second.get(); 1196fa3d789dSPierre van Houtryve } 119737865681SRahul Joshi TreePattern *getPatternFragmentIfRead(const Record *R) const { 1198fa3d789dSPierre van Houtryve auto F = PatternFragments.find(R); 1199fa3d789dSPierre van Houtryve if (F == PatternFragments.end()) 1200fa3d789dSPierre van Houtryve return nullptr; 1201fa3d789dSPierre van Houtryve return F->second.get(); 1202fa3d789dSPierre van Houtryve } 1203fa3d789dSPierre van Houtryve 120437865681SRahul Joshi using pf_iterator = decltype(PatternFragments)::const_iterator; 1205fa3d789dSPierre van Houtryve pf_iterator pf_begin() const { return PatternFragments.begin(); } 1206fa3d789dSPierre van Houtryve pf_iterator pf_end() const { return PatternFragments.end(); } 1207fa3d789dSPierre van Houtryve iterator_range<pf_iterator> ptfs() const { return PatternFragments; } 1208fa3d789dSPierre van Houtryve 1209fa3d789dSPierre van Houtryve // Patterns to match information. 1210fa3d789dSPierre van Houtryve typedef std::vector<PatternToMatch>::const_iterator ptm_iterator; 1211fa3d789dSPierre van Houtryve ptm_iterator ptm_begin() const { return PatternsToMatch.begin(); } 1212fa3d789dSPierre van Houtryve ptm_iterator ptm_end() const { return PatternsToMatch.end(); } 1213fa3d789dSPierre van Houtryve iterator_range<ptm_iterator> ptms() const { return PatternsToMatch; } 1214fa3d789dSPierre van Houtryve 1215fa3d789dSPierre van Houtryve /// Parse the Pattern for an instruction, and insert the result in DAGInsts. 121637865681SRahul Joshi typedef std::map<const Record *, DAGInstruction, LessRecordByID> DAGInstMap; 12173138eb50SRahul Joshi void parseInstructionPattern(CodeGenInstruction &CGI, const ListInit *Pattern, 1218fa3d789dSPierre van Houtryve DAGInstMap &DAGInsts); 1219fa3d789dSPierre van Houtryve 122037865681SRahul Joshi const DAGInstruction &getInstruction(const Record *R) const { 1221fa3d789dSPierre van Houtryve auto F = Instructions.find(R); 1222fa3d789dSPierre van Houtryve assert(F != Instructions.end() && "Unknown instruction!"); 1223fa3d789dSPierre van Houtryve return F->second; 1224fa3d789dSPierre van Houtryve } 1225fa3d789dSPierre van Houtryve 12263138eb50SRahul Joshi const Record *get_intrinsic_void_sdnode() const { 12273138eb50SRahul Joshi return intrinsic_void_sdnode; 12283138eb50SRahul Joshi } 12293138eb50SRahul Joshi const Record *get_intrinsic_w_chain_sdnode() const { 1230fa3d789dSPierre van Houtryve return intrinsic_w_chain_sdnode; 1231fa3d789dSPierre van Houtryve } 12323138eb50SRahul Joshi const Record *get_intrinsic_wo_chain_sdnode() const { 1233fa3d789dSPierre van Houtryve return intrinsic_wo_chain_sdnode; 1234fa3d789dSPierre van Houtryve } 1235fa3d789dSPierre van Houtryve 1236fa3d789dSPierre van Houtryve unsigned allocateScope() { return ++NumScopes; } 1237fa3d789dSPierre van Houtryve 1238bdf02249SRahul Joshi bool operandHasDefault(const Record *Op) const { 1239fa3d789dSPierre van Houtryve return Op->isSubClassOf("OperandWithDefaultOps") && 1240fa3d789dSPierre van Houtryve !getDefaultOperand(Op).DefaultOps.empty(); 1241fa3d789dSPierre van Houtryve } 1242fa3d789dSPierre van Houtryve 1243fa3d789dSPierre van Houtryve private: 1244fa3d789dSPierre van Houtryve void ParseNodeInfo(); 1245fa3d789dSPierre van Houtryve void ParseNodeTransforms(); 1246fa3d789dSPierre van Houtryve void ParseComplexPatterns(); 1247fa3d789dSPierre van Houtryve void ParsePatternFragments(bool OutFrags = false); 1248fa3d789dSPierre van Houtryve void ParseDefaultOperands(); 1249fa3d789dSPierre van Houtryve void ParseInstructions(); 1250fa3d789dSPierre van Houtryve void ParsePatterns(); 1251fa3d789dSPierre van Houtryve void ExpandHwModeBasedTypes(); 1252fa3d789dSPierre van Houtryve void InferInstructionFlags(); 1253fa3d789dSPierre van Houtryve void GenerateVariants(); 1254fa3d789dSPierre van Houtryve void VerifyInstructionFlags(); 1255fa3d789dSPierre van Houtryve 125637865681SRahul Joshi void ParseOnePattern(const Record *TheDef, TreePattern &Pattern, 1257fa3d789dSPierre van Houtryve TreePattern &Result, 12583138eb50SRahul Joshi ArrayRef<const Record *> InstImpResults, 1259eae7554dSjofrn bool ShouldIgnore = false); 1260fa3d789dSPierre van Houtryve void AddPatternToMatch(TreePattern *Pattern, PatternToMatch &&PTM); 1261fa3d789dSPierre van Houtryve void FindPatternInputsAndOutputs( 1262fa3d789dSPierre van Houtryve TreePattern &I, TreePatternNodePtr Pat, 1263fa3d789dSPierre van Houtryve std::map<std::string, TreePatternNodePtr> &InstInputs, 1264fa3d789dSPierre van Houtryve MapVector<std::string, TreePatternNodePtr, 1265fa3d789dSPierre van Houtryve std::map<std::string, unsigned>> &InstResults, 12663138eb50SRahul Joshi std::vector<const Record *> &InstImpResults); 126787e8b530SRahul Joshi unsigned getNewUID(); 1268fa3d789dSPierre van Houtryve }; 1269fa3d789dSPierre van Houtryve 1270fa3d789dSPierre van Houtryve inline bool SDNodeInfo::ApplyTypeConstraints(TreePatternNode &N, 1271fa3d789dSPierre van Houtryve TreePattern &TP) const { 1272fa3d789dSPierre van Houtryve bool MadeChange = false; 1273fa3d789dSPierre van Houtryve for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) 1274fa3d789dSPierre van Houtryve MadeChange |= TypeConstraints[i].ApplyTypeConstraint(N, *this, TP); 1275fa3d789dSPierre van Houtryve return MadeChange; 1276fa3d789dSPierre van Houtryve } 1277fa3d789dSPierre van Houtryve 1278fa3d789dSPierre van Houtryve } // end namespace llvm 1279fa3d789dSPierre van Houtryve 12808a61bfcfSRahul Joshi #endif // LLVM_UTILS_TABLEGEN_COMMON_CODEGENDAGPATTERNS_H 1281