1//===-- CommonAttrConstraints.td - Common Attr Constraints--*- 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 file contains commonly used attr constraints. 10// 11//===----------------------------------------------------------------------===// 12 13#ifndef COMMON_ATTR_CONSTRAINTS_TD 14#define COMMON_ATTR_CONSTRAINTS_TD 15 16include "mlir/IR/Constraints.td" 17include "mlir/IR/CommonTypeConstraints.td" 18include "mlir/IR/DialectBase.td" 19 20//===----------------------------------------------------------------------===// 21// Attribute definitions 22//===----------------------------------------------------------------------===// 23 24//===----------------------------------------------------------------------===// 25// Base attribute definition 26 27// Base class for all attributes. 28class Attr<Pred condition, string summary = ""> : 29 AttrConstraint<condition, summary> { 30 code storageType = ?; // The backing mlir::Attribute type 31 code returnType = ?; // The underlying C++ value type 32 33 // The call expression to convert from the storage type to the return 34 // type. For example, an enum can be stored as an int but returned as an 35 // enum class. 36 // 37 // Format: $_self will be expanded to the attribute. 38 // 39 // For example, `$_self.getValue().getSExtValue()` for `IntegerAttr val` will 40 // expand to `getAttrOfType<IntegerAttr>("val").getValue().getSExtValue()`. 41 code convertFromStorage = "$_self.getValue()"; 42 43 // The call expression to build an attribute from a constant value. 44 // 45 // Format: $0 will be expanded to the constant value of the attribute. 46 // 47 // For example, `$_builder.getStringAttr("$0")` for `StringAttr:"foo"` will 48 // expand to `builder.getStringAttr("foo")`. 49 string constBuilderCall = ?; 50 51 // Default value for attribute. 52 // Requires a constBuilderCall defined. 53 string defaultValue = ?; 54 55 // The value type of this attribute. This corresponds to the mlir::Type that 56 // this attribute returns via `getType()`. 57 Type valueType = ?; 58 59 // Whether the attribute is optional. Typically requires a custom 60 // convertFromStorage method to handle the case where the attribute is 61 // not present. 62 bit isOptional = 0; 63 64 // What is the base-level Attr instantiation that this Attr is built upon. 65 // Unset means this is a base-level Attr. 66 // 67 // This field is used by attribute wrapper classes (DefaultValuedAttr, 68 // OptionalAttr, etc.) to retrieve the base-level attribute definition. 69 // This can be used for getting its name; otherwise, we will see 70 // "anonymous_<number>" as the attribute def name because of template 71 // instantiation. 72 // TOOD(b/132458159): deduplicate the fields in attribute wrapper classes. 73 Attr baseAttr = ?; 74 75 // The fully-qualified C++ namespace where the generated class lives. 76 string cppNamespace = ""; 77 78 // The full description of this attribute. 79 string description = ""; 80} 81 82// An attribute of a specific dialect. 83class DialectAttr<Dialect d, Pred condition, string summary = ""> : 84 Attr<condition, summary> { 85 Dialect dialect = d; 86 let cppNamespace = d.cppNamespace; 87} 88 89//===----------------------------------------------------------------------===// 90// Attribute modifier definition 91 92// Decorates an attribute to have an (unvalidated) default value if not present. 93class DefaultValuedAttr<Attr attr, string val> : 94 Attr<attr.predicate, attr.summary> { 95 // Construct this attribute with the input attribute and change only 96 // the default value. 97 // Note: this has to be kept up to date with Attr above. 98 let storageType = attr.storageType; 99 let returnType = attr.returnType; 100 let convertFromStorage = attr.convertFromStorage; 101 let constBuilderCall = attr.constBuilderCall; 102 let defaultValue = val; 103 let valueType = attr.valueType; 104 105 let baseAttr = attr; 106} 107 108// Decorates an optional attribute to have an (unvalidated) default value 109// return by ODS generated accessors if not present. 110class DefaultValuedOptionalAttr<Attr attr, string val> : 111 Attr<attr.predicate, attr.summary> { 112 // Construct this attribute with the input attribute and change only 113 // the default value. 114 // Note: this has to be kept up to date with Attr above. 115 let storageType = attr.storageType; 116 let returnType = attr.returnType; 117 let convertFromStorage = attr.convertFromStorage; 118 let constBuilderCall = attr.constBuilderCall; 119 let defaultValue = val; 120 let valueType = attr.valueType; 121 let isOptional = 1; 122 123 let baseAttr = attr; 124} 125 126// Decorates an attribute as optional. The return type of the generated 127// attribute accessor method will be Optional<>. 128class OptionalAttr<Attr attr> : Attr<attr.predicate, attr.summary> { 129 // Rewrite the attribute to be optional. 130 // Note: this has to be kept up to date with Attr above. 131 let storageType = attr.storageType; 132 let returnType = "::std::optional<" # attr.returnType #">"; 133 let convertFromStorage = "$_self ? " # returnType # "(" # 134 attr.convertFromStorage # ") : (::std::nullopt)"; 135 let valueType = attr.valueType; 136 let isOptional = 1; 137 138 let baseAttr = attr; 139} 140 141// Default-valued string-based attribute. Wraps the default value in escaped 142// quotes. 143class DefaultValuedStrAttr<Attr attr, string val> 144 : DefaultValuedAttr<attr, "\"" # val # "\"">; 145class DefaultValuedOptionalStrAttr<Attr attr, string val> 146 : DefaultValuedOptionalAttr<attr, "\"" # val # "\"">; 147 148//===----------------------------------------------------------------------===// 149// Primitive attribute kinds 150 151// A generic attribute that must be constructed around a specific buildable type 152// `attrValType`. Backed by MLIR attribute kind `attrKind`. 153class TypedAttrBase<Type attrValType, string attrKind, Pred condition, 154 string descr> : 155 Attr<condition, descr> { 156 let constBuilderCall = "$_builder.get" # attrKind # "(" # 157 attrValType.builderCall # ", $0)"; 158 let storageType = "::mlir::" # attrKind; 159 let valueType = attrValType; 160} 161 162// Any attribute. 163def AnyAttr : Attr<CPred<"true">, "any attribute"> { 164 let storageType = "::mlir::Attribute"; 165 let returnType = "::mlir::Attribute"; 166 let convertFromStorage = "$_self"; 167 let constBuilderCall = "$0"; 168} 169 170// Any attribute from the given list 171class AnyAttrOf<list<Attr> allowedAttrs, string summary = "", 172 string cppType = "::mlir::Attribute", 173 string fromStorage = "$_self"> : Attr< 174 // Satisfy any of the allowed attribute's condition 175 Or<!foreach(allowedattr, allowedAttrs, allowedattr.predicate)>, 176 !if(!eq(summary, ""), 177 !interleave(!foreach(t, allowedAttrs, t.summary), " or "), 178 summary)> { 179 let returnType = cppType; 180 let convertFromStorage = fromStorage; 181 list<Attr> allowedAttributes = allowedAttrs; 182} 183 184def LocationAttr : Attr<CPred<"::llvm::isa<::mlir::LocationAttr>($_self)">, 185 "location attribute">; 186 187def BoolAttr : Attr<CPred<"::llvm::isa<::mlir::BoolAttr>($_self)">, "bool attribute"> { 188 let storageType = [{ ::mlir::BoolAttr }]; 189 let returnType = [{ bool }]; 190 let valueType = I1; 191 let constBuilderCall = "$_builder.getBoolAttr($0)"; 192} 193 194// Index attribute. 195def IndexAttr : 196 TypedAttrBase< 197 Index, "IntegerAttr", 198 And<[CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">, 199 CPred<"::llvm::isa<::mlir::IndexType>(::llvm::cast<::mlir::IntegerAttr>($_self).getType())">]>, 200 "index attribute"> { 201 let returnType = [{ ::llvm::APInt }]; 202} 203 204// Base class for any integer (regardless of signedness semantics) attributes 205// of fixed width. 206class AnyIntegerAttrBase<AnyI attrValType, string descr> : 207 TypedAttrBase< 208 attrValType, "IntegerAttr", 209 And<[CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">, 210 CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getType()." 211 "isInteger(" # attrValType.bitwidth # ")">]>, 212 descr> { 213 let returnType = [{ ::llvm::APInt }]; 214 let constBuilderCall = ?; 215} 216 217def AnyI1Attr : AnyIntegerAttrBase<AnyI1, "1-bit integer attribute">; 218def AnyI8Attr : AnyIntegerAttrBase<AnyI8, "8-bit integer attribute">; 219def AnyI16Attr : AnyIntegerAttrBase<AnyI16, "16-bit integer attribute">; 220def AnyI32Attr : AnyIntegerAttrBase<AnyI32, "32-bit integer attribute">; 221def AnyI64Attr : AnyIntegerAttrBase<AnyI64, "64-bit integer attribute">; 222 223def APIntAttr : Attr<CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">, 224 "arbitrary integer attribute"> { 225 let storageType = [{ ::mlir::IntegerAttr }]; 226 let returnType = [{ ::mlir::APInt }]; 227} 228 229// Base class for signless integer attributes of fixed width. 230class SignlessIntegerAttrBase<I attrValType, string descr> : 231 TypedAttrBase< 232 attrValType, "IntegerAttr", 233 And<[CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">, 234 CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getType()." 235 "isSignlessInteger(" # attrValType.bitwidth # ")">]>, 236 descr> { 237 let returnType = [{ ::llvm::APInt }]; 238} 239// Base class for signless integer attributes of fixed width that have a 240// corresponding C++ type. 241class TypedSignlessIntegerAttrBase<I attrValType, string retType, string descr> 242 : SignlessIntegerAttrBase<attrValType, descr> { 243 let returnType = retType; 244 let convertFromStorage = "$_self.getValue().getZExtValue()"; 245} 246 247def I1Attr : TypedSignlessIntegerAttrBase< 248 I1, "bool", "1-bit signless integer attribute">; 249def I8Attr : TypedSignlessIntegerAttrBase< 250 I8, "uint8_t", "8-bit signless integer attribute">; 251def I16Attr : TypedSignlessIntegerAttrBase< 252 I16, "uint16_t", "16-bit signless integer attribute">; 253def I32Attr : TypedSignlessIntegerAttrBase< 254 I32, "uint32_t", "32-bit signless integer attribute">; 255def I64Attr : TypedSignlessIntegerAttrBase< 256 I64, "uint64_t", "64-bit signless integer attribute">; 257 258// Base class for signed integer attributes of fixed width. 259class SignedIntegerAttrBase<SI attrValType, string descr> : 260 TypedAttrBase< 261 attrValType, "IntegerAttr", 262 And<[CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">, 263 CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getType()." 264 "isSignedInteger(" # attrValType.bitwidth # ")">]>, 265 descr> { 266 let returnType = [{ ::llvm::APInt }]; 267} 268// Base class for signed integer attributes of fixed width that have a 269// corresponding C++ type. 270class TypedSignedIntegerAttrBase<SI attrValType, string retType, string descr> 271 : SignedIntegerAttrBase<attrValType, descr> { 272 let returnType = retType; 273 let convertFromStorage = "$_self.getValue().getSExtValue()"; 274} 275 276def SI1Attr : TypedSignedIntegerAttrBase< 277 SI1, "bool", "1-bit signed integer attribute">; 278def SI8Attr : TypedSignedIntegerAttrBase< 279 SI8, "int8_t", "8-bit signed integer attribute">; 280def SI16Attr : TypedSignedIntegerAttrBase< 281 SI16, "int16_t", "16-bit signed integer attribute">; 282def SI32Attr : TypedSignedIntegerAttrBase< 283 SI32, "int32_t", "32-bit signed integer attribute">; 284def SI64Attr : TypedSignedIntegerAttrBase< 285 SI64, "int64_t", "64-bit signed integer attribute">; 286 287// Base class for unsigned integer attributes of fixed width. 288class UnsignedIntegerAttrBase<UI attrValType, string descr> : 289 TypedAttrBase< 290 attrValType, "IntegerAttr", 291 And<[CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">, 292 CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getType()." 293 "isUnsignedInteger(" # attrValType.bitwidth # ")">]>, 294 descr> { 295 let returnType = [{ ::llvm::APInt }]; 296} 297// Base class for unsigned integer attributes of fixed width that have a 298// corresponding C++ type. 299class TypedUnsignedIntegerAttrBase<UI attrValType, string retType, string descr> 300 : UnsignedIntegerAttrBase<attrValType, descr> { 301 let returnType = retType; 302 let convertFromStorage = "$_self.getValue().getZExtValue()"; 303} 304 305def UI1Attr : TypedUnsignedIntegerAttrBase< 306 UI1, "bool", "1-bit unsigned integer attribute">; 307def UI8Attr : TypedUnsignedIntegerAttrBase< 308 UI8, "uint8_t", "8-bit unsigned integer attribute">; 309def UI16Attr : TypedUnsignedIntegerAttrBase< 310 UI16, "uint16_t", "16-bit unsigned integer attribute">; 311def UI32Attr : TypedUnsignedIntegerAttrBase< 312 UI32, "uint32_t", "32-bit unsigned integer attribute">; 313def UI64Attr : TypedUnsignedIntegerAttrBase< 314 UI64, "uint64_t", "64-bit unsigned integer attribute">; 315 316// Base class for float attributes of fixed width. 317class FloatAttrBase<F attrValType, string descr> : 318 TypedAttrBase<attrValType, "FloatAttr", 319 And<[CPred<"::llvm::isa<::mlir::FloatAttr>($_self)">, 320 CPred<"::llvm::cast<::mlir::FloatAttr>($_self).getType().isF" # 321 attrValType.bitwidth # "()">]>, 322 descr> { 323 let returnType = [{ ::llvm::APFloat }]; 324} 325 326def F32Attr : FloatAttrBase<F32, "32-bit float attribute">; 327def F64Attr : FloatAttrBase<F64, "64-bit float attribute">; 328 329// An attribute backed by a string type. 330class StringBasedAttr<Pred condition, string descr> : Attr<condition, descr> { 331 let constBuilderCall = "$_builder.getStringAttr($0)"; 332 let storageType = [{ ::mlir::StringAttr }]; 333 let returnType = [{ ::llvm::StringRef }]; 334 let valueType = NoneType; 335} 336 337def StrAttrPred : CPred<"::llvm::isa<::mlir::StringAttr>($_self)">; 338 339def StrAttr : StringBasedAttr<StrAttrPred, "string attribute">; 340 341// A string attribute that represents the name of a symbol. 342def SymbolNameAttr : StringBasedAttr<StrAttrPred, "string attribute">; 343 344// String attribute that has a specific value type. 345class TypedStrAttr<Type ty> 346 : StringBasedAttr<And<[StrAttrPred, 347 SubstLeaves<"$_self", "::mlir::cast<StringAttr>($_self).getType()", 348 ty.predicate>]>, 349 "string attribute of " # ty.summary> { 350 let valueType = ty; 351} 352 353// Base class for attributes containing types. Example: 354// def IntTypeAttr : TypeAttrBase<"IntegerType", "integer type attribute"> 355// defines a type attribute containing an integer type. 356class TypeAttrBase<string retType, string summary, 357 Pred typePred = CPred<"true">> : 358 Attr<And<[ 359 CPred<"::llvm::isa<::mlir::TypeAttr>($_self)">, 360 CPred<"::llvm::isa<" # retType # ">(::llvm::cast<::mlir::TypeAttr>($_self).getValue())">, 361 SubstLeaves<"$_self", 362 "::llvm::cast<::mlir::TypeAttr>($_self).getValue()", typePred>]>, 363 summary> { 364 let storageType = [{ ::mlir::TypeAttr }]; 365 let returnType = retType; 366 let valueType = NoneType; 367 let convertFromStorage = "::llvm::cast<" # retType # ">($_self.getValue())"; 368} 369 370def TypeAttr : TypeAttrBase<"::mlir::Type", "any type attribute"> { 371 let constBuilderCall = "::mlir::TypeAttr::get($0)"; 372} 373 374class TypeAttrOf<Type ty> 375 : TypeAttrBase<ty.cppType, "type attribute of " # ty.summary, 376 ty.predicate> { 377 let constBuilderCall = "::mlir::TypeAttr::get($0)"; 378} 379 380// The mere presence of unit attributes has a meaning. Therefore, unit 381// attributes are always treated as optional and accessors to them return 382// "true" if the attribute is present and "false" otherwise. 383def UnitAttr : Attr<CPred<"::llvm::isa<::mlir::UnitAttr>($_self)">, "unit attribute"> { 384 let storageType = [{ ::mlir::UnitAttr }]; 385 let constBuilderCall = "(($0) ? $_builder.getUnitAttr() : nullptr)"; 386 let convertFromStorage = "$_self != nullptr"; 387 let returnType = "bool"; 388 let defaultValue = "false"; 389 let valueType = NoneType; 390 let isOptional = 1; 391} 392 393//===----------------------------------------------------------------------===// 394// Composite attribute kinds 395 396class DictionaryAttrBase<Pred condition, string summary> : 397 Attr<condition, summary> { 398 let storageType = [{ ::mlir::DictionaryAttr }]; 399 let constBuilderCall = "$_builder.getDictionaryAttr($0)"; 400 let returnType = [{ ::mlir::DictionaryAttr }]; 401 let valueType = NoneType; 402 let convertFromStorage = "$_self"; 403} 404 405def DictionaryAttr 406 : DictionaryAttrBase<CPred<"::llvm::isa<::mlir::DictionaryAttr>($_self)">, 407 "dictionary of named attribute values">; 408 409class ElementsAttrBase<Pred condition, string summary> : 410 Attr<condition, summary> { 411 let storageType = [{ ::mlir::ElementsAttr }]; 412 let returnType = [{ ::mlir::ElementsAttr }]; 413 let convertFromStorage = "$_self"; 414} 415 416def ElementsAttr : ElementsAttrBase<CPred<"::llvm::isa<::mlir::ElementsAttr>($_self)">, 417 "constant vector/tensor attribute">; 418 419class IntElementsAttrBase<Pred condition, string summary> : 420 ElementsAttrBase<And<[CPred<"::llvm::isa<::mlir::DenseIntElementsAttr>($_self)">, 421 condition]>, 422 summary> { 423 let storageType = [{ ::mlir::DenseIntElementsAttr }]; 424 let returnType = [{ ::mlir::DenseIntElementsAttr }]; 425 426 let convertFromStorage = "$_self"; 427} 428 429class DenseArrayAttrBase<string denseAttrName, string cppType, string summaryName> : 430 ElementsAttrBase<CPred<"::llvm::isa<::mlir::" # denseAttrName # ">($_self)">, 431 summaryName # " dense array attribute"> { 432 let storageType = "::mlir::" # denseAttrName; 433 let returnType = "::llvm::ArrayRef<" # cppType # ">"; 434 let constBuilderCall = "$_builder.get" # denseAttrName # "($0)"; 435} 436def DenseBoolArrayAttr : DenseArrayAttrBase<"DenseBoolArrayAttr", "bool", "i1">; 437def DenseI8ArrayAttr : DenseArrayAttrBase<"DenseI8ArrayAttr", "int8_t", "i8">; 438def DenseI16ArrayAttr : DenseArrayAttrBase<"DenseI16ArrayAttr", "int16_t", "i16">; 439def DenseI32ArrayAttr : DenseArrayAttrBase<"DenseI32ArrayAttr", "int32_t", "i32">; 440def DenseI64ArrayAttr : DenseArrayAttrBase<"DenseI64ArrayAttr", "int64_t", "i64">; 441def DenseF32ArrayAttr : DenseArrayAttrBase<"DenseF32ArrayAttr", "float", "f32">; 442def DenseF64ArrayAttr : DenseArrayAttrBase<"DenseF64ArrayAttr", "double", "f64">; 443 444def IndexElementsAttr 445 : IntElementsAttrBase<CPred<[{::llvm::cast<::mlir::DenseIntElementsAttr>($_self) 446 .getType() 447 .getElementType() 448 .isIndex()}]>, 449 "index elements attribute">; 450 451def AnyIntElementsAttr : IntElementsAttrBase<CPred<"true">, "integer elements attribute">; 452 453class IntElementsAttrOf<int width> : IntElementsAttrBase< 454 CPred<"::llvm::cast<::mlir::DenseIntElementsAttr>($_self).getType()." 455 "getElementType().isInteger(" # width # ")">, 456 width # "-bit integer elements attribute">; 457 458def AnyI32ElementsAttr : IntElementsAttrOf<32>; 459def AnyI64ElementsAttr : IntElementsAttrOf<64>; 460 461class SignlessIntElementsAttr<int width> : IntElementsAttrBase< 462 CPred<"::llvm::cast<::mlir::DenseIntElementsAttr>($_self).getType()." 463 "getElementType().isSignlessInteger(" # width # ")">, 464 width # "-bit signless integer elements attribute"> { 465 466 // Note that this is only constructing scalar elements attribute. 467 let constBuilderCall = "::llvm::cast<::mlir::DenseIntElementsAttr>(" 468 "::mlir::DenseElementsAttr::get(" 469 "::mlir::RankedTensorType::get({}, $_builder.getIntegerType(" # width # ")), " 470 "::llvm::ArrayRef($0)))"; 471} 472 473def I32ElementsAttr : SignlessIntElementsAttr<32>; 474def I64ElementsAttr : SignlessIntElementsAttr<64>; 475 476// A `width`-bit signless integer elements attribute. The attribute should be 477// ranked and has a shape as specified in `dims`. 478class RankedSignlessIntElementsAttr<int width, list<int> dims> : 479 SignlessIntElementsAttr<width> { 480 // Check that this has the specified shape. 481 let predicate = And<[ 482 SignlessIntElementsAttr<width>.predicate, 483 CPred<"::llvm::cast<::mlir::DenseIntElementsAttr>($_self).getType().getShape() == " 484 "::mlir::ArrayRef<int64_t>({" # !interleave(dims, ", ") # "})">]>; 485 486 let summary = width # "-bit signless int elements attribute of shape [" # 487 !interleave(dims, ", ") # "]"; 488 489 let constBuilderCall = "::mlir::DenseIntElementsAttr::get(" 490 "::mlir::RankedTensorType::get({" # !interleave(dims, ", ") # 491 "}, $_builder.getIntegerType(" # width # ")), ::llvm::ArrayRef($0))"; 492} 493 494class RankedI32ElementsAttr<list<int> dims> : 495 RankedSignlessIntElementsAttr<32, dims>; 496class RankedI64ElementsAttr<list<int> dims> : 497 RankedSignlessIntElementsAttr<64, dims>; 498 499class FloatElementsAttr<int width> : ElementsAttrBase< 500 CPred<"::llvm::isa<::mlir::DenseFPElementsAttr>($_self) &&" 501 "::llvm::cast<::mlir::DenseElementsAttr>($_self).getType()." 502 "getElementType().isF" # width # "()">, 503 width # "-bit float elements attribute"> { 504 505 let storageType = [{ ::mlir::DenseElementsAttr }]; 506 let returnType = [{ ::mlir::DenseElementsAttr }]; 507 508 // Note that this is only constructing scalar elements attribute. 509 let constBuilderCall = "::mlir::DenseElementsAttr::get(" 510 "::mlir::RankedTensorType::get({}, $_builder.getF" # width # "Type())," 511 "::llvm::ArrayRef($0))"; 512 let convertFromStorage = "$_self"; 513} 514 515def F64ElementsAttr : FloatElementsAttr<64>; 516 517// A `width`-bit floating point elements attribute. The attribute should be 518// ranked and has a shape as specified in `dims`. 519class RankedFloatElementsAttr<int width, list<int> dims> : ElementsAttrBase< 520 CPred<"::llvm::isa<::mlir::DenseFPElementsAttr>($_self) &&" 521 "::llvm::cast<::mlir::DenseFPElementsAttr>($_self).getType()." 522 "getElementType().isF" # width # "() && " 523 // Check that this is ranked and has the specified shape. 524 "::llvm::cast<::mlir::DenseFPElementsAttr>($_self).getType().hasRank() && " 525 "::llvm::cast<::mlir::DenseFPElementsAttr>($_self).getType().getShape() == " 526 "::mlir::ArrayRef<int64_t>({" # !interleave(dims, ", ") # "})">, 527 width # "-bit float elements attribute of shape [" # 528 !interleave(dims, ", ") # "]"> { 529 530 let storageType = [{ ::mlir::DenseFPElementsAttr }]; 531 let returnType = [{ ::mlir::DenseFPElementsAttr }]; 532 533 let constBuilderCall = "::llvm::cast<::mlir::DenseFPElementsAttr>(" 534 "::mlir::DenseElementsAttr::get(" 535 "::mlir::RankedTensorType::get({" # !interleave(dims, ", ") # 536 "}, $_builder.getF" # width # "Type()), " 537 "::llvm::ArrayRef($0)))"; 538 let convertFromStorage = "$_self"; 539} 540 541class RankedF32ElementsAttr<list<int> dims> : RankedFloatElementsAttr<32, dims>; 542class RankedF64ElementsAttr<list<int> dims> : RankedFloatElementsAttr<64, dims>; 543 544def StringElementsAttr : ElementsAttrBase< 545 CPred<"::llvm::isa<::mlir::DenseStringElementsAttr>($_self)" >, 546 "string elements attribute"> { 547 548 let storageType = [{ ::mlir::DenseElementsAttr }]; 549 let returnType = [{ ::mlir::DenseElementsAttr }]; 550 551 let convertFromStorage = "$_self"; 552} 553 554// Attributes containing affine maps. 555def AffineMapAttr : Attr< 556CPred<"::llvm::isa<::mlir::AffineMapAttr>($_self)">, "AffineMap attribute"> { 557 let storageType = [{::mlir::AffineMapAttr }]; 558 let returnType = [{ ::mlir::AffineMap }]; 559 let valueType = Index; 560 let constBuilderCall = "::mlir::AffineMapAttr::get($0)"; 561} 562 563// Attributes containing integer sets. 564def IntegerSetAttr : Attr< 565CPred<"::llvm::isa<::mlir::IntegerSetAttr>($_self)">, "IntegerSet attribute"> { 566 let storageType = [{::mlir::IntegerSetAttr }]; 567 let returnType = [{ ::mlir::IntegerSet }]; 568 let valueType = NoneType; 569 let constBuilderCall = "::mlir::IntegerSetAttr::get($0)"; 570} 571 572// Base class for array attributes. 573class ArrayAttrBase<Pred condition, string summary> : Attr<condition, summary> { 574 let storageType = [{ ::mlir::ArrayAttr }]; 575 let returnType = [{ ::mlir::ArrayAttr }]; 576 let valueType = NoneType; 577 let convertFromStorage = "$_self"; 578 let constBuilderCall = "$_builder.getArrayAttr($0)"; 579} 580 581def ArrayAttr : ArrayAttrBase<CPred<"::llvm::isa<::mlir::ArrayAttr>($_self)">, 582 "array attribute">; 583 584// Base class for array attributes whose elements are of the same kind. 585// `element` specifies the element attribute kind stored in this array. 586class TypedArrayAttrBase<Attr element, string summary>: ArrayAttrBase< 587 And<[ 588 // Guarantee this is an ArrayAttr first 589 CPred<"::llvm::isa<::mlir::ArrayAttr>($_self)">, 590 // Guarantee all elements satisfy the constraints from `element` 591 Concat<"::llvm::all_of(::llvm::cast<::mlir::ArrayAttr>($_self), " 592 "[&](::mlir::Attribute attr) { return attr && (", 593 SubstLeaves<"$_self", "attr", element.predicate>, 594 "); })">]>, 595 summary> { 596 597 Attr elementAttr = element; 598} 599 600def LocationArrayAttr : TypedArrayAttrBase<LocationAttr, 601 "location array attribute">; 602 603def AffineMapArrayAttr : TypedArrayAttrBase<AffineMapAttr, 604 "AffineMap array attribute"> { 605 let constBuilderCall = "$_builder.getAffineMapArrayAttr($0)"; 606} 607 608def BoolArrayAttr : TypedArrayAttrBase<BoolAttr, 609 "1-bit boolean array attribute"> { 610 let constBuilderCall = "$_builder.getBoolArrayAttr($0)"; 611} 612def I32ArrayAttr : TypedArrayAttrBase<I32Attr, 613 "32-bit integer array attribute"> { 614 let constBuilderCall = "$_builder.getI32ArrayAttr($0)"; 615} 616def I64ArrayAttr : TypedArrayAttrBase<I64Attr, 617 "64-bit integer array attribute"> { 618 let constBuilderCall = "$_builder.getI64ArrayAttr($0)"; 619} 620// Variant of I64ArrayAttr whose user accessor is SmallVector<in64_t>. 621def I64SmallVectorArrayAttr : 622 TypedArrayAttrBase<I64Attr, "64-bit integer array attribute"> { 623 let returnType = [{ ::llvm::SmallVector<int64_t, 8> }]; 624 let convertFromStorage = [{ 625 llvm::to_vector<4>( 626 llvm::map_range($_self.getAsRange<mlir::IntegerAttr>(), 627 [](mlir::IntegerAttr attr) { return attr.getInt(); })); 628 }]; 629 let constBuilderCall = "$_builder.getI64ArrayAttr($0)"; 630} 631def F32ArrayAttr : TypedArrayAttrBase<F32Attr, "32-bit float array attribute"> { 632 let constBuilderCall = "$_builder.getF32ArrayAttr($0)"; 633} 634def F64ArrayAttr : TypedArrayAttrBase<F64Attr, "64-bit float array attribute"> { 635 let constBuilderCall = "$_builder.getF64ArrayAttr($0)"; 636} 637def StrArrayAttr : TypedArrayAttrBase<StrAttr, "string array attribute"> { 638 let constBuilderCall = "$_builder.getStrArrayAttr($0)"; 639} 640def TypeArrayAttr : TypedArrayAttrBase<TypeAttr, "type array attribute"> { 641 let constBuilderCall = "$_builder.getTypeArrayAttr($0)"; 642} 643def IndexListArrayAttr : 644 TypedArrayAttrBase<I64ArrayAttr, "Array of 64-bit integer array attributes">; 645def DictArrayAttr : 646 TypedArrayAttrBase<DictionaryAttr, "Array of dictionary attributes">; 647 648// Attributes containing symbol references. 649def SymbolRefAttr : Attr<CPred<"::llvm::isa<::mlir::SymbolRefAttr>($_self)">, 650 "symbol reference attribute"> { 651 let storageType = [{ ::mlir::SymbolRefAttr }]; 652 let returnType = [{ ::mlir::SymbolRefAttr }]; 653 let valueType = NoneType; 654 let constBuilderCall = 655 "::mlir::SymbolRefAttr::get($_builder.getContext(), $0)"; 656 let convertFromStorage = "$_self"; 657} 658 659def FlatSymbolRefAttr : Attr<CPred<"::llvm::isa<::mlir::FlatSymbolRefAttr>($_self)">, 660 "flat symbol reference attribute"> { 661 let storageType = [{ ::mlir::FlatSymbolRefAttr }]; 662 let returnType = [{ ::llvm::StringRef }]; 663 let valueType = NoneType; 664 let constBuilderCall = 665 "::mlir::SymbolRefAttr::get($_builder.getContext(), $0)"; 666 let convertFromStorage = "$_self.getValue()"; 667} 668 669def SymbolRefArrayAttr : 670 TypedArrayAttrBase<SymbolRefAttr, "symbol ref array attribute"> { 671 let constBuilderCall = ?; 672} 673 674def FlatSymbolRefArrayAttr : 675 TypedArrayAttrBase<FlatSymbolRefAttr, "flat symbol ref array attribute"> { 676 let constBuilderCall = ?; 677} 678 679//===----------------------------------------------------------------------===// 680// Derive attribute kinds 681 682// DerivedAttr are attributes whose value is computed from properties 683// of the operation. They do not require additional storage and are 684// materialized as needed. 685// Note: All derived attributes should be materializable as an Attribute. E.g., 686// do not use DerivedAttr for things that could not have been stored as 687// Attribute. 688// 689class DerivedAttr<code ret, code b, code convert = ""> : 690 Attr<CPred<"true">, "derived attribute"> { 691 let returnType = ret; 692 code body = b; 693 694 // Specify how to convert from the derived attribute to an attribute. 695 // 696 // ## Special placeholders 697 // 698 // Special placeholders can be used to refer to entities during conversion: 699 // 700 // * `$_builder` will be replaced by a mlir::Builder instance. 701 // * `$_ctxt` will be replaced by the MLIRContext* instance. 702 // * `$_self` will be replaced with the derived attribute (value produces 703 // `returnType`). 704 let convertFromStorage = convert; 705} 706 707// Derived attribute that returns a mlir::Type. 708class DerivedTypeAttr<code body> : DerivedAttr<"::mlir::Type", body> { 709 let convertFromStorage = "::mlir::TypeAttr::get($_self)"; 710} 711 712//===----------------------------------------------------------------------===// 713// Constant attribute kinds 714 715// Represents a constant attribute of specific Attr type. A constant 716// attribute can be specified only of attributes that have a constant 717// builder call defined. The constant value is specified as a string. 718// 719// If used as a constraint, it generates a matcher on a constant attribute by 720// using the constant value builder of the attribute and the value. 721class ConstantAttr<Attr attribute, string val> : AttrConstraint< 722 CPred<"$_self == " # !subst("$0", val, attribute.constBuilderCall)>, 723 "constant attribute " # val> { 724 Attr attr = attribute; 725 string value = val; 726} 727 728class ConstF32Attr<string val> : ConstantAttr<F32Attr, val>; 729def ConstBoolAttrFalse : ConstantAttr<BoolAttr, "false">; 730def ConstBoolAttrTrue : ConstantAttr<BoolAttr, "true">; 731def ConstUnitAttr : ConstantAttr<UnitAttr, "true">; 732 733// Constant string-based attribute. Wraps the desired string in escaped quotes. 734class ConstantStrAttr<Attr attribute, string val> 735 : ConstantAttr<attribute, "\"" # val # "\"">; 736 737//===----------------------------------------------------------------------===// 738// Common attribute constraints 739//===----------------------------------------------------------------------===// 740 741// A general mechanism to further confine the given `attr` with all the 742// `constraints`. This allows to compose complex constraints out of a series 743// of more primitive ones. 744class ConfinedAttr<Attr attr, list<AttrConstraint> constraints> : Attr< 745 And<!listconcat([attr.predicate], 746 !foreach(pred, constraints, pred.predicate))>, 747 !foldl(/*init*/attr.summary, /*list*/constraints, 748 prev, cur, prev # " " # cur.summary)> { 749 let storageType = attr.storageType; 750 let returnType = attr.returnType; 751 let convertFromStorage = attr.convertFromStorage; 752 let constBuilderCall = attr.constBuilderCall; 753 let defaultValue = attr.defaultValue; 754 let valueType = attr.valueType; 755 let isOptional = attr.isOptional; 756 757 let baseAttr = attr; 758 759 list<AttrConstraint> attrConstraints = constraints; 760} 761 762// An AttrConstraint that holds if all attr constraints specified in 763// 'constraints' hold. 764class AllAttrOf<list<AttrConstraint> constraints> : AttrConstraint< 765 And<!listconcat([!head(constraints).predicate], 766 !foreach(pred, !tail(constraints), pred.predicate))>, 767 !interleave(!foreach(con, constraints, con.summary), " and ")> { 768} 769 770class IntNEQValue<int n> : AttrConstraint< 771 CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getInt() != " # n>, 772 "whose value is not " # n>; 773 774class IntMinValue<int n> : AttrConstraint< 775 CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getInt() >= " # n>, 776 "whose minimum value is " # n>; 777 778class IntMaxValue<int n> : AttrConstraint< 779 CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getInt() <= " # n>, 780 "whose maximum value is " # n>; 781 782def IntNonNegative : AttrConstraint< 783 CPred<"!::llvm::cast<::mlir::IntegerAttr>($_self).getValue().isNegative()">, 784 "whose value is non-negative">; 785 786def IntPositive : AttrConstraint< 787 CPred<"::llvm::cast<::mlir::IntegerAttr>($_self).getValue().isStrictlyPositive()">, 788 "whose value is positive">; 789 790class ArrayMaxCount<int n> : AttrConstraint< 791 CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() <= " # n>, 792 "with at most " # n # " elements">; 793 794class ArrayMinCount<int n> : AttrConstraint< 795 CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() >= " # n>, 796 "with at least " # n # " elements">; 797 798class ArrayCount<int n> : AttrConstraint< 799 CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() == " #n>, 800 "with exactly " # n # " elements">; 801 802class DenseArrayCount<int n> : AttrConstraint< 803 CPred<"::llvm::cast<::mlir::DenseArrayAttr>($_self).size() == " #n>, 804 "with exactly " # n # " elements">; 805 806class DenseArrayMaxCt<int n> : AttrConstraint< 807 CPred<"::llvm::cast<::mlir::DenseArrayAttr>($_self).size() <= " # n>, 808 "with at most " # n # " elements">; 809 810class DenseArrayMinCt<int n> : AttrConstraint< 811 CPred<"::llvm::cast<::mlir::DenseArrayAttr>($_self).size() >= " # n>, 812 "with at least " # n # " elements">; 813 814class DenseArrayStrictlyPositive<DenseArrayAttrBase arrayType> : AttrConstraint< 815 CPred<"::llvm::all_of(::llvm::cast<" # arrayType #">($_self).asArrayRef(), " 816 "[&](auto v) { return v > 0; })">, 817 "whose value is positive">; 818 819class DenseArrayNonNegative<DenseArrayAttrBase arrayType> : AttrConstraint< 820 CPred<"::llvm::all_of(::llvm::cast<" # arrayType #">($_self).asArrayRef(), " 821 "[&](auto v) { return v >= 0; })">, 822 "whose value is non-negative">; 823 824class DenseArraySorted<DenseArrayAttrBase arrayType> : AttrConstraint< 825 CPred<"llvm::is_sorted(::llvm::cast<" # arrayType # ">($_self).asArrayRef())">, 826 "should be in non-decreasing order">; 827 828class DenseArrayStrictlySorted<DenseArrayAttrBase arrayType> : AttrConstraint< 829 And<[ 830 CPred<"llvm::is_sorted(::llvm::cast<" # arrayType # ">($_self).asArrayRef())">, 831 // Check that no two adjacent elements are the same. 832 CPred<"[](" # arrayType.returnType # " a) {\n" 833 "return std::adjacent_find(std::begin(a), std::end(a)) == " 834 "std::end(a);\n" 835 "}(::llvm::cast<" # arrayType # ">($_self).asArrayRef())" 836 >]>, 837 "should be in increasing order">; 838 839class IntArrayNthElemEq<int index, int value> : AttrConstraint< 840 And<[ 841 CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() > " # index>, 842 CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<::mlir::ArrayAttr>($_self)[" 843 # index # "]).getInt() == " # value> 844 ]>, 845 "whose " # index # "-th element must be " # value>; 846 847class IntArrayNthElemMinValue<int index, int min> : AttrConstraint< 848 And<[ 849 CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() > " # index>, 850 CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<::mlir::ArrayAttr>($_self)[" 851 # index # "]).getInt() >= " # min> 852 ]>, 853 "whose " # index # "-th element must be at least " # min>; 854 855class IntArrayNthElemMaxValue<int index, int max> : AttrConstraint< 856 And<[ 857 CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() > " # index>, 858 CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<::mlir::ArrayAttr>($_self)[" 859 # index # "]).getInt() <= " # max> 860 ]>, 861 "whose " # index # "-th element must be at most " # max>; 862 863class IntArrayNthElemInRange<int index, int min, int max> : AttrConstraint< 864 And<[ 865 CPred<"::llvm::cast<::mlir::ArrayAttr>($_self).size() > " # index>, 866 CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<::mlir::ArrayAttr>($_self)[" 867 # index # "]).getInt() >= " # min>, 868 CPred<"::llvm::cast<::mlir::IntegerAttr>(::llvm::cast<::mlir::ArrayAttr>($_self)[" 869 # index # "]).getInt() <= " # max> 870 ]>, 871 "whose " # index # "-th element must be at least " # min # " and at most " # max>; 872 873def IsNullAttr : AttrConstraint< 874 CPred<"!$_self">, "empty attribute (for optional attributes)">; 875 876#endif // COMMON_ATTR_CONSTRAINTS_TD 877