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