This patch attempts to deduce when the oilist element must be printed based on the optional arguments to it. This especially helps creating an operation accurately because with the current implementation, the inferred unit attributes must be manually added to print the clauses appropriately. Reviewed By: Mogball Differential Revision: https://reviews.llvm.org/D121579
676 lines
24 KiB
MLIR
676 lines
24 KiB
MLIR
// RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -verify-diagnostics | FileCheck %s
|
|
|
|
// CHECK: succeededSameOperandsElementType
|
|
func @succeededSameOperandsElementType(%t10x10 : tensor<10x10xf32>, %t1f: tensor<1xf32>, %v1: vector<1xf32>, %t1i: tensor<1xi32>, %sf: f32) {
|
|
"test.same_operand_element_type"(%t1f, %t1f) : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xi32>
|
|
"test.same_operand_element_type"(%t1f, %t10x10) : (tensor<1xf32>, tensor<10x10xf32>) -> tensor<1xi32>
|
|
"test.same_operand_element_type"(%t10x10, %v1) : (tensor<10x10xf32>, vector<1xf32>) -> tensor<1xi32>
|
|
"test.same_operand_element_type"(%v1, %t1f) : (vector<1xf32>, tensor<1xf32>) -> tensor<1xi32>
|
|
"test.same_operand_element_type"(%v1, %t1f) : (vector<1xf32>, tensor<1xf32>) -> tensor<121xi32>
|
|
"test.same_operand_element_type"(%sf, %sf) : (f32, f32) -> i32
|
|
"test.same_operand_element_type"(%sf, %t1f) : (f32, tensor<1xf32>) -> tensor<121xi32>
|
|
"test.same_operand_element_type"(%sf, %v1) : (f32, vector<1xf32>) -> tensor<121xi32>
|
|
"test.same_operand_element_type"(%sf, %t10x10) : (f32, tensor<10x10xf32>) -> tensor<121xi32>
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandElementType(%t1f: tensor<1xf32>, %t1i: tensor<1xi32>) {
|
|
// expected-error@+1 {{requires the same element type for all operands}}
|
|
"test.same_operand_element_type"(%t1f, %t1i) : (tensor<1xf32>, tensor<1xi32>) -> tensor<1xf32>
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandAndResultElementType_no_operands() {
|
|
// expected-error@+1 {{expected 2 operands, but found 0}}
|
|
"test.same_operand_element_type"() : () -> tensor<1xf32>
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandElementType_scalar_type_mismatch(%si: i32, %sf: f32) {
|
|
// expected-error@+1 {{requires the same element type for all operands}}
|
|
"test.same_operand_element_type"(%sf, %si) : (f32, i32) -> tensor<1xf32>
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK: succeededSameOperandAndResultElementType
|
|
func @succeededSameOperandAndResultElementType(%t10x10 : tensor<10x10xf32>, %t1f: tensor<1xf32>, %v1: vector<1xf32>, %t1i: tensor<1xi32>, %sf: f32) {
|
|
"test.same_operand_and_result_element_type"(%t1f, %t1f) : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xf32>
|
|
"test.same_operand_and_result_element_type"(%t1f, %t10x10) : (tensor<1xf32>, tensor<10x10xf32>) -> tensor<1xf32>
|
|
"test.same_operand_and_result_element_type"(%t10x10, %v1) : (tensor<10x10xf32>, vector<1xf32>) -> tensor<1xf32>
|
|
"test.same_operand_and_result_element_type"(%v1, %t1f) : (vector<1xf32>, tensor<1xf32>) -> tensor<1xf32>
|
|
"test.same_operand_and_result_element_type"(%v1, %t1f) : (vector<1xf32>, tensor<1xf32>) -> tensor<121xf32>
|
|
"test.same_operand_and_result_element_type"(%sf, %sf) : (f32, f32) -> f32
|
|
"test.same_operand_and_result_element_type"(%sf, %t1f) : (f32, tensor<1xf32>) -> tensor<121xf32>
|
|
"test.same_operand_and_result_element_type"(%sf, %v1) : (f32, vector<1xf32>) -> tensor<121xf32>
|
|
"test.same_operand_and_result_element_type"(%sf, %t10x10) : (f32, tensor<10x10xf32>) -> tensor<121xf32>
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandAndResultElementType_operand_result_mismatch(%t1f: tensor<1xf32>) {
|
|
// expected-error@+1 {{requires the same element type for all operands and results}}
|
|
"test.same_operand_and_result_element_type"(%t1f, %t1f) : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xi32>
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandAndResultElementType_operand_mismatch(%t1f: tensor<1xf32>, %t1i: tensor<1xi32>) {
|
|
// expected-error@+1 {{requires the same element type for all operands and results}}
|
|
"test.same_operand_and_result_element_type"(%t1f, %t1i) : (tensor<1xf32>, tensor<1xi32>) -> tensor<1xf32>
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandAndResultElementType_result_mismatch(%t1f: tensor<1xf32>) {
|
|
// expected-error@+1 {{requires the same element type for all operands and results}}
|
|
%0:2 = "test.same_operand_and_result_element_type"(%t1f) : (tensor<1xf32>) -> (tensor<1xf32>, tensor<1xi32>)
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandAndResultElementType_no_operands() {
|
|
// expected-error@+1 {{expected 1 or more operands}}
|
|
"test.same_operand_and_result_element_type"() : () -> tensor<1xf32>
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandAndResultElementType_no_results(%t1f: tensor<1xf32>) {
|
|
// expected-error@+1 {{expected 1 or more results}}
|
|
"test.same_operand_and_result_element_type"(%t1f) : (tensor<1xf32>) -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK: succeededSameOperandShape
|
|
func @succeededSameOperandShape(%t10x10 : tensor<10x10xf32>, %t1: tensor<1xf32>, %m10x10 : memref<10x10xi32>, %tr: tensor<*xf32>) {
|
|
"test.same_operand_shape"(%t1, %t1) : (tensor<1xf32>, tensor<1xf32>) -> ()
|
|
"test.same_operand_shape"(%t10x10, %t10x10) : (tensor<10x10xf32>, tensor<10x10xf32>) -> ()
|
|
"test.same_operand_shape"(%t1, %tr) : (tensor<1xf32>, tensor<*xf32>) -> ()
|
|
"test.same_operand_shape"(%t10x10, %m10x10) : (tensor<10x10xf32>, memref<10x10xi32>) -> ()
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandShape_operand_mismatch(%t10x10 : tensor<10x10xf32>, %t1: tensor<1xf32>) {
|
|
// expected-error@+1 {{requires the same shape for all operands}}
|
|
"test.same_operand_shape"(%t1, %t10x10) : (tensor<1xf32>, tensor<10x10xf32>) -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandShape_no_operands() {
|
|
// expected-error@+1 {{expected 1 or more operands}}
|
|
"test.same_operand_shape"() : () -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK: succeededSameOperandAndResultShape
|
|
func @succeededSameOperandAndResultShape(%t10x10 : tensor<10x10xf32>, %t1: tensor<1xf32>, %tr: tensor<*xf32>, %t1d: tensor<?xf32>) {
|
|
"test.same_operand_and_result_shape"(%t1, %t1) : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xf32>
|
|
"test.same_operand_and_result_shape"(%t10x10, %t10x10) : (tensor<10x10xf32>, tensor<10x10xf32>) -> tensor<10x10xf32>
|
|
"test.same_operand_and_result_shape"(%t1, %tr) : (tensor<1xf32>, tensor<*xf32>) -> tensor<1xf32>
|
|
"test.same_operand_and_result_shape"(%t1, %t1d) : (tensor<1xf32>, tensor<?xf32>) -> tensor<1xf32>
|
|
"test.same_operand_and_result_shape"(%t1, %t1d) : (tensor<1xf32>, tensor<?xf32>) -> memref<1xf32>
|
|
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandAndResultShape_operand_result_mismatch(%t10x10 : tensor<10x10xf32>, %t1: tensor<1xf32>) {
|
|
// expected-error@+1 {{requires the same shape for all operands and results}}
|
|
"test.same_operand_and_result_shape"(%t1, %t10x10) : (tensor<1xf32>, tensor<10x10xf32>) -> tensor<10x10xf32>
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandAndResultShape_operand_result_mismatch(%t10 : tensor<10xf32>, %t1: tensor<?xf32>) {
|
|
// expected-error@+1 {{requires the same shape for all operands and results}}
|
|
"test.same_operand_and_result_shape"(%t1, %t10) : (tensor<?xf32>, tensor<10xf32>) -> tensor<3xf32>
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandAndResultShape_no_operands() {
|
|
// expected-error@+1 {{expected 1 or more operands}}
|
|
"test.same_operand_and_result_shape"() : () -> (tensor<1xf32>)
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandAndResultShape_no_operands(%t1: tensor<1xf32>) {
|
|
// expected-error@+1 {{expected 1 or more results}}
|
|
"test.same_operand_and_result_shape"(%t1) : (tensor<1xf32>) -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK: succeededSameOperandAndResultType
|
|
func @succeededSameOperandAndResultType(%t10x10 : tensor<10x10xf32>, %t1: tensor<1xf32>, %tr: tensor<*xf32>, %t1d: tensor<?xf32>, %i32 : i32) {
|
|
"test.same_operand_and_result_type"(%t1, %t1) : (tensor<1xf32>, tensor<1xf32>) -> tensor<1xf32>
|
|
"test.same_operand_and_result_type"(%t10x10, %t10x10) : (tensor<10x10xf32>, tensor<10x10xf32>) -> tensor<10x10xf32>
|
|
"test.same_operand_and_result_type"(%t1, %tr) : (tensor<1xf32>, tensor<*xf32>) -> tensor<1xf32>
|
|
"test.same_operand_and_result_type"(%t1, %t1d) : (tensor<1xf32>, tensor<?xf32>) -> tensor<1xf32>
|
|
"test.same_operand_and_result_type"(%i32, %i32) : (i32, i32) -> i32
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSameOperandAndResultType_operand_result_mismatch(%t10 : tensor<10xf32>, %t20 : tensor<20xf32>) {
|
|
// expected-error@+1 {{requires the same type for all operands and results}}
|
|
"test.same_operand_and_result_type"(%t10, %t20) : (tensor<10xf32>, tensor<20xf32>) -> tensor<10xf32>
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedElementwiseMappable_different_rankedness(%arg0: tensor<?xf32>, %arg1: tensor<*xf32>) {
|
|
// expected-error@+1 {{all non-scalar operands/results must have the same shape and base type}}
|
|
%0 = "test.elementwise_mappable"(%arg0, %arg1) : (tensor<?xf32>, tensor<*xf32>) -> tensor<*xf32>
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedElementwiseMappable_different_rank(%arg0: tensor<?xf32>, %arg1: tensor<?x?xf32>) {
|
|
// expected-error@+1 {{all non-scalar operands/results must have the same shape and base type}}
|
|
%0 = "test.elementwise_mappable"(%arg0, %arg1) : (tensor<?xf32>, tensor<?x?xf32>) -> tensor<?x?xf32>
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @elementwiseMappable_dynamic_shapes(%arg0: tensor<?xf32>,
|
|
%arg1: tensor<5xf32>) {
|
|
%0 = "test.elementwise_mappable"(%arg0, %arg1) :
|
|
(tensor<?xf32>, tensor<5xf32>) -> tensor<?xf32>
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedElementwiseMappable_different_base_type(%arg0: vector<2xf32>, %arg1: tensor<2xf32>) {
|
|
// expected-error@+1 {{all non-scalar operands/results must have the same shape and base type}}
|
|
%0 = "test.elementwise_mappable"(%arg0, %arg1) : (vector<2xf32>, tensor<2xf32>) -> tensor<2xf32>
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedElementwiseMappable_non_scalar_output(%arg0: vector<2xf32>) {
|
|
// expected-error@+1 {{if an operand is non-scalar, then there must be at least one non-scalar result}}
|
|
%0 = "test.elementwise_mappable"(%arg0) : (vector<2xf32>) -> f32
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedElementwiseMappable_non_scalar_result_all_scalar_input(%arg0: f32) {
|
|
// expected-error@+1 {{if a result is non-scalar, then at least one operand must be non-scalar}}
|
|
%0 = "test.elementwise_mappable"(%arg0) : (f32) -> tensor<f32>
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedElementwiseMappable_mixed_scalar_non_scalar_results(%arg0: tensor<10xf32>) {
|
|
// expected-error@+1 {{if an operand is non-scalar, then all results must be non-scalar}}
|
|
%0, %1 = "test.elementwise_mappable"(%arg0) : (tensor<10xf32>) -> (f32, tensor<10xf32>)
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedElementwiseMappable_zero_results(%arg0: tensor<10xf32>) {
|
|
// expected-error@+1 {{if an operand is non-scalar, then there must be at least one non-scalar result}}
|
|
"test.elementwise_mappable"(%arg0) : (tensor<10xf32>) -> ()
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedElementwiseMappable_zero_operands() {
|
|
// expected-error@+1 {{if a result is non-scalar, then at least one operand must be non-scalar}}
|
|
"test.elementwise_mappable"() : () -> (tensor<6xf32>)
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @succeededElementwiseMappable(%arg0: vector<2xf32>) {
|
|
// Check that varying element types are allowed.
|
|
// CHECK: test.elementwise_mappable
|
|
%0 = "test.elementwise_mappable"(%arg0) : (vector<2xf32>) -> vector<2xf16>
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedHasParent_wrong_parent() {
|
|
"some.op"() ({
|
|
// expected-error@+1 {{'test.child' op expects parent op 'test.parent'}}
|
|
"test.child"() : () -> ()
|
|
}) : () -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK: succeededParentOneOf
|
|
func @succeededParentOneOf() {
|
|
"test.parent"() ({
|
|
"test.child_with_parent_one_of"() : () -> ()
|
|
"test.finish"() : () -> ()
|
|
}) : () -> ()
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK: succeededParent1OneOf
|
|
func @succeededParent1OneOf() {
|
|
"test.parent1"() ({
|
|
"test.child_with_parent_one_of"() : () -> ()
|
|
"test.finish"() : () -> ()
|
|
}) : () -> ()
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedParentOneOf_wrong_parent1() {
|
|
"some.otherop"() ({
|
|
// expected-error@+1 {{'test.child_with_parent_one_of' op expects parent op to be one of 'test.parent, test.parent1'}}
|
|
"test.child_with_parent_one_of"() : () -> ()
|
|
"test.finish"() : () -> ()
|
|
}) : () -> ()
|
|
}
|
|
|
|
|
|
// -----
|
|
|
|
func @failedSingleBlockImplicitTerminator_empty_block() {
|
|
// expected-error@+1 {{'test.SingleBlockImplicitTerminator' op expects a non-empty block}}
|
|
"test.SingleBlockImplicitTerminator"() ({
|
|
^entry:
|
|
}) : () -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSingleBlockImplicitTerminator_too_many_blocks() {
|
|
// expected-error@+1 {{'test.SingleBlockImplicitTerminator' op expects region #0 to have 0 or 1 block}}
|
|
"test.SingleBlockImplicitTerminator"() ({
|
|
^entry:
|
|
"test.finish" () : () -> ()
|
|
^other:
|
|
"test.finish" () : () -> ()
|
|
}) : () -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedSingleBlockImplicitTerminator_missing_terminator() {
|
|
// expected-error@+2 {{'test.SingleBlockImplicitTerminator' op expects regions to end with 'test.finish'}}
|
|
// expected-note@+1 {{in custom textual format, the absence of terminator implies 'test.finish'}}
|
|
"test.SingleBlockImplicitTerminator"() ({
|
|
^entry:
|
|
"test.non_existent_op"() : () -> ()
|
|
}) : () -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test the invariants of operations with the Symbol Trait.
|
|
|
|
// expected-error@+1 {{op requires attribute 'sym_name'}}
|
|
"test.symbol"() {} : () -> ()
|
|
|
|
// -----
|
|
|
|
// expected-error@+1 {{op attribute 'sym_visibility' failed to satisfy constraint: string attribute}}
|
|
"test.symbol"() {sym_name = "foo_2", sym_visibility} : () -> ()
|
|
|
|
// -----
|
|
|
|
// expected-error@+1 {{visibility expected to be one of ["public", "private", "nested"]}}
|
|
"test.symbol"() {sym_name = "foo_2", sym_visibility = "foo"} : () -> ()
|
|
|
|
// -----
|
|
|
|
"test.symbol"() {sym_name = "foo_3", sym_visibility = "nested"} : () -> ()
|
|
"test.symbol"() {sym_name = "foo_4", sym_visibility = "private"} : () -> ()
|
|
"test.symbol"() {sym_name = "foo_5", sym_visibility = "public"} : () -> ()
|
|
"test.symbol"() {sym_name = "foo_6"} : () -> ()
|
|
|
|
// -----
|
|
|
|
// Test that operation with the SymbolTable Trait define a new symbol scope.
|
|
"test.symbol_scope"() ({
|
|
func private @foo()
|
|
"test.finish" () : () -> ()
|
|
}) : () -> ()
|
|
func private @foo()
|
|
|
|
// -----
|
|
|
|
// Test that operation with the SymbolTable Trait fails with too many blocks.
|
|
// expected-error@+1 {{op expects region #0 to have 0 or 1 blocks}}
|
|
"test.symbol_scope"() ({
|
|
^entry:
|
|
"test.finish" () : () -> ()
|
|
^other:
|
|
"test.finish" () : () -> ()
|
|
}) : () -> ()
|
|
|
|
// -----
|
|
|
|
func @failedMissingOperandSizeAttr(%arg: i32) {
|
|
// expected-error @+1 {{requires 1D i32 elements attribute 'operand_segment_sizes'}}
|
|
"test.attr_sized_operands"(%arg, %arg, %arg, %arg) : (i32, i32, i32, i32) -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedOperandSizeAttrWrongType(%arg: i32) {
|
|
// expected-error @+1 {{requires 1D i32 elements attribute 'operand_segment_sizes'}}
|
|
"test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = 10} : (i32, i32, i32, i32) -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedOperandSizeAttrWrongRank(%arg: i32) {
|
|
// expected-error @+1 {{requires 1D i32 elements attribute 'operand_segment_sizes'}}
|
|
"test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[[1, 1], [1, 1]]>: vector<2x2xi32>} : (i32, i32, i32, i32) -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedOperandSizeAttrWrongElementType(%arg: i32) {
|
|
// expected-error @+1 {{requires 1D i32 elements attribute 'operand_segment_sizes'}}
|
|
"test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[1, 1, 1, 1]>: vector<4xi64>} : (i32, i32, i32, i32) -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedOperandSizeAttrNegativeValue(%arg: i32) {
|
|
// expected-error @+1 {{'operand_segment_sizes' attribute cannot have negative elements}}
|
|
"test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[1, 1, -1, 1]>: vector<4xi32>} : (i32, i32, i32, i32) -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedOperandSizeAttrWrongTotalSize(%arg: i32) {
|
|
// expected-error @+1 {{operand count (4) does not match with the total size (3) specified in attribute 'operand_segment_sizes'}}
|
|
"test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[0, 1, 1, 1]>: vector<4xi32>} : (i32, i32, i32, i32) -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedOperandSizeAttrWrongCount(%arg: i32) {
|
|
// expected-error @+1 {{'operand_segment_sizes' attribute for specifying operand segments must have 4 elements}}
|
|
"test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[2, 1, 1]>: vector<3xi32>} : (i32, i32, i32, i32) -> ()
|
|
}
|
|
|
|
// -----
|
|
|
|
func @succeededOperandSizeAttr(%arg: i32) {
|
|
// CHECK: test.attr_sized_operands
|
|
"test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[0, 2, 1, 1]>: vector<4xi32>} : (i32, i32, i32, i32) -> ()
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedMissingResultSizeAttr() {
|
|
// expected-error @+1 {{requires 1D i32 elements attribute 'result_segment_sizes'}}
|
|
%0:4 = "test.attr_sized_results"() : () -> (i32, i32, i32, i32)
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedResultSizeAttrWrongType() {
|
|
// expected-error @+1 {{requires 1D i32 elements attribute 'result_segment_sizes'}}
|
|
%0:4 = "test.attr_sized_results"() {result_segment_sizes = 10} : () -> (i32, i32, i32, i32)
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedResultSizeAttrWrongRank() {
|
|
// expected-error @+1 {{requires 1D i32 elements attribute 'result_segment_sizes'}}
|
|
%0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[[1, 1], [1, 1]]>: vector<2x2xi32>} : () -> (i32, i32, i32, i32)
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedResultSizeAttrWrongElementType() {
|
|
// expected-error @+1 {{requires 1D i32 elements attribute 'result_segment_sizes'}}
|
|
%0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[1, 1, 1, 1]>: vector<4xi64>} : () -> (i32, i32, i32, i32)
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedResultSizeAttrNegativeValue() {
|
|
// expected-error @+1 {{'result_segment_sizes' attribute cannot have negative elements}}
|
|
%0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[1, 1, -1, 1]>: vector<4xi32>} : () -> (i32, i32, i32, i32)
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedResultSizeAttrWrongTotalSize() {
|
|
// expected-error @+1 {{result count (4) does not match with the total size (3) specified in attribute 'result_segment_sizes'}}
|
|
%0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[0, 1, 1, 1]>: vector<4xi32>} : () -> (i32, i32, i32, i32)
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedResultSizeAttrWrongCount() {
|
|
// expected-error @+1 {{'result_segment_sizes' attribute for specifying result segments must have 4 elements, but got 3}}
|
|
%0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[2, 1, 1]>: vector<3xi32>} : () -> (i32, i32, i32, i32)
|
|
}
|
|
|
|
// -----
|
|
|
|
func @succeededResultSizeAttr() {
|
|
// CHECK: test.attr_sized_results
|
|
%0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[0, 2, 1, 1]>: vector<4xi32>} : () -> (i32, i32, i32, i32)
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: @succeededOilistTrivial
|
|
func @succeededOilistTrivial() {
|
|
// CHECK: test.oilist_with_keywords_only keyword
|
|
test.oilist_with_keywords_only keyword
|
|
// CHECK: test.oilist_with_keywords_only otherKeyword
|
|
test.oilist_with_keywords_only otherKeyword
|
|
// CHECK: test.oilist_with_keywords_only keyword otherKeyword
|
|
test.oilist_with_keywords_only keyword otherKeyword
|
|
// CHECK: test.oilist_with_keywords_only keyword otherKeyword
|
|
test.oilist_with_keywords_only otherKeyword keyword
|
|
// CHECK: test.oilist_with_keywords_only thirdKeyword
|
|
test.oilist_with_keywords_only thirdKeyword
|
|
// CHECK: test.oilist_with_keywords_only keyword thirdKeyword
|
|
test.oilist_with_keywords_only keyword thirdKeyword
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: @succeededOilistSimple
|
|
func @succeededOilistSimple(%arg0 : i32, %arg1 : i32, %arg2 : i32) {
|
|
// CHECK: test.oilist_with_simple_args keyword %{{.*}} : i32
|
|
test.oilist_with_simple_args keyword %arg0 : i32
|
|
// CHECK: test.oilist_with_simple_args otherKeyword %{{.*}} : i32
|
|
test.oilist_with_simple_args otherKeyword %arg0 : i32
|
|
// CHECK: test.oilist_with_simple_args thirdKeyword %{{.*}} : i32
|
|
test.oilist_with_simple_args thirdKeyword %arg0 : i32
|
|
|
|
// CHECK: test.oilist_with_simple_args keyword %{{.*}} : i32 otherKeyword %{{.*}} : i32
|
|
test.oilist_with_simple_args keyword %arg0 : i32 otherKeyword %arg1 : i32
|
|
// CHECK: test.oilist_with_simple_args keyword %{{.*}} : i32 thirdKeyword %{{.*}} : i32
|
|
test.oilist_with_simple_args keyword %arg0 : i32 thirdKeyword %arg1 : i32
|
|
// CHECK: test.oilist_with_simple_args otherKeyword %{{.*}} : i32 thirdKeyword %{{.*}} : i32
|
|
test.oilist_with_simple_args thirdKeyword %arg0 : i32 otherKeyword %arg1 : i32
|
|
|
|
// CHECK: test.oilist_with_simple_args keyword %{{.*}} : i32 otherKeyword %{{.*}} : i32 thirdKeyword %{{.*}} : i32
|
|
test.oilist_with_simple_args keyword %arg0 : i32 otherKeyword %arg1 : i32 thirdKeyword %arg2 : i32
|
|
// CHECK: test.oilist_with_simple_args keyword %{{.*}} : i32 otherKeyword %{{.*}} : i32 thirdKeyword %{{.*}} : i32
|
|
test.oilist_with_simple_args otherKeyword %arg0 : i32 keyword %arg1 : i32 thirdKeyword %arg2 : i32
|
|
// CHECK: test.oilist_with_simple_args keyword %{{.*}} : i32 otherKeyword %{{.*}} : i32 thirdKeyword %{{.*}} : i32
|
|
test.oilist_with_simple_args otherKeyword %arg0 : i32 thirdKeyword %arg1 : i32 keyword %arg2 : i32
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: @succeededOilistVariadic
|
|
// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32, %[[ARG2:.*]]: i32)
|
|
func @succeededOilistVariadic(%arg0: i32, %arg1: i32, %arg2: i32) {
|
|
// CHECK: test.oilist_variadic_with_parens keyword(%[[ARG0]], %[[ARG1]] : i32, i32)
|
|
test.oilist_variadic_with_parens keyword (%arg0, %arg1 : i32, i32)
|
|
// CHECK: test.oilist_variadic_with_parens keyword(%[[ARG0]], %[[ARG1]] : i32, i32) otherKeyword(%[[ARG2]], %[[ARG1]] : i32, i32)
|
|
test.oilist_variadic_with_parens otherKeyword (%arg2, %arg1 : i32, i32) keyword (%arg0, %arg1 : i32, i32)
|
|
// CHECK: test.oilist_variadic_with_parens keyword(%[[ARG0]], %[[ARG1]] : i32, i32) otherKeyword(%[[ARG0]], %[[ARG1]] : i32, i32) thirdKeyword(%[[ARG2]], %[[ARG0]], %[[ARG1]] : i32, i32, i32)
|
|
test.oilist_variadic_with_parens thirdKeyword (%arg2, %arg0, %arg1 : i32, i32, i32) keyword (%arg0, %arg1 : i32, i32) otherKeyword (%arg0, %arg1 : i32, i32)
|
|
return
|
|
}
|
|
|
|
// -----
|
|
// CHECK-LABEL: succeededOilistCustom
|
|
// CHECK-SAME: (%[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32, %[[ARG2:.*]]: i32)
|
|
func @succeededOilistCustom(%arg0: i32, %arg1: i32, %arg2: i32) {
|
|
// CHECK: test.oilist_custom private(%[[ARG0]], %[[ARG1]] : i32, i32)
|
|
test.oilist_custom private (%arg0, %arg1 : i32, i32)
|
|
// CHECK: test.oilist_custom private(%[[ARG0]], %[[ARG1]] : i32, i32) nowait
|
|
test.oilist_custom private (%arg0, %arg1 : i32, i32) nowait
|
|
// CHECK: test.oilist_custom private(%arg0, %arg1 : i32, i32) reduction (%arg1) nowait
|
|
test.oilist_custom nowait reduction (%arg1) private (%arg0, %arg1 : i32, i32)
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @failedHasDominanceScopeOutsideDominanceFreeScope() -> () {
|
|
"test.ssacfg_region"() ({
|
|
test.graph_region {
|
|
// expected-error @+1 {{operand #0 does not dominate this use}}
|
|
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
|
|
}
|
|
// expected-note @+1 {{operand defined here}}
|
|
%1 = "baz"() : () -> (i64)
|
|
}) : () -> ()
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// Ensure that SSACFG regions of operations in GRAPH regions are
|
|
// checked for dominance
|
|
func @illegalInsideDominanceFreeScope() -> () {
|
|
test.graph_region {
|
|
func.func @test() -> i1 {
|
|
^bb1:
|
|
// expected-error @+1 {{operand #0 does not dominate this use}}
|
|
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
|
|
// expected-note @+1 {{operand defined here}}
|
|
%1 = "baz"(%2#0) : (i1) -> (i64)
|
|
return %2#1 : i1
|
|
}
|
|
"terminator"() : () -> ()
|
|
}
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// Ensure that SSACFG regions of operations in GRAPH regions are
|
|
// checked for dominance
|
|
func @illegalCDFGInsideDominanceFreeScope() -> () {
|
|
test.graph_region {
|
|
func.func @test() -> i1 {
|
|
^bb1:
|
|
// expected-error @+1 {{operand #0 does not dominate this use}}
|
|
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
|
|
cf.br ^bb4
|
|
^bb2:
|
|
cf.br ^bb2
|
|
^bb4:
|
|
%1 = "foo"() : ()->i64 // expected-note {{operand defined here}}
|
|
return %2#1 : i1
|
|
}
|
|
"terminator"() : () -> ()
|
|
}
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// Ensure that GRAPH regions still have all values defined somewhere.
|
|
func @illegalCDFGInsideDominanceFreeScope() -> () {
|
|
test.graph_region {
|
|
// expected-error @+1 {{use of undeclared SSA value name}}
|
|
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
|
|
"terminator"() : () -> ()
|
|
}
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
func @graph_region_cant_have_blocks() {
|
|
test.graph_region {
|
|
// expected-error@-1 {{'test.graph_region' op expects graph region #0 to have 0 or 1 blocks}}
|
|
^bb42:
|
|
cf.br ^bb43
|
|
^bb43:
|
|
"terminator"() : () -> ()
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Check that we can query traits in types
|
|
func @succeeded_type_traits() {
|
|
// CHECK: "test.result_type_with_trait"() : () -> !test.test_type_with_trait
|
|
"test.result_type_with_trait"() : () -> !test.test_type_with_trait
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// Check that we can query traits in types
|
|
func @failed_type_traits() {
|
|
// expected-error@+1 {{result type should have trait 'TestTypeTrait'}}
|
|
"test.result_type_with_trait"() : () -> i32
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// Check that we can query traits in attributes
|
|
func @succeeded_attr_traits() {
|
|
// CHECK: "test.attr_with_trait"() {attr = #test.attr_with_trait} : () -> ()
|
|
"test.attr_with_trait"() {attr = #test.attr_with_trait} : () -> ()
|
|
return
|
|
}
|
|
|
|
// -----
|
|
|
|
// Check that we can query traits in attributes
|
|
func @failed_attr_traits() {
|
|
// expected-error@+1 {{'attr' attribute should have trait 'TestAttrTrait'}}
|
|
"test.attr_with_trait"() {attr = 42 : i32} : () -> ()
|
|
return
|
|
}
|