1// RUN: mlir-opt %s -split-input-file -verify-diagnostics 2 3func.func @reduce_op_args_num_mismatch(%shape : !shape.shape, %init : !shape.size) { 4 // expected-error@+1 {{ReduceOp body is expected to have 3 arguments}} 5 %num_elements = shape.reduce(%shape, %init) : !shape.shape -> !shape.size { 6 ^bb0(%index: index, %dim: !shape.size): 7 shape.yield %dim : !shape.size 8 } 9 return 10} 11 12// ----- 13 14func.func @reduce_op_arg0_wrong_type(%shape : !shape.shape, %init : !shape.size) { 15 // expected-error@+1 {{argument 0 of ReduceOp body is expected to be of IndexType}} 16 %num_elements = shape.reduce(%shape, %init) : !shape.shape -> !shape.size { 17 ^bb0(%index: f32, %dim: !shape.size, %acc: !shape.size): 18 %new_acc = "shape.add"(%acc, %dim) 19 : (!shape.size, !shape.size) -> !shape.size 20 shape.yield %new_acc : !shape.size 21 } 22 return 23} 24 25// ----- 26 27func.func @reduce_op_arg1_wrong_type(%shape : !shape.shape, %init : !shape.size) { 28 // expected-error@+1 {{argument 1 of ReduceOp body is expected to be of SizeType if the ReduceOp operates on a ShapeType}} 29 %num_elements = shape.reduce(%shape, %init) : !shape.shape -> !shape.size { 30 ^bb0(%index: index, %dim: f32, %lci: !shape.size): 31 shape.yield 32 } 33 return 34} 35 36// ----- 37 38func.func @reduce_op_arg1_wrong_type(%shape : tensor<?xindex>, %init : index) { 39 // expected-error@+1 {{argument 1 of ReduceOp body is expected to be of IndexType if the ReduceOp operates on an extent tensor}} 40 %num_elements = shape.reduce(%shape, %init) : tensor<?xindex> -> index { 41 ^bb0(%index: index, %dim: f32, %lci: index): 42 shape.yield 43 } 44 return 45} 46 47// ----- 48 49func.func @reduce_op_init_type_mismatch(%shape : !shape.shape, %init : f32) { 50 // expected-error@+1 {{type mismatch between argument 2 of ReduceOp body and initial value 0}} 51 %num_elements = shape.reduce(%shape, %init) : !shape.shape -> f32 { 52 ^bb0(%index: index, %dim: !shape.size, %lci: !shape.size): 53 shape.yield 54 } 55 return 56} 57 58// ----- 59 60func.func @yield_op_args_num_mismatch(%shape : !shape.shape, %init : !shape.size) { 61 // expected-error@+3 {{number of operands does not match number of results of its parent}} 62 %num_elements = shape.reduce(%shape, %init) : !shape.shape -> !shape.size { 63 ^bb0(%index: index, %dim: !shape.size, %lci: !shape.size): 64 shape.yield %dim, %dim : !shape.size, !shape.size 65 } 66 return 67} 68 69// ----- 70 71func.func @yield_op_type_mismatch(%shape : !shape.shape, %init : !shape.size) { 72 // expected-error@+4 {{types mismatch between yield op and its parent}} 73 %num_elements = shape.reduce(%shape, %init) : !shape.shape -> !shape.size { 74 ^bb0(%index: index, %dim: !shape.size, %lci: !shape.size): 75 %c0 = arith.constant 1 : index 76 shape.yield %c0 : index 77 } 78 return 79} 80 81// ----- 82 83func.func @assuming_all_op_too_few_operands() { 84 // expected-error@+1 {{no operands specified}} 85 %w0 = shape.assuming_all 86 return 87} 88 89// ----- 90 91func.func @shape_of(%value_arg : !shape.value_shape, 92 %shaped_arg : tensor<?x3x4xf32>) { 93 // expected-error@+1 {{if at least one of the operands can hold error values then the result must be of type `shape` to propagate them}} 94 %0 = shape.shape_of %value_arg : !shape.value_shape -> tensor<?xindex> 95 return 96} 97 98// ----- 99 100func.func @shape_of_incompatible_return_types(%value_arg : tensor<1x2xindex>) { 101 // expected-error@+2 {{failed to infer returned types}} 102 // expected-error@+1 {{'shape.shape_of' op inferred type(s) 'tensor<2xindex>' are incompatible with return type(s) of operation 'tensor<3xindex>'}} 103 %0 = shape.shape_of %value_arg : tensor<1x2xindex> -> tensor<3xindex> 104 return 105} 106 107// ----- 108 109func.func @rank(%arg : !shape.shape) { 110 // expected-error@+1 {{if at least one of the operands can hold error values then the result must be of type `size` to propagate them}} 111 %0 = shape.rank %arg : !shape.shape -> index 112 return 113} 114 115// ----- 116 117func.func @get_extent(%arg : tensor<?xindex>) -> index { 118 %c0 = shape.const_size 0 119 // expected-error@+1 {{if at least one of the operands can hold error values then the result must be of type `size` to propagate them}} 120 %result = shape.get_extent %arg, %c0 : tensor<?xindex>, !shape.size -> index 121 return %result : index 122} 123 124// ----- 125 126func.func @mul(%lhs : !shape.size, %rhs : index) -> index { 127 // expected-error@+1 {{if at least one of the operands can hold error values then the result must be of type `size` to propagate them}} 128 %result = shape.mul %lhs, %rhs : !shape.size, index -> index 129 return %result : index 130} 131 132// ----- 133 134func.func @num_elements(%arg : !shape.shape) -> index { 135 // expected-error@+1 {{if at least one of the operands can hold error values then the result must be of type `size` to propagate them}} 136 %result = shape.num_elements %arg : !shape.shape -> index 137 return %result : index 138} 139 140// ----- 141 142func.func @add(%lhs : !shape.size, %rhs : index) -> index { 143 // expected-error@+1 {{if at least one of the operands can hold error values then the result must be of type `size` to propagate them}} 144 %result = shape.add %lhs, %rhs : !shape.size, index -> index 145 return %result : index 146} 147 148// ----- 149 150func.func @broadcast(%arg0 : !shape.shape, %arg1 : !shape.shape) -> tensor<?xindex> { 151 // expected-error@+1 {{if at least one of the operands can hold error values then the result must be of type `shape` to propagate them}} 152 %result = shape.broadcast %arg0, %arg1 153 : !shape.shape, !shape.shape -> tensor<?xindex> 154 return %result : tensor<?xindex> 155} 156 157 158// ----- 159 160func.func @broadcast(%arg0 : !shape.shape, %arg1 : tensor<?xindex>) -> tensor<?xindex> { 161 // expected-error@+1 {{if at least one of the operands can hold error values then the result must be of type `shape` to propagate them}} 162 %result = shape.broadcast %arg0, %arg1 163 : !shape.shape, tensor<?xindex> -> tensor<?xindex> 164 return %result : tensor<?xindex> 165} 166 167// ----- 168 169// Test using an unsupported shape.lib attribute type. 170 171// expected-error@+1 {{only SymbolRefAttr allowed in shape.lib attribute array}} 172module attributes {shape.lib = [@shape_lib, "shape_lib"]} { 173 174shape.function_library @shape_lib { 175 // Test shape function that returns the shape of input arg as result shape. 176 func.func @same_result_shape(%arg: !shape.value_shape) -> !shape.shape { 177 %0 = shape.shape_of %arg : !shape.value_shape -> !shape.shape 178 return %0 : !shape.shape 179 } 180} mapping { 181 test.same_operand_result_type = @same_result_shape 182} 183 184} 185 186// ----- 187 188// Test that duplicate op to shape function mappings are flagged, this uses 189// the same library twice for easy overlap. 190 191// expected-error@+1 {{only one op to shape mapping allowed}} 192module attributes {shape.lib = [@shape_lib, @shape_lib]} { 193 194shape.function_library @shape_lib { 195 // Test shape function that returns the shape of input arg as result shape. 196 func.func @same_result_shape(%arg: !shape.value_shape) -> !shape.shape { 197 %0 = shape.shape_of %arg : !shape.value_shape -> !shape.shape 198 return %0 : !shape.shape 199 } 200} mapping { 201 test.same_operand_result_type = @same_result_shape 202} 203 204} 205 206// ----- 207 208// Test that duplicate op to shape function mappings are flagged (this is 209// more an invariant of using the dictionary attribute here than anything 210// specific to function library op). 211 212module attributes {shape.lib = [@shape_lib]} { 213 214shape.function_library @shape_lib { 215 // Test shape function that returns the shape of input arg as result shape. 216 func.func @same_result_shape(%arg: !shape.value_shape) -> !shape.shape { 217 %0 = shape.shape_of %arg : !shape.value_shape -> !shape.shape 218 return %0 : !shape.shape 219 } 220} mapping { 221 // expected-error @+2 {{duplicate key}} 222 test.same_operand_result_type = @same_result_shape, 223 test.same_operand_result_type = @same_result_shape 224} 225 226} 227 228// ----- 229 230// Test that op referred to by shape lib is a shape function library. 231 232// expected-error@+1 {{required to be shape function library}} 233module attributes {shape.lib = @fn} { 234 235func.func @fn(%arg: !shape.value_shape) -> !shape.shape { 236 %0 = shape.shape_of %arg : !shape.value_shape -> !shape.shape 237 return %0 : !shape.shape 238} 239 240} 241 242// ----- 243 244// Test that op referred to by shape lib is a shape function library. 245 246func.func @fn(%arg: !shape.value_shape) -> !shape.shape { 247 // expected-error@+1 {{SymbolTable}} 248 %0 = shape.shape_of %arg {shape.lib = @fn} : !shape.value_shape -> !shape.shape 249 return %0 : !shape.shape 250} 251 252// ----- 253 254// Test that shape function library is defined. 255 256// expected-error@+1 {{@fn not found}} 257module attributes {shape.lib = @fn} { } 258 259// ----- 260 261func.func @fn(%arg: !shape.shape) -> !shape.witness { 262 // expected-error@+1 {{required at least 2 input shapes}} 263 %0 = shape.cstr_broadcastable %arg : !shape.shape 264 return %0 : !shape.witness 265} 266 267// ----- 268 269// Test that type inference flags the wrong return type. 270 271func.func @const_shape() { 272 // expected-error@+2 {{failed to infer returned types}} 273 // expected-error@+1 {{'tensor<3xindex>' are incompatible with return type(s) of operation 'tensor<2xindex>'}} 274 %0 = shape.const_shape [4, 5, 6] : tensor<2xindex> 275 return 276} 277 278// ----- 279 280func.func @invalid_meet(%arg0 : !shape.shape, %arg1 : index) -> index { 281 // expected-error@+2 {{failed to infer returned types}} 282 // expected-error@+1 {{requires all sizes or shapes}} 283 %result = shape.meet %arg0, %arg1 : !shape.shape, index -> index 284 return %result : index 285} 286 287// ----- 288 289func.func @invalid_meet(%arg0 : tensor<2xindex>, %arg1 : tensor<3xindex>) -> tensor<?xindex> { 290 // expected-error@+2 {{failed to infer returned types}} 291 // expected-error@+1 {{unequal shape cardinality}} 292 %result = shape.meet %arg0, %arg1 : tensor<2xindex>, tensor<3xindex> -> tensor<?xindex> 293 return %result : tensor<?xindex> 294} 295 296