diff --git a/mlir/lib/Parser/AttributeParser.cpp b/mlir/lib/Parser/AttributeParser.cpp --- a/mlir/lib/Parser/AttributeParser.cpp +++ b/mlir/lib/Parser/AttributeParser.cpp @@ -335,10 +335,6 @@ unsigned width = type.isIndex() ? IndexType::kInternalStorageBitWidth : type.getIntOrFloatBitWidth(); - // APInt cannot hold a zero bit value. - if (width == 0) - return llvm::None; - if (width > result.getBitWidth()) { result = result.zext(width); } else if (width < result.getBitWidth()) { @@ -350,7 +346,12 @@ result = result.trunc(width); } - if (isNegative) { + if (width == 0) { + // 0 bit integers cannot be negative and manipulation of their sign bit will + // assert, so short-cut validation here. + if (isNegative) + return llvm::None; + } else if (isNegative) { // The value is negative, we have an overflow if the sign bit is not set // in the negated apInt. result.negate(); diff --git a/mlir/test/IR/attribute.mlir b/mlir/test/IR/attribute.mlir --- a/mlir/test/IR/attribute.mlir +++ b/mlir/test/IR/attribute.mlir @@ -150,8 +150,54 @@ } : () -> () return } + // ----- +//===----------------------------------------------------------------------===// +// Check that i0 is parsed and verified correctly. It can only have value 0. +// We check it explicitly because there are various special cases for it that +// are good to verify. +//===----------------------------------------------------------------------===// + +func @int0_attrs_pass() { + "test.i0_attr"() { + // CHECK: attr_00 = 0 : i0 + attr_00 = 0 : i0, + // CHECK: attr_01 = 0 : si0 + attr_01 = 0 : si0, + // CHECK: attr_02 = 0 : ui0 + attr_02 = 0 : ui0, + // CHECK: attr_03 = 0 : i0 + attr_03 = 0x0000 : i0, + // CHECK: attr_04 = 0 : si0 + attr_04 = 0x0000 : si0, + // CHECK: attr_05 = 0 : ui0 + attr_05 = 0x0000 : ui0 + } : () -> () + return +} + +// ----- + +func @int0_attrs_negative_fail() { + "test.i0_attr"() { + // expected-error @+1 {{integer constant out of range for attribute}} + attr_00 = -1 : i0 + } : () -> () + return +} + +// ----- + +func @int0_attrs_positive_fail() { + "test.i0_attr"() { + // expected-error @+1 {{integer constant out of range for attribute}} + attr_00 = 1 : i0 + } : () -> () + return +} + +// ----- func @wrong_int_attrs_signedness_fail() { // expected-error @+1 {{'si32_attr' failed to satisfy constraint: 32-bit signed integer attribute}} diff --git a/mlir/test/IR/invalid-ops.mlir b/mlir/test/IR/invalid-ops.mlir --- a/mlir/test/IR/invalid-ops.mlir +++ b/mlir/test/IR/invalid-ops.mlir @@ -187,11 +187,3 @@ } return } - -// ----- - -func @no_zero_bit_integer_attrs() { - // expected-error @+1 {{integer constant out of range for attribute}} - %x = "some.op"(){value = 0 : i0} : () -> f32 - return -}