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