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