From 5b2cc6c3d0024d0d05e881d74d63be0ea2dca546 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Wed, 4 Mar 2020 14:41:27 -0500 Subject: [PATCH] [mlir][ods] Improve integer signedness modelling A previous commit added support for integer signedness in C++ IntegerType. This change introduces ODS definitions for integer types and integer (element) attributes w.r.t. signedness. This commit also updates various existing definitions' descriptions to mention signless where suitable to make it more clear. Positive and non-negative integer attributes are removed to avoid the explosion of subclasses. Instead, one should use more atmoic constraints together with Confined to model that. For example, `Confined<..., [IntPositive]>`. Differential Revision: https://reviews.llvm.org/D75610 --- mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 14 +- mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td | 6 +- mlir/include/mlir/Dialect/StandardOps/IR/Ops.td | 3 +- mlir/include/mlir/IR/OpBase.td | 228 +++++++++++++++++------- mlir/test/Dialect/LLVMIR/global.mlir | 4 +- mlir/test/Dialect/Loops/invalid.mlir | 2 +- mlir/test/Dialect/SPIRV/ops.mlir | 2 +- mlir/test/IR/attribute.mlir | 153 ++++++++++++++-- mlir/test/IR/invalid-ops.mlir | 18 +- mlir/test/lib/TestDialect/TestOps.td | 32 +++- mlir/test/mlir-tblgen/predicate.td | 4 +- mlir/test/mlir-tblgen/types.mlir | 53 ++++-- 12 files changed, 399 insertions(+), 120 deletions(-) diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index 66d5f9d..b458540 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -565,11 +565,15 @@ def LLVM_AddressOfOp def LLVM_GlobalOp : LLVM_ZeroResultOp<"mlir.global", [IsolatedFromAbove, - SingleBlockImplicitTerminator<"ReturnOp">, Symbol]>, - Arguments<(ins TypeAttr:$type, UnitAttr:$constant, StrAttr:$sym_name, - Linkage:$linkage, - OptionalAttr:$value, - DefaultValuedAttr:$addr_space)> { + SingleBlockImplicitTerminator<"ReturnOp">, Symbol]> { + let arguments = (ins + TypeAttr:$type, + UnitAttr:$constant, + StrAttr:$sym_name, + Linkage:$linkage, + OptionalAttr:$value, + DefaultValuedAttr, "0">:$addr_space + ); let summary = "LLVM dialect global."; let description = [{ Can contain an optional initializer region or attribute for simple diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td b/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td index 2dbee40..65bdd1e 100644 --- a/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td +++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td @@ -63,7 +63,7 @@ class SPV_BitEnumAttr cases> : BitEnumAttr { let predicate = And<[ - IntegerAttrBase.predicate, + I32Attr.predicate, SPV_IsKnownEnumCaseFor, ]>; let cppNamespace = "::mlir::spirv"; @@ -74,7 +74,7 @@ class SPV_I32EnumAttr cases> : I32EnumAttr { let predicate = And<[ - IntegerAttrBase.predicate, + I32Attr.predicate, SPV_IsKnownEnumCaseFor, ]>; let cppNamespace = "::mlir::spirv"; @@ -2955,7 +2955,7 @@ def SPV_IsStructType : CPred<"$_self.isa<::mlir::spirv::StructType>()">; def SPV_Void : TypeAlias; def SPV_Bool : I<1>; -def SPV_Integer : IntOfWidths<[8, 16, 32, 64]>; +def SPV_Integer : AnyIntOfWidths<[8, 16, 32, 64]>; def SPV_Float : FloatOfWidths<[16, 32, 64]>; def SPV_Float16or32 : FloatOfWidths<[16, 32]>; def SPV_Vector : VectorOfLengthAndType<[2, 3, 4], diff --git a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td index a9217b3..2fe0365 100644 --- a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td +++ b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td @@ -253,7 +253,8 @@ def AssumeAlignmentOp : Std_Op<"assume_alignment"> { This operation doesn't affect the semantics of a correct program. It's for optimization only, and the optimization is best-effort. }]; - let arguments = (ins AnyMemRef:$memref, PositiveI32Attr:$alignment); + let arguments = (ins AnyMemRef:$memref, + Confined:$alignment); let results = (outs); let assemblyFormat = "$memref `,` $alignment attr-dict `:` type($memref)"; diff --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td index d431d4e..2bc6546 100644 --- a/mlir/include/mlir/IR/OpBase.td +++ b/mlir/include/mlir/IR/OpBase.td @@ -313,25 +313,41 @@ class AnyTypeOf allowedTypes, string description = ""> : Type< description)>; // Integer types. -// Any integer type irrespective of its width. -def AnySignlessInteger : Type< - CPred<"$_self.isSignlessInteger()">, "integer">; -// Index type. -def Index : Type()">, "index">, - BuildableType<"$_builder.getIndexType()">; +// Any integer type irrespective of its width and signedness semantics. +def AnyInteger : Type, "integer">; + +// Any integer type (regardless of signedness semantics) of a specific width. +class AnyI + : Type, width # "-bit integer"> { + int bitwidth = width; +} -// Integer type of a specific width. +class AnyIntOfWidths widths> : + AnyTypeOf), + StrJoinInt.result # "-bit integer">; + +def AnyI1 : AnyI<1>; +def AnyI8 : AnyI<8>; +def AnyI16 : AnyI<16>; +def AnyI32 : AnyI<32>; +def AnyI64 : AnyI<64>; + +// Any signless integer type irrespective of its width. +def AnySignlessInteger : Type< + CPred<"$_self.isSignlessInteger()">, "signless integer">; + +// Signless integer type of a specific width. class I : Type, - width # "-bit integer">, + width # "-bit signless integer">, BuildableType<"$_builder.getIntegerType(" # width # ")"> { int bitwidth = width; } -class IntOfWidths widths> : +class SignlessIntOfWidths widths> : AnyTypeOf), - StrJoinInt.result # "-bit integer">; + StrJoinInt.result # "-bit signless integer">; def I1 : I<1>; def I8 : I<8>; @@ -339,7 +355,29 @@ def I16 : I<16>; def I32 : I<32>; def I64 : I<64>; -// Unsigned integer types. +// Any signed integer type irrespective of its width. +def AnySignedInteger : Type< + CPred<"$_self.isSignedInteger()">, "signed integer">; + +// Signed integer type of a specific width. +class SI + : Type, + width # "-bit signed integer">, + BuildableType< + "$_builder.getIntegerType(" # width # ", /*isSigned=*/true)"> { + int bitwidth = width; +} + +class SignedIntOfWidths widths> : + AnyTypeOf), + StrJoinInt.result # "-bit signed integer">; + +def SI1 : SI<1>; +def SI8 : SI<8>; +def SI16 : SI<16>; +def SI32 : SI<32>; +def SI64 : SI<64>; + // Any unsigned integer type irrespective of its width. def AnyUnsignedInteger : Type< CPred<"$_self.isUnsignedInteger()">, "unsigned integer">; @@ -348,8 +386,8 @@ def AnyUnsignedInteger : Type< class UI : Type, width # "-bit unsigned integer">, - BuildableType<"$_builder.getIntegerType(" # width # - ", /*isSigned=*/false)"> { + BuildableType< + "$_builder.getIntegerType(" # width # ", /*isSigned=*/false)"> { int bitwidth = width; } @@ -363,6 +401,10 @@ def UI16 : UI<16>; def UI32 : UI<32>; def UI64 : UI<64>; +// Index type. +def Index : Type()">, "index">, + BuildableType<"$_builder.getIndexType()">; + // Floating point types. // Any float type irrespective of its width. @@ -613,23 +655,23 @@ def BoolLike : TypeConstraint.predicate, TensorOf<[I1]>.predicate]>, "bool-like">; -// Type constraint for integer-like types: integers, indices, vectors of -// integers, tensors of integers. +// Type constraint for signless-integer-like types: signless integers, indices, +// vectors of signless integers, tensors of signless integers. def SignlessIntegerLike : TypeConstraint.predicate, TensorOf<[AnySignlessInteger]>.predicate]>, - "integer-like">; + "signless-integer-like">; // Type constraint for float-like types: floats, vectors or tensors thereof. def FloatLike : TypeConstraint.predicate, TensorOf<[AnyFloat]>.predicate]>, "floating-point-like">; -// Type constraint for integer-like or float-like types. +// Type constraint for signless-integer-like or float-like types. def SignlessIntegerOrFloatLike : TypeConstraint, - "integer-like or floating-point-like">; + "signless-integer-like or floating-point-like">; //===----------------------------------------------------------------------===// @@ -750,57 +792,91 @@ def BoolAttr : Attr()">, "bool attribute"> { let constBuilderCall = "$_builder.getBoolAttr($0)"; } -// Base class for integer attributes of fixed width. -class IntegerAttrBase : +// Base class for any integer (regardless of signedness semantics) attributes +// of fixed width. +class AnyIntegerAttrBase : TypedAttrBase< attrValType, "IntegerAttr", And<[CPred<"$_self.isa()">, CPred<"$_self.cast().getType()." - "isSignlessInteger(" # attrValType.bitwidth # ")">]>, + "isInteger(" # attrValType.bitwidth # ")">]>, descr> { let returnType = [{ APInt }]; + let constBuilderCall = ?; } +def AnyI1Attr : AnyIntegerAttrBase; +def AnyI8Attr : AnyIntegerAttrBase; +def AnyI16Attr : AnyIntegerAttrBase; +def AnyI32Attr : AnyIntegerAttrBase; +def AnyI64Attr : AnyIntegerAttrBase; + def APIntAttr : Attr()">, "arbitrary integer attribute"> { let storageType = [{ IntegerAttr }]; let returnType = [{ APInt }]; } -def I1Attr : IntegerAttrBase; -def I8Attr : IntegerAttrBase; -def I16Attr : IntegerAttrBase; -def I32Attr : IntegerAttrBase; -def I64Attr : IntegerAttrBase; +// Base class for signless integer attributes of fixed width. +class SignlessIntegerAttrBase : + TypedAttrBase< + attrValType, "IntegerAttr", + And<[CPred<"$_self.isa()">, + CPred<"$_self.cast().getType()." + "isSignlessInteger(" # attrValType.bitwidth # ")">]>, + descr> { + let returnType = [{ APInt }]; +} + +def I1Attr : SignlessIntegerAttrBase; +def I8Attr : SignlessIntegerAttrBase; +def I16Attr : SignlessIntegerAttrBase; +def I32Attr : SignlessIntegerAttrBase; +def I64Attr : SignlessIntegerAttrBase; -class NonNegativeIntAttrBase : +// Base class for signed integer attributes of fixed width. +class SignedIntegerAttrBase : TypedAttrBase< attrValType, "IntegerAttr", - And<[IntegerAttrBase.predicate, - CPred<"!$_self.cast().getValue().isNegative()">]>, + And<[CPred<"$_self.isa()">, + CPred<"$_self.cast().getType()." + "isSignedInteger(" # attrValType.bitwidth # ")">]>, descr> { let returnType = [{ APInt }]; } -def NonNegativeI32Attr : NonNegativeIntAttrBase< - I32, "non-negative 32-bit integer attribute">; -def NonNegativeI64Attr : NonNegativeIntAttrBase< - I64, "non-negative 64-bit integer attribute">; +def SI1Attr : SignedIntegerAttrBase< + SI1, "1-bit signed integer attribute">; +def SI8Attr : SignedIntegerAttrBase< + SI8, "8-bit signed integer attribute">; +def SI16Attr : SignedIntegerAttrBase< + SI16, "16-bit signed integer attribute">; +def SI32Attr : SignedIntegerAttrBase< + SI32, "32-bit signed integer attribute">; +def SI64Attr : SignedIntegerAttrBase< + SI64, "64-bit signed integer attribute">; -class PositiveIntAttrBase : +// Base class for unsigned integer attributes of fixed width. +class UnsignedIntegerAttrBase : TypedAttrBase< attrValType, "IntegerAttr", - And<[IntegerAttrBase.predicate, - CPred<"$_self.cast().getValue()" - ".isStrictlyPositive()">]>, + And<[CPred<"$_self.isa()">, + CPred<"$_self.cast().getType()." + "isUnsignedInteger(" # attrValType.bitwidth # ")">]>, descr> { let returnType = [{ APInt }]; } -def PositiveI32Attr : PositiveIntAttrBase< - I32, "positive 32-bit integer attribute">; -def PositiveI64Attr : PositiveIntAttrBase< - I64, "positive 64-bit integer attribute">; +def UI1Attr : UnsignedIntegerAttrBase< + UI1, "1-bit unsigned integer attribute">; +def UI8Attr : UnsignedIntegerAttrBase< + UI8, "8-bit unsigned integer attribute">; +def UI16Attr : UnsignedIntegerAttrBase< + UI16, "16-bit unsigned integer attribute">; +def UI32Attr : UnsignedIntegerAttrBase< + UI32, "32-bit unsigned integer attribute">; +def UI64Attr : UnsignedIntegerAttrBase< + UI64, "64-bit unsigned integer attribute">; // Base class for float attributes of fixed width. class FloatAttrBase : @@ -879,7 +955,7 @@ class StrEnumAttrCase : // its representation as a string and a C++ symbol name which may be different. class IntEnumAttrCaseBase : EnumAttrCaseInfo, - IntegerAttrBase { + SignlessIntegerAttrBase { let predicate = CPred<"$_self.cast().getInt() == " # intVal>; } @@ -896,7 +972,7 @@ class I64EnumAttrCase // one bit set. class BitEnumAttrCase : EnumAttrCaseInfo, - IntegerAttrBase { + SignlessIntegerAttrBase { let predicate = CPred< "$_self.cast().getValue().getZExtValue() & " # val # "u">; } @@ -982,11 +1058,11 @@ class StrEnumAttr cases> : EnumAttrInfo, - IntegerAttrBase.result, description)> { let predicate = And<[ - IntegerAttrBase.predicate, + SignlessIntegerAttrBase.predicate, Or]>; } @@ -1015,9 +1091,9 @@ class I64EnumAttr cases> : - EnumAttrInfo, IntegerAttrBase { + EnumAttrInfo, SignlessIntegerAttrBase { let predicate = And<[ - IntegerAttrBase.predicate, + I32Attr.predicate, // Make sure we don't have unknown bit set. CPred<"!($_self.cast().getValue().getZExtValue() & (~(" # StrJoin.result # @@ -1057,37 +1133,51 @@ class ElementsAttrBase : } def ElementsAttr : ElementsAttrBase()">, - "constant vector/tensor attribute">; - -class IntElementsAttr : ElementsAttrBase< - CPred<"$_self.isa() &&" - "$_self.cast().getType()." - "getElementType().isSignlessInteger(" # width # ")">, - width # "-bit integer elements attribute"> { + "constant vector/tensor attribute">; +class IntElementsAttrBase : + ElementsAttrBase()">, + condition]>, + description> { let storageType = [{ DenseIntElementsAttr }]; let returnType = [{ DenseIntElementsAttr }]; + let convertFromStorage = "$_self"; +} + +class AnyIntElementsAttr : IntElementsAttrBase< + CPred<"$_self.cast().getType()." + "getElementType().isInteger(" # width # ")">, + width # "-bit integer elements attribute">; + +def AnyI32ElementsAttr : AnyIntElementsAttr<32>; +def AnyI64ElementsAttr : AnyIntElementsAttr<64>; + +class SignlessIntElementsAttr : IntElementsAttrBase< + CPred<"$_self.cast().getType()." + "getElementType().isSignlessInteger(" # width # ")">, + width # "-bit signless integer elements attribute"> { + // Note that this is only constructing scalar elements attribute. let constBuilderCall = "DenseElementsAttr::get(" "RankedTensorType::get({}, $_builder.getIntegerType(" # width # ")), " "llvm::makeArrayRef($0)).cast()"; - let convertFromStorage = "$_self"; } -def I32ElementsAttr : IntElementsAttr<32>; -def I64ElementsAttr : IntElementsAttr<64>; +def I32ElementsAttr : SignlessIntElementsAttr<32>; +def I64ElementsAttr : SignlessIntElementsAttr<64>; -// A `width`-bit integer elements attribute. The attribute should be ranked and -// has a shape as specified in `dims`. -class RankedIntElementsAttr dims> : IntElementsAttr { +// A `width`-bit signless integer elements attribute. The attribute should be +// ranked and has a shape as specified in `dims`. +class RankedSignlessIntElementsAttr dims> : + SignlessIntElementsAttr { // Check that this has the specified shape. let predicate = And<[ - IntElementsAttr.predicate, + SignlessIntElementsAttr.predicate, CPred<"$_self.cast().getType().getShape() == " "ArrayRef({" # StrJoinInt.result # "})">]>; - let description = width # "-bit int elements attribute of shape [" # + let description = width # "-bit signless int elements attribute of shape [" # StrJoinInt.result # "]"; let constBuilderCall = "DenseIntElementsAttr::get(" @@ -1095,8 +1185,10 @@ class RankedIntElementsAttr dims> : IntElementsAttr "}, $_builder.getIntegerType(" # width # ")), makeArrayRef($0))"; } -class RankedI32ElementsAttr dims> : RankedIntElementsAttr<32, dims>; -class RankedI64ElementsAttr dims> : RankedIntElementsAttr<64, dims>; +class RankedI32ElementsAttr dims> : + RankedSignlessIntElementsAttr<32, dims>; +class RankedI64ElementsAttr dims> : + RankedSignlessIntElementsAttr<64, dims>; class FloatElementsAttr : ElementsAttrBase< CPred<"$_self.isa() &&" @@ -1317,6 +1409,14 @@ class IntMaxValue : AttrConstraint< CPred<"$_self.cast().getInt() <= " # n>, "whose maximum value is " # n>; +def IntNonNegative : AttrConstraint< + CPred<"!$_self.cast().getValue().isNegative()">, + "whose value is non-negative">; + +def IntPositive : AttrConstraint< + CPred<"$_self.cast().getValue().isStrictlyPositive()">, + "whose value is positive">; + class ArrayMinCount : AttrConstraint< CPred<"$_self.cast().size() >= " # n>, "with at least " # n # " elements">; diff --git a/mlir/test/Dialect/LLVMIR/global.mlir b/mlir/test/Dialect/LLVMIR/global.mlir index 4e7cd28..70944b8 100644 --- a/mlir/test/Dialect/LLVMIR/global.mlir +++ b/mlir/test/Dialect/LLVMIR/global.mlir @@ -74,12 +74,12 @@ llvm.mlir.global internal constant @constant(37.0) : !llvm<"label"> // ----- -// expected-error @+1 {{'addr_space' failed to satisfy constraint: non-negative 32-bit integer}} +// expected-error @+1 {{'addr_space' failed to satisfy constraint: 32-bit signless integer attribute whose value is non-negative}} "llvm.mlir.global"() {sym_name = "foo", type = !llvm.i64, value = 42 : i64, addr_space = -1 : i32, linkage = 0} : () -> () // ----- -// expected-error @+1 {{'addr_space' failed to satisfy constraint: non-negative 32-bit integer}} +// expected-error @+1 {{'addr_space' failed to satisfy constraint: 32-bit signless integer attribute whose value is non-negative}} "llvm.mlir.global"() {sym_name = "foo", type = !llvm.i64, value = 42 : i64, addr_space = 1.0 : f32, linkage = 0} : () -> () // ----- diff --git a/mlir/test/Dialect/Loops/invalid.mlir b/mlir/test/Dialect/Loops/invalid.mlir index 9b17027..44075ac 100644 --- a/mlir/test/Dialect/Loops/invalid.mlir +++ b/mlir/test/Dialect/Loops/invalid.mlir @@ -76,7 +76,7 @@ func @loop_for_single_index_argument(%arg0: index) { // ----- func @loop_if_not_i1(%arg0: index) { - // expected-error@+1 {{operand #0 must be 1-bit integer}} + // expected-error@+1 {{operand #0 must be 1-bit signless integer}} "loop.if"(%arg0) : (index) -> () return } diff --git a/mlir/test/Dialect/SPIRV/ops.mlir b/mlir/test/Dialect/SPIRV/ops.mlir index cf7ab60..d2f9eba 100644 --- a/mlir/test/Dialect/SPIRV/ops.mlir +++ b/mlir/test/Dialect/SPIRV/ops.mlir @@ -752,7 +752,7 @@ func @logicalUnary(%arg0 : i1) func @logicalUnary(%arg0 : i32) { - // expected-error @+1 {{'spv.LogicalNot' op operand #0 must be 1-bit integer or vector of 1-bit integer values of length 2/3/4, but got 'i32'}} + // expected-error @+1 {{operand #0 must be 1-bit signless integer or vector of 1-bit signless integer values of length 2/3/4, but got 'i32'}} %0 = spv.LogicalNot %arg0 : i32 return } diff --git a/mlir/test/IR/attribute.mlir b/mlir/test/IR/attribute.mlir index c0ee566..50d4e8c 100644 --- a/mlir/test/IR/attribute.mlir +++ b/mlir/test/IR/attribute.mlir @@ -1,6 +1,75 @@ // RUN: mlir-opt %s -split-input-file -verify-diagnostics | FileCheck %s //===----------------------------------------------------------------------===// +// Test integer attributes +//===----------------------------------------------------------------------===// + +func @int_attrs_pass() { + "test.int_attrs"() { + // CHECK: any_i32_attr = 5 : ui32 + any_i32_attr = 5 : ui32, + // CHECK-SAME: si32_attr = 7 : si32 + si32_attr = 7 : si32, + // CHECK-SAME: ui32_attr = 6 : ui32 + ui32_attr = 6 : ui32 + } : () -> () + + "test.int_attrs"() { + // CHECK: any_i32_attr = 5 : si32 + any_i32_attr = 5 : si32, + si32_attr = 7 : si32, + ui32_attr = 6 : ui32 + } : () -> () + + "test.int_attrs"() { + // CHECK: any_i32_attr = 5 : i32 + any_i32_attr = 5 : i32, + si32_attr = 7 : si32, + ui32_attr = 6 : ui32 + } : () -> () + + return +} + +// ----- + +func @wrong_int_attrs_signedness_fail() { + // expected-error @+1 {{'si32_attr' failed to satisfy constraint: 32-bit signed integer attribute}} + "test.int_attrs"() { + any_i32_attr = 5 : i32, + si32_attr = 7 : ui32, + ui32_attr = 6 : ui32 + } : () -> () + return +} + +// ----- + +func @wrong_int_attrs_signedness_fail() { + // expected-error @+1 {{'ui32_attr' failed to satisfy constraint: 32-bit unsigned integer attribute}} + "test.int_attrs"() { + any_i32_attr = 5 : i32, + si32_attr = 7 : si32, + ui32_attr = 6 : si32 + } : () -> () + return +} + +// ----- + +func @wrong_int_attrs_type_fail() { + // expected-error @+1 {{'any_i32_attr' failed to satisfy constraint: 32-bit integer attribute}} + "test.int_attrs"() { + any_i32_attr = 5.0 : f32, + si32_attr = 7 : si32, + ui32_attr = 6 : ui32 + } : () -> () + return +} + +// ----- + +//===----------------------------------------------------------------------===// // Test Non-negative Int Attr //===----------------------------------------------------------------------===// @@ -15,7 +84,7 @@ func @non_negative_int_attr_pass() { // ----- func @negative_int_attr_fail() { - // expected-error @+1 {{'i32attr' failed to satisfy constraint: non-negative 32-bit integer attribute}} + // expected-error @+1 {{'i32attr' failed to satisfy constraint: 32-bit signless integer attribute whose value is non-negative}} "test.non_negative_int_attr"() {i32attr = -5 : i32, i64attr = 10 : i64} : () -> () return } @@ -23,7 +92,7 @@ func @negative_int_attr_fail() { // ----- func @negative_int_attr_fail() { - // expected-error @+1 {{'i64attr' failed to satisfy constraint: non-negative 64-bit integer attribute}} + // expected-error @+1 {{'i64attr' failed to satisfy constraint: 64-bit signless integer attribute whose value is non-negative}} "test.non_negative_int_attr"() {i32attr = 5 : i32, i64attr = -10 : i64} : () -> () return } @@ -43,7 +112,7 @@ func @positive_int_attr_pass() { // ----- func @positive_int_attr_fail() { - // expected-error @+1 {{'i32attr' failed to satisfy constraint: positive 32-bit integer attribute}} + // expected-error @+1 {{'i32attr' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive}} "test.positive_int_attr"() {i32attr = 0 : i32, i64attr = 5: i64} : () -> () return } @@ -51,7 +120,7 @@ func @positive_int_attr_fail() { // ----- func @positive_int_attr_fail() { - // expected-error @+1 {{'i64attr' failed to satisfy constraint: positive 64-bit integer attribute}} + // expected-error @+1 {{'i64attr' failed to satisfy constraint: 64-bit signless integer attribute whose value is positive}} "test.positive_int_attr"() {i32attr = 5 : i32, i64attr = 0: i64} : () -> () return } @@ -59,7 +128,7 @@ func @positive_int_attr_fail() { // ----- func @positive_int_attr_fail() { - // expected-error @+1 {{'i32attr' failed to satisfy constraint: positive 32-bit integer attribute}} + // expected-error @+1 {{'i32attr' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive}} "test.positive_int_attr"() {i32attr = -10 : i32, i64attr = 5 : i64} : () -> () return } @@ -67,7 +136,7 @@ func @positive_int_attr_fail() { // ----- func @positive_int_attr_fail() { - // expected-error @+1 {{'i64attr' failed to satisfy constraint: positive 64-bit integer attribute}} + // expected-error @+1 {{'i64attr' failed to satisfy constraint: 64-bit signless integer attribute whose value is positive}} "test.positive_int_attr"() {i32attr = 5 : i32, i64attr = -10 : i64} : () -> () return } @@ -146,7 +215,7 @@ func @allowed_cases_pass() { // ----- func @disallowed_case7_fail() { - // expected-error @+1 {{allowed 32-bit integer cases: 5, 10}} + // expected-error @+1 {{allowed 32-bit signless integer cases: 5, 10}} %0 = "test.i32_enum_attr"() {attr = 7: i32} : () -> i32 return } @@ -154,7 +223,7 @@ func @disallowed_case7_fail() { // ----- func @disallowed_case7_fail() { - // expected-error @+1 {{allowed 32-bit integer cases: 5, 10}} + // expected-error @+1 {{allowed 32-bit signless integer cases: 5, 10}} %0 = "test.i32_enum_attr"() {attr = 5: i64} : () -> i32 return } @@ -177,7 +246,7 @@ func @allowed_cases_pass() { // ----- func @disallowed_case7_fail() { - // expected-error @+1 {{allowed 64-bit integer cases: 5, 10}} + // expected-error @+1 {{allowed 64-bit signless integer cases: 5, 10}} %0 = "test.i64_enum_attr"() {attr = 7: i64} : () -> i32 return } @@ -185,7 +254,7 @@ func @disallowed_case7_fail() { // ----- func @disallowed_case7_fail() { - // expected-error @+1 {{allowed 64-bit integer cases: 5, 10}} + // expected-error @+1 {{allowed 64-bit signless integer cases: 5, 10}} %0 = "test.i64_enum_attr"() {attr = 5: i32} : () -> i32 return } @@ -250,8 +319,58 @@ func @fn() { return } // Test IntElementsAttr //===----------------------------------------------------------------------===// -func @correct_type_pass() { +func @correct_int_elements_attr_pass() { "test.int_elements_attr"() { + // CHECK: any_i32_attr = dense<5> : tensor<1x2x3x4xui32>, + any_i32_attr = dense<5> : tensor<1x2x3x4xui32>, + i32_attr = dense<5> : tensor<6xi32> + } : () -> () + + "test.int_elements_attr"() { + // CHECK: any_i32_attr = dense<5> : tensor<1x2x3x4xsi32>, + any_i32_attr = dense<5> : tensor<1x2x3x4xsi32>, + i32_attr = dense<5> : tensor<6xi32> + } : () -> () + + "test.int_elements_attr"() { + // CHECK: any_i32_attr = dense<5> : tensor<1x2x3x4xi32>, + any_i32_attr = dense<5> : tensor<1x2x3x4xi32>, + i32_attr = dense<5> : tensor<6xi32> + } : () -> () + + return +} + +// ----- + +func @wrong_int_elements_attr_type_fail() { + // expected-error @+1 {{'any_i32_attr' failed to satisfy constraint: 32-bit integer elements attribute}} + "test.int_elements_attr"() { + any_i32_attr = dense<5.0> : tensor<1x2x3x4xf32>, + i32_attr = dense<5> : tensor<6xi32> + } : () -> () + return +} + +// ----- + +func @wrong_int_elements_attr_signedness_fail() { + // expected-error @+1 {{'i32_attr' failed to satisfy constraint: 32-bit signless integer elements attribute}} + "test.int_elements_attr"() { + any_i32_attr = dense<5> : tensor<1x2x3x4xi32>, + i32_attr = dense<5> : tensor<6xsi32> + } : () -> () + return +} + +// ----- + +//===----------------------------------------------------------------------===// +// Test Ranked IntElementsAttr +//===----------------------------------------------------------------------===// + +func @correct_type_pass() { + "test.ranked_int_elements_attr"() { // CHECK: matrix_i64_attr = dense<6> : tensor<4x8xi64> // CHECK: vector_i32_attr = dense<5> : tensor<2xi32> matrix_i64_attr = dense<6> : tensor<4x8xi64>, @@ -263,8 +382,8 @@ func @correct_type_pass() { // ----- func @wrong_element_type_fail() { - // expected-error @+1 {{failed to satisfy constraint: 32-bit int elements attribute of shape [2]}} - "test.int_elements_attr"() { + // expected-error @+1 {{failed to satisfy constraint: 32-bit signless int elements attribute of shape [2]}} + "test.ranked_int_elements_attr"() { matrix_i64_attr = dense<6> : tensor<4x8xi64>, vector_i32_attr = dense<5> : tensor<2xi64> } : () -> () @@ -274,8 +393,8 @@ func @wrong_element_type_fail() { // ----- func @wrong_shape_fail() { - // expected-error @+1 {{failed to satisfy constraint: 64-bit int elements attribute of shape [4, 8]}} - "test.int_elements_attr"() { + // expected-error @+1 {{failed to satisfy constraint: 64-bit signless int elements attribute of shape [4, 8]}} + "test.ranked_int_elements_attr"() { matrix_i64_attr = dense<6> : tensor<4xi64>, vector_i32_attr = dense<5> : tensor<2xi32> } : () -> () @@ -285,8 +404,8 @@ func @wrong_shape_fail() { // ----- func @wrong_shape_fail() { - // expected-error @+1 {{failed to satisfy constraint: 32-bit int elements attribute of shape [2]}} - "test.int_elements_attr"() { + // expected-error @+1 {{failed to satisfy constraint: 32-bit signless int elements attribute of shape [2]}} + "test.ranked_int_elements_attr"() { matrix_i64_attr = dense<6> : tensor<4x8xi64>, vector_i32_attr = dense<5> : tensor } : () -> () diff --git a/mlir/test/IR/invalid-ops.mlir b/mlir/test/IR/invalid-ops.mlir index 07b6b9f..f50bced 100644 --- a/mlir/test/IR/invalid-ops.mlir +++ b/mlir/test/IR/invalid-ops.mlir @@ -186,7 +186,7 @@ func @func_with_ops(f32) { func @func_with_ops(f32) { ^bb0(%a : f32): - // expected-error@+1 {{'std.addi' op operand #0 must be integer-like}} + // expected-error@+1 {{'std.addi' op operand #0 must be signless-integer-like}} %sf = addi %a, %a : f32 } @@ -201,7 +201,7 @@ func @func_with_ops(i32) { func @func_with_ops(i32) { ^bb0(%a : i32): - // expected-error@+1 {{failed to satisfy constraint: allowed 64-bit integer cases: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}} + // expected-error@+1 {{failed to satisfy constraint: allowed 64-bit signless integer cases: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}} %r = "std.cmpi"(%a, %a) {predicate = 42} : (i32, i32) -> i1 } @@ -226,7 +226,7 @@ func @func_with_ops(i32, i32) { // Integer comparisons are not recognized for float types. func @func_with_ops(f32, f32) { ^bb0(%a : f32, %b : f32): - %r = cmpi "eq", %a, %b : f32 // expected-error {{'lhs' must be integer-like, but got 'f32'}} + %r = cmpi "eq", %a, %b : f32 // expected-error {{'lhs' must be signless-integer-like, but got 'f32'}} } // ----- @@ -298,13 +298,13 @@ func @func_with_ops(i1, tensor<42xi32>, tensor) { // ----- func @invalid_select_shape(%cond : i1, %idx : () -> ()) { - // expected-error@+1 {{'result' must be integer-like or floating-point-like, but got '() -> ()'}} + // expected-error@+1 {{'result' must be signless-integer-like or floating-point-like, but got '() -> ()'}} %sel = select %cond, %idx, %idx : () -> () // ----- func @invalid_cmp_shape(%idx : () -> ()) { - // expected-error@+1 {{'lhs' must be integer-like, but got '() -> ()'}} + // expected-error@+1 {{'lhs' must be signless-integer-like, but got '() -> ()'}} %cmp = cmpi "eq", %idx, %idx : () -> () // ----- @@ -346,7 +346,7 @@ func @invalid_cmp_attr(%idx : i32) { // ----- func @cmpf_generic_invalid_predicate_value(%a : f32) { - // expected-error@+1 {{attribute 'predicate' failed to satisfy constraint: allowed 64-bit integer cases}} + // expected-error@+1 {{attribute 'predicate' failed to satisfy constraint: allowed 64-bit signless integer cases}} %r = "std.cmpf"(%a, %a) {predicate = 42} : (f32, f32) -> i1 } @@ -827,7 +827,7 @@ func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) { func @invalid_view(%arg0 : index, %arg1 : index, %arg2 : index) { %0 = alloc() : memref<2048xf32> - // expected-error@+1 {{must be 1D memref of 8-bit integer values}} + // expected-error@+1 {{must be 1D memref of 8-bit signless integer values}} %1 = view %0[][%arg0, %arg1] : memref<2048xf32> to memref (d0 * 4 + d1 + s0)>> return @@ -1091,7 +1091,7 @@ func @invalid_prefetch_cache_type(%i : index) { func @invalid_prefetch_locality_hint(%i : index) { %0 = alloc() : memref<10xf32> - // expected-error@+1 {{32-bit integer attribute whose minimum value is 0 whose maximum value is 3}} + // expected-error@+1 {{32-bit signless integer attribute whose minimum value is 0 whose maximum value is 3}} prefetch %0[%i], read, locality<5>, data : memref<10xf32> return } @@ -1154,7 +1154,7 @@ func @assume_alignment(%0: memref<4x4xf16>) { // 0 alignment value. func @assume_alignment(%0: memref<4x4xf16>) { - // expected-error@+1 {{'std.assume_alignment' op attribute 'alignment' failed to satisfy constraint: positive 32-bit integer attribute}} + // expected-error@+1 {{'std.assume_alignment' op attribute 'alignment' failed to satisfy constraint: 32-bit signless integer attribute whose value is positive}} std.assume_alignment %0, 0 : memref<4x4xf16> return } diff --git a/mlir/test/lib/TestDialect/TestOps.td b/mlir/test/lib/TestDialect/TestOps.td index 135dcde..26205e7 100644 --- a/mlir/test/lib/TestDialect/TestOps.td +++ b/mlir/test/lib/TestDialect/TestOps.td @@ -26,6 +26,14 @@ class TEST_Op traits = []> : // Test Types //===----------------------------------------------------------------------===// +def IntTypesOp : TEST_Op<"int_types"> { + let results = (outs + AnyI16:$any_i16, + SI32:$si32, + UI64:$ui64 + ); +} + def ComplexF64 : Complex; def ComplexOp : TEST_Op<"complex_f64"> { let results = (outs ComplexF64); @@ -127,15 +135,15 @@ def MixedNormalVariadicResults : TEST_Op< def NonNegIntAttrOp : TEST_Op<"non_negative_int_attr"> { let arguments = (ins - NonNegativeI32Attr:$i32attr, - NonNegativeI64Attr:$i64attr + Confined:$i32attr, + Confined:$i64attr ); } def PositiveIntAttrOp : TEST_Op<"positive_int_attr"> { let arguments = (ins - PositiveI32Attr:$i32attr, - PositiveI64Attr:$i64attr + Confined:$i32attr, + Confined:$i64attr ); } @@ -187,6 +195,15 @@ def I64EnumAttrOp : TEST_Op<"i64_enum_attr"> { let results = (outs I32:$val); } + +def IntAttrOp : TEST_Op<"int_attrs"> { + let arguments = (ins + AnyI32Attr:$any_i32_attr, + UI32Attr:$ui32_attr, + SI32Attr:$si32_attr + ); +} + def FloatElementsAttrOp : TEST_Op<"float_elements_attr"> { let arguments = (ins RankedF32ElementsAttr<[2]>:$scalar_f32_attr, @@ -206,6 +223,13 @@ def UpdateFloatElementsAttr : Pat< def IntElementsAttrOp : TEST_Op<"int_elements_attr"> { let arguments = (ins + AnyI32ElementsAttr:$any_i32_attr, + I32ElementsAttr:$i32_attr + ); +} + +def RankedIntElementsAttrOp : TEST_Op<"ranked_int_elements_attr"> { + let arguments = (ins RankedI32ElementsAttr<[2]>:$vector_i32_attr, RankedI64ElementsAttr<[4, 8]>:$matrix_i64_attr ); diff --git a/mlir/test/mlir-tblgen/predicate.td b/mlir/test/mlir-tblgen/predicate.td index 8ce4913..c679bd9 100644 --- a/mlir/test/mlir-tblgen/predicate.td +++ b/mlir/test/mlir-tblgen/predicate.td @@ -33,7 +33,7 @@ def OpF : NS_Op<"op_for_int_min_val", []> { // CHECK-LABEL: OpF::verify() // CHECK: (tblgen_attr.cast().getInt() >= 10) -// CHECK-SAME: return emitOpError("attribute 'attr' failed to satisfy constraint: 32-bit integer attribute whose minimum value is 10"); +// CHECK-SAME: return emitOpError("attribute 'attr' failed to satisfy constraint: 32-bit signless integer attribute whose minimum value is 10"); def OpFX : NS_Op<"op_for_int_max_val", []> { let arguments = (ins Confined]>:$attr); @@ -41,7 +41,7 @@ def OpFX : NS_Op<"op_for_int_max_val", []> { // CHECK-LABEL: OpFX::verify() // CHECK: (tblgen_attr.cast().getInt() <= 10) -// CHECK-SAME: return emitOpError("attribute 'attr' failed to satisfy constraint: 32-bit integer attribute whose maximum value is 10"); +// CHECK-SAME: return emitOpError("attribute 'attr' failed to satisfy constraint: 32-bit signless integer attribute whose maximum value is 10"); def OpG : NS_Op<"op_for_arr_min_count", []> { let arguments = (ins Confined]>:$attr); diff --git a/mlir/test/mlir-tblgen/types.mlir b/mlir/test/mlir-tblgen/types.mlir index 8c3cce7..f498a74 100644 --- a/mlir/test/mlir-tblgen/types.mlir +++ b/mlir/test/mlir-tblgen/types.mlir @@ -1,5 +1,36 @@ // RUN: mlir-opt %s -split-input-file -verify-diagnostics | FileCheck %s +func @correct_int_types_success() { + "test.int_types"() : () -> (i16, si32, ui64) + "test.int_types"() : () -> (si16, si32, ui64) + "test.int_types"() : () -> (ui16, si32, ui64) + return +} + +// ----- + +func @wrong_int_type_signedness_failure() { + // expected-error @+1 {{result #1 must be 32-bit signed integer, but got 'ui32'}} + "test.int_types"() : () -> (ui16, ui32, ui64) + return +} + +// ----- + +func @wrong_int_type_signedness_failure() { + // expected-error @+1 {{result #2 must be 64-bit unsigned integer, but got 'si64'}} + "test.int_types"() : () -> (ui16, si32, si64) + return +} + +// ----- + +func @wrong_int_type_failure() { + // expected-error @+1 {{result #0 must be 16-bit integer, but got 'f16'}} + "test.int_types"() : () -> (f16, si32, ui64) + return +} + // ----- // CHECK-LABEL: @complex_f64_success @@ -50,7 +81,7 @@ func @tuple_empty_success() { // ----- func @tuple_wrong_type_scalar() { - // expected-error@+1 {{must be tuple with any combination of 32-bit integer or 32-bit float values}} + // expected-error@+1 {{must be tuple with any combination of 32-bit signless integer or 32-bit float values}} "test.tuple_32_bit"() : () -> (tuple) return } @@ -58,7 +89,7 @@ func @tuple_wrong_type_scalar() { // ----- func @tuple_wrong_type_tensor() { - // expected-error@+1 {{must be tuple with any combination of 32-bit integer or 32-bit float values}} + // expected-error@+1 {{must be tuple with any combination of 32-bit signless integer or 32-bit float values}} "test.tuple_32_bit"() : () -> (tuple>) return } @@ -98,7 +129,7 @@ func @nested_tuple_multi_level_mixed_success() { // ----- func @nested_tuple_multi_level_wrong_type() { - // expected-error@+1 {{must be nested tuple with any combination of 32-bit integer or 32-bit float values}} + // expected-error@+1 {{must be nested tuple with any combination of 32-bit signless integer or 32-bit float values}} "test.nested_tuple_32_bit"() : () -> (tuple>>) return } @@ -117,7 +148,7 @@ func @rank_less_than_2_I8_F32_memref_success() { // ----- func @rank_less_than_2_I8_F32_memref_bad_type() { - // expected-error@+1 {{must be 0D/1D memref of 8-bit integer or 32-bit float values}} + // expected-error@+1 {{must be 0D/1D memref of 8-bit signless integer or 32-bit float values}} "test.rank_less_than_2_I8_F32_memref"() : () -> (memref) return } @@ -125,7 +156,7 @@ func @rank_less_than_2_I8_F32_memref_bad_type() { // ----- func @rank_less_than_2_I8_F32_memref_bad_rank() { - // expected-error@+1 {{must be 0D/1D memref of 8-bit integer or 32-bit float values}} + // expected-error@+1 {{must be 0D/1D memref of 8-bit signless integer or 32-bit float values}} "test.rank_less_than_2_I8_F32_memref"() : () -> (memref<1x2xi8>) return } @@ -148,7 +179,7 @@ func @nd_tensor_of_success_wrong_type_0d(%arg0: tensor, %arg1: tensor<10xf3 // ----- func @nd_tensor_of_success_wrong_type_4d(%arg0: tensor, %arg1: tensor<10xf32>, %arg2: tensor<20x30xi16>, %arg3: tensor<40x50x60xi16>, %arg4: tensor<70x80x90x100xi32>) { - // expected-error @+1 {{'test.nd_tensor_of' op operand #4 must be 4D tensor of 16-bit integer values}} + // expected-error @+1 {{'test.nd_tensor_of' op operand #4 must be 4D tensor of 16-bit signless integer values}} "test.nd_tensor_of"(%arg0, %arg1, %arg2, %arg3, %arg3) : (tensor, tensor<10xf32>, tensor<20x30xi16>, tensor<40x50x60xi16>, tensor<40x50x60xi16>) -> () return } @@ -193,7 +224,7 @@ func @multi_tensor_rank_of_success(%arg0: tensor, %arg1: tensor, %arg2: // ----- func @multi_tensor_rank_of_wrong_unranked_type(%arg0: tensor<2x2xi8>) { - // expected-error @+1 {{'test.multi_tensor_rank_of' op operand #0 must be 0D/1D tensor of 8-bit integer or 32-bit integer or 32-bit float values}} + // expected-error @+1 {{'test.multi_tensor_rank_of' op operand #0 must be 0D/1D tensor of 8-bit signless integer or 32-bit signless integer or 32-bit float values}} "test.multi_tensor_rank_of"(%arg0) : (tensor<2x2xi8>) -> () return } @@ -201,7 +232,7 @@ func @multi_tensor_rank_of_wrong_unranked_type(%arg0: tensor<2x2xi8>) { // ----- func @multi_tensor_rank_of_wrong_element_type(%arg0: tensor<2xi16>) { - // expected-error @+1 {{'test.multi_tensor_rank_of' op operand #0 must be 0D/1D tensor of 8-bit integer or 32-bit integer or 32-bit float values}} + // expected-error @+1 {{'test.multi_tensor_rank_of' op operand #0 must be 0D/1D tensor of 8-bit signless integer or 32-bit signless integer or 32-bit float values}} "test.multi_tensor_rank_of"(%arg0) : (tensor<2xi16>) -> () return } @@ -218,7 +249,7 @@ func @fixed_element_types(%ti32: tensor<* x i32>, %tf32: tensor<* x f32>, %mi32 // ----- func @fixed_element_types(%arg0: tensor<* x i32>, %arg1: tensor<* x f32>) { - // expected-error@+1 {{'res' is 16-bit integer}} + // expected-error@+1 {{'res' is 16-bit signless integer}} "test.arg_and_res_have_fixed_element_types"(%arg0, %arg1) : (tensor<* x i32>, tensor<* x f32>) -> tensor<* x i32> return } @@ -430,7 +461,7 @@ func @does_not_have_static_memref(%arg0: memref) { // ----- func @elements_attr_not_i32_f32() { - // expected-error@+1 {{32-bit integer elements attribute}} + // expected-error@+1 {{32-bit signless integer elements attribute}} "test.i32ElementsAttr"() {attr = dense<[1.0, 20.0]>:tensor<2xf32>} : () -> () return } @@ -438,7 +469,7 @@ func @elements_attr_not_i32_f32() { // ----- func @elements_attr_not_i32_i64() { - // expected-error@+1 {{32-bit integer elements attribute}} + // expected-error@+1 {{32-bit signless integer elements attribute}} "test.i32ElementsAttr"() {attr = dense<[1, 20]>:tensor<2xi64>} : () -> () return } -- 2.7.4