diff --git a/mlir/test/Dialect/MemRef/canonicalize.mlir b/mlir/test/Dialect/MemRef/canonicalize.mlir new file mode 100644 --- /dev/null +++ b/mlir/test/Dialect/MemRef/canonicalize.mlir @@ -0,0 +1,64 @@ +// RUN: mlir-opt %s -canonicalize --split-input-file | FileCheck %s + +// Test case: Basic folding of memref.tensor_load(memref.buffer_cast(t)) -> t +// CHECK-LABEL: func @tensor_load_of_buffer_cast( +// CHECK-SAME: %[[TENSOR:.*]]: tensor) -> tensor { +// CHECK: return %[[TENSOR]] +func @tensor_load_of_buffer_cast(%arg0: tensor) -> tensor { + %0 = memref.buffer_cast %arg0 : memref + %1 = memref.tensor_load %0 : memref + return %1 : tensor +} + +// ----- + +// Test case: Basic folding of memref.buffer_cast(memref.tensor_load(m)) -> m +// CHECK-LABEL: func @buffer_cast_of_tensor_load( +// CHECK-SAME: %[[MEMREF:.*]]: memref) -> memref { +// CHECK: return %[[MEMREF]] +func @buffer_cast_of_tensor_load(%arg0: memref) -> memref { + %0 = memref.tensor_load %arg0 : memref + %1 = memref.buffer_cast %0 : memref + return %1 : memref +} + +// ----- + +// Test case: If the memrefs are not the same type, don't fold them. +// Test case: If the memrefs are not cast-compatible (e.g. different address space), +// don't canonicalize them either. +// CHECK-LABEL: func @no_fold_buffer_cast_of_tensor_load( +// CHECK-SAME: %[[MEMREF_ADDRSPACE2:.*]]: memref) +// CHECK-SAME: -> memref { +// CHECK: %[[TENSOR:.*]] = memref.tensor_load +// CHECK_SAME: %[[MEMREF_ADDRSPACE2]] : memref +// CHECK: %[[MEMREF_ADDRSPACE7:.*]] = memref.buffer_cast +// CHECK_SAME: %[[TENSOR]] : memref +// CHECK: return %[[MEMREF_ADDRSPACE7]] +func @no_fold_buffer_cast_of_tensor_load(%arg0: memref) -> memref { + %0 = memref.tensor_load %arg0 : memref + %1 = memref.buffer_cast %0 : memref + return %1 : memref +} + +// ----- + +// CHECK-DAG: #[[$OFF_3:[a-z0-9]+]] = affine_map<(d0) -> (d0 + 3)> +// CHECK-DAG: #[[$OFF_UNK:[a-z0-9]+]] = affine_map<(d0)[s0] -> (d0 + s0)> + +// Test case: If the memrefs are cast-compatible, canonicalize. +// CHECK-LABEL: func @canonicalize_buffer_cast_of_tensor_load( +// CHECK-SAME: %[[M:.*]]: memref) +// CHEKC-SAME: -> memref { +// CHECK-NOT: memref.tensor_load +// CHECK-NOT: memref.buffer_cast +// CHECK: %[[R:.*]] = memref.cast %[[M]] +// CHECK-SAME: memref to memref +// CHECK: return %[[R]] +func @canonicalize_buffer_cast_of_tensor_load(%arg0: memref) + -> memref +{ + %0 = memref.tensor_load %arg0 : memref + %1 = memref.buffer_cast %0 : memref + return %1 : memref +} diff --git a/mlir/test/Dialect/Standard/invalid.mlir b/mlir/test/Dialect/MemRef/invalid.mlir copy from mlir/test/Dialect/Standard/invalid.mlir copy to mlir/test/Dialect/MemRef/invalid.mlir --- a/mlir/test/Dialect/Standard/invalid.mlir +++ b/mlir/test/Dialect/MemRef/invalid.mlir @@ -1,21 +1,5 @@ // RUN: mlir-opt -split-input-file %s -verify-diagnostics -func @test_index_cast_shape_error(%arg0 : tensor) -> tensor<2xi64> { - // expected-error @+1 {{all non-scalar operands/results must have the same shape and base type}} - %0 = index_cast %arg0 : tensor to tensor<2xi64> - return %0 : tensor<2xi64> -} - -// ----- - -func @test_index_cast_tensor_error(%arg0 : tensor) -> i64 { - // expected-error @+1 {{if an operand is non-scalar, then there must be at least one non-scalar result}} - %0 = index_cast %arg0 : tensor to i64 - return %0 : i64 -} - -// ----- - func @transpose_not_permutation(%v : memref(off + M * i + j)>>) { // expected-error @+1 {{expected a permutation map}} memref.transpose %v (i, j) -> (i, i) : memref(off + M * i + j)>> to memref(off + M * i + j)>> @@ -231,27 +215,3 @@ %0 = memref.get_global @gv : memref<3xf32> return } - -// ----- - -func @non_signless_constant() { - // expected-error @+1 {{requires integer result types to be signless}} - %0 = constant 0 : ui32 - return -} - -// ----- - -func @non_signless_constant() { - // expected-error @+1 {{requires integer result types to be signless}} - %0 = constant 0 : si32 - return -} - -// ----- - -func @unsupported_attribute() { - // expected-error @+1 {{unsupported 'value' attribute: "" : index}} - %0 = constant "" : index - return -} diff --git a/mlir/test/Dialect/Standard/ops.mlir b/mlir/test/Dialect/MemRef/ops.mlir copy from mlir/test/Dialect/Standard/ops.mlir copy to mlir/test/Dialect/MemRef/ops.mlir --- a/mlir/test/Dialect/Standard/ops.mlir +++ b/mlir/test/Dialect/MemRef/ops.mlir @@ -1,24 +1,6 @@ // RUN: mlir-opt %s | mlir-opt | FileCheck %s // RUN: mlir-opt %s --mlir-print-op-generic | mlir-opt | FileCheck %s -// CHECK-LABEL: test_index_cast -func @test_index_cast(%arg0 : index) -> i64 { - %0 = index_cast %arg0 : index to i64 - return %0 : i64 -} - -// CHECK-LABEL: test_index_cast_tensor -func @test_index_cast_tensor(%arg0 : tensor) -> tensor { - %0 = index_cast %arg0 : tensor to tensor - return %0 : tensor -} - -// CHECK-LABEL: test_index_cast_tensor_reverse -func @test_index_cast_tensor_reverse(%arg0 : tensor) -> tensor { - %0 = index_cast %arg0 : tensor to tensor - return %0 : tensor -} - // CHECK-LABEL: test_buffer_cast func @test_buffer_cast(%arg0: tensor, %arg1: tensor<*xi64>) -> (memref (d0 + 7)>>, memref<*xi64, 1>) { %0 = memref.buffer_cast %arg0 : memref (d0 + 7)>> @@ -26,24 +8,6 @@ return %0, %1 : memref (d0 + 7)>>, memref<*xi64, 1> } -// CHECK-LABEL: @assert -func @assert(%arg : i1) { - assert %arg, "Some message in case this assertion fails." - return -} - -// CHECK-LABEL: @atan -func @atan(%arg : f32) -> f32 { - %result = math.atan %arg : f32 - return %result : f32 -} - -// CHECK-LABEL: @atan2 -func @atan2(%arg0 : f32, %arg1 : f32) -> f32 { - %result = math.atan2 %arg0, %arg1 : f32 - return %result : f32 -} - // CHECK-LABEL: func @memref_reinterpret_cast func @memref_reinterpret_cast(%in: memref) -> memref<10x?xf32, offset: ?, strides: [?, 1]> { @@ -96,35 +60,3 @@ %1 = memref.tensor_load %0 : memref<2xf32> return } - -// CHECK-LABEL: func @switch( -func @switch(%flag : i32, %caseOperand : i32) { - switch %flag : i32, [ - default: ^bb1(%caseOperand : i32), - 42: ^bb2(%caseOperand : i32), - 43: ^bb3(%caseOperand : i32) - ] - - ^bb1(%bb1arg : i32): - return - ^bb2(%bb2arg : i32): - return - ^bb3(%bb3arg : i32): - return -} - -// CHECK-LABEL: func @switch_i64( -func @switch_i64(%flag : i64, %caseOperand : i32) { - switch %flag : i64, [ - default: ^bb1(%caseOperand : i32), - 42: ^bb2(%caseOperand : i32), - 43: ^bb3(%caseOperand : i32) - ] - - ^bb1(%bb1arg : i32): - return - ^bb2(%bb2arg : i32): - return - ^bb3(%bb3arg : i32): - return -} diff --git a/mlir/test/Dialect/Standard/canonicalize-cf.mlir b/mlir/test/Dialect/Standard/canonicalize-cf.mlir --- a/mlir/test/Dialect/Standard/canonicalize-cf.mlir +++ b/mlir/test/Dialect/Standard/canonicalize-cf.mlir @@ -443,4 +443,3 @@ assert %arg, "Computer says no" return } - diff --git a/mlir/test/Dialect/Standard/canonicalize.mlir b/mlir/test/Dialect/Standard/canonicalize.mlir --- a/mlir/test/Dialect/Standard/canonicalize.mlir +++ b/mlir/test/Dialect/Standard/canonicalize.mlir @@ -1,67 +1,5 @@ // RUN: mlir-opt %s -canonicalize --split-input-file | FileCheck %s -// ----- - -// Test case: Basic folding of memref.tensor_load(memref.buffer_cast(t)) -> t -// CHECK-LABEL: func @tensor_load_of_buffer_cast( -// CHECK-SAME: %[[TENSOR:.*]]: tensor) -> tensor { -// CHECK: return %[[TENSOR]] -func @tensor_load_of_buffer_cast(%arg0: tensor) -> tensor { - %0 = memref.buffer_cast %arg0 : memref - %1 = memref.tensor_load %0 : memref - return %1 : tensor -} - -// ----- - -// Test case: Basic folding of memref.buffer_cast(memref.tensor_load(m)) -> m -// CHECK-LABEL: func @buffer_cast_of_tensor_load( -// CHECK-SAME: %[[MEMREF:.*]]: memref) -> memref { -// CHECK: return %[[MEMREF]] -func @buffer_cast_of_tensor_load(%arg0: memref) -> memref { - %0 = memref.tensor_load %arg0 : memref - %1 = memref.buffer_cast %0 : memref - return %1 : memref -} - -// ----- - -// Test case: If the memrefs are not the same type, don't fold them. -// Test case: If the memrefs are not cast-compatible (e.g. different address space), -// don't canonicalize them either. -// CHECK-LABEL: func @no_fold_buffer_cast_of_tensor_load( -// CHECK-SAME: %[[MEMREF_ADDRSPACE2:.*]]: memref) -> memref { -// CHECK: %[[TENSOR:.*]] = memref.tensor_load %[[MEMREF_ADDRSPACE2]] : memref -// CHECK: %[[MEMREF_ADDRSPACE7:.*]] = memref.buffer_cast %[[TENSOR]] : memref -// CHECK: return %[[MEMREF_ADDRSPACE7]] -func @no_fold_buffer_cast_of_tensor_load(%arg0: memref) -> memref { - %0 = memref.tensor_load %arg0 : memref - %1 = memref.buffer_cast %0 : memref - return %1 : memref -} - -// ----- - -// CHECK-DAG: #[[$OFF_3:[a-z0-9]+]] = affine_map<(d0) -> (d0 + 3)> -// CHECK-DAG: #[[$OFF_UNK:[a-z0-9]+]] = affine_map<(d0)[s0] -> (d0 + s0)> - -// Test case: If the memrefs are cast-compatible, canonicalize. -// CHECK-LABEL: func @canonicalize_buffer_cast_of_tensor_load( -// CHECK-SAME: %[[M:.*]]: memref) -> memref { -// CHECK-NOT: memref.tensor_load -// CHECK-NOT: memref.buffer_cast -// CHECK: %[[R:.*]] = memref.cast %[[M]] : memref to memref -// CHECK: return %[[R]] -func @canonicalize_buffer_cast_of_tensor_load(%arg0: memref) - -> memref -{ - %0 = memref.tensor_load %arg0 : memref - %1 = memref.buffer_cast %0 : memref - return %1 : memref -} - -// ----- - // Test case: Basic folding of memref.dim(memref.tensor_load(m)) -> memref.dim(m). // CHECK-LABEL: func @dim_of_tensor_load( // CHECK-SAME: %[[MEMREF:[0-9a-z]*]]: memref diff --git a/mlir/test/Dialect/Standard/invalid.mlir b/mlir/test/Dialect/Standard/invalid.mlir --- a/mlir/test/Dialect/Standard/invalid.mlir +++ b/mlir/test/Dialect/Standard/invalid.mlir @@ -16,224 +16,6 @@ // ----- -func @transpose_not_permutation(%v : memref(off + M * i + j)>>) { - // expected-error @+1 {{expected a permutation map}} - memref.transpose %v (i, j) -> (i, i) : memref(off + M * i + j)>> to memref(off + M * i + j)>> -} - -// ----- - -func @transpose_bad_rank(%v : memref(off + M * i + j)>>) { - // expected-error @+1 {{expected a permutation map of same rank as the input}} - memref.transpose %v (i) -> (i) : memref(off + M * i + j)>> to memref(off + M * i + j)>> -} - -// ----- - -func @transpose_wrong_type(%v : memref(off + M * i + j)>>) { - // expected-error @+1 {{output type 'memref (d0 * s1 + s0 + d1)>>' does not match transposed input type 'memref (d0 * s1 + s0 + d1)>>'}} - memref.transpose %v (i, j) -> (j, i) : memref(off + M * i + j)>> to memref(off + M * i + j)>> -} - -// ----- - -func @memref_reinterpret_cast_too_many_offsets(%in: memref) { - // expected-error @+1 {{expected <= 1 offset values}} - %out = memref.reinterpret_cast %in to - offset: [0, 0], sizes: [10, 10], strides: [10, 1] - : memref to memref<10x10xf32, offset: 0, strides: [10, 1]> - return -} - -// ----- - -func @memref_reinterpret_cast_incompatible_element_types(%in: memref<*xf32>) { - // expected-error @+1 {{different element types specified}} - %out = memref.reinterpret_cast %in to - offset: [0], sizes: [10], strides: [1] - : memref<*xf32> to memref<10xi32, offset: 0, strides: [1]> - return -} - -// ----- - -func @memref_reinterpret_cast_incompatible_memory_space(%in: memref<*xf32>) { - // expected-error @+1 {{different memory spaces specified}} - %out = memref.reinterpret_cast %in to - offset: [0], sizes: [10], strides: [1] - : memref<*xf32> to memref<10xi32, offset: 0, strides: [1], 2> - return -} - -// ----- - -func @memref_reinterpret_cast_offset_mismatch(%in: memref) { - // expected-error @+1 {{expected result type with offset = 2 instead of 1}} - %out = memref.reinterpret_cast %in to - offset: [1], sizes: [10], strides: [1] - : memref to memref<10xf32, offset: 2, strides: [1]> - return -} - -// ----- - -func @memref_reinterpret_cast_size_mismatch(%in: memref<*xf32>) { - // expected-error @+1 {{expected result type with size = 10 instead of 1 in dim = 0}} - %out = memref.reinterpret_cast %in to - offset: [0], sizes: [10], strides: [1] - : memref<*xf32> to memref<1xf32, offset: 0, strides: [1]> - return -} - -// ----- - -func @memref_reinterpret_cast_offset_mismatch(%in: memref) { - // expected-error @+1 {{expected result type with stride = 2 instead of 1 in dim = 0}} - %out = memref.reinterpret_cast %in to - offset: [2], sizes: [10], strides: [2] - : memref to memref<10xf32, offset: 2, strides: [1]> - return -} - -// ----- - -func @memref_reinterpret_cast_offset_mismatch(%in: memref) { - %c0 = constant 0 : index - %c10 = constant 10 : index - // expected-error @+1 {{expected result type with size = 10 instead of -1 in dim = 0}} - %out = memref.reinterpret_cast %in to - offset: [%c0], sizes: [10, %c10], strides: [%c10, 1] - : memref to memref - return -} - -// ----- - -func @memref_reshape_element_type_mismatch( - %buf: memref<*xf32>, %shape: memref<1xi32>) { - // expected-error @+1 {{element types of source and destination memref types should be the same}} - memref.reshape %buf(%shape) : (memref<*xf32>, memref<1xi32>) -> memref -} - -// ----- - -func @memref_reshape_dst_ranked_shape_unranked( - %buf: memref<*xf32>, %shape: memref) { - // expected-error @+1 {{cannot use shape operand with dynamic length to reshape to statically-ranked memref type}} - memref.reshape %buf(%shape) : (memref<*xf32>, memref) -> memref -} - -// ----- - -func @memref_reshape_dst_shape_rank_mismatch( - %buf: memref<*xf32>, %shape: memref<1xi32>) { - // expected-error @+1 {{length of shape operand differs from the result's memref rank}} - memref.reshape %buf(%shape) - : (memref<*xf32>, memref<1xi32>) -> memref -} - -// ----- - -func @memref_reshape_src_affine_map_is_not_identity( - %buf: memref<4x4xf32, offset: 0, strides: [3, 2]>, - %shape: memref<1xi32>) { - // expected-error @+1 {{source memref type should have identity affine map}} - memref.reshape %buf(%shape) - : (memref<4x4xf32, offset: 0, strides: [3, 2]>, memref<1xi32>) - -> memref<8xf32> -} - -// ----- - -func @memref_reshape_result_affine_map_is_not_identity( - %buf: memref<4x4xf32>, %shape: memref<1xi32>) { - // expected-error @+1 {{result memref type should have identity affine map}} - memref.reshape %buf(%shape) - : (memref<4x4xf32>, memref<1xi32>) -> memref<8xf32, offset: 0, strides: [2]> -} - -// ----- - -// expected-error @+1 {{type should be static shaped memref}} -memref.global @foo : i32 - -// ----- - -// expected-error @+1 {{type should be static shaped memref}} -memref.global @foo : i32 = 5 - -// ----- - -// expected-error @+1 {{type should be static shaped memref}} -memref.global @foo : memref<*xf32> - -// ----- - -// expected-error @+1 {{type should be static shaped memref}} -memref.global @foo : memref - -// ----- - -// expected-error @+1 {{initial value should be a unit or elements attribute}} -memref.global @foo : memref<2x2xf32> = "foo" - -// ----- - -// expected-error @+1 {{inferred shape of elements literal ([2]) does not match type ([2, 2])}} -memref.global @foo : memref<2x2xf32> = dense<[0.0, 1.0]> - -// ----- - -// expected-error @+1 {{expected valid '@'-identifier for symbol name}} -memref.global "private" "public" @foo : memref<2x2xf32> = "foo" - -// ----- - -// expected-error @+1 {{expected valid '@'-identifier for symbol name}} -memref.global constant external @foo : memref<2x2xf32> = "foo" - -// ----- - -// constant qualifier must be after visibility. -// expected-error @+1 {{expected valid '@'-identifier for symbol name}} -memref.global constant "private" @foo : memref<2x2xf32> = "foo" - - -// ----- - -// expected-error @+1 {{op visibility expected to be one of ["public", "private", "nested"], but got "priate"}} -memref.global "priate" constant @memref5 : memref<2xf32> = uninitialized - -// ----- - -func @nonexistent_global_memref() { - // expected-error @+1 {{'gv' does not reference a valid global memref}} - %0 = memref.get_global @gv : memref<3xf32> - return -} - -// ----- - -func @foo() - -func @nonexistent_global_memref() { - // expected-error @+1 {{'foo' does not reference a valid global memref}} - %0 = memref.get_global @foo : memref<3xf32> - return -} - -// ----- - -memref.global @gv : memref<3xi32> - -func @mismatched_types() { - // expected-error @+1 {{result type 'memref<3xf32>' does not match type 'memref<3xi32>' of the global memref @gv}} - %0 = memref.get_global @gv : memref<3xf32> - return -} - -// ----- - func @non_signless_constant() { // expected-error @+1 {{requires integer result types to be signless}} %0 = constant 0 : ui32 diff --git a/mlir/test/Dialect/Standard/ops.mlir b/mlir/test/Dialect/Standard/ops.mlir --- a/mlir/test/Dialect/Standard/ops.mlir +++ b/mlir/test/Dialect/Standard/ops.mlir @@ -19,13 +19,6 @@ return %0 : tensor } -// CHECK-LABEL: test_buffer_cast -func @test_buffer_cast(%arg0: tensor, %arg1: tensor<*xi64>) -> (memref (d0 + 7)>>, memref<*xi64, 1>) { - %0 = memref.buffer_cast %arg0 : memref (d0 + 7)>> - %1 = memref.buffer_cast %arg1 : memref<*xi64, 1> - return %0, %1 : memref (d0 + 7)>>, memref<*xi64, 1> -} - // CHECK-LABEL: @assert func @assert(%arg : i1) { assert %arg, "Some message in case this assertion fails." @@ -44,59 +37,6 @@ return %result : f32 } -// CHECK-LABEL: func @memref_reinterpret_cast -func @memref_reinterpret_cast(%in: memref) - -> memref<10x?xf32, offset: ?, strides: [?, 1]> { - %c0 = constant 0 : index - %c10 = constant 10 : index - %out = memref.reinterpret_cast %in to - offset: [%c0], sizes: [10, %c10], strides: [%c10, 1] - : memref to memref<10x?xf32, offset: ?, strides: [?, 1]> - return %out : memref<10x?xf32, offset: ?, strides: [?, 1]> -} - -// CHECK-LABEL: func @memref_reshape( -func @memref_reshape(%unranked: memref<*xf32>, %shape1: memref<1xi32>, - %shape2: memref<2xi32>, %shape3: memref) -> memref<*xf32> { - %dyn_vec = memref.reshape %unranked(%shape1) - : (memref<*xf32>, memref<1xi32>) -> memref - %dyn_mat = memref.reshape %dyn_vec(%shape2) - : (memref, memref<2xi32>) -> memref - %new_unranked = memref.reshape %dyn_mat(%shape3) - : (memref, memref) -> memref<*xf32> - return %new_unranked : memref<*xf32> -} - -// CHECK-LABEL: memref.global @memref0 : memref<2xf32> -memref.global @memref0 : memref<2xf32> - -// CHECK-LABEL: memref.global constant @memref1 : memref<2xf32> = dense<[0.000000e+00, 1.000000e+00]> -memref.global constant @memref1 : memref<2xf32> = dense<[0.0, 1.0]> - -// CHECK-LABEL: memref.global @memref2 : memref<2xf32> = uninitialized -memref.global @memref2 : memref<2xf32> = uninitialized - -// CHECK-LABEL: memref.global "private" @memref3 : memref<2xf32> = uninitialized -memref.global "private" @memref3 : memref<2xf32> = uninitialized - -// CHECK-LABEL: memref.global "private" constant @memref4 : memref<2xf32> = uninitialized -memref.global "private" constant @memref4 : memref<2xf32> = uninitialized - -// CHECK-LABEL: func @write_global_memref -func @write_global_memref() { - %0 = memref.get_global @memref0 : memref<2xf32> - %1 = constant dense<[1.0, 2.0]> : tensor<2xf32> - memref.tensor_store %1, %0 : memref<2xf32> - return -} - -// CHECK-LABEL: func @read_global_memref -func @read_global_memref() { - %0 = memref.get_global @memref0 : memref<2xf32> - %1 = memref.tensor_load %0 : memref<2xf32> - return -} - // CHECK-LABEL: func @switch( func @switch(%flag : i32, %caseOperand : i32) { switch %flag : i32, [