[MLIR] Introduce constraint attributes for DenseArrayAttr
authorLorenzo Chelini <l.chelini@icloud.com>
Tue, 29 Nov 2022 18:45:37 +0000 (19:45 +0100)
committerLorenzo Chelini <l.chelini@icloud.com>
Thu, 1 Dec 2022 14:15:32 +0000 (15:15 +0100)
- `DenseArrayStrictlyPositive` all elements are required to be > 0.
  Returns true if the range is empty.

- `DenseArrayNonNegative` all elements are required to be >= 0. Returns
  true if the range is empty.

Both constraints will simplify verifier logic as we move from using `I64ArrayAttr` to `DenseI64ArrayAttr`.

Reviewed By: rriddle

Differential Revision: https://reviews.llvm.org/D138988

mlir/include/mlir/IR/OpBase.td
mlir/test/IR/attribute.mlir
mlir/test/lib/Dialect/Test/TestOps.td

index 9c87071..e74cd00 100644 (file)
@@ -1669,6 +1669,16 @@ class ArrayCount<int n> : AttrConstraint<
     CPred<"$_self.cast<::mlir::ArrayAttr>().size() == " #n>,
     "with exactly " # n # " elements">;
 
+class DenseArrayStrictlyPositive<DenseArrayAttrBase arrayType> : AttrConstraint<
+  CPred<"::llvm::all_of($_self.cast<" # arrayType #">().asArrayRef(), "
+                        "[&](auto v) { return v > 0; })">,
+  "whose value is positive">;
+
+class DenseArrayNonNegative<DenseArrayAttrBase arrayType> : AttrConstraint<
+  CPred<"::llvm::all_of($_self.cast<" # arrayType #">().asArrayRef(), "
+                        "[&](auto v) { return v >= 0; })">,
+  "whose value is non-negative">;
+
 class DenseArraySorted<DenseArrayAttrBase arrayType> : AttrConstraint<
     CPred<"llvm::is_sorted($_self.cast<" # arrayType # ">().asArrayRef())">,
     "should be in non-decreasing order">;
