xref: /llvm-project/llvm/utils/TableGen/Common/CodeGenDAGPatterns.h (revision 6aeffcdb913052e43335130e129e36babaa9b252)
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