llvm-project/mlir/test/IR/traits.mlir

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

353 lines
14 KiB
MLIR
Raw Normal View History

// RUN: mlir-opt %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_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>
}
// -----
func @failedHasParent_wrong_parent() {
"some.op"() ({
// expected-error@+1 {{'test.child' op expects parent op 'test.parent'}}
"test.child"() : () -> ()
}) : () -> ()
}
// -----
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"() : () -> ()
}) : () -> ()
}
// -----
[mlir] Add support for attaching a visibility to symbols. Summary: The visibility defines the structural reachability of the symbol within the IR. Symbols can define one of three visibilities: * Public The symbol \may be accessed from outside of the visible IR. We cannot assume that we can observe all of the uses of this symbol. * Private The symbol may only be referenced from within the operations in the current symbol table, via SymbolRefAttr. * Nested The symbol may be referenced by operations in symbol tables above the current symbol table, as long as each symbol table parent also defines a non-private symbol. This allows or referencing the symbol from outside of the defining symbol table, while retaining the ability for the compiler to see all uses. These properties help to reason about the properties of a symbol, and will be used in a follow up to implement a dce pass on dead symbols. A few examples of what this would look like in the IR are shown below: module @public_module { // This function can be accessed by 'live.user' func @nested_function() attributes { sym_visibility = "nested" } // This function cannot be accessed outside of 'public_module' func @private_function() attributes { sym_visibility = "private" } } // This function can only be accessed from within this module. func @private_function() attributes { sym_visibility = "private" } // This function may be referenced externally. func @public_function() "live.user"() {uses = [@public_module::@nested_function, @private_function, @public_function]} : () -> () Depends On D72043 Reviewed By: mehdi_amini Differential Revision: https://reviews.llvm.org/D72044
2020-01-14 07:54:08 +08:00
// Test the invariants of operations with the Symbol Trait.
// expected-error@+1 {{requires string attribute 'sym_name'}}
"test.symbol"() {} : () -> ()
// -----
// expected-error@+1 {{requires visibility attribute 'sym_visibility' to be a 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 @foo() {
}
"test.finish" () : () -> ()
}) : () -> ()
func @foo() {
}
// -----
// Test that operation with the SymbolTable Trait fails with too many blocks.
// expected-error@+1 {{Operations with a 'SymbolTable' must have exactly one block}}
"test.symbol_scope"() ({
^entry:
"test.finish" () : () -> ()
^other:
"test.finish" () : () -> ()
}) : () -> ()
// -----
func @failedMissingOperandSizeAttr(%arg: i32) {
// expected-error @+1 {{requires 1D vector 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 vector attribute 'operand_segment_sizes'}}
"test.attr_sized_operands"(%arg, %arg, %arg, %arg) {operand_segment_sizes = dense<[1, 1, 1, 1]>: tensor<4xi32>} : (i32, i32, i32, i32) -> ()
}
// -----
func @failedOperandSizeAttrWrongRank(%arg: i32) {
// expected-error @+1 {{requires 1D vector 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 @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 vector attribute 'result_segment_sizes'}}
%0:4 = "test.attr_sized_results"() : () -> (i32, i32, i32, i32)
}
// -----
func @failedResultSizeAttrWrongType() {
// expected-error @+1 {{requires 1D vector attribute 'result_segment_sizes'}}
%0:4 = "test.attr_sized_results"() {result_segment_sizes = dense<[1, 1, 1, 1]>: tensor<4xi32>} : () -> (i32, i32, i32, i32)
}
// -----
func @failedResultSizeAttrWrongRank() {
// expected-error @+1 {{requires 1D vector 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 @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}}
%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
}