• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//===-- OpBase.td - Base op definition file ----------------*- tablegen -*-===//
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 is the base operation definition file.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef OP_BASE
14#define OP_BASE
15
16//===----------------------------------------------------------------------===//
17// Common utilities for defining TableGen mechanisms
18//===----------------------------------------------------------------------===//
19
20// A workaround for the inability to define functions in Tablegen.
21//
22// The template parameter defines a string that can be extracted from an
23// instance of this class by accessing the "result" member. Subclasses can take
24// their own template parameters as function "arguments" and use them to
25// populate result.
26// For example, if it didn't already exist, a concat function could be defined
27// like:
28//
29// class StrConcat<list<string> strings> :
30//     StrFunc<!foldl("", strings, prev, cur, prev # cur)>
31//
32// and then called like
33//
34// StrConcat<["a", "b", "c"]>.result
35//
36// to get the string "abc"
37class StrFunc<string r> {
38  string result = r;
39}
40
41// TODO: Use !interleave() directly rather than through StrJoin/StrJoinInt.
42
43// Concatenates a list of strings with a separator (default ", ")
44class StrJoin<list<string> strings, string sep = ", "> :
45    StrFunc<!interleave(strings, sep)>;
46
47// Concatenates a list of integers into a string with a separator (default ", ")
48class StrJoinInt<list<int> integers, string sep = ", "> :
49    StrFunc<!interleave(integers, sep)>;
50
51//===----------------------------------------------------------------------===//
52// Predicate definitions
53//===----------------------------------------------------------------------===//
54
55// Base class for logical predicates.
56//
57// Predicates are used to compose constraints (see next section for details).
58// There are two categories of predicates:
59//
60// 1. CPred: the primitive leaf predicate.
61// 2. Compound predicate: a predicate composed from child predicates using
62//    predicate combiners ("conjunction", "disjunction", "negation" or
63//    "substitution").
64class Pred;
65
66// A logical predicate wrapping any C expression.
67//
68// This is the basis for composing more complex predicates. It is the "atom"
69// predicate from the perspective of TableGen and the "interface" between
70// TableGen and C++. What is inside is already C++ code, which will be treated
71// as opaque strings with special placeholders to be substituted.
72//
73// ## Special placeholders
74//
75// Special placeholders can be used to refer to entities in the context where
76// this predicate is used. They serve as "hooks" to the enclosing environment.
77// The following special placeholders are supported in constraints for an op:
78//
79// * `$_builder` will be replaced by a mlir::Builder instance.
80// * `$_op` will be replaced by the current operation.
81// * `$_self` will be replaced with the entity this predicate is attached to.
82//   E.g., `BoolAttr` is an attribute constraint that wraps a
83//   `CPred<"$_self.isa<BoolAttr>()">` (see the following sections for details).
84//   Then for `F32:$attr`,`$_self` will be replaced by `$attr`.
85//   For type constraints, it's a little bit special since we want the
86//   constraints on each type definition reads naturally and we want to attach
87//   type constraints directly to an operand/result, $_self will be replaced
88//   by the operand/result's type. E.g., for `F32` in `F32:$operand`, its
89//   `$_self` will be expanded as `getOperand(...).getType()`.
90class CPred<code pred> : Pred {
91  code predExpr = "(" # pred # ")";
92}
93
94// Kinds of predicate combiners.  These must closely match the predicates
95// implemented by the C++ backend (tblgen::PredCombinerKind).
96class PredCombinerKind;
97def PredCombinerAnd : PredCombinerKind;
98def PredCombinerOr : PredCombinerKind;
99def PredCombinerNot : PredCombinerKind;
100def PredCombinerSubstLeaves : PredCombinerKind;
101def PredCombinerConcat : PredCombinerKind;
102
103// A predicate that combines other predicates as defined by PredCombinerKind.
104// Instantiated below.
105class CombinedPred<PredCombinerKind k, list<Pred> c> : Pred {
106  PredCombinerKind kind = k;
107  list<Pred> children = c;
108}
109
110// Predicate combiners
111
112// A predicate that holds if all of its children hold.  Always holds for zero
113// children.
114class And<list<Pred> children> : CombinedPred<PredCombinerAnd, children>;
115
116// A predicate that holds if any of its children hold.  Never holds for zero
117// children.
118class Or<list<Pred> children> : CombinedPred<PredCombinerOr, children>;
119
120// A predicate that holds if its child does not.
121class Neg<Pred child> : CombinedPred<PredCombinerNot, [child]>;
122
123// A predicate that substitutes "pat" with "repl" in predicate calls of the
124// leaves of the predicate tree (i.e., not CombinedPred).
125//
126// This is plain string substitution without regular expressions or captures.
127// New predicates with more complex logical can be introduced should the need
128// arise.
129class SubstLeaves<string pat, string repl, Pred child>
130    : CombinedPred<PredCombinerSubstLeaves, [child]> {
131  string pattern = pat;
132  string replacement = repl;
133}
134
135// A predicate that prepends `pre` and appends `suf` to the final predicate
136// string composed from `child`. This is plain string concatenation and there
137// will be no substitution happening for `pre` and `suf`.
138class Concat<string pre, Pred child, string suf> :
139    CombinedPred<PredCombinerConcat, [child]> {
140  string prefix = pre;
141  string suffix = suf;
142}
143
144//===----------------------------------------------------------------------===//
145// Constraint definitions
146//===----------------------------------------------------------------------===//
147
148// TODO: Merge Constraints into Pred.
149
150// Base class for named constraints.
151//
152// An op's operands/attributes/results can have various requirements, e.g.,
153// having certain types, having values inside a certain range, and so on.
154// Besides, for a graph rewrite rule, the source pattern used to match against
155// the existing graph has conditions, like the op's operand must be of a more
156// constrained subtype, the attribute must have a certain value, and so on.
157//
158// These requirements and conditions are modeled using this class. Records of
159// this class are used to generate verification code in op verifier, and
160// matching code in pattern matcher.
161//
162// Constraints are predicates with descriptive names, to facilitate inspection,
163// provide nice error messages, etc.
164class Constraint<Pred pred, string desc = ""> {
165  // The predicates that this constraint requires.
166  Pred predicate = pred;
167  // User-readable description used in error reporting messages. If empty, a
168  // generic message will be used.
169  string description = desc;
170}
171
172// Subclasses used to differentiate different constraint kinds. These are used
173// as markers for the TableGen backend to handle different constraint kinds
174// differently if needed. Constraints not deriving from the following subclasses
175// are considered as uncategorized constraints.
176
177// Subclass for constraints on a type.
178class TypeConstraint<Pred predicate, string description = ""> :
179    Constraint<predicate, description>;
180
181// Subclass for constraints on an attribute.
182class AttrConstraint<Pred predicate, string description = ""> :
183    Constraint<predicate, description>;
184
185// Subclass for constraints on a region.
186class RegionConstraint<Pred predicate, string description = ""> :
187    Constraint<predicate, description>;
188
189// Subclass for constraints on a successor.
190class SuccessorConstraint<Pred predicate, string description = ""> :
191    Constraint<predicate, description>;
192
193// How to use these constraint categories:
194//
195// * Use TypeConstraint to specify
196//   * Constraints on an op's operand/result definition
197//   * Further constraints to match an op's operand/result in source pattern
198//
199// * Use Attr (a subclass for AttrConstraint) for
200//   * Constraints on an op's attribute definition
201// * Use AttrConstraint to specify
202//   * Further constraints to match an op's attribute in source pattern
203//
204// * Use uncategorized constraint to specify
205//   * Multi-entity constraints in rewrite rules
206
207//===----------------------------------------------------------------------===//
208// Common predicates
209//===----------------------------------------------------------------------===//
210
211// Whether a type is a VectorType.
212def IsVectorTypePred : CPred<"$_self.isa<::mlir::VectorType>()">;
213
214// Whether a type is a TensorType.
215def IsTensorTypePred : CPred<"$_self.isa<::mlir::TensorType>()">;
216
217// Whether a type is a MemRefType.
218def IsMemRefTypePred : CPred<"$_self.isa<::mlir::MemRefType>()">;
219
220// Whether a type is an  IsUnrankedMemRefType
221def IsUnrankedMemRefTypePred
222        : CPred<"$_self.isa<::mlir::UnrankedMemRefType>()">;
223
224// Whether a type is a ShapedType.
225def IsShapedTypePred : CPred<"$_self.isa<::mlir::ShapedType>()">;
226
227// For a ShapedType, verify that it has a static shape.
228def HasStaticShapePred :
229        CPred<"$_self.cast<::mlir::ShapedType>().hasStaticShape()">;
230
231// Whether a type is a TupleType.
232def IsTupleTypePred : CPred<"$_self.isa<::mlir::TupleType>()">;
233
234//===----------------------------------------------------------------------===//
235// Dialect definitions
236//===----------------------------------------------------------------------===//
237
238class Dialect {
239  // The name of the dialect.
240  string name = ?;
241
242  // Short summary of the dialect.
243  string summary = ?;
244
245  // The description of the dialect.
246  string description = ?;
247
248  // A list of dialects this dialect will load on construction as dependencies.
249  // These are dialects that this dialect may involved in canonicalization
250  // pattern or interfaces.
251  list<string> dependentDialects = [];
252
253  // The C++ namespace that ops of this dialect should be placed into.
254  //
255  // By default, uses the name of the dialect as the only namespace. To avoid
256  // placing in any namespace, use "". To specify nested namespaces, use "::"
257  // as the delimiter, e.g., given "A::B", ops will be placed in
258  // `namespace A { namespace B { <ops> } }`.
259  //
260  // Note that this works in conjunction with dialect C++ code. Depending on how
261  // the generated files are included into the dialect, you may want to specify
262  // a full namespace path or a partial one.
263  string cppNamespace = name;
264
265  // An optional code block containing extra declarations to place in the
266  // dialect declaration.
267  code extraClassDeclaration = "";
268
269  // If this dialect overrides the hook for materializing constants.
270  bit hasConstantMaterializer = 0;
271
272  // If this dialect overrides the hook for verifying operation attributes.
273  bit hasOperationAttrVerify = 0;
274
275  // If this dialect overrides the hook for verifying region argument
276  // attributes.
277  bit hasRegionArgAttrVerify = 0;
278
279  // If this dialect overrides the hook for verifying region result attributes.
280  bit hasRegionResultAttrVerify = 0;
281}
282
283//===----------------------------------------------------------------------===//
284// Type definitions
285//===----------------------------------------------------------------------===//
286
287// A type, carries type constraints.
288class Type<Pred condition, string descr = ""> :
289    TypeConstraint<condition, descr> {
290  string typeDescription = "";
291  string builderCall = "";
292}
293
294// Allows providing an alternative name and description to an existing type def.
295class TypeAlias<Type t, string description = t.description> :
296    Type<t.predicate, description> {
297  let typeDescription = t.typeDescription;
298  let builderCall = t.builderCall;
299}
300
301// A type of a specific dialect.
302class DialectType<Dialect d, Pred condition, string descr = ""> :
303    Type<condition, descr> {
304  Dialect dialect = d;
305}
306
307// A variadic type constraint. It expands to zero or more of the base type. This
308// class is used for supporting variadic operands/results.
309class Variadic<Type type> : TypeConstraint<type.predicate, type.description> {
310  Type baseType = type;
311}
312
313// An optional type constraint. It expands to either zero or one of the base
314// type. This class is used for supporting optional operands/results.
315class Optional<Type type> : TypeConstraint<type.predicate, type.description> {
316  Type baseType = type;
317}
318
319// A type that can be constructed using MLIR::Builder.
320// Note that this does not "inherit" from Type because it would require
321// duplicating Type subclasses for buildable and non-buildable cases to avoid
322// diamond "inheritance".
323// TODO: we may extend this to a more general 'Buildable' trait, making some
324// Types and some Attrs buildable.
325class BuildableType<code builder> {
326  // The builder call to invoke (if specified) to construct the BuildableType.
327  code builderCall = builder;
328}
329
330// Any type at all.
331def AnyType : Type<CPred<"true">, "any type">;
332
333// None type
334def NoneType : Type<CPred<"$_self.isa<::mlir::NoneType>()">, "none type">,
335      BuildableType<"$_builder.getType<::mlir::NoneType>()">;
336
337// Any type from the given list
338class AnyTypeOf<list<Type> allowedTypes, string description = ""> : Type<
339    // Satisfy any of the allowed type's condition
340    Or<!foreach(allowedtype, allowedTypes, allowedtype.predicate)>,
341    !if(!eq(description, ""),
342        StrJoin<!foreach(t, allowedTypes, t.description), " or ">.result,
343        description)>;
344
345// Integer types.
346
347// Any integer type irrespective of its width and signedness semantics.
348def AnyInteger : Type<CPred<"$_self.isa<::mlir::IntegerType>()">, "integer">;
349
350// Any integer type (regardless of signedness semantics) of a specific width.
351class AnyI<int width>
352    : Type<CPred<"$_self.isInteger(" # width # ")">, width # "-bit integer"> {
353  int bitwidth = width;
354}
355
356class AnyIntOfWidths<list<int> widths> :
357    AnyTypeOf<!foreach(w, widths, AnyI<w>),
358              StrJoinInt<widths, "/">.result # "-bit integer">;
359
360def AnyI1  : AnyI<1>;
361def AnyI8  : AnyI<8>;
362def AnyI16 : AnyI<16>;
363def AnyI32 : AnyI<32>;
364def AnyI64 : AnyI<64>;
365
366// Any signless integer type irrespective of its width.
367def AnySignlessInteger : Type<
368  CPred<"$_self.isSignlessInteger()">, "signless integer">;
369
370// Signless integer type of a specific width.
371class I<int width>
372    : Type<CPred<"$_self.isSignlessInteger(" # width # ")">,
373                  width # "-bit signless integer">,
374      BuildableType<"$_builder.getIntegerType(" # width # ")"> {
375  int bitwidth = width;
376}
377
378class SignlessIntOfWidths<list<int> widths> :
379    AnyTypeOf<!foreach(w, widths, I<w>),
380              StrJoinInt<widths, "/">.result # "-bit signless integer">;
381
382def I1  : I<1>;
383def I8  : I<8>;
384def I16 : I<16>;
385def I32 : I<32>;
386def I64 : I<64>;
387
388// Any signed integer type irrespective of its width.
389def AnySignedInteger : Type<
390  CPred<"$_self.isSignedInteger()">, "signed integer">;
391
392// Signed integer type of a specific width.
393class SI<int width>
394    : Type<CPred<"$_self.isSignedInteger(" # width # ")">,
395                  width # "-bit signed integer">,
396      BuildableType<
397        "$_builder.getIntegerType(" # width # ", /*isSigned=*/true)"> {
398  int bitwidth = width;
399}
400
401class SignedIntOfWidths<list<int> widths> :
402    AnyTypeOf<!foreach(w, widths, SI<w>),
403              StrJoinInt<widths, "/">.result # "-bit signed integer">;
404
405def SI1  : SI<1>;
406def SI8  : SI<8>;
407def SI16 : SI<16>;
408def SI32 : SI<32>;
409def SI64 : SI<64>;
410
411// Any unsigned integer type irrespective of its width.
412def AnyUnsignedInteger : Type<
413  CPred<"$_self.isUnsignedInteger()">, "unsigned integer">;
414
415// Unsigned integer type of a specific width.
416class UI<int width>
417    : Type<CPred<"$_self.isUnsignedInteger(" # width # ")">,
418                  width # "-bit unsigned integer">,
419      BuildableType<
420        "$_builder.getIntegerType(" # width # ", /*isSigned=*/false)"> {
421  int bitwidth = width;
422}
423
424class UnsignedIntOfWidths<list<int> widths> :
425    AnyTypeOf<!foreach(w, widths, UI<w>),
426              StrJoinInt<widths, "/">.result # "-bit unsigned integer">;
427
428def UI1  : UI<1>;
429def UI8  : UI<8>;
430def UI16 : UI<16>;
431def UI32 : UI<32>;
432def UI64 : UI<64>;
433
434// Index type.
435def Index : Type<CPred<"$_self.isa<::mlir::IndexType>()">, "index">,
436            BuildableType<"$_builder.getIndexType()">;
437
438// Floating point types.
439
440// Any float type irrespective of its width.
441def AnyFloat : Type<CPred<"$_self.isa<::mlir::FloatType>()">, "floating-point">;
442
443// Float type of a specific width.
444class F<int width>
445    : Type<CPred<"$_self.isF" # width # "()">,
446                width # "-bit float">,
447      BuildableType<"$_builder.getF" # width # "Type()"> {
448  int bitwidth = width;
449}
450
451class FloatOfWidths<list<int> widths> :
452    AnyTypeOf<!foreach(w, widths, F<w>),
453              StrJoinInt<widths, "/">.result # "-bit float">;
454
455def F16 : F<16>;
456def F32 : F<32>;
457def F64 : F<64>;
458
459def BF16 : Type<CPred<"$_self.isBF16()">, "bfloat16 type">,
460           BuildableType<"$_builder.getBF16Type()">;
461
462class Complex<Type type>
463    : Type<And<[
464          CPred<"$_self.isa<::mlir::ComplexType>()">,
465          SubstLeaves<"$_self",
466                      "$_self.cast<::mlir::ComplexType>().getElementType()",
467           type.predicate>]>,
468           "complex type with " # type.description # " elements"> {
469  Type elementType = type;
470}
471
472def AnyComplex : Type<CPred<"$_self.isa<::mlir::ComplexType>()">,
473                            "complex-type">;
474
475class OpaqueType<string dialect, string name, string description>
476  : Type<CPred<"isOpaqueTypeWithName($_self, \""#dialect#"\", \""#name#"\")">,
477         description>,
478    BuildableType<"::mlir::OpaqueType::get($_builder.getIdentifier(\""
479                  # dialect # "\"), \"" # name # "\", $_builder.getContext())">;
480
481// Function Type
482
483// Any function type.
484def FunctionType : Type<CPred<"$_self.isa<::mlir::FunctionType>()">,
485                              "function type">;
486
487// A container type is a type that has another type embedded within it.
488class ContainerType<Type etype, Pred containerPred, code elementTypeCall,
489                    string descr> :
490    // First, check the container predicate.  Then, substitute the extracted
491    // element into the element type checker.
492    Type<And<[containerPred,
493                SubstLeaves<"$_self", !cast<string>(elementTypeCall),
494                etype.predicate>]>,
495         descr # " of " # etype.description # " values"> {
496  // The type of elements in the container.
497  Type elementType = etype;
498
499  // Call to retrieve.
500  code getElementTypeCall = elementTypeCall;
501}
502
503class ShapedContainerType<list<Type> allowedTypes,
504                          Pred containerPred, string descr> :
505    ContainerType<AnyTypeOf<allowedTypes>, containerPred,
506                  "$_self.cast<::mlir::ShapedType>().getElementType()", descr>;
507
508// Whether a shaped type is ranked.
509def HasRankPred : CPred<"$_self.cast<::mlir::ShapedType>().hasRank()">;
510
511// Whether a shaped type has one of the specified ranks.
512class HasAnyRankOfPred<list<int> ranks> : And<[
513    HasRankPred,
514    Or<!foreach(rank, ranks,
515                CPred<[{$_self.cast<::mlir::ShapedType>().getRank()
516                         == }]
517                      # rank>)>]>;
518
519// Vector types.
520
521class VectorOf<list<Type> allowedTypes> :
522  ShapedContainerType<allowedTypes, IsVectorTypePred, "vector">;
523
524// Whether the number of elements of a vector is from the given
525// `allowedRanks` list
526class IsVectorOfRankPred<list<int> allowedRanks> :
527  And<[IsVectorTypePred,
528       Or<!foreach(allowedlength, allowedRanks,
529                   CPred<[{$_self.cast<::mlir::VectorType>().getRank()
530                           == }]
531                         # allowedlength>)>]>;
532
533// Any vector where the rank is from the given `allowedRanks` list
534class VectorOfRank<list<int> allowedRanks> : Type<
535  IsVectorOfRankPred<allowedRanks>,
536  " of ranks " # StrJoinInt<allowedRanks, "/">.result>;
537
538// Any vector where the rank is from the given `allowedRanks` list and the type
539// is from the given `allowedTypes` list
540class VectorOfRankAndType<list<int> allowedRanks,
541                          list<Type> allowedTypes> : Type<
542  And<[VectorOf<allowedTypes>.predicate,
543       VectorOfRank<allowedRanks>.predicate]>,
544  VectorOf<allowedTypes>.description #
545  VectorOfRank<allowedRanks>.description>;
546
547// Whether the number of elements of a vector is from the given
548// `allowedLengths` list
549class IsVectorOfLengthPred<list<int> allowedLengths> :
550  And<[IsVectorTypePred,
551       Or<!foreach(allowedlength, allowedLengths,
552                   CPred<[{$_self.cast<::mlir::VectorType>().getNumElements()
553                           == }]
554                         # allowedlength>)>]>;
555
556// Any vector where the number of elements is from the given
557// `allowedLengths` list
558class VectorOfLength<list<int> allowedLengths> : Type<
559  IsVectorOfLengthPred<allowedLengths>,
560  " of length " # StrJoinInt<allowedLengths, "/">.result>;
561
562
563// Any vector where the number of elements is from the given
564// `allowedLengths` list and the type is from the given `allowedTypes`
565// list
566class VectorOfLengthAndType<list<int> allowedLengths,
567                            list<Type> allowedTypes> : Type<
568  And<[VectorOf<allowedTypes>.predicate,
569       VectorOfLength<allowedLengths>.predicate]>,
570  VectorOf<allowedTypes>.description #
571  VectorOfLength<allowedLengths>.description>;
572
573def AnyVector : VectorOf<[AnyType]>;
574
575// Shaped types.
576
577def AnyShaped: ShapedContainerType<[AnyType], IsShapedTypePred, "shaped">;
578
579// Tensor types.
580
581// Any tensor type whose element type is from the given `allowedTypes` list
582class TensorOf<list<Type> allowedTypes> :
583  ShapedContainerType<allowedTypes, IsTensorTypePred, "tensor">;
584
585def AnyTensor : TensorOf<[AnyType]>;
586
587def AnyRankedTensor :
588  ShapedContainerType<[AnyType], And<[IsTensorTypePred, HasRankPred]>,
589  "ranked tensor">;
590
591// TODO: Have an easy way to add another constraint to a type.
592class StaticShapeTensorOf<list<Type> allowedTypes>
593    : Type<And<[TensorOf<allowedTypes>.predicate, HasStaticShapePred]>,
594           "statically shaped " # TensorOf<allowedTypes>.description>;
595
596def AnyStaticShapeTensor : StaticShapeTensorOf<[AnyType]>;
597
598def I1Tensor   : TensorOf<[I1]>;
599def I8Tensor   : TensorOf<[I8]>;
600def I16Tensor  : TensorOf<[I16]>;
601def I32Tensor  : TensorOf<[I32]>;
602def I64Tensor  : TensorOf<[I64]>;
603def IndexTensor: TensorOf<[Index]>;
604
605def BF16Tensor : TensorOf<[BF16]>;
606def F16Tensor  : TensorOf<[F16]>;
607def F32Tensor  : TensorOf<[F32]>;
608def F64Tensor  : TensorOf<[F64]>;
609
610// Ranked tensor type with one of the specified types and ranks.
611class TensorRankOf<list<Type> allowedTypes, list<int> ranks> :
612    Type<And<[TensorOf<allowedTypes>.predicate, HasAnyRankOfPred<ranks>]>,
613         StrJoin<!foreach(rank, ranks, rank # "D"), "/">.result # " " #
614         TensorOf<allowedTypes>.description>;
615
616class 0DTensorOf<list<Type> allowedTypes> : TensorRankOf<allowedTypes, [0]>;
617class 1DTensorOf<list<Type> allowedTypes> : TensorRankOf<allowedTypes, [1]>;
618class 2DTensorOf<list<Type> allowedTypes> : TensorRankOf<allowedTypes, [2]>;
619class 3DTensorOf<list<Type> allowedTypes> : TensorRankOf<allowedTypes, [3]>;
620class 4DTensorOf<list<Type> allowedTypes> : TensorRankOf<allowedTypes, [4]>;
621
622// Unranked Memref type
623def AnyUnrankedMemRef :
624    ShapedContainerType<[AnyType],
625                        IsUnrankedMemRefTypePred, "unranked.memref">;
626// Memref type.
627
628// Memrefs are blocks of data with fixed type and rank.
629class MemRefOf<list<Type> allowedTypes> :
630    ShapedContainerType<allowedTypes, IsMemRefTypePred, "memref">;
631
632def AnyMemRef : MemRefOf<[AnyType]>;
633
634def AnyRankedOrUnrankedMemRef: AnyTypeOf<[AnyUnrankedMemRef, AnyMemRef]>;
635
636// Memref declarations handle any memref, independent of rank, size, (static or
637// dynamic), layout, or memory space.
638def I1MemRef  : MemRefOf<[I1]>;
639def I8MemRef  : MemRefOf<[I8]>;
640def I16MemRef : MemRefOf<[I16]>;
641def I32MemRef : MemRefOf<[I32]>;
642def I64MemRef : MemRefOf<[I64]>;
643
644def BF16MemRef : MemRefOf<[BF16]>;
645def F16MemRef  : MemRefOf<[F16]>;
646def F32MemRef  : MemRefOf<[F32]>;
647def F64MemRef  : MemRefOf<[F64]>;
648
649// TODO: Have an easy way to add another constraint to a type.
650class MemRefRankOf<list<Type> allowedTypes, list<int> ranks> :
651    Type<And<[MemRefOf<allowedTypes>.predicate, HasAnyRankOfPred<ranks>]>,
652         StrJoin<!foreach(rank, ranks, rank # "D"), "/">.result # " " #
653         MemRefOf<allowedTypes>.description>;
654
655class StaticShapeMemRefOf<list<Type> allowedTypes>
656    : Type<And<[MemRefOf<allowedTypes>.predicate, HasStaticShapePred]>,
657           "statically shaped " # MemRefOf<allowedTypes>.description>;
658
659def AnyStaticShapeMemRef : StaticShapeMemRefOf<[AnyType]>;
660
661// For a MemRefType, verify that it has strides.
662def HasStridesPred : CPred<[{ isStrided($_self.cast<::mlir::MemRefType>()) }]>;
663
664class StridedMemRefOf<list<Type> allowedTypes>
665    : Type<And<[MemRefOf<allowedTypes>.predicate, HasStridesPred]>,
666           "strided " # MemRefOf<allowedTypes>.description>;
667
668def AnyStridedMemRef : StridedMemRefOf<[AnyType]>;
669
670class AnyStridedMemRefOfRank<int rank> :
671  Type<And<[AnyStridedMemRef.predicate,
672            MemRefRankOf<[AnyType], [rank]>.predicate]>,
673       AnyStridedMemRef.description # " of rank " # rank>;
674
675// This represents a generic tuple without any constraints on element type.
676def AnyTuple : Type<IsTupleTypePred, "tuple">;
677
678// A container type that has other types embedded in it, but (unlike
679// ContainerType) can hold elements with a mix of types. Requires a call that
680// produces a list of all elements' types.
681class MixedContainerType<Type etype, Pred containerPred, code elementTypesCall,
682                         string descr> :
683    Type<
684        And<[
685            containerPred,
686            Concat<
687                "::llvm::all_of(" # elementTypesCall # ", [](Type t) { return ",
688                SubstLeaves<"$_self", "t", etype.predicate>,
689                "; })"
690            >
691        ]>,
692        descr # " with any combination of " # etype.description # " values"> {
693  // The type of elements in the container.
694  Type elementType = etype;
695
696  // Call to retrieve.
697  code getElementTypesCall = elementTypesCall;
698}
699
700// A Tuple that holds a mix of elements of the allowed types.
701class TupleOf<list<Type> allowedTypes>
702    : MixedContainerType<AnyTypeOf<allowedTypes>, IsTupleTypePred,
703                         "$_self.cast<::mlir::TupleType>().getTypes()",
704                         "tuple">;
705
706// A Tuple with arbitrary nesting, where all elements are a mix of the allowed
707// types.
708class NestedTupleOf<list<Type> allowedTypes> :
709    MixedContainerType<AnyTypeOf<allowedTypes>, IsTupleTypePred,
710                       "getFlattenedTypes($_self.cast<::mlir::TupleType>())",
711                       "nested tuple">;
712
713//===----------------------------------------------------------------------===//
714// Common type constraints
715//===----------------------------------------------------------------------===//
716
717// Type constraint for bool-like types: bools, vectors of bools, tensors of
718// bools.
719def BoolLike : TypeConstraint<Or<[I1.predicate, VectorOf<[I1]>.predicate,
720                                  TensorOf<[I1]>.predicate]>,
721    "bool-like">;
722
723// Type constraint for signless-integer-like types: signless integers, indices,
724// vectors of signless integers, tensors of signless integers.
725def SignlessIntegerLike : TypeConstraint<Or<[
726        AnySignlessInteger.predicate, Index.predicate,
727        VectorOf<[AnySignlessInteger]>.predicate,
728        TensorOf<[AnySignlessInteger]>.predicate]>,
729    "signless-integer-like">;
730
731// Type constraint for float-like types: floats, vectors or tensors thereof.
732def FloatLike : TypeConstraint<Or<[AnyFloat.predicate,
733        VectorOf<[AnyFloat]>.predicate, TensorOf<[AnyFloat]>.predicate]>,
734    "floating-point-like">;
735
736// Type constraint for signless-integer-like or float-like types.
737def SignlessIntegerOrFloatLike : TypeConstraint<Or<[
738    SignlessIntegerLike.predicate, FloatLike.predicate]>,
739    "signless-integer-like or floating-point-like">;
740
741//===----------------------------------------------------------------------===//
742// Attribute definitions
743//===----------------------------------------------------------------------===//
744
745//===----------------------------------------------------------------------===//
746// Base attribute definition
747
748// Base class for all attributes.
749class Attr<Pred condition, string descr = ""> :
750    AttrConstraint<condition, descr> {
751  code storageType = ?; // The backing mlir::Attribute type
752  code returnType = ?;  // The underlying C++ value type
753
754  // The call expression to convert from the storage type to the return
755  // type. For example, an enum can be stored as an int but returned as an
756  // enum class.
757  //
758  // Format: $_self will be expanded to the attribute.
759  //
760  // For example, `$_self.getValue().getSExtValue()` for `IntegerAttr val` will
761  // expand to `getAttrOfType<IntegerAttr>("val").getValue().getSExtValue()`.
762  code convertFromStorage = "$_self.getValue()";
763
764  // The call expression to build an attribute from a constant value.
765  //
766  // Format: $0 will be expanded to the constant value of the attribute.
767  //
768  // For example, `$_builder.getStringAttr("$0")` for `StringAttr:"foo"` will
769  // expand to `builder.getStringAttr("foo")`.
770  string constBuilderCall = ?;
771
772  // Default value for attribute.
773  // Requires a constBuilderCall defined.
774  string defaultValue = ?;
775
776  // The value type of this attribute. This corresponds to the mlir::Type that
777  // this attribute returns via `getType()`.
778  Type valueType = ?;
779
780  // Whether the attribute is optional. Typically requires a custom
781  // convertFromStorage method to handle the case where the attribute is
782  // not present.
783  bit isOptional = 0;
784
785  // What is the base-level Attr instantiation that this Attr is built upon.
786  // Unset means this is a base-level Attr.
787  //
788  // This field is used by attribute wrapper classes (DefaultValuedAttr,
789  // OptionalAttr, etc.) to retrieve the base-level attribute definition.
790  // This can be used for getting its name; otherwise, we will see
791  // "anonymous_<number>" as the attribute def name because of template
792  // instantiation.
793  // TOOD(b/132458159): deduplicate the fields in attribute wrapper classes.
794  Attr baseAttr = ?;
795
796  // The fully-qualified C++ namespace where the generated class lives.
797  string cppNamespace = "";
798}
799
800// An attribute of a specific dialect.
801class DialectAttr<Dialect d, Pred condition, string descr = ""> :
802    Attr<condition, descr> {
803  Dialect dialect = d;
804  let cppNamespace = d.cppNamespace;
805}
806
807//===----------------------------------------------------------------------===//
808// Attribute modifier definition
809
810// Decorates an attribute to have an (unvalidated) default value if not present.
811class DefaultValuedAttr<Attr attr, string val> :
812    Attr<attr.predicate, attr.description> {
813  // Construct this attribute with the input attribute and change only
814  // the default value.
815  // Note: this has to be kept up to date with Attr above.
816  let storageType = attr.storageType;
817  let returnType = attr.returnType;
818  let convertFromStorage = attr.convertFromStorage;
819  let constBuilderCall = attr.constBuilderCall;
820  let defaultValue = val;
821  let valueType = attr.valueType;
822
823  let baseAttr = attr;
824}
825
826// Decorates an attribute as optional. The return type of the generated
827// attribute accessor method will be Optional<>.
828class OptionalAttr<Attr attr> : Attr<attr.predicate, attr.description> {
829  // Rewrite the attribute to be optional.
830  // Note: this has to be kept up to date with Attr above.
831  let storageType = attr.storageType;
832  let returnType = "::llvm::Optional<" # attr.returnType #">";
833  let convertFromStorage = "$_self ? " # returnType # "(" #
834                           attr.convertFromStorage # ") : (::llvm::None)";
835  let valueType = attr.valueType;
836  let isOptional = 1;
837
838  let baseAttr = attr;
839}
840
841//===----------------------------------------------------------------------===//
842// Primitive attribute kinds
843
844// A generic attribute that must be constructed around a specific buildable type
845// `attrValType`. Backed by MLIR attribute kind `attrKind`.
846class TypedAttrBase<Type attrValType, string attrKind, Pred condition,
847                    string descr> :
848    Attr<condition, descr> {
849  let constBuilderCall = "$_builder.get" # attrKind # "(" #
850                         attrValType.builderCall # ", $0)";
851  let storageType = "::mlir::" # attrKind;
852  let valueType = attrValType;
853}
854
855// Any attribute.
856def AnyAttr : Attr<CPred<"true">, "any attribute"> {
857  let storageType = "::mlir::Attribute";
858  let returnType = "::mlir::Attribute";
859  let convertFromStorage = "$_self";
860  let constBuilderCall = "$0";
861}
862
863def BoolAttr : Attr<CPred<"$_self.isa<::mlir::BoolAttr>()">, "bool attribute"> {
864  let storageType = [{ ::mlir::BoolAttr }];
865  let returnType = [{ bool }];
866  let valueType = I1;
867  let constBuilderCall = "$_builder.getBoolAttr($0)";
868}
869
870// Index attribute.
871def IndexAttr :
872    TypedAttrBase<
873      Index, "IntegerAttr",
874      And<[CPred<"$_self.isa<::mlir::IntegerAttr>()">,
875           CPred<"$_self.cast<::mlir::IntegerAttr>().getType()"
876                 ".isa<::mlir::IndexType>()">]>,
877      "index attribute"> {
878  let returnType = [{ ::llvm::APInt }];
879}
880
881// Base class for any integer (regardless of signedness semantics) attributes
882// of fixed width.
883class AnyIntegerAttrBase<AnyI attrValType, string descr> :
884    TypedAttrBase<
885      attrValType, "IntegerAttr",
886      And<[CPred<"$_self.isa<::mlir::IntegerAttr>()">,
887           CPred<"$_self.cast<::mlir::IntegerAttr>().getType()."
888                 "isInteger(" # attrValType.bitwidth # ")">]>,
889      descr> {
890  let returnType = [{ ::llvm::APInt }];
891  let constBuilderCall = ?;
892}
893
894def AnyI1Attr  : AnyIntegerAttrBase<AnyI1,  "1-bit integer attribute">;
895def AnyI8Attr  : AnyIntegerAttrBase<AnyI8,  "8-bit integer attribute">;
896def AnyI16Attr : AnyIntegerAttrBase<AnyI16, "16-bit integer attribute">;
897def AnyI32Attr : AnyIntegerAttrBase<AnyI32, "32-bit integer attribute">;
898def AnyI64Attr : AnyIntegerAttrBase<AnyI64, "64-bit integer attribute">;
899
900def APIntAttr : Attr<CPred<"$_self.isa<::mlir::IntegerAttr>()">,
901                     "arbitrary integer attribute"> {
902  let storageType = [{ ::mlir::IntegerAttr }];
903  let returnType = [{ ::mlir::APInt }];
904}
905
906// Base class for signless integer attributes of fixed width.
907class SignlessIntegerAttrBase<I attrValType, string descr> :
908    TypedAttrBase<
909      attrValType, "IntegerAttr",
910      And<[CPred<"$_self.isa<::mlir::IntegerAttr>()">,
911           CPred<"$_self.cast<::mlir::IntegerAttr>().getType()."
912                 "isSignlessInteger(" # attrValType.bitwidth # ")">]>,
913      descr> {
914  let returnType = [{ ::llvm::APInt }];
915}
916// Base class for signless integer attributes of fixed width that have a
917// corresponding C++ type.
918class TypedSignlessIntegerAttrBase<I attrValType, string retType, string descr>
919    : SignlessIntegerAttrBase<attrValType, descr> {
920  let returnType = retType;
921  let convertFromStorage = "$_self.getValue().getZExtValue()";
922}
923
924def I1Attr  : TypedSignlessIntegerAttrBase<
925    I1,  "bool",     "1-bit signless integer attribute">;
926def I8Attr  : TypedSignlessIntegerAttrBase<
927    I8,  "uint8_t",  "8-bit signless integer attribute">;
928def I16Attr : TypedSignlessIntegerAttrBase<
929    I16, "uint16_t", "16-bit signless integer attribute">;
930def I32Attr : TypedSignlessIntegerAttrBase<
931    I32, "uint32_t", "32-bit signless integer attribute">;
932def I64Attr : TypedSignlessIntegerAttrBase<
933    I64, "uint64_t", "64-bit signless integer attribute">;
934
935// Base class for signed integer attributes of fixed width.
936class SignedIntegerAttrBase<SI attrValType, string descr> :
937    TypedAttrBase<
938      attrValType, "IntegerAttr",
939      And<[CPred<"$_self.isa<::mlir::IntegerAttr>()">,
940           CPred<"$_self.cast<::mlir::IntegerAttr>().getType()."
941                 "isSignedInteger(" # attrValType.bitwidth # ")">]>,
942      descr> {
943  let returnType = [{ ::llvm::APInt }];
944}
945// Base class for signed integer attributes of fixed width that have a
946// corresponding C++ type.
947class TypedSignedIntegerAttrBase<SI attrValType, string retType, string descr>
948    : SignedIntegerAttrBase<attrValType, descr> {
949  let returnType = retType;
950  let convertFromStorage = "$_self.getValue().getSExtValue()";
951}
952
953def SI1Attr  : TypedSignedIntegerAttrBase<
954    SI1,  "bool",    "1-bit signed integer attribute">;
955def SI8Attr  : TypedSignedIntegerAttrBase<
956    SI8,  "int8_t",  "8-bit signed integer attribute">;
957def SI16Attr : TypedSignedIntegerAttrBase<
958    SI16, "int16_t", "16-bit signed integer attribute">;
959def SI32Attr : TypedSignedIntegerAttrBase<
960    SI32, "int32_t", "32-bit signed integer attribute">;
961def SI64Attr : TypedSignedIntegerAttrBase<
962    SI64, "int64_t", "64-bit signed integer attribute">;
963
964// Base class for unsigned integer attributes of fixed width.
965class UnsignedIntegerAttrBase<UI attrValType, string descr> :
966    TypedAttrBase<
967      attrValType, "IntegerAttr",
968      And<[CPred<"$_self.isa<::mlir::IntegerAttr>()">,
969           CPred<"$_self.cast<::mlir::IntegerAttr>().getType()."
970                 "isUnsignedInteger(" # attrValType.bitwidth # ")">]>,
971      descr> {
972  let returnType = [{ ::llvm::APInt }];
973}
974// Base class for unsigned integer attributes of fixed width that have a
975// corresponding C++ type.
976class TypedUnsignedIntegerAttrBase<UI attrValType, string retType, string descr>
977    : UnsignedIntegerAttrBase<attrValType, descr> {
978  let returnType = retType;
979  let convertFromStorage = "$_self.getValue().getZExtValue()";
980}
981
982def UI1Attr  : TypedUnsignedIntegerAttrBase<
983    UI1,  "bool",     "1-bit unsigned integer attribute">;
984def UI8Attr  : TypedUnsignedIntegerAttrBase<
985    UI8,  "uint8_t",  "8-bit unsigned integer attribute">;
986def UI16Attr : TypedUnsignedIntegerAttrBase<
987    UI16, "uint16_t", "16-bit unsigned integer attribute">;
988def UI32Attr : TypedUnsignedIntegerAttrBase<
989    UI32, "uint32_t", "32-bit unsigned integer attribute">;
990def UI64Attr : TypedUnsignedIntegerAttrBase<
991    UI64, "uint64_t", "64-bit unsigned integer attribute">;
992
993// Base class for float attributes of fixed width.
994class FloatAttrBase<F attrValType, string descr> :
995    TypedAttrBase<attrValType, "FloatAttr",
996              And<[CPred<"$_self.isa<::mlir::FloatAttr>()">,
997                     CPred<"$_self.cast<::mlir::FloatAttr>().getType().isF" #
998                           attrValType.bitwidth # "()">]>,
999              descr> {
1000  let returnType = [{ ::llvm::APFloat }];
1001}
1002
1003def F32Attr : FloatAttrBase<F32, "32-bit float attribute">;
1004def F64Attr : FloatAttrBase<F64, "64-bit float attribute">;
1005
1006// An attribute backed by a string type.
1007class StringBasedAttr<Pred condition, string descr> : Attr<condition, descr> {
1008  let constBuilderCall = "$_builder.getStringAttr(\"$0\")";
1009  let storageType = [{ ::mlir::StringAttr }];
1010  let returnType = [{ ::llvm::StringRef }];
1011  let valueType = NoneType;
1012}
1013
1014def StrAttr : StringBasedAttr<CPred<"$_self.isa<::mlir::StringAttr>()">,
1015                              "string attribute">;
1016
1017// A string attribute that represents the name of a symbol.
1018def SymbolNameAttr : StringBasedAttr<CPred<"$_self.isa<::mlir::StringAttr>()">,
1019                                     "string attribute">;
1020
1021// String attribute that has a specific value type.
1022class TypedStrAttr<Type ty>
1023    : StringBasedAttr<CPred<"$_self.isa<::mlir::StringAttr>()">,
1024                            "string attribute"> {
1025  let valueType = ty;
1026}
1027
1028// Base class for attributes containing types. Example:
1029//   def IntTypeAttr : TypeAttrBase<"IntegerType", "integer type attribute">
1030// defines a type attribute containing an integer type.
1031class TypeAttrBase<string retType, string description> :
1032    Attr<And<[
1033      CPred<"$_self.isa<::mlir::TypeAttr>()">,
1034      CPred<"$_self.cast<::mlir::TypeAttr>().getValue().isa<"
1035            # retType # ">()">]>,
1036    description> {
1037  let storageType = [{ ::mlir::TypeAttr }];
1038  let returnType = retType;
1039  let valueType = NoneType;
1040  let convertFromStorage = "$_self.getValue().cast<" # retType # ">()";
1041}
1042
1043def TypeAttr : TypeAttrBase<"::mlir::Type", "any type attribute">;
1044
1045// The mere presence of unit attributes has a meaning.  Therefore, unit
1046// attributes are always treated as optional and accessors to them return
1047// "true" if the attribute is present and "false" otherwise.
1048def UnitAttr : Attr<CPred<"$_self.isa<::mlir::UnitAttr>()">, "unit attribute"> {
1049  let storageType = [{ ::mlir::UnitAttr }];
1050  let constBuilderCall = "$_builder.getUnitAttr()";
1051  let convertFromStorage = "$_self != nullptr";
1052  let returnType = "bool";
1053  let valueType = NoneType;
1054  let isOptional = 1;
1055}
1056
1057//===----------------------------------------------------------------------===//
1058// Enum attribute kinds
1059
1060// Additional information for an enum attribute case.
1061class EnumAttrCaseInfo<string sym, int intVal, string strVal> {
1062  // The C++ enumerant symbol.
1063  string symbol = sym;
1064
1065  // The C++ enumerant value.
1066  // If less than zero, there will be no explicit discriminator values assigned
1067  // to enumerators in the generated enum class.
1068  int value = intVal;
1069
1070  // The string representation of the enumerant. May be the same as symbol.
1071  string str = strVal;
1072}
1073
1074// An enum attribute case stored with StringAttr.
1075class StrEnumAttrCase<string sym, int val = -1> :
1076    EnumAttrCaseInfo<sym, val, sym>,
1077    StringBasedAttr<
1078      CPred<"$_self.cast<::mlir::StringAttr>().getValue() == \"" # sym # "\"">,
1079      "case " # sym>;
1080
1081// An enum attribute case stored with IntegerAttr, which has an integer value,
1082// its representation as a string and a C++ symbol name which may be different.
1083class IntEnumAttrCaseBase<I intType, string sym, string strVal, int intVal> :
1084    EnumAttrCaseInfo<sym, intVal, strVal>,
1085    SignlessIntegerAttrBase<intType, "case " # strVal> {
1086  let predicate =
1087    CPred<"$_self.cast<::mlir::IntegerAttr>().getInt() == " # intVal>;
1088}
1089
1090// Cases of integer enum attributes with a specific type. By default, the string
1091// representation is the same as the C++ symbol name.
1092class I32EnumAttrCase<string sym, int val, string str = sym>
1093    : IntEnumAttrCaseBase<I32, sym, str, val>;
1094class I64EnumAttrCase<string sym, int val, string str = sym>
1095    : IntEnumAttrCaseBase<I64, sym, str, val>;
1096
1097// A bit enum case stored with 32-bit IntegerAttr. `val` here is *not* the
1098// ordinal number of the bit that is set. It is the 32-bit integer with only
1099// one bit set.
1100class BitEnumAttrCase<string sym, int val> :
1101    EnumAttrCaseInfo<sym, val, sym>,
1102    SignlessIntegerAttrBase<I32, "case " # sym> {
1103  let predicate = CPred<
1104    "$_self.cast<::mlir::IntegerAttr>().getValue().getZExtValue() & "
1105    # val # "u">;
1106}
1107
1108// Additional information for an enum attribute.
1109class EnumAttrInfo<string name, list<EnumAttrCaseInfo> cases> {
1110  // The C++ enum class name
1111  string className = name;
1112
1113  // List of all accepted cases
1114  list<EnumAttrCaseInfo> enumerants = cases;
1115
1116  // The following fields are only used by the EnumsGen backend to generate
1117  // an enum class definition and conversion utility functions.
1118
1119  // The underlying type for the C++ enum class. An empty string mean the
1120  // underlying type is not explicitly specified.
1121  string underlyingType = "";
1122
1123  // The name of the utility function that converts a value of the underlying
1124  // type to the corresponding symbol. It will have the following signature:
1125  //
1126  // ```c++
1127  // llvm::Optional<<qualified-enum-class-name>> <fn-name>(<underlying-type>);
1128  // ```
1129  string underlyingToSymbolFnName = "symbolize" # name;
1130
1131  // The name of the utility function that converts a string to the
1132  // corresponding symbol. It will have the following signature:
1133  //
1134  // ```c++
1135  // llvm::Optional<<qualified-enum-class-name>> <fn-name>(llvm::StringRef);
1136  // ```
1137  string stringToSymbolFnName = "symbolize" # name;
1138
1139  // The name of the utility function that converts a symbol to the
1140  // corresponding string. It will have the following signature:
1141  //
1142  // ```c++
1143  // <return-type> <fn-name>(<qualified-enum-class-name>);
1144  // ```
1145  string symbolToStringFnName = "stringify" # name;
1146  string symbolToStringFnRetType = "::llvm::StringRef";
1147
1148  // The name of the utility function that returns the max enum value used
1149  // within the enum class. It will have the following signature:
1150  //
1151  // ```c++
1152  // static constexpr unsigned <fn-name>();
1153  // ```
1154  string maxEnumValFnName = "getMaxEnumValFor" # name;
1155}
1156
1157// An enum attribute backed by StringAttr.
1158//
1159// Op attributes of this kind are stored as StringAttr. Extra verification will
1160// be generated on the string though: only the symbols of the allowed cases are
1161// permitted as the string value.
1162class StrEnumAttr<string name, string description,
1163                  list<StrEnumAttrCase> cases> :
1164    EnumAttrInfo<name, cases>,
1165    StringBasedAttr<
1166      And<[StrAttr.predicate, Or<!foreach(case, cases, case.predicate)>]>,
1167      !if(!empty(description), "allowed string cases: " #
1168          StrJoin<!foreach(case, cases, "'" # case.symbol # "'")>.result,
1169          description)>;
1170
1171// An enum attribute backed by IntegerAttr.
1172//
1173// Op attributes of this kind are stored as IntegerAttr. Extra verification will
1174// be generated on the integer though: only the values of the allowed cases are
1175// permitted as the integer value.
1176class IntEnumAttr<I intType, string name, string description,
1177                  list<IntEnumAttrCaseBase> cases> :
1178    EnumAttrInfo<name, cases>,
1179    SignlessIntegerAttrBase<intType,
1180      !if(!empty(description), "allowed " # intType.description # " cases: " #
1181          StrJoinInt<!foreach(case, cases, case.value)>.result, description)> {
1182  let predicate = And<[
1183    SignlessIntegerAttrBase<intType, "">.predicate,
1184    Or<!foreach(case, cases, case.predicate)>]>;
1185}
1186
1187class I32EnumAttr<string name, string description,
1188                  list<I32EnumAttrCase> cases> :
1189    IntEnumAttr<I32, name, description, cases> {
1190  let returnType = cppNamespace # "::" # name;
1191  let underlyingType = "uint32_t";
1192  let convertFromStorage = "static_cast<" # returnType # ">($_self.getInt())";
1193  let constBuilderCall =
1194          "$_builder.getI32IntegerAttr(static_cast<int32_t>($0))";
1195}
1196class I64EnumAttr<string name, string description,
1197                  list<I64EnumAttrCase> cases> :
1198    IntEnumAttr<I64, name, description, cases> {
1199  let returnType = cppNamespace # "::" # name;
1200  let underlyingType = "uint64_t";
1201  let convertFromStorage = "static_cast<" # returnType # ">($_self.getInt())";
1202  let constBuilderCall =
1203          "$_builder.getI64IntegerAttr(static_cast<int64_t>($0))";
1204}
1205
1206// A bit enum stored with 32-bit IntegerAttr.
1207//
1208// Op attributes of this kind are stored as IntegerAttr. Extra verification will
1209// be generated on the integer to make sure only allowed bit are set. Besides,
1210// helper methods are generated to parse a string separated with a specified
1211// delimiter to a symbol and vice versa.
1212class BitEnumAttr<string name, string description,
1213                  list<BitEnumAttrCase> cases> :
1214    EnumAttrInfo<name, cases>, SignlessIntegerAttrBase<I32, description> {
1215  let predicate = And<[
1216    I32Attr.predicate,
1217    // Make sure we don't have unknown bit set.
1218    CPred<"!($_self.cast<::mlir::IntegerAttr>().getValue().getZExtValue() & (~("
1219          # StrJoin<!foreach(case, cases, case.value # "u"), "|">.result #
1220          ")))">
1221  ]>;
1222
1223  let returnType = cppNamespace # "::" # name;
1224  let underlyingType = "uint32_t";
1225  let convertFromStorage = "static_cast<" # returnType # ">($_self.getInt())";
1226  let constBuilderCall =
1227          "$_builder.getI32IntegerAttr(static_cast<int32_t>($0))";
1228
1229  // We need to return a string because we may concatenate symbols for multiple
1230  // bits together.
1231  let symbolToStringFnRetType = "std::string";
1232
1233  // The delimiter used to separate bit enum cases in strings.
1234  string separator = "|";
1235}
1236
1237//===----------------------------------------------------------------------===//
1238// Composite attribute kinds
1239
1240class DictionaryAttrBase<Pred condition, string description> :
1241    Attr<condition, description> {
1242  let storageType = [{ ::mlir::DictionaryAttr }];
1243  let returnType = [{ ::mlir::DictionaryAttr }];
1244  let valueType = NoneType;
1245  let convertFromStorage = "$_self";
1246}
1247
1248def DictionaryAttr
1249    : DictionaryAttrBase<CPred<"$_self.isa<::mlir::DictionaryAttr>()">,
1250                               "dictionary of named attribute values">;
1251
1252class ElementsAttrBase<Pred condition, string description> :
1253    Attr<condition, description> {
1254  let storageType = [{ ::mlir::ElementsAttr }];
1255  let returnType = [{ ::mlir::ElementsAttr }];
1256  let convertFromStorage = "$_self";
1257}
1258
1259def ElementsAttr : ElementsAttrBase<CPred<"$_self.isa<::mlir::ElementsAttr>()">,
1260                                    "constant vector/tensor attribute">;
1261
1262class IntElementsAttrBase<Pred condition, string description> :
1263    ElementsAttrBase<And<[CPred<"$_self.isa<::mlir::DenseIntElementsAttr>()">,
1264                          condition]>,
1265                     description> {
1266  let storageType = [{ ::mlir::DenseIntElementsAttr }];
1267  let returnType = [{ ::mlir::DenseIntElementsAttr }];
1268
1269  let convertFromStorage = "$_self";
1270}
1271
1272def IndexElementsAttr
1273    : IntElementsAttrBase<CPred<[{$_self.cast<::mlir::DenseIntElementsAttr>()
1274                                      .getType()
1275                                      .getElementType()
1276                                      .isIndex()}]>,
1277                          "index elements attribute">;
1278
1279class AnyIntElementsAttr<int width> : IntElementsAttrBase<
1280  CPred<"$_self.cast<::mlir::DenseIntElementsAttr>().getType()."
1281        "getElementType().isInteger(" # width # ")">,
1282  width # "-bit integer elements attribute">;
1283
1284def AnyI32ElementsAttr : AnyIntElementsAttr<32>;
1285def AnyI64ElementsAttr : AnyIntElementsAttr<64>;
1286
1287class SignlessIntElementsAttr<int width> : IntElementsAttrBase<
1288  CPred<"$_self.cast<::mlir::DenseIntElementsAttr>().getType()."
1289        "getElementType().isSignlessInteger(" # width # ")">,
1290  width # "-bit signless integer elements attribute"> {
1291
1292  // Note that this is only constructing scalar elements attribute.
1293  let constBuilderCall = "::mlir::DenseElementsAttr::get("
1294    "::mlir::RankedTensorType::get({}, "
1295                                  "$_builder.getIntegerType(" # width # ")), "
1296    "::llvm::makeArrayRef($0)).cast<::mlir::DenseIntElementsAttr>()";
1297}
1298
1299def I32ElementsAttr : SignlessIntElementsAttr<32>;
1300def I64ElementsAttr : SignlessIntElementsAttr<64>;
1301
1302// A `width`-bit signless integer elements attribute. The attribute should be
1303// ranked and has a shape as specified in `dims`.
1304class RankedSignlessIntElementsAttr<int width, list<int> dims> :
1305    SignlessIntElementsAttr<width> {
1306  // Check that this has the specified shape.
1307  let predicate = And<[
1308    SignlessIntElementsAttr<width>.predicate,
1309    CPred<"$_self.cast<::mlir::DenseIntElementsAttr>().getType().getShape() == "
1310        "::mlir::ArrayRef<int64_t>({" # StrJoinInt<dims>.result # "})">]>;
1311
1312  let description = width # "-bit signless int elements attribute of shape [" #
1313                    StrJoinInt<dims>.result # "]";
1314
1315  let constBuilderCall = "::mlir::DenseIntElementsAttr::get("
1316    "::mlir::RankedTensorType::get({" # StrJoinInt<dims>.result #
1317    "}, $_builder.getIntegerType(" # width # ")), ::llvm::makeArrayRef($0))";
1318}
1319
1320class RankedI32ElementsAttr<list<int> dims> :
1321    RankedSignlessIntElementsAttr<32, dims>;
1322class RankedI64ElementsAttr<list<int> dims> :
1323    RankedSignlessIntElementsAttr<64, dims>;
1324
1325class FloatElementsAttr<int width> : ElementsAttrBase<
1326  CPred<"$_self.isa<::mlir::DenseFPElementsAttr>() &&"
1327      "$_self.cast<::mlir::DenseElementsAttr>().getType()."
1328      "getElementType().isF" # width # "()">,
1329  width # "-bit float elements attribute"> {
1330
1331  let storageType = [{ ::mlir::DenseElementsAttr }];
1332  let returnType = [{ ::mlir::DenseElementsAttr }];
1333
1334  // Note that this is only constructing scalar elements attribute.
1335  let constBuilderCall = "::mlir::DenseElementsAttr::get("
1336    "::mlir::RankedTensorType::get({}, $_builder.getF" # width # "Type()),"
1337    "::llvm::makeArrayRef($0))";
1338  let convertFromStorage = "$_self";
1339}
1340
1341def F64ElementsAttr : FloatElementsAttr<64>;
1342
1343// A `width`-bit floating point elements attribute. The attribute should be
1344// ranked and has a shape as specified in `dims`.
1345class RankedFloatElementsAttr<int width, list<int> dims> : ElementsAttrBase<
1346  CPred<"$_self.isa<::mlir::DenseFPElementsAttr>() &&"
1347      "$_self.cast<::mlir::DenseFPElementsAttr>().getType()."
1348      "getElementType().isF" # width # "() && "
1349      // Check that this is ranked and has the specified shape.
1350      "$_self.cast<::mlir::DenseFPElementsAttr>().getType().hasRank() && "
1351      "$_self.cast<::mlir::DenseFPElementsAttr>().getType().getShape() == "
1352      "::mlir::ArrayRef<int64_t>({" # StrJoinInt<dims>.result # "})">,
1353  width # "-bit float elements attribute of shape [" #
1354  StrJoinInt<dims>.result # "]"> {
1355
1356  let storageType = [{ ::mlir::DenseFPElementsAttr }];
1357  let returnType = [{ ::mlir::DenseFPElementsAttr }];
1358
1359  let constBuilderCall = "::mlir::DenseElementsAttr::get("
1360    "::mlir::RankedTensorType::get({" # StrJoinInt<dims>.result #
1361    "}, $_builder.getF" # width # "Type()), "
1362    "::llvm::makeArrayRef($0)).cast<::mlir::DenseFPElementsAttr>()";
1363  let convertFromStorage = "$_self";
1364}
1365
1366class RankedF32ElementsAttr<list<int> dims> : RankedFloatElementsAttr<32, dims>;
1367class RankedF64ElementsAttr<list<int> dims> : RankedFloatElementsAttr<64, dims>;
1368
1369def StringElementsAttr : ElementsAttrBase<
1370  CPred<"$_self.isa<::mlir::DenseStringElementsAttr>()" >,
1371  "string elements attribute"> {
1372
1373  let storageType = [{ ::mlir::DenseElementsAttr }];
1374  let returnType = [{ ::mlir::DenseElementsAttr }];
1375
1376  let convertFromStorage = "$_self";
1377}
1378
1379// Attributes containing affine maps.
1380def AffineMapAttr : Attr<
1381CPred<"$_self.isa<::mlir::AffineMapAttr>()">, "AffineMap attribute"> {
1382  let storageType = [{::mlir::AffineMapAttr }];
1383  let returnType = [{ ::mlir::AffineMap }];
1384  let valueType = Index;
1385  let constBuilderCall = "::mlir::AffineMapAttr::get($0)";
1386}
1387
1388// Base class for array attributes.
1389class ArrayAttrBase<Pred condition, string description> :
1390    Attr<condition, description> {
1391  let storageType = [{ ::mlir::ArrayAttr }];
1392  let returnType = [{ ::mlir::ArrayAttr }];
1393  let valueType = NoneType;
1394  let convertFromStorage = "$_self";
1395}
1396
1397def ArrayAttr : ArrayAttrBase<CPred<"$_self.isa<::mlir::ArrayAttr>()">,
1398                              "array attribute">;
1399
1400// Base class for array attributes whose elements are of the same kind.
1401// `element` specifies the element attribute kind stored in this array.
1402class TypedArrayAttrBase<Attr element, string description>: ArrayAttrBase<
1403    And<[
1404      // Guarantee this is an ArrayAttr first
1405      CPred<"$_self.isa<::mlir::ArrayAttr>()">,
1406      // Guarantee all elements satisfy the constraints from `element`
1407      Concat<"::llvm::all_of($_self.cast<::mlir::ArrayAttr>(), "
1408                            "[](::mlir::Attribute attr) { return ",
1409                               SubstLeaves<"$_self", "attr", element.predicate>,
1410                            "; })">]>,
1411    description> {
1412  let constBuilderCall = "$_builder.getArrayAttr($0)";
1413
1414  Attr elementAttr = element;
1415}
1416
1417def AffineMapArrayAttr : TypedArrayAttrBase<AffineMapAttr,
1418                                      "AffineMap array attribute"> {
1419  let constBuilderCall = "$_builder.getAffineMapArrayAttr($0)";
1420}
1421
1422def BoolArrayAttr : TypedArrayAttrBase<BoolAttr,
1423                                      "1-bit boolean array attribute"> {
1424  let constBuilderCall = "$_builder.getBoolArrayAttr($0)";
1425}
1426def I32ArrayAttr : TypedArrayAttrBase<I32Attr,
1427                                      "32-bit integer array attribute"> {
1428  let constBuilderCall = "$_builder.getI32ArrayAttr($0)";
1429}
1430def I64ArrayAttr : TypedArrayAttrBase<I64Attr,
1431                                      "64-bit integer array attribute"> {
1432  let constBuilderCall = "$_builder.getI64ArrayAttr($0)";
1433}
1434def F32ArrayAttr : TypedArrayAttrBase<F32Attr, "32-bit float array attribute"> {
1435  let constBuilderCall = "$_builder.getF32ArrayAttr($0)";
1436}
1437def F64ArrayAttr : TypedArrayAttrBase<F64Attr, "64-bit float array attribute"> {
1438  let constBuilderCall = "$_builder.getF64ArrayAttr($0)";
1439}
1440def StrArrayAttr : TypedArrayAttrBase<StrAttr, "string array attribute"> {
1441  let constBuilderCall = "$_builder.getStrArrayAttr($0)";
1442}
1443def TypeArrayAttr : TypedArrayAttrBase<TypeAttr, "type array attribute"> {
1444  let constBuilderCall = "$_builder.getTypeArrayAttr($0)";
1445}
1446
1447// Attribute information for an Attribute field within a StructAttr.
1448class StructFieldAttr<string thisName, Attr thisType> {
1449  // Name of this field in the StructAttr.
1450  string name = thisName;
1451
1452  // Attribute type wrapped by the struct attr.
1453  Attr type = thisType;
1454}
1455
1456// Structured attribute that wraps a DictionaryAttr and provides both a
1457// validation method and set of accessors for a fixed set of fields. This is
1458// useful when representing data that would normally be in a structure.
1459class StructAttr<string name, Dialect d,
1460                 list<StructFieldAttr> attributes> :
1461    DictionaryAttrBase<CPred<"$_self.isa<" # d.cppNamespace
1462                                           # "::" # name # ">()">,
1463        "DictionaryAttr with field(s): " #
1464        StrJoin<!foreach(a, attributes, "'" # a.name # "'"), ", ">.result #
1465        " (each field having its own constraints)"> {
1466  // Name for this StructAttr.
1467  string className = name;
1468
1469  // Return type should match the name of the structure.
1470  let returnType = d.cppNamespace # "::" # name;
1471
1472  // Storage type should match the name of the structure.
1473  let storageType = d.cppNamespace # "::" # name;
1474
1475  // The dialect this StructAttr belongs to.
1476  Dialect dialect = d;
1477
1478  let cppNamespace = d.cppNamespace;
1479
1480  // List of fields that the StructAttr contains.
1481  list<StructFieldAttr> fields = attributes;
1482}
1483
1484// Attributes containing symbol references.
1485def SymbolRefAttr : Attr<CPred<"$_self.isa<::mlir::SymbolRefAttr>()">,
1486                        "symbol reference attribute"> {
1487  let storageType = [{ ::mlir::SymbolRefAttr }];
1488  let returnType = [{ ::mlir::SymbolRefAttr }];
1489  let valueType = NoneType;
1490  let constBuilderCall = "$_builder.getSymbolRefAttr($0)";
1491  let convertFromStorage = "$_self";
1492}
1493def FlatSymbolRefAttr : Attr<CPred<"$_self.isa<::mlir::FlatSymbolRefAttr>()">,
1494                                   "flat symbol reference attribute"> {
1495  let storageType = [{ ::mlir::FlatSymbolRefAttr }];
1496  let returnType = [{ ::llvm::StringRef }];
1497  let valueType = NoneType;
1498  let constBuilderCall = "$_builder.getSymbolRefAttr($0)";
1499  let convertFromStorage = "$_self.getValue()";
1500}
1501
1502def SymbolRefArrayAttr :
1503  TypedArrayAttrBase<SymbolRefAttr, "symbol ref array attribute"> {
1504  let constBuilderCall = ?;
1505}
1506
1507//===----------------------------------------------------------------------===//
1508// Derive attribute kinds
1509
1510// DerivedAttr are attributes whose value is computed from properties
1511// of the operation. They do not require additional storage and are
1512// materialized as needed.
1513// Note: All derived attributes should be materializable as an Attribute. E.g.,
1514// do not use DerivedAttr for things that could not have been stored as
1515// Attribute.
1516//
1517class DerivedAttr<code ret, code b, code convert = ""> :
1518    Attr<CPred<"true">, "derived attribute"> {
1519  let returnType = ret;
1520  code body = b;
1521
1522  // Specify how to convert from the derived attribute to an attribute.
1523  //
1524  // ## Special placeholders
1525  //
1526  // Special placeholders can be used to refer to entities during conversion:
1527  //
1528  // * `$_builder` will be replaced by a mlir::Builder instance.
1529  // * `$_ctx` will be replaced by the MLIRContext* instance.
1530  // * `$_self` will be replaced with the derived attribute (value produces
1531  //    `returnType`).
1532  let convertFromStorage = convert;
1533}
1534
1535// Derived attribute that returns a mlir::Type.
1536class DerivedTypeAttr<code body> : DerivedAttr<"Type", body> {
1537  let convertFromStorage = "::mlir::TypeAttr::get($_self)";
1538}
1539
1540//===----------------------------------------------------------------------===//
1541// Constant attribute kinds
1542
1543// Represents a constant attribute of specific Attr type. A constant
1544// attribute can be specified only of attributes that have a constant
1545// builder call defined. The constant value is specified as a string.
1546//
1547// If used as a constraint, it generates a matcher on a constant attribute by
1548// using the constant value builder of the attribute and the value.
1549class ConstantAttr<Attr attribute, string val> : AttrConstraint<
1550    CPred<"$_self == " # !subst("$0", val, attribute.constBuilderCall)>,
1551    "constant attribute " # val> {
1552  Attr attr = attribute;
1553  string value = val;
1554}
1555
1556class ConstF32Attr<string val> : ConstantAttr<F32Attr, val>;
1557def ConstBoolAttrFalse : ConstantAttr<BoolAttr, "false">;
1558def ConstBoolAttrTrue : ConstantAttr<BoolAttr, "true">;
1559def ConstUnitAttr : ConstantAttr<UnitAttr, "unit">;
1560
1561//===----------------------------------------------------------------------===//
1562// Common attribute constraints
1563//===----------------------------------------------------------------------===//
1564
1565// A general mechanism to further confine the given `attr` with all the
1566// `constraints`. This allows to compose complex constraints out of a series
1567// of more primitive ones.
1568class Confined<Attr attr, list<AttrConstraint> constraints> : Attr<
1569    And<!listconcat([attr.predicate],
1570                      !foreach(pred, constraints, pred.predicate))>,
1571    !foldl(/*init*/attr.description, /*list*/constraints,
1572           prev, cur, prev # " " # cur.description)> {
1573  let storageType = attr.storageType;
1574  let returnType = attr.returnType;
1575  let convertFromStorage = attr.convertFromStorage;
1576  let constBuilderCall = attr.constBuilderCall;
1577  let defaultValue = attr.defaultValue;
1578  let valueType = attr.valueType;
1579  let isOptional = attr.isOptional;
1580
1581  let baseAttr = attr;
1582}
1583
1584// An AttrConstraint that holds if all attr constraints specified in
1585// 'constraints' hold.
1586class AllAttrConstraintsOf<list<AttrConstraint> constraints> : AttrConstraint<
1587    And<!listconcat([!head(constraints).predicate],
1588                      !foreach(pred, !tail(constraints), pred.predicate))>,
1589    !interleave(!foreach(con, constraints, con.description), " and ")> {
1590}
1591
1592class IntMinValue<int n> : AttrConstraint<
1593    CPred<"$_self.cast<::mlir::IntegerAttr>().getInt() >= " # n>,
1594    "whose minimum value is " # n>;
1595
1596class IntMaxValue<int n> : AttrConstraint<
1597    CPred<"$_self.cast<::mlir::IntegerAttr>().getInt() <= " # n>,
1598    "whose maximum value is " # n>;
1599
1600def IntNonNegative : AttrConstraint<
1601    CPred<"!$_self.cast<::mlir::IntegerAttr>().getValue().isNegative()">,
1602    "whose value is non-negative">;
1603
1604def IntPositive : AttrConstraint<
1605    CPred<"$_self.cast<IntegerAttr>().getValue().isStrictlyPositive()">,
1606    "whose value is positive">;
1607
1608class ArrayMinCount<int n> : AttrConstraint<
1609    CPred<"$_self.cast<::mlir::ArrayAttr>().size() >= " # n>,
1610    "with at least " # n # " elements">;
1611
1612class ArrayCount<int n> : AttrConstraint<
1613    CPred<"$_self.cast<::mlir::ArrayAttr>().size() == " #n>,
1614    "with exactly " # n # " elements">;
1615
1616class IntArrayNthElemEq<int index, int value> : AttrConstraint<
1617    And<[
1618      CPred<"$_self.cast<::mlir::ArrayAttr>().size() > " # index>,
1619      CPred<"$_self.cast<::mlir::ArrayAttr>()[" # index # "]"
1620        ".cast<::mlir::IntegerAttr>().getInt() == " # value>
1621       ]>,
1622    "whose " # index # "-th element must be " # value>;
1623
1624class IntArrayNthElemMinValue<int index, int min> : AttrConstraint<
1625    And<[
1626      CPred<"$_self.cast<::mlir::ArrayAttr>().size() > " # index>,
1627      CPred<"$_self.cast<::mlir::ArrayAttr>()[" # index # "]"
1628        ".cast<::mlir::IntegerAttr>().getInt() >= " # min>
1629        ]>,
1630    "whose " # index # "-th element must be at least " # min>;
1631
1632def IsNullAttr : AttrConstraint<
1633    CPred<"!$_self">, "empty attribute (for optional attributes)">;
1634
1635// An attribute constraint on FlatSymbolRefAttr that requires that the
1636// reference point to an op of `opClass` within the closest parent with a symbol
1637// table.
1638// TODO: Add support for nested symbol references.
1639class ReferToOp<string opClass> : AttrConstraint<
1640    CPred<"isa_and_nonnull<" # opClass # ">("
1641            "::mlir::SymbolTable::lookupNearestSymbolFrom("
1642              "&$_op, $_self.cast<::mlir::FlatSymbolRefAttr>().getValue()))">,
1643    "referencing to a '" # opClass # "' symbol">;
1644
1645//===----------------------------------------------------------------------===//
1646// Region definitions
1647//===----------------------------------------------------------------------===//
1648
1649class Region<Pred condition, string descr = ""> :
1650    RegionConstraint<condition, descr>;
1651
1652// Any region.
1653def AnyRegion : Region<CPred<"true">, "any region">;
1654
1655// A region with the given number of blocks.
1656class SizedRegion<int numBlocks> : Region<
1657  CPred<"::llvm::hasNItems($_self, " # numBlocks # ")">,
1658  "region with " # numBlocks # " blocks">;
1659
1660// A variadic region constraint. It expands to zero or more of the base region.
1661class VariadicRegion<Region region>
1662  : Region<region.predicate, region.description>;
1663
1664//===----------------------------------------------------------------------===//
1665// Successor definitions
1666//===----------------------------------------------------------------------===//
1667
1668class Successor<Pred condition, string descr = ""> :
1669    SuccessorConstraint<condition, descr>;
1670
1671// Any successor.
1672def AnySuccessor : Successor<?, "any successor">;
1673
1674// A variadic successor constraint. It expands to zero or more of the base
1675// successor.
1676class VariadicSuccessor<Successor successor>
1677  : Successor<successor.predicate, successor.description>;
1678
1679//===----------------------------------------------------------------------===//
1680// OpTrait definitions
1681//===----------------------------------------------------------------------===//
1682
1683// OpTrait represents a trait regarding an op.
1684class OpTrait;
1685
1686// NativeOpTrait corresponds to the MLIR C++ OpTrait mechanism. The
1687// purpose to wrap around C++ symbol string with this class is to make
1688// traits specified for ops in TableGen less alien and more integrated.
1689class NativeOpTrait<string prop> : OpTrait {
1690  string trait = "::mlir::OpTrait::" # prop;
1691}
1692
1693// ParamNativeOpTrait corresponds to the template-parameterized traits in the
1694// C++ implementation.  MLIR uses nested class templates to implement such
1695// traits leading to constructs of the form "TraitName<Parameters>::Impl". Use
1696// the value in `prop` as the trait name and the value in `params` as
1697// parameters to construct the native trait class name.
1698class ParamNativeOpTrait<string prop, string params>
1699    : NativeOpTrait<prop # "<" # params # ">::Impl">;
1700
1701// GenInternalOpTrait is an op trait that does not have direct C++ mapping but
1702// affects op definition generator internals, like how op builders and
1703// operand/attribute/result getters are generated.
1704class GenInternalOpTrait<string prop> : OpTrait {
1705  string trait = "::mlir::OpTrait::" # prop;
1706}
1707
1708// PredOpTrait is an op trait implemented by way of a predicate on the op.
1709class PredOpTrait<string descr, Pred pred> : OpTrait {
1710  string description = descr;
1711  Pred predicate = pred;
1712}
1713
1714// Op defines an affine scope.
1715def AffineScope : NativeOpTrait<"AffineScope">;
1716// Op defines an automatic allocation scope.
1717def AutomaticAllocationScope : NativeOpTrait<"AutomaticAllocationScope">;
1718// Op supports operand broadcast behavior.
1719def ResultsBroadcastableShape :
1720  NativeOpTrait<"ResultsBroadcastableShape">;
1721// X op Y == Y op X
1722def Commutative  : NativeOpTrait<"IsCommutative">;
1723// op op X == op X
1724def Idempotent  : NativeOpTrait<"IsIdempotent">;
1725// op op X == X
1726def Involution  : NativeOpTrait<"IsInvolution">;
1727// Op behaves like a constant.
1728def ConstantLike : NativeOpTrait<"ConstantLike">;
1729// Op behaves like a function.
1730def FunctionLike : NativeOpTrait<"FunctionLike">;
1731// Op is isolated from above.
1732def IsolatedFromAbove : NativeOpTrait<"IsIsolatedFromAbove">;
1733// Op results are float or vectors/tensors thereof.
1734def ResultsAreFloatLike : NativeOpTrait<"ResultsAreFloatLike">;
1735// Op has the same operand type.
1736def SameTypeOperands : NativeOpTrait<"SameTypeOperands">;
1737// Op has same shape for all operands.
1738def SameOperandsShape : NativeOpTrait<"SameOperandsShape">;
1739// Op has same operand and result shape.
1740def SameOperandsAndResultShape : NativeOpTrait<"SameOperandsAndResultShape">;
1741// Op has the same operand and result type.
1742def SameOperandsAndResultType : NativeOpTrait<"SameOperandsAndResultType">;
1743// Op has the same element type (or type itself, if scalar) for all operands.
1744def SameOperandsElementType : NativeOpTrait<"SameOperandsElementType">;
1745// Op has the same operand and result element type (or type itself, if scalar).
1746def SameOperandsAndResultElementType :
1747  NativeOpTrait<"SameOperandsAndResultElementType">;
1748// Op is a terminator.
1749def Terminator : NativeOpTrait<"IsTerminator">;
1750// Op can be safely normalized in the presence of MemRefs with
1751// non-identity maps.
1752def MemRefsNormalizable : NativeOpTrait<"MemRefsNormalizable">;
1753// Op can be systematically interconverted between scalar and vector/tensor
1754// form by mapping elementwise based on the type.
1755def ElementwiseMappable : NativeOpTrait<"ElementwiseMappable">;
1756
1757// Op's regions have a single block with the specified terminator.
1758class SingleBlockImplicitTerminator<string op>
1759    : ParamNativeOpTrait<"SingleBlockImplicitTerminator", op>;
1760
1761// Op's parent operation is the provided one.
1762class HasParent<string op>
1763    : ParamNativeOpTrait<"HasParent", op>;
1764
1765class ParentOneOf<list<string> ops>
1766    : ParamNativeOpTrait<"HasParent", StrJoin<ops>.result>;
1767
1768// Op result type is derived from the first attribute. If the attribute is an
1769// subclass of `TypeAttrBase`, its value is used, otherwise, the type of the
1770// attribute content is used.
1771def FirstAttrDerivedResultType :
1772  GenInternalOpTrait<"FirstAttrDerivedResultType">;
1773
1774// TODO: Turn the following into normal traits and generate verification for
1775// them.
1776
1777// All variadic operands of the op have the same number of values.
1778// A variadic operand contains an array of values whose array size is only
1779// known at runtime. This trait requires all variadic operands of an op
1780// to have the same array size.
1781def SameVariadicOperandSize : GenInternalOpTrait<"SameVariadicOperandSize">;
1782// All variadic results of the op have the same number of values.
1783// A variadic result contains an array of values whose array size is only
1784// known at runtime. This trait requires all variadic results of an op
1785// to have the same array size.
1786def SameVariadicResultSize : GenInternalOpTrait<"SameVariadicResultSize">;
1787
1788// Uses an attribute named `operand_segment_sizes` to specify how many actual
1789// operand each ODS-declared operand (variadic or not) corresponds to.
1790// This trait is used for ops that have multiple variadic operands but do
1791// not know statically their size relationship. The attribute must be a 1D
1792// vector that has the same number of elements as the number of ODS declared
1793// operands. That means even if some operands are non-variadic, the attribute
1794// still need to have an element for its size, which is always 1.
1795def AttrSizedOperandSegments : NativeOpTrait<"AttrSizedOperandSegments">;
1796// Similar to AttrSizedOperandSegments, but used for results. The attribute
1797// should be named as `result_segment_sizes`.
1798def AttrSizedResultSegments  : NativeOpTrait<"AttrSizedResultSegments">;
1799
1800// Op attached regions have no arguments
1801def NoRegionArguments : NativeOpTrait<"NoRegionArguments">;
1802
1803//===----------------------------------------------------------------------===//
1804// OpInterface definitions
1805//===----------------------------------------------------------------------===//
1806
1807// Marker used to identify the argument list for an op or interface method.
1808def ins;
1809
1810// This class represents a typed argument with optional default value for C
1811// function signatures, e.g. builders or methods.
1812class CArg<string ty, string value = ""> {
1813  string type = ty;
1814  string defaultValue = value;
1815}
1816
1817// OpInterfaceTrait corresponds to a specific 'OpInterface' class defined in
1818// C++. The purpose to wrap around C++ symbol string with this class is to make
1819// interfaces specified for ops in TableGen less alien and more integrated.
1820class OpInterfaceTrait<string name, code verifyBody = [{}]>
1821          : NativeOpTrait<""> {
1822  let trait = name # "::Trait";
1823
1824  // Specify the body of the verification function. `$_op` will be replaced with
1825  // the operation being verified.
1826  code verify = verifyBody;
1827
1828  // An optional code block containing extra declarations to place in the
1829  // interface trait declaration.
1830  code extraTraitClassDeclaration = "";
1831}
1832
1833// This class represents a single, optionally static, interface method.
1834// Note: non-static interface methods have an implicit parameter, either
1835// $_op/$_attr/$_type corresponding to an instance of the derived value.
1836class InterfaceMethod<string desc, string retTy, string methodName,
1837                      dag args = (ins), code methodBody = [{}],
1838                      code defaultImplementation = [{}]> {
1839  // A human-readable description of what this method does.
1840  string description = desc;
1841
1842  // The name of the interface method.
1843  string name = methodName;
1844
1845  // The c++ type-name of the return type.
1846  string returnType = retTy;
1847
1848  // A dag of string that correspond to the arguments of the method.
1849  dag arguments = args;
1850
1851  // An optional body to the method.
1852  code body = methodBody;
1853
1854  // An optional default implementation of the method.
1855  code defaultBody = defaultImplementation;
1856}
1857
1858// This class represents a single static interface method.
1859class StaticInterfaceMethod<string desc, string retTy, string methodName,
1860                            dag args = (ins), code methodBody = [{}],
1861                            code defaultImplementation = [{}]>
1862    : InterfaceMethod<desc, retTy, methodName, args, methodBody,
1863                      defaultImplementation>;
1864
1865// Interface represents a base interface.
1866class Interface<string name> {
1867  // A human-readable description of what this interface does.
1868  string description = "";
1869
1870  // The name given to the c++ interface class.
1871  string cppClassName = name;
1872
1873  // The C++ namespace that this interface should be placed into.
1874  //
1875  // To specify nested namespaces, use "::" as the delimiter, e.g., given
1876  // "A::B", ops will be placed in `namespace A { namespace B { <def> } }`.
1877  string cppNamespace = "";
1878
1879  // The list of methods defined by this interface.
1880  list<InterfaceMethod> methods = [];
1881
1882  // An optional code block containing extra declarations to place in the
1883  // interface declaration.
1884  code extraClassDeclaration = "";
1885}
1886
1887// AttrInterface represents an interface registered to an attribute.
1888class AttrInterface<string name> : Interface<name> {
1889  // An optional code block containing extra declarations to place in the
1890  // interface trait declaration.
1891  code extraTraitClassDeclaration = "";
1892}
1893
1894// OpInterface represents an interface registered to an operation.
1895class OpInterface<string name> : Interface<name>, OpInterfaceTrait<name>;
1896
1897// TypeInterface represents an interface registered to a type.
1898class TypeInterface<string name> : Interface<name> {
1899  // An optional code block containing extra declarations to place in the
1900  // interface trait declaration.
1901  code extraTraitClassDeclaration = "";
1902}
1903
1904// Whether to declare the op interface methods in the op's header. This class
1905// simply wraps an OpInterface but is used to indicate that the method
1906// declarations should be generated. This class takes an optional set of methods
1907// that should have declarations generated even if the method has a default
1908// implementation.
1909class DeclareOpInterfaceMethods<OpInterface interface,
1910                                list<string> overridenMethods = []>
1911      : OpInterface<interface.cppClassName> {
1912    let description = interface.description;
1913    let cppClassName = interface.cppClassName;
1914    let cppNamespace = interface.cppNamespace;
1915    let methods = interface.methods;
1916
1917    // This field contains a set of method names that should always have their
1918    // declarations generated. This allows for generating declarations for
1919    // methods with default implementations that need to be overridden.
1920    list<string> alwaysOverriddenMethods = overridenMethods;
1921}
1922
1923//===----------------------------------------------------------------------===//
1924// Op definitions
1925//===----------------------------------------------------------------------===//
1926
1927// Marker used to identify the result list for an op.
1928def outs;
1929
1930// Marker used to identify the region list for an op.
1931def region;
1932
1933// Marker used to identify the successor list for an op.
1934def successor;
1935
1936// Base class for custom builders. This is a transient class that will go away
1937// when the transition to the DAG form of builder declaration is complete.
1938// Should not be used directly.
1939class OpBuilderBase<dag dp, code b> {
1940  string params = ?;
1941  dag dagParams = dp;
1942  code body = b;
1943}
1944
1945// Class for defining a custom builder.
1946//
1947// TableGen generates several generic builders for each op by default (see
1948// comment in the `Op` class). If the default generated ones cannot cover
1949// some use case, custom builders can be defined using instances of this class.
1950//
1951// The signature of the builder is always
1952//
1953// ```c++
1954// static void build(::mlir::OpBuilder &builder, ::mlir::OperationState &state,
1955//                   <other-parameters>...) {
1956//   <body>...
1957// }
1958// ```
1959//
1960// To define a custom builder, the parameter list (*excluding* the
1961// `OpBuilder &builder, OperationState &state` part) and body should be passed
1962// in as separate template arguments to this class. The parameter list is a
1963// TableGen DAG with `ins` operation with named arguments, which has either:
1964//   - string initializers ("Type":$name) to represent a typed parameter, or
1965//   - CArg-typed initializers (CArg<"Type", "default">:$name) to represent a
1966//     typed parameter that may have a default value.
1967// The type string is used verbatim to produce code and, therefore, must be a
1968// valid C++ type. It is used inside the C++ namespace of the parent Op's
1969// dialect; explicit namespace qualification like `::mlir` may be necessary if
1970// Ops are not placed inside the `mlir` namespace. The default value string is
1971// used verbatim to produce code and must be a valid C++ initializer the given
1972// type. For example, the following signature specification
1973//
1974// ```
1975// OpBuilderDAG<(ins "int":$integerArg, CArg<"float", "3.0f">:$floatArg)>
1976// ```
1977//
1978// has an integer parameter and a float parameter with a default value.
1979//
1980// If an empty string is passed in for `body`, then *only* the builder
1981// declaration will be generated; this provides a way to define complicated
1982// builders entirely in C++.
1983class OpBuilderDAG<dag p, code b = ""> : OpBuilderBase<p, b>;
1984
1985// Deprecated version of OpBuilder that takes the builder signature as string.
1986class OpBuilder<string p, code b = ""> : OpBuilderBase<(ins), b> {
1987  let params = p;
1988}
1989
1990// A base decorator class that may optionally be added to OpVariables.
1991class OpVariableDecorator;
1992
1993// Class for providing additional information on the variables, i.e. arguments
1994// and results, of an operation.
1995class OpVariable<Constraint varConstraint, string desc = "",
1996                 list<OpVariableDecorator> varDecorators = []> {
1997  // The constraint, either attribute or type, of the argument.
1998  Constraint constraint = varConstraint;
1999
2000  // A description for the argument.
2001  string description = desc;
2002
2003  // The list of decorators for this variable, e.g. side effects.
2004  list<OpVariableDecorator> decorators = varDecorators;
2005}
2006class Arg<Constraint constraint, string desc = "",
2007          list<OpVariableDecorator> decorators = []>
2008  : OpVariable<constraint, desc, decorators>;
2009class Res<Constraint constraint, string desc = "",
2010          list<OpVariableDecorator> decorators = []>
2011  : OpVariable<constraint, desc, decorators>;
2012
2013// Base class for all ops.
2014class Op<Dialect dialect, string mnemonic, list<OpTrait> props = []> {
2015  // The dialect of the op.
2016  Dialect opDialect = dialect;
2017
2018  // The mnemonic of the op.
2019  string opName = mnemonic;
2020
2021  // One-line human-readable description of what the op does.
2022  string summary = "";
2023
2024  // Additional, longer human-readable description of what the op does.
2025  string description = "";
2026
2027  // Dag containing the arguments of the op. Default to 0 arguments.
2028  dag arguments = (ins);
2029
2030  // The list of results of the op. Default to 0 results.
2031  dag results = (outs);
2032
2033  // The list of regions of the op. Default to 0 regions.
2034  dag regions = (region);
2035
2036  // The list of successors of the op. Default to 0 successors.
2037  dag successors = (successor);
2038
2039  // Attribute getters can be added to the op by adding an Attr member
2040  // with the name and type of the attribute. E.g., adding int attribute
2041  // with name "value" and type "i32":
2042  //   I32Attr value;
2043
2044  // Define the hooks used for building, parsing, printing, verification.
2045
2046  // Custom builder.
2047  // In addition to the custom builder provided here, and unless
2048  // skipDefaultBuilders is set, two default builders are generated, with the
2049  // following signatures:
2050  //
2051  // ```c++
2052  // static void build(OpBuilder &, OperationState &odsState,
2053  //                   Type <result0-name>, Type <result1-name>, ...,
2054  //                   Value <arg0-name>, Value <arg1-name>, ...,
2055  //                   Attribute <attr0-name>, Attribute <attr1-name>, ...);
2056  // ```
2057  // * where the attributes follow the same declaration order as in the op.
2058  //
2059  // ```c++
2060  // static void build(OpBuilder &, OperationState &odsState,
2061  //                   TypeRange resultTypes,
2062  //                   ValueRange operands,
2063  //                   ArrayRef<NamedAttribute> attributes);
2064  // ```
2065  list<OpBuilderBase> builders = ?;
2066
2067  // Avoid generating default build functions.  Custom builders must be
2068  // provided.
2069  bit skipDefaultBuilders = 0;
2070
2071  // Custom parser.
2072  code parser = ?;
2073
2074  // Custom printer.
2075  code printer = ?;
2076
2077  // Custom assembly format.
2078  string assemblyFormat = ?;
2079
2080  // Custom verifier.
2081  code verifier = ?;
2082
2083  // Whether this op has associated canonicalization patterns.
2084  // TODO: figure out a better way to write canonicalization patterns in
2085  // TableGen rules directly instead of using this marker and C++
2086  // implementations.
2087  bit hasCanonicalizer = 0;
2088
2089  // Whether this op has a folder.
2090  bit hasFolder = 0;
2091
2092  // Op traits.
2093  // Note: The list of traits will be uniqued by ODS.
2094  list<OpTrait> traits = props;
2095
2096  // Additional code that will be added to the public part of the generated
2097  // C++ code of the op declaration.
2098  code extraClassDeclaration = ?;
2099}
2100
2101// The arguments of an op.
2102class Arguments<dag args> {
2103  dag arguments = args;
2104}
2105
2106// The results of an op.
2107class Results<dag rets> {
2108  dag results = rets;
2109}
2110
2111//===----------------------------------------------------------------------===//
2112// Common value constraints
2113//===----------------------------------------------------------------------===//
2114
2115def HasNoUseOf: Constraint<
2116    CPred<"$_self.use_empty()">, "has no use">;
2117
2118//===----------------------------------------------------------------------===//
2119// Common op type constraints
2120//===----------------------------------------------------------------------===//
2121
2122// These traits are for verifying properties of an op that require knowledge of
2123// multiple arguments or results. For verifying properties of a single argument
2124// or result, prefer operand type constraints.
2125
2126// These traits often require including "mlir/IR/TypeUtilities.h".
2127
2128// TODO: Improve the autogenerated error messages.
2129
2130class Rank<string name> :
2131    StrFunc<"$" # name # ".getType().cast<::mlir::ShapedType>().getRank()">;
2132
2133class Shape<string name> :
2134    StrFunc<"$" # name # ".getType().cast<::mlir::ShapedType>().getShape()">;
2135
2136class ElementCount<string name> :
2137  StrFunc<"$" # name # ".getType().cast<::mlir::ShapedType>()"
2138                                 ".getNumElements()">;
2139
2140class ElementType<string name> : StrFunc<"getElementTypeOrSelf($" # name # ")">;
2141
2142class AllMatchPred<list<string> values> :
2143    CPred<"::llvm::is_splat(::llvm::makeArrayRef({"
2144          # StrJoin<values>.result #"}))">;
2145
2146class AllMatch<list<string> values, string description> :
2147    PredOpTrait<description, AllMatchPred<values>>;
2148
2149// TODO: Only works for non-variadic.
2150class AllMatchSameOperatorPred<list<string> names, string operator> :
2151    AllMatchPred<!foreach(n, names, !subst("$_self", "$" # n, operator))>;
2152
2153class AllMatchSameOperatorTrait<list<string> names, string operator,
2154                                string description> :
2155    PredOpTrait<
2156        "all of {" # StrJoin<names>.result # "} have same " # description,
2157        AllMatchSameOperatorPred<names, operator>> {
2158  list<string> values = names;
2159}
2160
2161class AllElementCountsMatch<list<string> names> :
2162    AllMatchSameOperatorTrait<names, ElementCount<"_self">.result,
2163                              "element count">;
2164
2165class AllElementTypesMatch<list<string> names> :
2166    AllMatchSameOperatorTrait<names, ElementType<"_self">.result,
2167                              "element type">;
2168
2169class AllRanksMatch<list<string> names> :
2170    AllMatchSameOperatorTrait<names, Rank<"_self">.result, "rank">;
2171
2172class AllShapesMatch<list<string> names> :
2173    AllMatchSameOperatorTrait<names, Shape<"_self">.result, "shape">;
2174
2175class AllTypesMatch<list<string> names> :
2176    AllMatchSameOperatorTrait<names, "$_self.getType()", "type">;
2177
2178// A type constraint that denotes `transform(lhs.getType()) == rhs.getType()`.
2179class TypesMatchWith<string description, string lhsArg, string rhsArg,
2180                     string transform> :
2181    PredOpTrait<description, CPred<
2182      !subst("$_self", "$" # lhsArg # ".getType()", transform)
2183      # " == $" # rhsArg # ".getType()">> {
2184  string lhs = lhsArg;
2185  string rhs = rhsArg;
2186  string transformer = transform;
2187}
2188
2189// Type Constraint operand `idx`'s Element type is `type`.
2190class TCopVTEtIs<int idx, Type type> : And<[
2191   CPred<"$_op.getNumOperands() > " # idx>,
2192   SubstLeaves<"$_self", "$_op.getOperand(" # idx # ").getType()",
2193     IsShapedTypePred>,
2194   SubstLeaves<"$_self", "getElementTypeOrSelf($_op.getOperand(" # idx # "))",
2195     type.predicate>]>;
2196
2197// Predicate to verify that a named argument or result's element type matches a
2198// given type.
2199class TypeIsPred<string name, Type type> :
2200   SubstLeaves<"$_self", "$" # name # ".getType()", type.predicate>;
2201class TypeIs<string name, Type type> : PredOpTrait<
2202  "'" # name # "' is " # type.description, TypeIsPred<name, type>>;
2203
2204// Predicate to verify that a named argument or result's element type matches a
2205// given type.
2206class ElementTypeIsPred<string name, Type type> : And<[
2207   SubstLeaves<"$_self", "$" # name # ".getType()", IsShapedTypePred>,
2208   SubstLeaves<"$_self", "getElementTypeOrSelf($" # name # ")",
2209     type.predicate>]>;
2210class ElementTypeIs<string name, Type type> : PredOpTrait<
2211  "'" # name # "' is " # type.description, ElementTypeIsPred<name, type>>;
2212
2213// Predicate to verify that the i'th operand and the j'th operand have the same
2214// elemental type.
2215// Type Constraint operand `i`'s Element type is Same As operand `j`'s Element
2216// type.
2217class TCopVTEtIsSameAs<int i, int j> : And<[
2218    CPred<"$_op.getNumOperands() > " # !if(!gt(i,j),i,j)>,
2219    SubstLeaves<"$_self", "$_op.getOperand(" # i # ").getType()",
2220      IsShapedTypePred>,
2221    SubstLeaves<"$_self", "$_op.getOperand(" # j # ").getType()",
2222      IsShapedTypePred>,
2223    CPred<"::mlir::getElementTypeOrSelf($_op.getOperand(" # i # ")) == "
2224          "::mlir::getElementTypeOrSelf($_op.getOperand(" # j # "))">]>;
2225
2226// Predicate to verify that the i'th result and the j'th operand exist and has
2227// shaped types.
2228class TCOpResIsShapedTypePred<int i, int j> : And<[
2229    CPred<"$_op.getNumResults() > " # i>,
2230    CPred<"$_op.getNumOperands() > " # j>,
2231    SubstLeaves<"$_self", "$_op.getResult(" # i # ").getType()",
2232      IsShapedTypePred>,
2233    SubstLeaves<"$_self", "$_op.getOperand(" # j # ").getType()",
2234      IsShapedTypePred>]>;
2235
2236// Predicate to verify that the i'th result and the j'th operand have the same
2237// type.
2238class TCresIsSameAsOpBase<int i, int j> :
2239    CPred<"$_op.getResult(" # i # ").getType() == "
2240          "$_op.getOperand(" # j # ").getType()">;
2241
2242// Basic Predicate to verify that the i'th result and the j'th operand have the
2243// same elemental type.
2244class TCresVTEtIsSameAsOpBase<int i, int j> :
2245    CPred<"getElementTypeOrSelf($_op.getResult(" # i # ")) == "
2246          "getElementTypeOrSelf($_op.getOperand(" # j # "))">;
2247
2248// Predicate to verify that the i'th result and the j'th operand have the same
2249// elemental type.
2250// Type Constraint result`i`'s Element type is Same As Operand `j`'s Element
2251// type.
2252class TCresVTEtIsSameAsOp<int i, int j> : And<[
2253    TCOpResIsShapedTypePred<i, j>,
2254    TCresVTEtIsSameAsOpBase<i, j>]>;
2255
2256// Predicate to verify that the opId'th operand can be broadcasted to the type
2257// of the resId'th result.
2258class TCOpIsBroadcastableToRes<int opId, int resId> : And<[
2259    TCOpResIsShapedTypePred<opId, resId>,
2260    CPred<"::mlir::OpTrait::util::getBroadcastedType("
2261                  "$_op.getOperand(" # opId # ").getType(), "
2262                  "$_op.getResult(" # resId # ").getType())">]>;
2263
2264// Predicate to verify that all the operands at the given `indices`
2265// have the same element type.
2266// Type Constraint operands' Element type are all Same At the given `indices`.
2267// We query the operands' types into a list and check they are all the same.
2268// Precondition:
2269// 1) all operands involved are of shaped type and
2270// 2) the indices are not out of range.
2271class TCopVTEtAreSameAt<list<int> indices> : CPred<
2272  "::llvm::is_splat(::llvm::map_range("
2273      "::mlir::ArrayRef<unsigned>({" # StrJoinInt<indices>.result # "}), "
2274      "[this](unsigned i) { return getElementTypeOrSelf(this->getOperand(i)); "
2275      "}))">;
2276
2277//===----------------------------------------------------------------------===//
2278// Pattern definitions
2279//===----------------------------------------------------------------------===//
2280
2281// Marker used to identify the delta value added to the default benefit value.
2282def addBenefit;
2283
2284// Base class for op+ -> op+ rewrite rules. These allow declaratively
2285// specifying rewrite rules.
2286//
2287// A rewrite rule contains two components: a source pattern and one or more
2288// result patterns. Each pattern is specified as a (recursive) DAG node (tree)
2289// in the form of `(node arg0, arg1, ...)`.
2290//
2291// The `node` are normally MLIR ops, but it can also be one of the directives
2292// listed later in this section.
2293//
2294// ## Symbol binding
2295//
2296// In the source pattern, `argN` can be used to specify matchers (e.g., using
2297// type/attribute type constraints, etc.) and bound to a name for later use.
2298// We can also bind names to op instances to reference them later in
2299// multi-entity constraints. Operands in the source pattern can have
2300// the same name. This bounds one operand to the name while verifying
2301// the rest are all equal.
2302//
2303//
2304// In the result pattern, `argN` can be used to refer to a previously bound
2305// name, with potential transformations (e.g., using tAttr, etc.). `argN` can
2306// itself be nested DAG node. We can also bound names to ops to reference
2307// them later in other result patterns.
2308//
2309// For example,
2310//
2311// ```
2312// def : Pattern<(OneResultOp1:$op1 $arg0, $arg1, $arg0),
2313//               [(OneResultOp2:$op2 $arg0, $arg1),
2314//                (OneResultOp3 $op2 (OneResultOp4))],
2315//               [(HasStaticShapePred $op1)]>;
2316// ```
2317//
2318// First `$arg0` and '$arg1' are bound to the `OneResultOp1`'s first
2319// and second arguments and used later to build `OneResultOp2`. Second '$arg0'
2320// is verified to be equal to the first '$arg0' operand.
2321// `$op1` is bound to `OneResultOp1` and used to check whether the result's
2322// shape is static. `$op2` is bound to `OneResultOp2` and used to
2323// build `OneResultOp3`.
2324//
2325// ## Multi-result op
2326//
2327// To create multi-result ops in result pattern, you can use a syntax similar
2328// to uni-result op, and it will act as a value pack for all results:
2329//
2330// ```
2331// def : Pattern<(ThreeResultOp ...),
2332//               [(TwoResultOp ...), (OneResultOp ...)]>;
2333// ```
2334//
2335// Then `TwoResultOp` will replace the first two values of `ThreeResultOp`.
2336//
2337// You can also use `$<name>__N` to explicitly access the N-th result.
2338// ```
2339// def : Pattern<(FiveResultOp ...),
2340//               [(TwoResultOp1:$res1__1 ...), (replaceWithValue $res1__0),
2341//                (TwoResultOp2:$res2 ...), (replaceWithValue $res2__1)]>;
2342// ```
2343//
2344// Then the values generated by `FiveResultOp` will be replaced by
2345//
2346// * `FiveResultOp`#0: `TwoResultOp1`#1
2347// * `FiveResultOp`#1: `TwoResultOp1`#0
2348// * `FiveResultOp`#2: `TwoResultOp2`#0
2349// * `FiveResultOp`#3: `TwoResultOp2`#1
2350// * `FiveResultOp`#4: `TwoResultOp2`#1
2351class Pattern<dag source, list<dag> results, list<dag> preds = [],
2352  dag benefitAdded = (addBenefit 0)> {
2353  dag sourcePattern = source;
2354  // Result patterns. Each result pattern is expected to replace one result
2355  // of the root op in the source pattern. In the case of more result patterns
2356  // than needed to replace the source op, only the last N results generated
2357  // by the last N result pattern is used to replace a N-result source op.
2358  // So that the beginning result patterns can be used to generate additional
2359  // ops to aid building the results used for replacement.
2360  list<dag> resultPatterns = results;
2361  // Multi-entity constraints. Each constraint here involves multiple entities
2362  // matched in source pattern and places further constraints on them as a
2363  // whole.
2364  list<dag> constraints = preds;
2365  // The delta value added to the default benefit value. The default value is
2366  // the number of ops in the source pattern. The rule with the highest final
2367  // benefit value will be applied first if there are multiple rules matches.
2368  // This delta value can be either positive or negative.
2369  dag benefitDelta = benefitAdded;
2370}
2371
2372// Form of a pattern which produces a single result.
2373class Pat<dag pattern, dag result, list<dag> preds = [],
2374  dag benefitAdded = (addBenefit 0)> :
2375  Pattern<pattern, [result], preds, benefitAdded>;
2376
2377// Native code call wrapper. This allows invoking an arbitrary C++ expression
2378// to create an op operand/attribute or replace an op result.
2379//
2380// ## Placeholders
2381//
2382// If used as a DAG leaf, i.e., `(... NativeCodeCall<"...">:$arg, ...)`,
2383// the wrapped expression can take special placeholders listed below:
2384//
2385// * `$_builder` will be replaced by the current `mlir::PatternRewriter`.
2386// * `$_self` will be replaced with the entity this transformer is attached to.
2387//   E.g., with the definition `def transform : NativeCodeCall<"$_self...">`,
2388//   `$_self` in `transform:$attr` will be replaced by the value for `$attr`.
2389//
2390// If used as a DAG node, i.e., `(NativeCodeCall<"..."> <arg0>, ..., <argN>)`,
2391// then positional placeholders are also supported; placeholder `$N` in the
2392// wrapped C++ expression will be replaced by `<argN>`.
2393
2394class NativeCodeCall<string expr> {
2395  string expression = expr;
2396}
2397
2398def ConstantLikeMatcher : NativeCodeCall<"success(matchPattern($0->getResult(0), m_Constant(&$1)))">;
2399
2400//===----------------------------------------------------------------------===//
2401// Rewrite directives
2402//===----------------------------------------------------------------------===//
2403
2404// Directive used in result pattern to specify the location of the generated
2405// op. This directive must be used as the last argument to the op creation
2406// DAG construct. The arguments to location must be previously captured symbol.
2407def location;
2408
2409// Directive used in result pattern to indicate that no new op are generated,
2410// so to replace the matched DAG with an existing SSA value.
2411def replaceWithValue;
2412
2413
2414//===----------------------------------------------------------------------===//
2415// Data type generation
2416//===----------------------------------------------------------------------===//
2417
2418// Define a new type belonging to a dialect and called 'name'.
2419class TypeDef<Dialect owningdialect, string name> {
2420  Dialect dialect = owningdialect;
2421  string cppClassName = name # "Type";
2422
2423  // Short summary of the type.
2424  string summary = ?;
2425  // The longer description of this type.
2426  string description = ?;
2427
2428  // Name of storage class to generate or use.
2429  string storageClass = name # "TypeStorage";
2430  // Namespace (withing dialect c++ namespace) in which the storage class
2431  // resides.
2432  string storageNamespace = "detail";
2433  // Specify if the storage class is to be generated.
2434  bit genStorageClass = 1;
2435  // Specify that the generated storage class has a constructor which is written
2436  // in C++.
2437  bit hasStorageCustomConstructor = 0;
2438
2439  // The list of parameters for this type. Parameters will become both
2440  // parameters to the get() method and storage class member variables.
2441  //
2442  // The format of this dag is:
2443  //    (ins
2444  //        "<c++ type>":$param1Name,
2445  //        "<c++ type>":$param2Name,
2446  //        TypeParameter<"c++ type", "param description">:$param3Name)
2447  // TypeParameters (or more likely one of their subclasses) are required to add
2448  // more information about the parameter, specifically:
2449  //  - Documentation
2450  //  - Code to allocate the parameter (if allocation is needed in the storage
2451  //    class constructor)
2452  //
2453  // For example:
2454  //    (ins
2455  //        "int":$width,
2456  //        ArrayRefParameter<"bool", "list of bools">:$yesNoArray)
2457  //
2458  // (ArrayRefParameter is a subclass of TypeParameter which has allocation code
2459  // for re-allocating ArrayRefs. It is defined below.)
2460  dag parameters = (ins);
2461
2462  // Use the lowercased name as the keyword for parsing/printing. Specify only
2463  // if you want tblgen to generate declarations and/or definitions of
2464  // printer/parser for this type.
2465  string mnemonic = ?;
2466  // If 'mnemonic' specified,
2467  //   If null, generate just the declarations.
2468  //   If a non-empty code block, just use that code as the definition code.
2469  //   Error if an empty code block.
2470  code printer = ?;
2471  code parser = ?;
2472
2473  // If set, generate accessors for each Type parameter.
2474  bit genAccessors = 1;
2475  // Generate the verifyConstructionInvariants declaration and getChecked
2476  // method.
2477  bit genVerifyInvariantsDecl = 0;
2478  // Extra code to include in the class declaration.
2479  code extraClassDeclaration = [{}];
2480}
2481
2482// 'Parameters' should be subclasses of this or simple strings (which is a
2483// shorthand for TypeParameter<"C++Type">).
2484class TypeParameter<string type, string desc> {
2485  // Custom memory allocation code for storage constructor.
2486  code allocator = ?;
2487  // The C++ type of this parameter.
2488  string cppType = type;
2489  // A description of this parameter.
2490  string description = desc;
2491  // The format string for the asm syntax (documentation only).
2492  string syntax = ?;
2493}
2494
2495// For StringRefs, which require allocation.
2496class StringRefParameter<string desc> :
2497    TypeParameter<"::llvm::StringRef", desc> {
2498  let allocator = [{$_dst = $_allocator.copyInto($_self);}];
2499}
2500
2501// For standard ArrayRefs, which require allocation.
2502class ArrayRefParameter<string arrayOf, string desc> :
2503    TypeParameter<"::llvm::ArrayRef<" # arrayOf # ">", desc> {
2504  let allocator = [{$_dst = $_allocator.copyInto($_self);}];
2505}
2506
2507// For classes which require allocation and have their own allocateInto method.
2508class SelfAllocationParameter<string type, string desc> :
2509    TypeParameter<type, desc> {
2510  let allocator = [{$_dst = $_self.allocateInto($_allocator);}];
2511}
2512
2513// For ArrayRefs which contain things which allocate themselves.
2514class ArrayRefOfSelfAllocationParameter<string arrayOf, string desc> :
2515    TypeParameter<"::llvm::ArrayRef<" # arrayOf # ">", desc> {
2516  let allocator = [{
2517    llvm::SmallVector<}] # arrayOf # [{, 4> tmpFields;
2518    for (size_t i = 0, e = $_self.size(); i < e; ++i)
2519      tmpFields.push_back($_self[i].allocateInto($_allocator));
2520    $_dst = $_allocator.copyInto(ArrayRef<}] # arrayOf # [{>(tmpFields));
2521  }];
2522}
2523
2524
2525#endif // OP_BASE
2526