From a1b24a0e0851fda5bc11be945c4a60356c6cf2fb Mon Sep 17 00:00:00 2001 From: Jacques Pienaar Date: Wed, 8 May 2019 12:11:10 -0700 Subject: [PATCH] Verify that attribute type and constant op return type matches. -- PiperOrigin-RevId: 247263129 --- mlir/lib/StandardOps/Ops.cpp | 29 +++++++---------- mlir/test/IR/invalid-ops.mlir | 41 ++++++++++-------------- mlir/test/IR/memory-ops.mlir | 4 +-- mlir/test/Transforms/Vectorize/vector_utils.mlir | 4 +-- 4 files changed, 33 insertions(+), 45 deletions(-) diff --git a/mlir/lib/StandardOps/Ops.cpp b/mlir/lib/StandardOps/Ops.cpp index 9de36a7..c89d66d 100644 --- a/mlir/lib/StandardOps/Ops.cpp +++ b/mlir/lib/StandardOps/Ops.cpp @@ -1164,22 +1164,21 @@ static LogicalResult verify(ConstantOp &op) { return op.emitOpError("requires a 'value' attribute"); auto type = op.getType(); - if (type.isa() || type.isIndex()) { - auto intAttr = value.dyn_cast(); - if (!intAttr) - return op.emitOpError( - "requires 'value' to be an integer for an integer result type"); + if (type != value.getType()) + return op.emitOpError() << "requires attribute's type (" << value.getType() + << ") to match op's return type (" << type << ")"; + if (type.isa()) + return success(); + + if (auto intAttr = value.dyn_cast()) { // If the type has a known bitwidth we verify that the value can be // represented with the given bitwidth. - if (!type.isIndex()) { - auto bitwidth = type.cast().getWidth(); - auto intVal = intAttr.getValue(); - if (!intVal.isSignedIntN(bitwidth) && !intVal.isIntN(bitwidth)) - return op.emitOpError( - "requires 'value' to be an integer within the range " - "of the integer result type"); - } + auto bitwidth = type.cast().getWidth(); + auto intVal = intAttr.getValue(); + if (!intVal.isSignedIntN(bitwidth) && !intVal.isIntN(bitwidth)) + return op.emitOpError("requires 'value' to be an integer within the " + "range of the integer result type"); return success(); } @@ -1201,10 +1200,6 @@ static LogicalResult verify(ConstantOp &op) { return success(); } - if (value.getType() != type) - return op.emitOpError("requires the type of the 'value' attribute to match " - "that of the operation result"); - return op.emitOpError( "requires a result type that aligns with the 'value' attribute"); } diff --git a/mlir/test/IR/invalid-ops.mlir b/mlir/test/IR/invalid-ops.mlir index b2bd89b..419c6ad 100644 --- a/mlir/test/IR/invalid-ops.mlir +++ b/mlir/test/IR/invalid-ops.mlir @@ -26,7 +26,7 @@ func @dim3(tensor<1xf32>) { func @constant() { ^bb: - %x = "std.constant"(){value: "xyz"} : () -> i32 // expected-error {{'std.constant' op requires 'value' to be an integer for an integer result type}} + %x = "std.constant"(){value: "xyz"} : () -> i32 // expected-error {{requires attribute's type (none) to match op's return type (i32)}} return } @@ -34,15 +34,22 @@ func @constant() { func @constant_out_of_range() { ^bb: - %x = "std.constant"(){value: 100} : () -> i1 // expected-error {{'std.constant' op requires 'value' to be an integer within the range of the integer result type}} + %x = "std.constant"(){value: 100} : () -> i1 // expected-error {{requires attribute's type (i64) to match op's return type (i1)}} return } // ----- +func @constant_wrong_type() { +^bb: + %x = "std.constant"(){value: 10.} : () -> f32 // expected-error {{requires attribute's type (f64) to match op's return type (f32)}} + return +} + +// ----- func @affine_apply_no_map() { ^bb0: - %i = "std.constant"() {value: 0} : () -> index + %i = constant 0 : index %x = "affine.apply" (%i) { } : (index) -> (index) // expected-error {{'affine.apply' op requires an affine map}} return } @@ -51,7 +58,7 @@ func @affine_apply_no_map() { func @affine_apply_wrong_operand_count() { ^bb0: - %i = "std.constant"() {value: 0} : () -> index + %i = constant 0 : index %x = "affine.apply" (%i) {map: (d0, d1) -> ((d0 + 1), (d1 + 2))} : (index) -> (index) // expected-error {{'affine.apply' op operand count and affine map dimension and symbol count must match}} return } @@ -60,8 +67,8 @@ func @affine_apply_wrong_operand_count() { func @affine_apply_wrong_result_count() { ^bb0: - %i = "std.constant"() {value: 0} : () -> index - %j = "std.constant"() {value: 1} : () -> index + %i = constant 0 : index + %j = constant 1 : index %x = "affine.apply" (%i, %j) {map: (d0, d1) -> ((d0 + 1), (d1 + 2))} : (index,index) -> (index) // expected-error {{'affine.apply' op mapping must produce one value}} return } @@ -86,7 +93,7 @@ func @unknown_std_op() { func @bad_alloc_wrong_dynamic_dim_count() { ^bb0: - %0 = "std.constant"() {value: 7} : () -> index + %0 = constant 7 : index // Test alloc with wrong number of dynamic dimensions. %1 = alloc(%0)[%1] : memref<2x4xf32, (d0, d1)[s0] -> ((d0 + s0), d1), 1> // expected-error {{custom op 'alloc' dimension operand count does not equal memref dynamic dimension count}} return @@ -96,7 +103,7 @@ func @bad_alloc_wrong_dynamic_dim_count() { func @bad_alloc_wrong_symbol_count() { ^bb0: - %0 = "std.constant"() {value: 7} : () -> index + %0 = constant 7 : index // Test alloc with wrong number of symbols %1 = alloc(%0) : memref<2x?xf32, (d0, d1)[s0] -> ((d0 + s0), d1), 1> // expected-error {{operand count does not equal dimension plus symbol operand count}} return @@ -107,8 +114,8 @@ func @bad_alloc_wrong_symbol_count() { func @test_store_zero_results() { ^bb0: %0 = alloc() : memref<1024x64xf32, (d0, d1) -> (d0, d1), 1> - %1 = "std.constant"() {value: 0} : () -> index - %2 = "std.constant"() {value: 1} : () -> index + %1 = constant 0 : index + %2 = constant 1 : index %3 = load %0[%1, %2] : memref<1024x64xf32, (d0, d1) -> (d0, d1), 1> // Test that store returns zero results. %4 = store %3, %0[%1, %2] : memref<1024x64xf32, (d0, d1) -> (d0, d1), 1> // expected-error {{cannot name an operation with no results}} @@ -141,20 +148,6 @@ func @intlimit2() { // ----- -func @func_constant() { - %x = "std.constant"(){value: "xyz"} : () -> i32 // expected-error {{'std.constant' op requires 'value' to be an integer for an integer result type}} - return -} - -// ----- - -func @func_constant_out_of_range() { - %x = "std.constant"(){value: 100} : () -> i1 // expected-error {{'std.constant' op requires 'value' to be an integer within the range of the integer result type}} - return -} - -// ----- - func @calls(%arg0: i32) { %x = call @calls() : () -> i32 // expected-error {{reference to function with mismatched type}} return diff --git a/mlir/test/IR/memory-ops.mlir b/mlir/test/IR/memory-ops.mlir index b078c35..6c5ec07 100644 --- a/mlir/test/IR/memory-ops.mlir +++ b/mlir/test/IR/memory-ops.mlir @@ -9,8 +9,8 @@ func @alloc() { // CHECK: %0 = alloc() : memref<1024x64xf32, 1> %0 = alloc() : memref<1024x64xf32, (d0, d1) -> (d0, d1), 1> - %c0 = "std.constant"() {value: 0} : () -> index - %c1 = "std.constant"() {value: 1} : () -> index + %c0 = "std.constant"() {value: 0: index} : () -> index + %c1 = "std.constant"() {value: 1: index} : () -> index // Test alloc with dynamic dimensions. // CHECK: %1 = alloc(%c0, %c1) : memref diff --git a/mlir/test/Transforms/Vectorize/vector_utils.mlir b/mlir/test/Transforms/Vectorize/vector_utils.mlir index ceb295b..cec3650 100644 --- a/mlir/test/Transforms/Vectorize/vector_utils.mlir +++ b/mlir/test/Transforms/Vectorize/vector_utils.mlir @@ -17,7 +17,7 @@ func @vector_add_2d(%arg0: index, %arg1: index) -> f32 { // CHECK:matched: {{.*}} constant splat{{.*}} with shape ratio: 1, 3, 7, 2, 1 %cst_a = constant splat, 1.000000e+00> : vector<1x3x7x8x8xf32> // CHECK-NOT:matched: {{.*}} constant splat{{.*}} with shape ratio: 1, 3, 7, 1{{.*}} - %cst_b = constant splat, 1.000000e+00> : vector<1x3x7x8x8xf32> + %cst_b = constant splat, 1.000000e+00> : vector<1x3x7x4x4xf32> // TEST-3x4x5x8:matched: {{.*}} constant splat{{.*}} with shape ratio: 3, 2, 1, 4 %cst_c = constant splat, 1.000000e+00> : vector<3x4x5x8xf32> // TEST-3x4x4x8-NOT:matched: {{.*}} constant splat{{.*}} with shape ratio{{.*}} @@ -34,4 +34,4 @@ func @vector_add_2d(%arg0: index, %arg1: index) -> f32 { %c42 = constant 42 : index %9 = load %2[%c7, %c42] : memref return %9 : f32 -} \ No newline at end of file +} -- 2.7.4