1// RUN: mlir-opt -split-input-file -verify-diagnostics %s 2 3func.func @test_conv_op_not_linalg_op(%arg0 : tensor<?xf32>, %arg1 : tensor<?xf32>, 4 %arg2 : tensor<?xf32>) -> tensor<?xf32> { 5 // expected-error @+1 {{expected a LinalgOp}} 6 %0 = "test.conv_op_not_linalg_op"(%arg0, %arg1, %arg2) 7 : (tensor<?xf32>, tensor<?xf32>, tensor<?xf32>) -> tensor<?xf32> 8 return %0 : tensor<?xf32> 9} 10 11// ----- 12 13// Check for number of operands being >= 2. 14#map = affine_map<(d0) -> (d0)> 15func.func @test_conv_op_wrong_num_operands(%arg0 : tensor<?xf32>, 16 %arg1 : tensor<?xf32>) -> tensor<?xf32> { 17 // expected-error @+1 {{expected op with 2 inputs and 1 output}} 18 %0 = test.linalg_conv_op { 19 indexing_maps = [#map, #map], 20 iterator_types = ["parallel"]} 21 ins(%arg0 : tensor<?xf32>) outs(%arg1 : tensor<?xf32>) { 22 ^bb0(%arg2 : f32, %arg3 : f32): 23 linalg.yield %arg3 : f32 24 } -> tensor<?xf32> 25 return %0 : tensor<?xf32> 26} 27 28// ----- 29 30func.func @test_conv_op_wrong_input_indexing_map1(%arg0 : tensor<?xf32>, 31 %arg1 : tensor<?xf32>, %arg2 : tensor<?xf32>) -> tensor<?xf32> { 32 // expected-error @+1 {{unexpected input index map for convolution}} 33 %0 = test.linalg_conv_op { 34 indexing_maps = [affine_map<(d0, d1) -> (d0 * 2)>, 35 affine_map<(d0, d1) -> (d1)>, 36 affine_map<(d0, d1) -> (d0)>], 37 iterator_types = ["parallel", "reduction"]} 38 ins(%arg0, %arg1 : tensor<?xf32>, tensor<?xf32>) 39 outs(%arg2 : tensor<?xf32>) { 40 ^bb0(%arg3 : f32, %arg4 : f32, %arg5 : f32): 41 linalg.yield %arg5 : f32 42 } -> tensor<?xf32> 43 return %0 : tensor<?xf32> 44} 45 46// ----- 47 48func.func @test_conv_op_wrong_input_indexing_map2(%arg0 : tensor<?x?xf32>, 49 %arg1 : tensor<?xf32>, %arg2 : tensor<?xf32>) -> tensor<?xf32> { 50 // expected-error @+1 {{unexpected input index map for convolution}} 51 %0 = test.linalg_conv_op { 52 indexing_maps = [affine_map<(d0, d1) -> (d0 + d1, d0)>, 53 affine_map<(d0, d1) -> (d1)>, 54 affine_map<(d0, d1) -> (d0)>], 55 iterator_types = ["parallel", "reduction"]} 56 ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?xf32>) 57 outs(%arg2 : tensor<?xf32>) { 58 ^bb0(%arg3 : f32, %arg4 : f32, %arg5 : f32): 59 linalg.yield %arg5 : f32 60 } -> tensor<?xf32> 61 return %0 : tensor<?xf32> 62} 63 64// ----- 65 66func.func @test_conv_op_filter_index_map_not_projection(%arg0 : tensor<?xf32>, 67 %arg1 : tensor<?xf32>, %arg2 : tensor<?xf32>) -> tensor<?xf32> { 68 // expected-error @+1 {{expected output/filter indexing maps to be projected permutations}} 69 %0 = test.linalg_conv_op { 70 indexing_maps = [affine_map<(d0, d1) -> (d1)>, 71 affine_map<(d0, d1) -> (d1 + d0)>, 72 affine_map<(d0, d1) -> (d0)>], 73 iterator_types = ["parallel", "reduction"]} 74 ins(%arg0, %arg1 : tensor<?xf32>, tensor<?xf32>) 75 outs(%arg2 : tensor<?xf32>) { 76 ^bb0(%arg3 : f32, %arg4 : f32, %arg5 : f32): 77 linalg.yield %arg5 : f32 78 } -> tensor<?xf32> 79 return %0 : tensor<?xf32> 80} 81 82// ----- 83 84func.func @test_conv_op_output_index_map_not_projection(%arg0 : tensor<?xf32>, 85 %arg1 : tensor<?xf32>, %arg2 : tensor<?xf32>) -> tensor<?xf32> { 86 // expected-error @+1 {{expected output/filter indexing maps to be projected permutations}} 87 %0 = test.linalg_conv_op { 88 indexing_maps = [affine_map<(d0, d1) -> (d0)>, 89 affine_map<(d0, d1) -> (d1)>, 90 affine_map<(d0, d1) -> (d0 + d1)>], 91 iterator_types = ["parallel", "parallel"]} 92 ins(%arg0, %arg1 : tensor<?xf32>, tensor<?xf32>) 93 outs(%arg2 : tensor<?xf32>) { 94 ^bb0(%arg3 : f32, %arg4 : f32, %arg5 : f32): 95 linalg.yield %arg5 : f32 96 } -> tensor<?xf32> 97 return %0 : tensor<?xf32> 98} 99 100// ----- 101 102// Convolution op illegal if a loop dimension is used to access 103// output, filter and is convolved. 104func.func @test_conv_op_output_filter_convolved(%arg0 : tensor<?xf32>, 105 %arg1 : tensor<?xf32>, %arg2 : tensor<?x?xf32>) -> tensor<?x?xf32> { 106 // expected-error @+1 {{unexpected loop dimension for convolution op}} 107 %0 = test.linalg_conv_op { 108 indexing_maps = [affine_map<(d0, d1) -> (d0 + d1)>, 109 affine_map<(d0, d1) -> (d1)>, 110 affine_map<(d0, d1) -> (d0, d1)>], 111 iterator_types = ["parallel", "parallel"]} 112 ins(%arg0, %arg1 : tensor<?xf32>, tensor<?xf32>) 113 outs(%arg2 : tensor<?x?xf32>) { 114 ^bb0(%arg3 : f32, %arg4 : f32, %arg5 : f32): 115 linalg.yield %arg5 : f32 116 } -> tensor<?x?xf32> 117 return %0 : tensor<?x?xf32> 118} 119 120// ----- 121 122// Convolution op illegal if a loop dimension is used only in the output. 123func.func @test_conv_op_output_only_dim(%arg0 : tensor<?xf32>, 124 %arg1 : tensor<?xf32>, %arg2 : tensor<?x?xf32>) -> tensor<?x?xf32> { 125 // expected-error @+1 {{unexpected loop dimension for convolution op}} 126 %0 = test.linalg_conv_op { 127 indexing_maps = [affine_map<(d0, d1, d2) -> (d0 + d1)>, 128 affine_map<(d0, d1, d2) -> (d1)>, 129 affine_map<(d0, d1, d2) -> (d0, d2)>], 130 iterator_types = ["parallel", "reduction", "parallel"]} 131 ins(%arg0, %arg1 : tensor<?xf32>, tensor<?xf32>) 132 outs(%arg2 : tensor<?x?xf32>) { 133 ^bb0(%arg3 : f32, %arg4 : f32, %arg5 : f32): 134 linalg.yield %arg5 : f32 135 } -> tensor<?x?xf32> 136 return %0 : tensor<?x?xf32> 137} 138 139// ----- 140 141// Convolution op illegal if a loop dimension is used only in the filter. 142func.func @test_conv_op_filter_only_dim(%arg0 : tensor<?xf32>, 143 %arg1 : tensor<?x?xf32>, %arg2 : tensor<?xf32>) -> tensor<?xf32> { 144 // expected-error @+1 {{unexpected loop dimension for convolution op}} 145 %0 = test.linalg_conv_op { 146 indexing_maps = [affine_map<(d0, d1, d2) -> (d0 + d1)>, 147 affine_map<(d0, d1, d2) -> (d1, d2)>, 148 affine_map<(d0, d1, d2) -> (d0)>], 149 iterator_types = ["parallel", "reduction", "reduction"]} 150 ins(%arg0, %arg1 : tensor<?xf32>, tensor<?x?xf32>) 151 outs(%arg2 : tensor<?xf32>) { 152 ^bb0(%arg3 : f32, %arg4 : f32, %arg5 : f32): 153 linalg.yield %arg5 : f32 154 } -> tensor<?xf32> 155 return %0 : tensor<?xf32> 156} 157 158// ----- 159 160// Convolution op illegal if a loop dimension is used only in the input. 161func.func @test_conv_op_input_only_dim(%arg0 : tensor<?x?xf32>, 162 %arg1 : tensor<?xf32>, %arg2 : tensor<?xf32>) -> tensor<?xf32> { 163 // expected-error @+1 {{unexpected loop dimension for convolution op}} 164 %0 = test.linalg_conv_op { 165 indexing_maps = [affine_map<(d0, d1, d2) -> (d0 + d1, d2)>, 166 affine_map<(d0, d1, d2) -> (d1)>, 167 affine_map<(d0, d1, d2) -> (d0)>], 168 iterator_types = ["parallel", "reduction", "reduction"]} 169 ins(%arg0, %arg1 : tensor<?x?xf32>, tensor<?xf32>) 170 outs(%arg2 : tensor<?xf32>) { 171 ^bb0(%arg3 : f32, %arg4 : f32, %arg5 : f32): 172 linalg.yield %arg5 : f32 173 } -> tensor<?xf32> 174 return %0 : tensor<?xf32> 175} 176 177// ----- 178 179// Convolution op illegal if a loop dimension accessing output is not parallel. 180func.func @test_conv_op_non_output_access_loop_parallel(%arg0 : tensor<?xf32>, 181 %arg1 : tensor<?xf32>, %arg2 : tensor<?xf32>) -> tensor<?xf32> { 182 // expected-error @+1 {{expected all iterators not used to access outputs to be reduction}} 183 %0 = test.linalg_conv_op { 184 indexing_maps = [affine_map<(d0, d1) -> (d0 + d1)>, 185 affine_map<(d0, d1) -> (d1)>, 186 affine_map<(d0, d1) -> (d0)>], 187 iterator_types = ["parallel", "parallel"]} 188 ins(%arg0, %arg1 : tensor<?xf32>, tensor<?xf32>) 189 outs(%arg2 : tensor<?xf32>) { 190 ^bb0(%arg3 : f32, %arg4 : f32, %arg5 : f32): 191 linalg.yield %arg5 : f32 192 } -> tensor<?xf32> 193 return %0 : tensor<?xf32> 194} 195