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