2018-09-20 12:35:11 +08:00
// RUN: mlir-opt %s -split-input-file -verify
2018-07-24 23:34:58 +08:00
cfgfunc @dim ( tensor < 1x f32 > ) {
bb( %0 : tensor < 1x f32 > ) :
"dim" ( %0 ) { index : "xyz" } : ( tensor < 1x f32 > ) -> i32 // expected-error {{'dim' op requires an integer attribute named 'index'}}
return
}
// -----
cfgfunc @dim2 ( tensor < 1x f32 > ) {
bb( %0 : tensor < 1x f32 > ) :
"dim" ( ) { index : "xyz" } : ( ) -> i32 // expected-error {{'dim' op requires a single operand}}
return
}
// -----
cfgfunc @dim3 ( tensor < 1x f32 > ) {
bb( %0 : tensor < 1x f32 > ) :
"dim" ( %0 ) { index : 1 } : ( tensor < 1x f32 > ) -> i32 // expected-error {{'dim' op index is out of range}}
return
}
// -----
cfgfunc @constant ( ) {
bb:
%x = "constant" ( ) { value: "xyz" } : ( ) -> i32 // expected-error {{'constant' op requires 'value' to be an integer for an integer result type}}
return
}
2018-07-25 01:13:31 +08:00
// -----
2018-11-21 09:51:07 +08:00
cfgfunc @constant_out_of_range ( ) {
bb:
%x = "constant" ( ) { value: 100 } : ( ) -> i1 // expected-error {{'constant' op requires 'value' to be an integer within the range of the integer result type}}
return
}
// -----
2018-07-25 01:13:31 +08:00
cfgfunc @affine_apply_no_map ( ) {
bb0:
2018-10-07 08:21:53 +08:00
%i = "constant" ( ) { value: 0 } : ( ) -> index
%x = "affine_apply" ( %i ) { } : ( index ) -> ( index ) // expected-error {{'affine_apply' op requires an affine map}}
2018-07-25 01:13:31 +08:00
return
}
2018-07-25 08:43:56 +08:00
// -----
cfgfunc @affine_apply_wrong_operand_count ( ) {
bb0:
2018-10-07 08:21:53 +08:00
%i = "constant" ( ) { value: 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}}
2018-07-25 08:43:56 +08:00
return
}
// -----
cfgfunc @affine_apply_wrong_result_count ( ) {
bb0:
2018-10-07 08:21:53 +08:00
%i = "constant" ( ) { value: 0 } : ( ) -> index
%j = "constant" ( ) { value: 1 } : ( ) -> index
%x = "affine_apply" ( %i , %j ) { map: ( d0, d1) -> ( ( d0 + 1 ) , ( d1 + 2 ) ) } : ( index , index ) -> ( index ) // expected-error {{'affine_apply' op result count and affine map result count must match}}
2018-07-25 08:43:56 +08:00
return
}
2018-07-26 02:15:20 +08:00
// -----
cfgfunc @unknown_custom_op ( ) {
bb0:
2018-10-07 08:21:53 +08:00
%i = crazyThing( ) { value: 0 } : ( ) -> index // expected-error {{custom op 'crazyThing' is unknown}}
2018-07-26 02:15:20 +08:00
return
}
2018-07-31 04:08:05 +08:00
// -----
cfgfunc @bad_alloc_wrong_dynamic_dim_count ( ) {
bb0:
2018-10-07 08:21:53 +08:00
%0 = "constant" ( ) { value: 7 } : ( ) -> index
2018-07-31 04:08:05 +08:00
// Test alloc with wrong number of dynamic dimensions.
2018-08-08 00:12:35 +08:00
%1 = alloc( %0 ) [ %1 ] : memref < 2x4x f32 , ( d0, d1) [ s0] -> ( ( d0 + s0) , d1) , 1 > // expected-error {{custom op 'alloc' dimension operand count does not equal memref dynamic dimension count}}
2018-07-31 04:08:05 +08:00
return
}
// -----
cfgfunc @bad_alloc_wrong_symbol_count ( ) {
bb0:
2018-10-07 08:21:53 +08:00
%0 = "constant" ( ) { value: 7 } : ( ) -> index
2018-07-31 04:08:05 +08:00
// Test alloc with wrong number of symbols
2018-09-21 00:39:55 +08:00
%1 = alloc( %0 ) : memref < 2x?x f32 , ( d0, d1) [ s0] -> ( ( d0 + s0) , d1) , 1 > // expected-error {{operand count does not equal dimension plus symbol operand count}}
2018-07-31 04:08:05 +08:00
return
}
2018-08-01 05:11:38 +08:00
// -----
cfgfunc @test_store_zero_results ( ) {
bb0:
%0 = alloc( ) : memref < 1024x64x f32 , ( d0, d1) -> ( d0, d1) , 1 >
2018-10-07 08:21:53 +08:00
%1 = "constant" ( ) { value: 0 } : ( ) -> index
%2 = "constant" ( ) { value: 1 } : ( ) -> index
2018-08-01 05:11:38 +08:00
%3 = load %0 [ %1 , %2 ] : memref < 1024x64x f32 , ( d0, d1) -> ( d0, d1) , 1 >
// Test that store returns zero results.
%4 = store %3 , %0 [ %1 , %2 ] : memref < 1024x64x f32 , ( d0, d1) -> ( d0, d1) , 1 > // expected-error {{cannot name an operation with no results}}
return
}
2018-08-21 23:42:19 +08:00
// -----
2018-09-27 12:18:42 +08:00
mlfunc @test_store_zero_results2 ( %x : i32 , %p : memref < i32 > ) {
"store" ( %x , %p ) : ( i32 , memref < i32 > ) -> i32 // expected-error {{'store' op requires zero results}}
return
}
// -----
2018-09-21 00:39:55 +08:00
cfgfunc @test_alloc_memref_map_rank_mismatch ( ) {
bb0:
2018-11-02 16:48:22 +08:00
%0 = alloc( ) : memref < 1024x64x f32 , ( d0) -> ( d0) , 1 > // expected-error {{memref affine map dimension mismatch}}
2018-09-21 00:39:55 +08:00
return
}
// -----
2018-08-28 01:26:15 +08:00
cfgfunc @intlimit2 ( ) {
bb:
%0 = "constant" ( ) { value: 0 } : ( ) -> i4096
%1 = "constant" ( ) { value: 1 } : ( ) -> i4097 // expected-error {{integer bitwidth is limited to 4096 bits}}
return
}
// -----
2018-08-21 23:42:19 +08:00
mlfunc @mlfunc_constant ( ) {
%x = "constant" ( ) { value: "xyz" } : ( ) -> i32 // expected-error {{'constant' op requires 'value' to be an integer for an integer result type}}
return
}
2018-08-22 08:55:22 +08:00
// -----
2018-11-21 09:51:07 +08:00
mlfunc @mlfunc_constant_out_of_range ( ) {
%x = "constant" ( ) { value: 100 } : ( ) -> i1 // expected-error {{'constant' op requires 'value' to be an integer within the range of the integer result type}}
return
}
// -----
2018-08-22 08:55:22 +08:00
mlfunc @calls ( %arg0 : i32 ) {
%x = call @calls ( ) : ( ) -> i32 // expected-error {{reference to function with mismatched type}}
return
}
2018-09-10 04:41:19 +08:00
// -----
cfgfunc @cfgfunc_with_ops ( f32 ) {
bb0( %a : f32 ) :
2018-09-10 08:59:22 +08:00
%sf = addf %a , %a , %a : f32 // expected-error {{custom op 'addf' expected 2 operands}}
2018-09-10 04:41:19 +08:00
}
2018-09-10 08:59:22 +08:00
// -----
cfgfunc @cfgfunc_with_ops ( f32 ) {
bb0( %a : f32 ) :
%sf = addf( %a , %a ) : f32 // expected-error {{unexpected delimiter}}
}
// -----
cfgfunc @cfgfunc_with_ops ( f32 ) {
bb0( %a : f32 ) :
2018-09-10 23:26:58 +08:00
%sf = addf{ %a , %a } : f32 // expected-error {{invalid operand}}
2018-09-10 08:59:22 +08:00
}
2018-09-20 00:18:36 +08:00
// -----
cfgfunc @cfgfunc_with_ops ( i32 ) {
bb0( %a : i32 ) :
%sf = addf %a , %a : i32 // expected-error {{'addf' op requires a floating point type}}
2018-11-02 16:48:22 +08:00
}
2018-11-08 20:02:00 +08:00
// -----
cfgfunc @cfgfunc_with_ops ( i32 ) {
bb0( %a : i32 ) :
// expected-error@+1 {{'predicate' attribute value out of range}}
%r = "cmpi" ( %a , %b ) { predicate: 42 } : ( i32 , i32 ) -> i1
}
// -----
// Comparison are defined for arguments of the same type.
cfgfunc @cfgfunc_with_ops ( i32 , i64 ) {
bb0( %a : i32 , %b : i64 ) : // expected-error {{prior use here}}
%r = cmpi "eq" , %a , %b : i32 // expected-error {{use of value '%b' expects different type than prior uses}}
}
// -----
// Comparisons must have the "predicate" attribute.
cfgfunc @cfgfunc_with_ops ( i32 , i32 ) {
bb0( %a : i32 , %b : i32 ) :
%r = cmpi %a , %b : i32 // expected-error {{expected type}}
}
// -----
// Integer comparisons are not recognized for float types.
cfgfunc @cfgfunc_with_ops ( f32 , f32 ) {
bb0( %a : f32 , %b : f32 ) :
Enable arithmetics for index types.
Arithmetic and comparison instructions are necessary to implement, e.g.,
control flow when lowering MLFunctions to CFGFunctions. (While it is possible
to replace some of the arithmetics by affine_apply instructions for loop
bounds, it is still necessary for loop bounds checking, steps, if-conditions,
non-trivial memref subscripts, etc.) Furthermore, working with indirect
accesses in, e.g., lookup tables for large embeddings, may require operating on
tensors of indexes. For example, the equivalents to C code "LUT[Index[i]]" or
"ResultIndex[i] = i + j" where i, j are loop induction variables require the
arithmetics on indices as well as the possibility to operate on tensors
thereof. Allow arithmetic and comparison operations to apply to index types by
declaring them integer-like. Allow tensors whose element type is index for
indirection purposes.
The absence of vectors with "index" element type is explicitly tested, but the
only justification for this restriction in the CL introducing the test is
"because we don't need them". Do NOT enable vectors of index types, although
it makes vector and tensor types inconsistent with respect to allowed element
types.
PiperOrigin-RevId: 220614055
2018-11-08 20:04:32 +08:00
%r = cmpi "eq" , %a , %b : f32 // expected-error {{op requires an integer or index type}}
2018-11-08 20:02:00 +08:00
}
// -----
cfgfunc @cfgfunc_with_ops ( i32 , i32 ) {
bb0( %a : i32 , %b : i32 ) :
// expected-error@+1 {{requires an integer attribute named 'predicate'}}
%r = "cmpi" ( %a , %b ) { foo: 1 } : ( i32 , i32 ) -> i1
}
// -----
cfgfunc @cfgfunc_with_ops ( ) {
bb0:
%c = constant splat< vector < 42 x i32 > , 0 > : vector < 42 x i32 >
// expected-error@+1 {{op result must have the same shape as inputs}}
%r = "cmpi" ( %c , %c ) { predicate: 0 } : ( vector < 42 x i32 > , vector < 42 x i32 > ) -> vector < 42 x i32 >
}