2020-03-30 06:35:38 +08:00
|
|
|
// RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -verify-diagnostics
|
2018-06-25 00:10:36 +08:00
|
|
|
|
2021-10-03 07:53:02 +08:00
|
|
|
// See http://llvm.org/pr52045
|
|
|
|
// UNSUPPORTED: asan
|
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// Check different error cases.
|
|
|
|
// -----
|
2018-06-25 02:18:29 +08:00
|
|
|
|
2019-02-06 03:47:02 +08:00
|
|
|
func @illegaltype(i) // expected-error {{expected non-function type}}
|
2018-06-25 02:18:29 +08:00
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-06-25 23:10:46 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @illegaltype() {
|
2019-06-26 07:06:13 +08:00
|
|
|
%0 = constant dense<0> : <vector 4 x f32> : vector<4 x f32> // expected-error {{expected non-function type}}
|
2018-11-10 13:24:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @nestedtensor(tensor<tensor<i8>>) -> () // expected-error {{invalid tensor element type}}
|
2018-06-25 02:18:29 +08:00
|
|
|
|
2018-12-12 05:49:43 +08:00
|
|
|
// -----
|
|
|
|
|
2020-08-08 02:40:58 +08:00
|
|
|
func @illegalmemrefelementtype(memref<?xtensor<i8>>) -> () // expected-error {{invalid memref element type}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @illegalunrankedmemrefelementtype(memref<*xtensor<i8>>) -> () // expected-error {{invalid memref element type}}
|
|
|
|
|
2018-07-17 00:45:22 +08:00
|
|
|
// -----
|
|
|
|
// Test no map in memref type.
|
2019-01-03 02:20:00 +08:00
|
|
|
func @memrefs(memref<2x4xi8, >) // expected-error {{expected list element}}
|
2018-07-17 00:45:22 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
// Test non-existent map in memref type.
|
2019-05-16 00:10:52 +08:00
|
|
|
func @memrefs(memref<2x4xi8, #map7>) // expected-error {{undefined symbol alias id 'map7'}}
|
2018-07-17 00:45:22 +08:00
|
|
|
|
|
|
|
// -----
|
2021-02-05 21:53:00 +08:00
|
|
|
// Test unsupported memory space.
|
|
|
|
func @memrefs(memref<2x4xi8, i8>) // expected-error {{unsupported memory space Attribute}}
|
2018-07-17 00:45:22 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
// Test non-existent map in map composition of memref type.
|
2020-01-14 05:12:37 +08:00
|
|
|
#map0 = affine_map<(d0, d1) -> (d0, d1)>
|
2018-07-17 00:45:22 +08:00
|
|
|
|
2019-05-16 00:10:52 +08:00
|
|
|
func @memrefs(memref<2x4xi8, #map0, #map8>) // expected-error {{undefined symbol alias id 'map8'}}
|
2018-07-17 00:45:22 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
// Test multiple memory space error.
|
2020-01-14 05:12:37 +08:00
|
|
|
#map0 = affine_map<(d0, d1) -> (d0, d1)>
|
2019-01-03 02:20:00 +08:00
|
|
|
func @memrefs(memref<2x4xi8, #map0, 1, 2>) // expected-error {{multiple memory spaces specified in memref type}}
|
2018-07-17 00:45:22 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
// Test affine map after memory space.
|
2020-01-14 05:12:37 +08:00
|
|
|
#map0 = affine_map<(d0, d1) -> (d0, d1)>
|
|
|
|
#map1 = affine_map<(d0, d1) -> (d0, d1)>
|
2018-07-17 00:45:22 +08:00
|
|
|
|
2019-10-04 03:33:47 +08:00
|
|
|
func @memrefs(memref<2x4xi8, #map0, 1, #map1>) // expected-error {{expected memory space to be last in memref type}}
|
2018-07-17 00:45:22 +08:00
|
|
|
|
2018-10-26 21:15:38 +08:00
|
|
|
// -----
|
|
|
|
// Test dimension mismatch between memref and layout map.
|
|
|
|
// The error must be emitted even for the trivial identity layout maps that are
|
|
|
|
// dropped in type creation.
|
2020-01-14 05:12:37 +08:00
|
|
|
#map0 = affine_map<(d0, d1) -> (d0, d1)>
|
2019-01-03 02:20:00 +08:00
|
|
|
func @memrefs(memref<42xi8, #map0>) // expected-error {{memref affine map dimension mismatch}}
|
2018-11-02 16:48:22 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
#map0 = affine_map<(d0, d1) -> (d0, d1)>
|
|
|
|
#map1 = affine_map<(d0) -> (d0)>
|
2019-01-03 02:20:00 +08:00
|
|
|
func @memrefs(memref<42x42xi8, #map0, #map1>) // expected-error {{memref affine map dimension mismatch}}
|
2018-10-26 21:15:38 +08:00
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-06-25 02:18:29 +08:00
|
|
|
|
2019-10-04 03:33:47 +08:00
|
|
|
func @memref_space_after_strides(memref<42x42xi8, 0, offset: ?, strides: [?, ?]>) // expected-error {{expected memory space to be last in memref type}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @memref_stride_missing_colon(memref<42x42xi8, offset ?, strides: [?, ?]>) // expected-error {{expected colon after `offset` keyword}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @memref_stride_invalid_offset(memref<42x42xi8, offset: [], strides: [?, ?]>) // expected-error {{invalid offset}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @memref_stride_missing_strides(memref<42x42xi8, offset: 0 [?, ?]>) // expected-error {{expected comma after offset value}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @memref_stride_missing_strides(memref<42x42xi8, offset: 0, [?, ?]>) // expected-error {{expected `strides` keyword after offset specification}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @memref_stride_missing_colon_2(memref<42x42xi8, offset: 0, strides [?, ?]>) // expected-error {{expected colon after `strides` keyword}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2021-09-21 09:27:40 +08:00
|
|
|
// expected-error @+1 {{expected '['}}
|
|
|
|
func @memref_stride_invalid_strides(memref<42x42xi8, offset: 0, strides: ()>)
|
2019-10-04 03:33:47 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @memref_zero_stride(memref<42x42xi8, offset: ?, strides: [0, ?]>) // expected-error {{invalid memref stride}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
[mlir] introduce "encoding" attribute to tensor type
This CL introduces a generic attribute (called "encoding") on tensors.
The attribute currently does not carry any concrete information, but the type
system already correctly determines that tensor<8xi1,123> != tensor<8xi1,321>.
The attribute will be given meaning through an interface in subsequent CLs.
See ongoing discussion on discourse:
[RFC] Introduce a sparse tensor type to core MLIR
https://llvm.discourse.group/t/rfc-introduce-a-sparse-tensor-type-to-core-mlir/2944
A sparse tensor will look something like this:
```
// named alias with all properties we hold dear:
#CSR = {
// individual named attributes
}
// actual sparse tensor type:
tensor<?x?xf64, #CSR>
```
I see the following rough 5 step plan going forward:
(1) introduce this format attribute in this CL, currently still empty
(2) introduce attribute interface that gives it "meaning", focused on sparse in first phase
(3) rewrite sparse compiler to use new type, remove linalg interface and "glue"
(4) teach passes to deal with new attribute, by rejecting/asserting on non-empty attribute as simplest solution, or doing meaningful rewrite in the longer run
(5) add FE support, document, test, publicize new features, extend "format" meaning to other domains if useful
Reviewed By: stellaraccident, bondhugula
Differential Revision: https://reviews.llvm.org/D99548
2021-04-13 00:28:41 +08:00
|
|
|
func @tensor_encoding_mismatch(%arg0: tensor<8xi32, "enc">) -> (tensor<8xi32>) { // expected-note {{prior use here}}
|
|
|
|
return %arg0: tensor<8xi32> // expected-error {{use of value '%arg0' expects different type than prior uses: 'tensor<8xi32>' vs 'tensor<8xi32, "enc">'}}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @bad_branch() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb12:
|
|
|
|
br ^missing // expected-error {{reference to an undefined block}}
|
2018-06-25 02:18:29 +08:00
|
|
|
}
|
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-06-25 02:18:29 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @block_redef() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb42:
|
2018-06-25 02:18:29 +08:00
|
|
|
return
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb42: // expected-error {{redefinition of block '^bb42'}}
|
2018-06-25 23:10:46 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-06-25 23:10:46 +08:00
|
|
|
|
2021-03-12 07:58:02 +08:00
|
|
|
func @no_terminator() { // expected-error {{empty block: expect at least a terminator}}
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb40:
|
2018-06-25 23:10:46 +08:00
|
|
|
return
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb41:
|
2018-12-30 05:36:59 +08:00
|
|
|
^bb42:
|
2018-06-25 02:18:29 +08:00
|
|
|
return
|
|
|
|
}
|
2018-06-29 08:02:32 +08:00
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-06-29 08:02:32 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @block_no_rparen() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb42 (%bb42 : i32: // expected-error {{expected ')' to end argument list}}
|
2018-07-23 06:45:24 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @block_arg_no_ssaid() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb42 (i32): // expected-error {{expected SSA operand}}
|
2018-07-23 06:45:24 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @block_arg_no_type() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb42 (%0): // expected-error {{expected ':' and type for SSA operand}}
|
2018-07-23 06:45:24 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @block_arg_no_close_paren() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb42:
|
2020-03-06 04:48:28 +08:00
|
|
|
br ^bb2( // expected-error@+1 {{expected ':'}}
|
2018-10-14 22:55:29 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @block_first_has_predecessor() {
|
2019-06-08 00:46:13 +08:00
|
|
|
// expected-error@-1 {{entry block of region may not have predecessors}}
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb42:
|
|
|
|
br ^bb43
|
|
|
|
^bb43:
|
|
|
|
br ^bb42
|
2018-10-23 23:12:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @no_return() {
|
2020-11-07 08:24:35 +08:00
|
|
|
%x = constant 0 : i32
|
|
|
|
%y = constant 1 : i32 // expected-error {{block with no terminator}}
|
2018-08-10 03:28:58 +08:00
|
|
|
}
|
2018-06-29 11:45:33 +08:00
|
|
|
|
2021-06-17 02:59:43 +08:00
|
|
|
// -----
|
|
|
|
|
|
|
|
func @no_terminator() {
|
|
|
|
br ^bb1
|
|
|
|
^bb1:
|
|
|
|
%x = constant 0 : i32
|
|
|
|
%y = constant 1 : i32 // expected-error {{block with no terminator}}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-06-29 11:45:33 +08:00
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
" // expected-error {{expected}}
|
2018-06-29 11:45:33 +08:00
|
|
|
"
|
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-06-29 11:45:33 +08:00
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
" // expected-error {{expected}}
|
2018-06-29 11:45:33 +08:00
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-06-29 11:45:33 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @bad_op_type() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb40:
|
2018-07-19 06:31:25 +08:00
|
|
|
"foo"() : i32 // expected-error {{expected function type}}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @no_terminator() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb40:
|
2018-07-19 06:31:25 +08:00
|
|
|
"foo"() : ()->()
|
|
|
|
""() : ()->() // expected-error {{empty operation name is invalid}}
|
2018-06-29 11:45:33 +08:00
|
|
|
return
|
|
|
|
}
|
2018-06-30 13:08:05 +08:00
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-06-30 13:08:05 +08:00
|
|
|
|
2020-12-13 13:24:18 +08:00
|
|
|
func @illegaltype(i21312312323120) // expected-error {{invalid integer width}}
|
2018-06-30 13:08:05 +08:00
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-07-04 08:51:28 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @malformed_for_percent() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for i = 1 to 10 { // expected-error {{expected SSA operand}}
|
2018-08-10 03:28:58 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @malformed_for_equal() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i 1 to 10 { // expected-error {{expected '='}}
|
2018-08-10 03:28:58 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @malformed_for_to() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 too 10 { // expected-error {{expected 'to' between bounds}}
|
2018-07-20 00:52:39 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @incomplete_for() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 step 2
|
2019-03-15 01:38:44 +08:00
|
|
|
} // expected-error {{expected '{' to begin a region}}
|
2018-06-30 13:08:05 +08:00
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-07-04 08:51:28 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
#map0 = affine_map<(d0) -> (d0 floordiv 4)>
|
2019-02-28 09:58:09 +08:00
|
|
|
|
|
|
|
func @reference_to_iv_in_bound() {
|
2019-08-20 06:26:43 +08:00
|
|
|
// expected-error@+2 {{region entry argument '%i0' is already in use}}
|
|
|
|
// expected-note@+1 {{previously referenced here}}
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i0 = #map0(%i0) to 10 {
|
2019-02-28 09:58:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @nonconstant_step(%1 : i32) {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %2 = 1 to 5 step %1 { // expected-error {{expected non-function type}}
|
2018-07-20 00:52:39 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @for_negative_stride() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 step -1
|
2019-02-02 08:42:18 +08:00
|
|
|
} // expected-error@-1 {{expected step to be representable as a positive signed integer}}
|
2018-09-28 09:03:27 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-03-28 23:24:38 +08:00
|
|
|
func @non_operation() {
|
2021-08-28 11:03:49 +08:00
|
|
|
test.asd // expected-error {{custom op 'test.asd' is unknown}}
|
2018-07-04 08:51:28 +08:00
|
|
|
}
|
2018-07-05 11:45:39 +08:00
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-07-05 11:45:39 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @invalid_if_conditional2() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.if affine_set<(i)[N] : (i >= )> // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
2018-08-08 05:24:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @invalid_if_conditional3() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.if affine_set<(i)[N] : (i == 1)> // expected-error {{expected '0' after '=='}}
|
2018-08-08 05:24:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @invalid_if_conditional4() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.if affine_set<(i)[N] : (i >= 2)> // expected-error {{expected '0' after '>='}}
|
2018-08-08 05:24:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @invalid_if_conditional5() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.if affine_set<(i)[N] : (i <= 0)> // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
2018-08-08 05:24:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @invalid_if_conditional6() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.if affine_set<(i) : (i)> // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
2018-08-08 05:24:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
2020-07-07 16:35:23 +08:00
|
|
|
// TODO: support affine.if (1)?
|
2019-01-03 02:20:00 +08:00
|
|
|
func @invalid_if_conditional7() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.if affine_set<(i) : (1)> // expected-error {{expected '== 0' or '>= 0' at end of affine constraint}}
|
2018-08-08 05:24:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
#map = affine_map<(d0) -> (% // expected-error {{invalid SSA name}}
|
2018-07-12 04:26:23 +08:00
|
|
|
|
2018-07-15 14:06:24 +08:00
|
|
|
// -----
|
2018-07-19 23:35:28 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @test() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb40:
|
2018-07-21 00:28:54 +08:00
|
|
|
%1 = "foo"() : (i32)->i64 // expected-error {{expected 0 operand types but had 1}}
|
2018-07-19 23:35:28 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @redef() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb42:
|
2019-06-26 10:06:06 +08:00
|
|
|
%x = "xxx"(){index = 0} : ()->i32 // expected-note {{previously defined here}}
|
|
|
|
%x = "xxx"(){index = 0} : ()->i32 // expected-error {{redefinition of SSA value '%x'}}
|
2018-07-19 23:35:28 +08:00
|
|
|
return
|
2018-07-20 00:52:39 +08:00
|
|
|
}
|
|
|
|
|
2018-07-21 09:41:34 +08:00
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @undef() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb42:
|
2018-07-21 09:41:34 +08:00
|
|
|
%x = "xxx"(%y) : (i32)->i32 // expected-error {{use of undeclared SSA value}}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-02-06 03:47:02 +08:00
|
|
|
func @malformed_type(%a : intt) { // expected-error {{expected non-function type}}
|
2018-07-20 00:52:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @resulterror() -> i32 {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb42:
|
2020-06-11 08:22:30 +08:00
|
|
|
return // expected-error {{'std.return' op has 0 operands, but enclosing function (@resulterror) returns 1}}
|
2018-07-22 05:32:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
2018-07-23 06:45:24 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @func_resulterror() -> i32 {
|
2020-06-11 08:22:30 +08:00
|
|
|
return // expected-error {{'std.return' op has 0 operands, but enclosing function (@func_resulterror) returns 1}}
|
2018-08-10 03:28:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @argError() {
|
2019-05-14 02:43:17 +08:00
|
|
|
^bb1(%a: i64): // expected-note {{previously defined here}}
|
2018-12-30 03:32:37 +08:00
|
|
|
br ^bb2
|
|
|
|
^bb2(%a: i64): // expected-error{{redefinition of SSA value '%a'}}
|
2018-07-23 06:45:24 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @br_mismatch() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-03-29 05:58:52 +08:00
|
|
|
%0:2 = "foo"() : () -> (i1, i17)
|
2019-12-04 03:23:48 +08:00
|
|
|
// expected-error @+1 {{branch has 2 operands for successor #0, but target block has 1}}
|
2018-12-30 03:32:37 +08:00
|
|
|
br ^bb1(%0#1, %0#0 : i17, i1)
|
2018-07-23 23:42:19 +08:00
|
|
|
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb1(%x: i17):
|
2018-07-23 23:42:19 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-12-04 03:23:48 +08:00
|
|
|
// -----
|
|
|
|
|
|
|
|
func @succ_arg_type_mismatch() {
|
|
|
|
^bb0:
|
|
|
|
%0 = "getBool"() : () -> i1
|
|
|
|
// expected-error @+1 {{type mismatch for bb argument #0 of successor #0}}
|
|
|
|
br ^bb1(%0 : i1)
|
|
|
|
|
|
|
|
^bb1(%x: i32):
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-24 02:48:22 +08:00
|
|
|
// -----
|
|
|
|
|
|
|
|
// Test no nested vector.
|
2019-01-03 02:20:00 +08:00
|
|
|
func @vectors(vector<1 x vector<1xi32>>, vector<2x4xf32>)
|
2021-04-08 16:15:14 +08:00
|
|
|
// expected-error@-1 {{vector elements must be int/index/float type}}
|
Eliminate "primitive" types from being a thing, splitting them into FloatType
and OtherType. Other type is now the thing that holds AffineInt, Control,
eventually Resource, Variant, String, etc. FloatType holds the floating point
types, and allows convenient query of isa<FloatType>().
This fixes issues where we allowed control to be the element type of tensor,
memref, vector. At the same time, ban AffineInt from being an element of a
vector/memref/tensor as well since we don't need it.
I updated the spec to match this as well.
PiperOrigin-RevId: 206361942
2018-07-28 04:09:58 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @condbr_notbool() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-05-14 02:43:17 +08:00
|
|
|
%a = "foo"() : () -> i32 // expected-note {{prior use here}}
|
2019-06-25 08:51:44 +08:00
|
|
|
cond_br %a, ^bb0, ^bb0 // expected-error {{use of value '%a' expects different type than prior uses: 'i1' vs 'i32'}}
|
2018-07-25 06:01:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @condbr_badtype() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2018-07-25 06:01:27 +08:00
|
|
|
%c = "foo"() : () -> i1
|
|
|
|
%a = "foo"() : () -> i32
|
2019-02-06 03:47:02 +08:00
|
|
|
cond_br %c, ^bb0(%a, %a : i32, ^bb0) // expected-error {{expected non-function type}}
|
2018-07-25 06:01:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @condbr_a_bb_is_not_a_type() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2018-07-25 06:01:27 +08:00
|
|
|
%c = "foo"() : () -> i1
|
|
|
|
%a = "foo"() : () -> i32
|
2018-12-30 03:32:37 +08:00
|
|
|
cond_br %c, ^bb0(%a, %a : i32, i32), i32 // expected-error {{expected block name}}
|
2018-07-25 06:01:27 +08:00
|
|
|
}
|
2018-07-27 09:09:20 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-10 04:28:30 +08:00
|
|
|
func @successors_in_non_terminator(%a : i32, %b : i32) {
|
2019-03-03 10:03:03 +08:00
|
|
|
%c = "std.addi"(%a, %b)[^bb1] : () -> () // expected-error {{successors in non-terminator}}
|
2019-01-10 04:28:30 +08:00
|
|
|
^bb1:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @undef() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2018-10-14 22:55:29 +08:00
|
|
|
%x = "xxx"(%y) : (i32)->i32 // expected-error {{use of undeclared SSA value name}}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @undef() {
|
2019-01-02 23:00:07 +08:00
|
|
|
%x = "xxx"(%y) : (i32)->i32 // expected-error {{use of undeclared SSA value name}}
|
2018-07-27 09:09:20 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-07-31 06:18:10 +08:00
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @duplicate_induction_var() {
|
2019-08-20 06:26:43 +08:00
|
|
|
affine.for %i = 1 to 10 { // expected-note {{previously referenced here}}
|
|
|
|
affine.for %i = 1 to 10 { // expected-error {{region entry argument '%i' is already in use}}
|
2018-07-31 06:18:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2018-08-06 12:12:29 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-06-04 00:43:22 +08:00
|
|
|
func @name_scope_failure() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 {
|
2018-08-06 12:12:29 +08:00
|
|
|
}
|
2019-06-04 00:43:22 +08:00
|
|
|
"xxx"(%i) : (index)->() // expected-error {{use of undeclared SSA value name}}
|
2018-08-06 12:12:29 +08:00
|
|
|
return
|
|
|
|
}
|
2018-08-10 03:28:58 +08:00
|
|
|
|
2018-09-22 05:40:36 +08:00
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @dominance_failure() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2018-09-22 05:40:36 +08:00
|
|
|
"foo"(%x) : (i32) -> () // expected-error {{operand #0 does not dominate this use}}
|
2018-12-30 03:32:37 +08:00
|
|
|
br ^bb1
|
|
|
|
^bb1:
|
2020-12-16 12:18:41 +08:00
|
|
|
%x = "bar"() : () -> i32 // expected-note {{operand defined here (op in the same region)}}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @dominance_failure() {
|
|
|
|
^bb0:
|
|
|
|
"foo"(%x) : (i32) -> () // expected-error {{operand #0 does not dominate this use}}
|
|
|
|
%x = "bar"() : () -> i32 // expected-note {{operand defined here (op in the same block)}}
|
|
|
|
br ^bb1
|
|
|
|
^bb1:
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @dominance_failure() {
|
|
|
|
"foo"() ({
|
|
|
|
"foo"(%x) : (i32) -> () // expected-error {{operand #0 does not dominate this use}}
|
|
|
|
}) : () -> ()
|
|
|
|
%x = "bar"() : () -> i32 // expected-note {{operand defined here (op in a parent region)}}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @dominance_failure() { // expected-note {{operand defined as a block argument (block #1 in the same region)}}
|
|
|
|
^bb0:
|
|
|
|
br ^bb1(%x : i32) // expected-error {{operand #0 does not dominate this use}}
|
|
|
|
^bb1(%x : i32):
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @dominance_failure() { // expected-note {{operand defined as a block argument (block #1 in a parent region)}}
|
|
|
|
^bb0:
|
|
|
|
%f = "foo"() ({
|
|
|
|
"foo"(%x) : (i32) -> () // expected-error {{operand #0 does not dominate this use}}
|
|
|
|
}) : () -> (i32)
|
|
|
|
br ^bb1(%f : i32)
|
|
|
|
^bb1(%x : i32):
|
2018-09-22 05:40:36 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-08-10 03:28:58 +08:00
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @return_type_mismatch() -> i32 {
|
2018-08-10 03:28:58 +08:00
|
|
|
%0 = "foo"() : ()->f32
|
2020-06-11 08:22:30 +08:00
|
|
|
return %0 : f32 // expected-error {{type of return operand 0 ('f32') doesn't match function result type ('i32') in function @return_type_mismatch}}
|
2018-08-10 03:28:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-02-09 01:52:26 +08:00
|
|
|
func @return_inside_loop() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 100 {
|
2020-07-10 03:02:20 +08:00
|
|
|
// expected-error@-1 {{op expects regions to end with 'affine.yield', found 'std.return'}}
|
2019-03-27 20:11:58 +08:00
|
|
|
// expected-note@-2 {{in custom textual format, the absence of terminator implies}}
|
2019-02-09 01:52:26 +08:00
|
|
|
return
|
2018-08-10 03:28:58 +08:00
|
|
|
}
|
2019-01-26 04:48:25 +08:00
|
|
|
return
|
2018-08-10 03:28:58 +08:00
|
|
|
}
|
2018-08-18 07:49:42 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-08-09 00:41:48 +08:00
|
|
|
// expected-error@+1 {{expected three consecutive dots for an ellipsis}}
|
|
|
|
func @malformed_ellipsis_one(.)
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error@+1 {{expected three consecutive dots for an ellipsis}}
|
|
|
|
func @malformed_ellipsis_two(..)
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error@+1 {{expected non-function type}}
|
|
|
|
func @func_variadic(...)
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-07-01 01:44:07 +08:00
|
|
|
func @redef() // expected-note {{see existing symbol definition here}}
|
|
|
|
func @redef() // expected-error {{redefinition of symbol named 'redef'}}
|
2018-08-20 12:17:22 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @foo() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2018-08-20 12:17:22 +08:00
|
|
|
%x = constant @foo : (i32) -> () // expected-error {{reference to function with mismatched type}}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @undefined_function() {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2020-06-29 15:56:40 +08:00
|
|
|
%x = constant @qux : (i32) -> () // expected-error {{reference to undefined function 'qux'}}
|
2018-08-20 12:17:22 +08:00
|
|
|
return
|
|
|
|
}
|
2018-08-25 14:38:14 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
#map1 = affine_map<(i)[j] -> (i+j)>
|
2018-08-25 14:38:14 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @bound_symbol_mismatch(%N : index) {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = #map1(%N) to 100 {
|
2020-03-16 10:56:30 +08:00
|
|
|
// expected-error@-1 {{symbol operand count and affine map symbol count must match}}
|
2018-08-25 14:38:14 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
#map1 = affine_map<(i)[j] -> (i+j)>
|
2018-08-25 14:38:14 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @bound_dim_mismatch(%N : index) {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = #map1(%N, %N)[%N] to 100 {
|
2020-03-16 10:56:30 +08:00
|
|
|
// expected-error@-1 {{dim operand count and affine map dim count must match}}
|
2018-08-25 14:38:14 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @large_bound() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 9223372036854775810 {
|
2019-02-02 08:42:18 +08:00
|
|
|
// expected-error@-1 {{integer constant out of range for attribute}}
|
2018-08-25 14:38:14 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @max_in_upper_bound(%N : index) {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.for %i = 1 to max affine_map<(i)->(N, 100)> { //expected-error {{expected non-function type}}
|
2018-08-25 14:38:14 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @step_typo() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 100 step -- 1 { //expected-error {{expected constant integer}}
|
2018-08-25 14:38:14 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @invalid_bound_map(%N : i32) {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.for %i = 1 to affine_map<(i)->(j)>(%N) { //expected-error {{use of undeclared identifier}}
|
2018-08-25 14:38:14 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2018-08-29 06:26:20 +08:00
|
|
|
|
2019-01-15 01:45:09 +08:00
|
|
|
// -----
|
|
|
|
|
2021-09-21 09:27:40 +08:00
|
|
|
// expected-error @+1 {{expected '(' in integer set constraint list}}
|
|
|
|
#set0 = affine_set<(i)[N, M] : )i >= 0)>
|
2019-01-15 01:45:09 +08:00
|
|
|
|
2018-08-29 06:26:20 +08:00
|
|
|
// -----
|
2020-01-14 05:12:37 +08:00
|
|
|
#set0 = affine_set<(i)[N] : (i >= 0, N - i >= 0)>
|
2018-08-29 06:26:20 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @invalid_if_operands1(%N : index) {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 {
|
2019-03-25 11:35:07 +08:00
|
|
|
affine.if #set0(%i) {
|
2018-08-29 06:26:20 +08:00
|
|
|
// expected-error@-1 {{symbol operand count and integer set symbol count must match}}
|
|
|
|
|
|
|
|
// -----
|
2020-01-14 05:12:37 +08:00
|
|
|
#set0 = affine_set<(i)[N] : (i >= 0, N - i >= 0)>
|
2018-08-29 06:26:20 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @invalid_if_operands2(%N : index) {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 {
|
2019-03-25 11:35:07 +08:00
|
|
|
affine.if #set0()[%N] {
|
2018-08-29 06:26:20 +08:00
|
|
|
// expected-error@-1 {{dim operand count and integer set dim count must match}}
|
|
|
|
|
|
|
|
// -----
|
2020-01-14 05:12:37 +08:00
|
|
|
#set0 = affine_set<(i)[N] : (i >= 0, N - i >= 0)>
|
2018-08-29 06:26:20 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @invalid_if_operands3(%N : index) {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 {
|
2019-03-25 11:35:07 +08:00
|
|
|
affine.if #set0(%i)[%i] {
|
2019-01-29 13:23:53 +08:00
|
|
|
// expected-error@-1 {{operand cannot be used as a symbol}}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2018-08-29 06:26:20 +08:00
|
|
|
|
2018-10-10 05:40:41 +08:00
|
|
|
// -----
|
|
|
|
// expected-error@+1 {{expected '"' in string literal}}
|
|
|
|
"J// -----
|
2019-01-03 02:20:00 +08:00
|
|
|
func @calls(%arg0: i32) {
|
2019-02-06 03:47:02 +08:00
|
|
|
// expected-error@+1 {{expected non-function type}}
|
2018-10-10 05:40:41 +08:00
|
|
|
%z = "casdasda"(%x) : (ppop32) -> i32
|
|
|
|
}
|
2018-10-14 22:55:29 +08:00
|
|
|
// -----
|
|
|
|
// expected-error@+2 {{expected SSA operand}}
|
2019-01-03 02:20:00 +08:00
|
|
|
func@n(){^b(
|
2018-10-14 22:55:29 +08:00
|
|
|
// -----
|
2018-10-19 04:54:44 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @elementsattr_non_tensor_type() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"(){bar = dense<[4]> : i32} : () -> () // expected-error {{elements literal must be a ranked tensor or vector type}}
|
2018-10-19 04:54:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @elementsattr_non_ranked() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"(){bar = dense<[4]> : tensor<?xi32>} : () -> () // expected-error {{elements literal type must have static shape}}
|
2018-10-19 04:54:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @elementsattr_shape_mismatch() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"(){bar = dense<[4]> : tensor<5xi32>} : () -> () // expected-error {{inferred shape of elements literal ([1]) does not match type ([5])}}
|
2018-10-19 04:54:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @elementsattr_invalid() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"(){bar = dense<[4, [5]]> : tensor<2xi32>} : () -> () // expected-error {{tensor literal is invalid; ranks are not consistent between elements}}
|
2018-10-19 04:54:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @elementsattr_badtoken() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"(){bar = dense<[tf_opaque]> : tensor<1xi32>} : () -> () // expected-error {{expected element literal of primitive type}}
|
2018-10-19 04:54:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @elementsattr_floattype1() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 07:06:13 +08:00
|
|
|
// expected-error@+1 {{expected integer elements, but parsed floating-point}}
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"(){bar = dense<[4.0]> : tensor<1xi32>} : () -> ()
|
2018-10-19 04:54:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-05 03:27:58 +08:00
|
|
|
func @elementsattr_floattype1() -> () {
|
|
|
|
^bb0:
|
2019-06-26 07:06:13 +08:00
|
|
|
// expected-error@+1 {{expected integer elements, but parsed floating-point}}
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"(){bar = dense<4.0> : tensor<i32>} : () -> ()
|
2019-01-05 03:27:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @elementsattr_floattype2() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 07:06:13 +08:00
|
|
|
// expected-error@+1 {{expected floating-point elements, but parsed integer}}
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"(){bar = dense<[4]> : tensor<1xf32>} : () -> ()
|
2018-10-19 04:54:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @elementsattr_toolarge1() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"(){bar = dense<[777]> : tensor<1xi8>} : () -> () // expected-error {{integer constant out of range}}
|
2018-10-19 04:54:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2020-12-11 04:44:35 +08:00
|
|
|
// expected-error@+1 {{parsed zero elements, but type ('tensor<i64>') expected at least 1}}
|
|
|
|
#attr = dense<> : tensor<i64>
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @elementsattr_toolarge2() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"(){bar = dense<[-777]> : tensor<1xi8>} : () -> () // expected-error {{integer constant out of range}}
|
2018-10-19 04:54:44 +08:00
|
|
|
}
|
2018-10-24 04:44:04 +08:00
|
|
|
|
|
|
|
// -----
|
2019-01-15 05:18:34 +08:00
|
|
|
|
2020-05-06 03:39:22 +08:00
|
|
|
"foo"(){bar = dense<[()]> : tensor<complex<i64>>} : () -> () // expected-error {{expected element literal of primitive type}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
"foo"(){bar = dense<[(10)]> : tensor<complex<i64>>} : () -> () // expected-error {{expected ',' between complex elements}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
"foo"(){bar = dense<[(10,)]> : tensor<complex<i64>>} : () -> () // expected-error {{expected element literal of primitive type}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
"foo"(){bar = dense<[(10,10]> : tensor<complex<i64>>} : () -> () // expected-error {{expected ')' after complex elements}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @elementsattr_malformed_opaque() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"(){bar = opaque<10, "0xQZz123"> : tensor<1xi8>} : () -> () // expected-error {{expected dialect namespace}}
|
2018-10-24 04:44:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @elementsattr_malformed_opaque1() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2021-03-17 07:30:46 +08:00
|
|
|
"foo"(){bar = opaque<"_", "0xQZz123"> : tensor<1xi8>} : () -> () // expected-error {{expected string containing hex digits starting with `0x`}}
|
2019-02-12 14:51:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @elementsattr_malformed_opaque2() -> () {
|
|
|
|
^bb0:
|
2021-03-17 07:30:46 +08:00
|
|
|
"foo"(){bar = opaque<"_", "00abc"> : tensor<1xi8>} : () -> () // expected-error {{expected string containing hex digits starting with `0x`}}
|
2018-10-26 09:33:42 +08:00
|
|
|
}
|
2018-12-30 01:01:59 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @redundant_signature(%a : i32) -> () {
|
2019-06-04 00:43:22 +08:00
|
|
|
^bb0(%b : i32): // expected-error {{invalid block name in region with named arguments}}
|
2018-12-30 01:01:59 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @mixed_named_arguments(%a : i32,
|
2018-12-30 01:01:59 +08:00
|
|
|
f32) -> () {
|
|
|
|
// expected-error @-1 {{expected SSA identifier}}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
func @mixed_named_arguments(f32,
|
2018-12-30 01:01:59 +08:00
|
|
|
%a : i32) -> () { // expected-error {{expected type instead of SSA identifier}}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-01-08 00:16:32 +08:00
|
|
|
// -----
|
|
|
|
|
|
|
|
// This used to crash the parser, but should just error out by interpreting
|
|
|
|
// `tensor` as operator rather than as a type.
|
|
|
|
func @f(f32) {
|
|
|
|
^bb0(%a : f32):
|
2021-01-15 03:35:15 +08:00
|
|
|
%18 = cmpi slt, %idx, %idx : index
|
2019-01-08 00:16:32 +08:00
|
|
|
tensor<42 x index // expected-error {{custom op 'tensor' is unknown}}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-01-08 00:16:49 +08:00
|
|
|
// -----
|
|
|
|
|
|
|
|
func @f(%m : memref<?x?xf32>) {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i0 = 0 to 42 {
|
2019-08-20 06:26:43 +08:00
|
|
|
// expected-note@+1 {{previously referenced here}}
|
2021-02-10 20:53:11 +08:00
|
|
|
%x = memref.load %m[%i0, %i1] : memref<?x?xf32>
|
2019-01-08 00:16:49 +08:00
|
|
|
}
|
2019-08-20 06:26:43 +08:00
|
|
|
// expected-error@+1 {{region entry argument '%i1' is already in use}}
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i1 = 0 to 42 {
|
2019-01-08 00:16:49 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2019-01-08 01:58:34 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-08 10:42:04 +08:00
|
|
|
func @dialect_type_empty_namespace(!<"">) -> () { // expected-error {{invalid type identifier}}
|
2019-01-08 01:58:34 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-05-16 00:10:52 +08:00
|
|
|
func @dialect_type_no_string_type_data(!foo<>) -> () { // expected-error {{expected string literal data in dialect symbol}}
|
2019-01-08 01:58:34 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-05-16 00:10:52 +08:00
|
|
|
func @dialect_type_missing_greater(!foo<"") -> () { // expected-error {{expected '>' in dialect symbol}}
|
2019-01-08 01:58:34 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-05-16 00:10:52 +08:00
|
|
|
func @type_alias_unknown(!unknown_alias) -> () { // expected-error {{undefined symbol alias id 'unknown_alias'}}
|
2019-01-08 01:58:34 +08:00
|
|
|
return
|
|
|
|
}
|
2019-01-08 10:42:04 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-04-06 10:36:42 +08:00
|
|
|
// expected-error @+1 {{type names with a '.' are reserved for dialect-defined names}}
|
|
|
|
!foo.bar = i32
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-01-08 10:42:04 +08:00
|
|
|
!missing_eq_alias type i32 // expected-error {{expected '=' in type alias definition}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
!missing_kw_type_alias = i32 // expected-error {{expected 'type' in type alias definition}}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-02-06 03:47:02 +08:00
|
|
|
!missing_type_alias = type // expected-error@+2 {{expected non-function type}}
|
2019-01-08 10:42:04 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
!redef_alias = type i32
|
|
|
|
!redef_alias = type i32 // expected-error {{redefinition of type alias id 'redef_alias'}}
|
2019-01-12 01:03:34 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Check ill-formed opaque tensor.
|
|
|
|
func @complex_loops() {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i1 = 1 to 100 {
|
2019-01-12 01:03:34 +08:00
|
|
|
// expected-error @+1 {{expected '"' in string literal}}
|
2021-03-17 07:30:46 +08:00
|
|
|
"opaqueIntTensor"(){bar = opaque<"_", "0x686]> : tensor<2x1x4xi32>} : () -> ()
|
2019-01-12 02:30:40 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @mi() {
|
2019-04-02 01:01:47 +08:00
|
|
|
// expected-error @+1 {{expected element literal of primitive type}}
|
2019-06-26 10:06:06 +08:00
|
|
|
"fooi64"(){bar = sparse<vector<1xi64>,[,[,1]
|
2019-01-12 03:23:15 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @invalid_tensor_literal() {
|
2021-09-21 09:40:04 +08:00
|
|
|
// expected-error @+1 {{expected 1-d tensor for sparse element values}}
|
2019-06-26 10:06:06 +08:00
|
|
|
"foof16"(){bar = sparse<[[0, 0, 0]], [[-2.0]]> : vector<1x1x1xf16>} : () -> ()
|
2019-01-15 04:23:38 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @invalid_tensor_literal() {
|
2019-04-02 01:01:47 +08:00
|
|
|
// expected-error @+1 {{expected element literal of primitive type}}
|
2019-06-26 10:06:06 +08:00
|
|
|
"fooi16"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0,, [[0, 0, 0]], [-2.0]> : tensor<2x2x2xi16>} : () -> ()
|
2019-01-15 05:56:59 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2021-09-21 09:40:04 +08:00
|
|
|
func @invalid_tensor_literal() {
|
|
|
|
// expected-error @+1 {{sparse index #0 is not contained within the value shape, with index=[1, 1], and type='tensor<1x1xi16>'}}
|
|
|
|
"fooi16"(){bar = sparse<1, 10> : tensor<1x1xi16>} : () -> ()
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-02-02 16:07:30 +08:00
|
|
|
func @invalid_affine_structure() {
|
|
|
|
%c0 = constant 0 : index
|
2020-01-14 05:12:37 +08:00
|
|
|
%idx = affine.apply affine_map<(d0, d1)> (%c0, %c0) // expected-error {{expected '->' or ':'}}
|
2019-02-02 16:07:30 +08:00
|
|
|
return
|
|
|
|
}
|
2019-02-06 12:41:52 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @missing_for_max(%arg0: index, %arg1: index, %arg2: memref<100xf32>) {
|
|
|
|
// expected-error @+1 {{lower loop bound affine map with multiple results requires 'max' prefix}}
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.for %i0 = affine_map<()[s]->(0,s-1)>()[%arg0] to %arg1 {
|
2019-02-06 12:41:52 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @missing_for_min(%arg0: index, %arg1: index, %arg2: memref<100xf32>) {
|
|
|
|
// expected-error @+1 {{upper loop bound affine map with multiple results requires 'min' prefix}}
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.for %i0 = %arg0 to affine_map<()[s]->(100,s+1)>()[%arg1] {
|
2019-02-06 12:41:52 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2019-02-08 02:13:50 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{vector types must have positive constant sizes}}
|
|
|
|
func @zero_vector_type() -> vector<0xi32>
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{vector types must have positive constant sizes}}
|
|
|
|
func @zero_in_vector_type() -> vector<1x0xi32>
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{expected dimension size in vector type}}
|
|
|
|
func @negative_vector_size() -> vector<-1xi32>
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{expected non-function type}}
|
|
|
|
func @negative_in_vector_size() -> vector<1x-1xi32>
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{expected non-function type}}
|
|
|
|
func @negative_memref_size() -> memref<-1xi32>
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{expected non-function type}}
|
|
|
|
func @negative_in_memref_size() -> memref<1x-1xi32>
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{expected non-function type}}
|
|
|
|
func @negative_tensor_size() -> tensor<-1xi32>
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{expected non-function type}}
|
|
|
|
func @negative_in_tensor_size() -> tensor<1x-1xi32>
|
2019-02-27 02:07:27 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @invalid_nested_dominance() {
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
"test.ssacfg_region"() ({
|
2019-02-27 02:07:27 +08:00
|
|
|
// expected-error @+1 {{operand #0 does not dominate this use}}
|
|
|
|
"foo.use" (%1) : (i32) -> ()
|
|
|
|
br ^bb2
|
|
|
|
|
|
|
|
^bb2:
|
|
|
|
// expected-note @+1 {{operand defined here}}
|
|
|
|
%1 = constant 0 : i32
|
|
|
|
"foo.yield" () : () -> ()
|
2019-05-06 16:40:13 +08:00
|
|
|
}) : () -> ()
|
2019-02-27 02:07:27 +08:00
|
|
|
return
|
|
|
|
}
|
2019-02-27 08:43:12 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-04-15 04:41:09 +08:00
|
|
|
// expected-error @+1 {{unbalanced ']' character in pretty dialect name}}
|
|
|
|
func @invalid_unknown_type_dialect_name() -> !invalid.dialect<!x@#]!@#>
|
2019-02-27 09:11:24 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{@ identifier expected to start with letter or '_'}}
|
|
|
|
func @$invalid_function_name()
|
2019-03-03 14:34:18 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-07-04 04:21:24 +08:00
|
|
|
// expected-error @+1 {{arguments may only have dialect attributes}}
|
2019-06-26 10:06:06 +08:00
|
|
|
func @invalid_func_arg_attr(i1 {non_dialect_attr = 10})
|
2019-03-20 01:59:02 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-10-19 07:02:56 +08:00
|
|
|
// expected-error @+1 {{results may only have dialect attributes}}
|
|
|
|
func @invalid_func_result_attr() -> (i1 {non_dialect_attr = 10})
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-03-20 01:59:02 +08:00
|
|
|
// expected-error @+1 {{expected '<' in tuple type}}
|
|
|
|
func @invalid_tuple_missing_less(tuple i32>)
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{expected '>' in tuple type}}
|
|
|
|
func @invalid_tuple_missing_greater(tuple<i32)
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Should not crash because of deletion order here.
|
|
|
|
func @invalid_region_dominance() {
|
|
|
|
"foo.use" (%1) : (i32) -> ()
|
2019-05-06 16:40:13 +08:00
|
|
|
"foo.region"() ({
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
%1 = constant 0 : i32 // This value is used outside of the region.
|
|
|
|
"foo.yield" () : () -> ()
|
2019-05-06 16:40:13 +08:00
|
|
|
}, {
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
// expected-error @+1 {{expected operation name in quotes}}
|
|
|
|
%2 = constant 1 i32 // Syntax error causes region deletion.
|
2019-05-06 16:40:13 +08:00
|
|
|
}) : () -> ()
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Should not crash because of deletion order here.
|
|
|
|
func @invalid_region_block() {
|
|
|
|
"foo.branch"()[^bb2] : () -> () // Attempt to jump into the region.
|
|
|
|
|
|
|
|
^bb1:
|
2019-05-06 16:40:13 +08:00
|
|
|
"foo.region"() ({
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
^bb2:
|
|
|
|
"foo.yield"() : () -> ()
|
2019-05-06 16:40:13 +08:00
|
|
|
}, {
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
// expected-error @+1 {{expected operation name in quotes}}
|
|
|
|
%2 = constant 1 i32 // Syntax error causes region deletion.
|
2019-05-06 16:40:13 +08:00
|
|
|
}) : () -> ()
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Should not crash because of deletion order here.
|
|
|
|
func @invalid_region_dominance() {
|
|
|
|
"foo.use" (%1) : (i32) -> ()
|
2019-05-06 16:40:13 +08:00
|
|
|
"foo.region"() ({
|
|
|
|
"foo.region"() ({
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
%1 = constant 0 : i32 // This value is used outside of the region.
|
|
|
|
"foo.yield" () : () -> ()
|
2019-05-06 16:40:13 +08:00
|
|
|
}) : () -> ()
|
|
|
|
}, {
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
// expected-error @+1 {{expected operation name in quotes}}
|
|
|
|
%2 = constant 1 i32 // Syntax error causes region deletion.
|
2019-05-06 16:40:13 +08:00
|
|
|
}) : () -> ()
|
Allow creating standalone Regions
Currently, regions can only be constructed by passing in a `Function` or an
`Instruction` pointer referencing the parent object, unlike `Function`s or
`Instruction`s themselves that can be created without a parent. It leads to a
rather complex flow in operation construction where one has to create the
operation first before being able to work with its regions. It may be
necessary to work with the regions before the operation is created. In
particular, in `build` and `parse` functions that are executed _before_ the
operation is created in cases where boilerplate region manipulation is required
(for example, inserting the hypothetical default terminator in affine regions).
Allow creating standalone regions. Such regions are meant to own a list of
blocks and transfer them to other regions on demand.
Each instruction stores a fixed number of regions as trailing objects and has
ownership of them. This decreases the size of the Instruction object for the
common case of instructions without regions. Keep this behavior intact. To
allow some flexibility in construction, make OperationState store an owning
vector of regions. When the Builder creates an Instruction from
OperationState, the bodies of the regions are transferred into the
instruction-owned regions to minimize copying. Thus, it becomes possible to
fill standalone regions with blocks and move them to an operation when it is
constructed, or move blocks from a region to an operation region, e.g., for
inlining.
PiperOrigin-RevId: 240368183
2019-03-27 00:55:06 +08:00
|
|
|
return
|
|
|
|
}
|
2019-03-29 05:58:52 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-05-06 16:40:13 +08:00
|
|
|
func @unfinished_region_list() {
|
|
|
|
// expected-error@+1 {{expected ')' to end region list}}
|
|
|
|
"region"() ({},{},{} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-03-29 05:58:52 +08:00
|
|
|
func @multi_result_missing_count() {
|
|
|
|
// expected-error@+1 {{expected integer number of results}}
|
|
|
|
%0: = "foo" () : () -> (i32, i32)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @multi_result_zero_count() {
|
|
|
|
// expected-error@+1 {{expected named operation to have atleast 1 result}}
|
|
|
|
%0:0 = "foo" () : () -> (i32, i32)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @multi_result_invalid_identifier() {
|
|
|
|
// expected-error@+1 {{expected valid ssa identifier}}
|
|
|
|
%0, = "foo" () : () -> (i32, i32)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @multi_result_mismatch_count() {
|
2019-03-29 07:18:52 +08:00
|
|
|
// expected-error@+1 {{operation defines 2 results but was provided 1 to bind}}
|
2019-03-29 05:58:52 +08:00
|
|
|
%0:1 = "foo" () : () -> (i32, i32)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @multi_result_mismatch_count() {
|
2019-03-29 07:18:52 +08:00
|
|
|
// expected-error@+1 {{operation defines 2 results but was provided 3 to bind}}
|
2019-03-29 05:58:52 +08:00
|
|
|
%0, %1, %3 = "foo" () : () -> (i32, i32)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @no_result_with_name() {
|
|
|
|
// expected-error@+1 {{cannot name an operation with no results}}
|
|
|
|
%0 = "foo" () : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @conflicting_names() {
|
2019-05-14 02:43:17 +08:00
|
|
|
// expected-note@+1 {{previously defined here}}
|
2019-03-29 05:58:52 +08:00
|
|
|
%foo, %bar = "foo" () : () -> (i32, i32)
|
|
|
|
|
|
|
|
// expected-error@+1 {{redefinition of SSA value '%bar'}}
|
|
|
|
%bar, %baz = "foo" () : () -> (i32, i32)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @ssa_name_missing_eq() {
|
|
|
|
// expected-error@+1 {{expected '=' after SSA name}}
|
|
|
|
%0:2 "foo" () : () -> (i32, i32)
|
|
|
|
return
|
|
|
|
}
|
2019-03-30 13:23:34 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{invalid element type for complex}}
|
|
|
|
func @bad_complex(complex<memref<2x4xi8>>)
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{expected '<' in complex type}}
|
|
|
|
func @bad_complex(complex memref<2x4xi8>>)
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{expected '>' in complex type}}
|
|
|
|
func @bad_complex(complex<i32)
|
2019-05-28 23:57:38 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// expected-error @+1 {{attribute names with a '.' are reserved for dialect-defined names}}
|
|
|
|
#foo.attr = i32
|
2019-06-04 00:43:22 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @invalid_region_dominance() {
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
"test.ssacfg_region"() ({
|
2019-06-04 00:43:22 +08:00
|
|
|
// expected-error @+1 {{operand #0 does not dominate this use}}
|
|
|
|
"foo.use" (%def) : (i32) -> ()
|
|
|
|
"foo.yield" () : () -> ()
|
|
|
|
}, {
|
|
|
|
// expected-note @+1 {{operand defined here}}
|
|
|
|
%def = "foo.def" () : () -> i32
|
|
|
|
}) : () -> ()
|
|
|
|
return
|
|
|
|
}
|
2019-07-31 05:05:49 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-09-19 09:23:12 +08:00
|
|
|
func @invalid_region_dominance() {
|
|
|
|
// expected-note @+1 {{operand defined here}}
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
%def = "test.ssacfg_region"() ({
|
2019-09-19 09:23:12 +08:00
|
|
|
// expected-error @+1 {{operand #0 does not dominate this use}}
|
|
|
|
"foo.use" (%def) : (i32) -> ()
|
|
|
|
"foo.yield" () : () -> ()
|
|
|
|
}) : () -> (i32)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2019-07-31 05:05:49 +08:00
|
|
|
func @hexadecimal_float_leading_minus() {
|
|
|
|
// expected-error @+1 {{hexadecimal float literal should not have a leading minus}}
|
|
|
|
"foo"() {value = -0x7fff : f16} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @hexadecimal_float_literal_overflow() {
|
2019-07-31 05:24:30 +08:00
|
|
|
// expected-error @+1 {{hexadecimal float constant out of range for type}}
|
2019-07-31 05:05:49 +08:00
|
|
|
"foo"() {value = 0xffffffff : f16} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @decimal_float_literal() {
|
2021-03-18 04:09:53 +08:00
|
|
|
// expected-error @+2 {{unexpected decimal integer literal for a floating point value}}
|
2019-07-31 05:05:49 +08:00
|
|
|
// expected-note @+1 {{add a trailing dot to make the literal a float}}
|
|
|
|
"foo"() {value = 42 : f32} : () -> ()
|
|
|
|
}
|
2019-07-31 05:24:30 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @float_in_int_tensor() {
|
|
|
|
// expected-error @+1 {{expected integer elements, but parsed floating-point}}
|
|
|
|
"foo"() {bar = dense<[42.0, 42]> : tensor<2xi32>} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @float_in_bool_tensor() {
|
|
|
|
// expected-error @+1 {{expected integer elements, but parsed floating-point}}
|
|
|
|
"foo"() {bar = dense<[true, 42.0]> : tensor<2xi1>} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @decimal_int_in_float_tensor() {
|
|
|
|
// expected-error @+1 {{expected floating-point elements, but parsed integer}}
|
|
|
|
"foo"() {bar = dense<[42, 42.0]> : tensor<2xf32>} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @bool_in_float_tensor() {
|
|
|
|
// expected-error @+1 {{expected floating-point elements, but parsed integer}}
|
|
|
|
"foo"() {bar = dense<[42.0, true]> : tensor<2xf32>} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @hexadecimal_float_leading_minus_in_tensor() {
|
|
|
|
// expected-error @+1 {{hexadecimal float literal should not have a leading minus}}
|
|
|
|
"foo"() {bar = dense<-0x7FFFFFFF> : tensor<2xf32>} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Check that we report an error when a value could be parsed, but does not fit
|
|
|
|
// into the specified type.
|
|
|
|
func @hexadecimal_float_too_wide_for_type_in_tensor() {
|
|
|
|
// expected-error @+1 {{hexadecimal float constant out of range for type}}
|
|
|
|
"foo"() {bar = dense<0x7FF0000000000000> : tensor<2xf32>} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
// Check that we report an error when a value is too wide to be parsed.
|
|
|
|
func @hexadecimal_float_too_wide_in_tensor() {
|
2021-03-18 04:09:53 +08:00
|
|
|
// expected-error @+1 {{hexadecimal float constant out of range for type}}
|
2019-07-31 05:24:30 +08:00
|
|
|
"foo"() {bar = dense<0x7FFFFFF0000000000000> : tensor<2xf32>} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @integer_too_wide_in_tensor() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for type}}
|
|
|
|
"foo"() {bar = dense<0xFFFFFFFFFFFFFF> : tensor<2xi16>} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @bool_literal_in_non_bool_tensor() {
|
|
|
|
// expected-error @+1 {{expected i1 type for 'true' or 'false' values}}
|
|
|
|
"foo"() {bar = dense<true> : tensor<2xi16>} : () -> ()
|
2019-08-08 01:31:14 +08:00
|
|
|
}
|
2019-08-29 04:55:11 +08:00
|
|
|
|
2020-01-11 03:48:24 +08:00
|
|
|
// -----
|
|
|
|
|
2019-08-29 04:55:11 +08:00
|
|
|
// expected-error @+1 {{unbalanced ')' character in pretty dialect name}}
|
|
|
|
func @bad_arrow(%arg : !unreg.ptr<(i32)->)
|
2020-01-11 03:48:24 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @negative_value_in_unsigned_int_attr() {
|
|
|
|
// expected-error @+1 {{negative integer literal not valid for unsigned integer type}}
|
|
|
|
"foo"() {bar = -5 : ui32} : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @negative_value_in_unsigned_vector_attr() {
|
|
|
|
// expected-error @+1 {{expected unsigned integer elements, but parsed negative value}}
|
|
|
|
"foo"() {bar = dense<[5, -5]> : vector<2xui32>} : () -> ()
|
|
|
|
}
|
2020-03-26 02:51:34 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = -129 : i8
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 256 : i8
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = -129 : si8
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 129 : si8
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{negative integer literal not valid for unsigned integer type}}
|
|
|
|
attr = -1 : ui8
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 256 : ui8
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = -32769 : i16
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 65536 : i16
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = -32769 : si16
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 32768 : si16
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{negative integer literal not valid for unsigned integer type}}
|
|
|
|
attr = -1 : ui16
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 65536: ui16
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = -2147483649 : i32
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 4294967296 : i32
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = -2147483649 : si32
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 2147483648 : si32
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{negative integer literal not valid for unsigned integer type}}
|
|
|
|
attr = -1 : ui32
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 4294967296 : ui32
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = -9223372036854775809 : i64
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 18446744073709551616 : i64
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = -9223372036854775809 : si64
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 9223372036854775808 : si64
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{negative integer literal not valid for unsigned integer type}}
|
|
|
|
attr = -1 : ui64
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 18446744073709551616 : ui64
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
Fix the MLIR integer attribute parser to be correct in the face of large integer attributes, it was previously artificially limited to 64 bits.
Reviewers: rriddle!
Subscribers: mehdi_amini, rriddle, jpienaar, burmako, shauheen, antiagainst, nicolasvasilache, arpith-jacob, mgester, lucyrfox, liufengdb, Joonsoo, grosul1, frgossen, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D78065
2020-04-14 07:37:00 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @really_large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 79228162514264337593543950336 : ui96
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @really_large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 79228162514264337593543950336 : i96
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @really_large_bound() {
|
|
|
|
"test.out_of_range_attribute"() {
|
|
|
|
// expected-error @+1 {{integer constant out of range for attribute}}
|
|
|
|
attr = 39614081257132168796771975168 : si96
|
|
|
|
} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
2020-04-28 06:21:52 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @duplicate_dictionary_attr_key() {
|
2020-11-04 06:31:23 +08:00
|
|
|
// expected-error @+1 {{duplicate key 'a' in dictionary attribute}}
|
2020-04-28 06:21:52 +08:00
|
|
|
"foo.op"() {a, a} : () -> ()
|
|
|
|
}
|
2020-05-05 17:03:26 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2020-11-04 06:31:23 +08:00
|
|
|
// expected-error @+1 {{attribute 'attr' occurs more than once in the attribute list}}
|
|
|
|
test.format_symbol_name_attr_op @name { attr = "xx" }
|
|
|
|
|
|
|
|
// -----
|
|
|
|
|
2020-05-05 17:03:26 +08:00
|
|
|
func @forward_reference_type_check() -> (i8) {
|
|
|
|
br ^bb2
|
|
|
|
|
|
|
|
^bb1:
|
|
|
|
// expected-note @+1 {{previously used here with type 'i8'}}
|
|
|
|
return %1 : i8
|
|
|
|
|
|
|
|
^bb2:
|
|
|
|
// expected-error @+1 {{definition of SSA value '%1#0' has type 'f32'}}
|
|
|
|
%1 = "bar"() : () -> (f32)
|
|
|
|
br ^bb1
|
|
|
|
}
|
2020-05-14 13:32:21 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @dominance_error_in_unreachable_op() -> i1 {
|
2020-06-03 09:20:38 +08:00
|
|
|
%c = constant false
|
2020-05-14 13:32:21 +08:00
|
|
|
return %c : i1
|
|
|
|
^bb0:
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
"test.ssacfg_region" () ({ // unreachable
|
2020-05-14 13:32:21 +08:00
|
|
|
^bb1:
|
|
|
|
// expected-error @+1 {{operand #0 does not dominate this use}}
|
|
|
|
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
|
|
|
|
br ^bb4
|
|
|
|
^bb2:
|
|
|
|
br ^bb2
|
|
|
|
^bb4:
|
|
|
|
%1 = "foo"() : ()->i64 // expected-note {{operand defined here}}
|
|
|
|
}) : () -> ()
|
|
|
|
return %c : i1
|
|
|
|
}
|
[MLIR] Add RegionKindInterface
Some dialects have semantics which is not well represented by common
SSA structures with dominance constraints. This patch allows
operations to declare the 'kind' of their contained regions.
Currently, two kinds are allowed: "SSACFG" and "Graph". The only
difference between them at the moment is that SSACFG regions are
required to have dominance, while Graph regions are not required to
have dominance. The intention is that this Interface would be
generated by ODS for existing operations, although this has not yet
been implemented. Presumably, if someone were interested in code
generation, we might also have a "CFG" dialect, which defines control
flow, but does not require SSA.
The new behavior is mostly identical to the previous behavior, since
registered operations without a RegionKindInterface are assumed to
contain SSACFG regions. However, the behavior has changed for
unregistered operations. Previously, these were checked for
dominance, however the new behavior allows dominance violations, in
order to allow the processing of unregistered dialects with Graph
regions. One implication of this is that regions in unregistered
operations with more than one op are no longer CSE'd (since it
requires dominance info).
I've also reorganized the LangRef documentation to remove assertions
about "sequential execution", "SSA Values", and "Dominance". Instead,
the core IR is simply "ordered" (i.e. totally ordered) and consists of
"Values". I've also clarified some things about how control flow
passes between blocks in an SSACFG region. Control Flow must enter a
region at the entry block and follow terminator operation successors
or be returned to the containing op. Graph regions do not define a
notion of control flow.
see discussion here:
https://llvm.discourse.group/t/rfc-allowing-dialects-to-relax-the-ssa-dominance-condition/833/53
Differential Revision: https://reviews.llvm.org/D80358
2020-05-16 01:33:13 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @invalid_region_dominance_with_dominance_free_regions() {
|
|
|
|
test.graph_region {
|
|
|
|
"foo.use" (%1) : (i32) -> ()
|
|
|
|
"foo.region"() ({
|
|
|
|
%1 = constant 0 : i32 // This value is used outside of the region.
|
|
|
|
"foo.yield" () : () -> ()
|
|
|
|
}, {
|
|
|
|
// expected-error @+1 {{expected operation name in quotes}}
|
|
|
|
%2 = constant 1 i32 // Syntax error causes region deletion.
|
|
|
|
}) : () -> ()
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2020-12-03 08:49:47 +08:00
|
|
|
|
|
|
|
// -----
|
|
|
|
|
|
|
|
func @foo() {} // expected-error {{expected non-empty function body}}
|