index ebfbb89..1066b90 100644 (file)
@@ -672,6 +672,70 @@ func.func @testConfinedDenseArrayAttrDecreasingOrder() {
 
 // -----
 
+func.func @testConfinedStrictlyPositiveDenseArrayAttr() {
+  "test.confined_strictly_positive_attr"() {
+    boolattr = array<i1: true, true>,
+    i8attr = array<i8: 2, 3>,
+    i16attr = array<i16: 20, 30>,
+    i32attr = array<i32: 1>,
+    i64attr = array<i64: 1, 2, 3>,
+    f32attr = array<f32: 1.1, 2.1>,
+    f64attr = array<f64: 2.1, 3.1>,
+    emptyattr = array<i16>
+  } : () -> ()
+  func.return
+}
+
+// -----
+
+func.func @testConfinedStrictlyPositiveDenseArrayAttr() {
+  // expected-error@+1{{'test.confined_strictly_positive_attr' op attribute 'i64attr' failed to satisfy constraint: i64 dense array attribute whose value is positive}}
+  "test.confined_strictly_positive_attr"() {
+    boolattr = array<i1: true, true>,
+    i8attr = array<i8: 2, 3>,
+    i16attr = array<i16: 20, 30>,
+    i32attr = array<i32: 1>,
+    i64attr = array<i64: 0, 2, 3>,
+    f32attr = array<f32: 1.1, 2.1>,
+    f64attr = array<f64: 2.1, 3.1>,
+    emptyattr = array<i16>
+  } : () -> ()
+  func.return
+}
+
+// -----
+
+func.func @testConfinedNonNegativeDenseArrayAttr() {
+  "test.confined_non_negative_attr"() {
+    i8attr = array<i8: 0, 3>,
+    i16attr = array<i16: 0, 30>,
+    i32attr = array<i32: 1>,
+    i64attr = array<i64: 1, 0, 3>,
+    f32attr = array<f32: 0.0, 2.1>,
+    f64attr = array<f64: 0.0, 3.1>,
+    emptyattr = array<i16>
+  } : () -> ()
+  func.return
+}
+
+// -----
+
+func.func @testConfinedNonNegativeDenseArrayAttr() {
+  // expected-error@+1{{'test.confined_non_negative_attr' op attribute 'i64attr' failed to satisfy constraint: i64 dense array attribute whose value is non-negative}}
+  "test.confined_non_negative_attr"() {
+    i8attr = array<i8: 0, 3>,
+    i16attr = array<i16: 0, 30>,
+    i32attr = array<i32: 1>,
+    i64attr = array<i64: -1, 0, 3>,
+    f32attr = array<f32: 0.0, 2.1>,
+    f64attr = array<f64: 0.0, 3.1>,
+    emptyattr = array<i16>
+  } : () -> ()
+  func.return
+}
+
+// -----
+
 //===----------------------------------------------------------------------===//
 // Test SymbolRefAttr
 //===----------------------------------------------------------------------===//
index 660ce7d..0dd839e 100644 (file)
@@ -186,9 +186,11 @@ def PositiveIntAttrOp : TEST_Op<"positive_int_attr"> {
 def TypeArrayAttrOp : TEST_Op<"type_array_attr"> {
   let arguments = (ins TypeArrayAttr:$attr);
 }
+
 def TypeArrayAttrWithDefaultOp : TEST_Op<"type_array_attr_with_default"> {
   let arguments = (ins DefaultValuedAttr<TypeArrayAttr, "{}">:$attr);
 }
+
 def TypeStringAttrWithTypeOp : TEST_Op<"string_attr_with_type"> {
   let arguments = (ins TypedStrAttr<AnyType>:$attr);
   let assemblyFormat = "$attr attr-dict";
@@ -292,6 +294,10 @@ def DenseArrayAttrOp : TEST_Op<"dense_array_attr"> {
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// Test Attributes Constraints
+//===----------------------------------------------------------------------===//
+
 def ConfinedDenseArrayAttrOp : TEST_Op<"confined_dense_array_attr"> {
   let arguments = (ins
       ConfinedAttr<DenseI16ArrayAttr,
@@ -303,6 +309,48 @@ def ConfinedDenseArrayAttrOp : TEST_Op<"confined_dense_array_attr"> {
   );
 }
 
+def DenseArrayStrictlyPositiveAttrOp : TEST_Op<"confined_strictly_positive_attr"> {
+  let arguments = (ins
+      ConfinedAttr<DenseBoolArrayAttr,
+                   [DenseArrayStrictlyPositive<DenseBoolArrayAttr>]>:$boolattr,
+      ConfinedAttr<DenseI8ArrayAttr,
+                   [DenseArrayStrictlyPositive<DenseI8ArrayAttr>]>:$i8attr,
+      ConfinedAttr<DenseI16ArrayAttr,
+                   [DenseArrayStrictlyPositive<DenseI16ArrayAttr>]>:$i16attr,
+      ConfinedAttr<DenseI32ArrayAttr,
+                   [DenseArrayStrictlyPositive<DenseI32ArrayAttr>]>:$i32attr,
+      ConfinedAttr<DenseI64ArrayAttr,
+                   [DenseArrayStrictlyPositive<DenseI64ArrayAttr>]>:$i64attr,
+      ConfinedAttr<DenseF32ArrayAttr,
+                   [DenseArrayStrictlyPositive<DenseF32ArrayAttr>]>:$f32attr,
+      ConfinedAttr<DenseF64ArrayAttr,
+                   [DenseArrayStrictlyPositive<DenseF64ArrayAttr>]>:$f64attr,
+      ConfinedAttr<DenseI16ArrayAttr,
+                   [DenseArrayStrictlyPositive<DenseI16ArrayAttr>]>:$emptyattr
+  );
+}
+
+// It does not make sense to have this constraint on a DenseBoolArrayAttr.
+// It is always true.
+def DenseArrayNonNegativeOp : TEST_Op<"confined_non_negative_attr"> {
+  let arguments = (ins
+      ConfinedAttr<DenseI8ArrayAttr,
+                   [DenseArrayNonNegative<DenseI8ArrayAttr>]>:$i8attr,
+      ConfinedAttr<DenseI16ArrayAttr,
+                   [DenseArrayNonNegative<DenseI16ArrayAttr>]>:$i16attr,
+      ConfinedAttr<DenseI32ArrayAttr,
+                   [DenseArrayNonNegative<DenseI32ArrayAttr>]>:$i32attr,
+      ConfinedAttr<DenseI64ArrayAttr,
+                   [DenseArrayNonNegative<DenseI64ArrayAttr>]>:$i64attr,
+      ConfinedAttr<DenseF32ArrayAttr,
+                   [DenseArrayNonNegative<DenseF32ArrayAttr>]>:$f32attr,
+      ConfinedAttr<DenseF64ArrayAttr,
+                   [DenseArrayNonNegative<DenseF64ArrayAttr>]>:$f64attr,
+      ConfinedAttr<DenseI16ArrayAttr,
+                   [DenseArrayNonNegative<DenseI16ArrayAttr>]>:$emptyattr
+  );
+}
+
 //===----------------------------------------------------------------------===//
 // Test Enum Attributes
 //===----------------------------------------------------------------------===//