2020-03-30 06:35:38 +08:00
|
|
|
// RUN: mlir-opt -allow-unregistered-dialect %s | FileCheck %s
|
2018-06-23 01:39:19 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0, d1, d2, d3, d4)[s0] -> (d0, d1, d2, d4, d3)>
|
|
|
|
#map0 = affine_map<(d0, d1, d2, d3, d4)[s0] -> (d0, d1, d2, d4, d3)>
|
2018-07-18 07:56:54 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0) -> (d0)>
|
|
|
|
#map1 = affine_map<(d0) -> (d0)>
|
2018-07-18 07:56:54 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
|
|
|
|
#map2 = affine_map<(d0, d1, d2) -> (d0, d1, d2)>
|
2018-07-18 07:56:54 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0, d1, d2) -> (d1, d0, d2)>
|
|
|
|
#map3 = affine_map<(d0, d1, d2) -> (d1, d0, d2)>
|
2018-07-18 07:56:54 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #map{{[0-9]+}} = affine_map<()[s0] -> (0, s0 - 1)>
|
|
|
|
#inline_map_minmax_loop1 = affine_map<()[s0] -> (0, s0 - 1)>
|
2018-08-25 14:38:14 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #map{{[0-9]+}} = affine_map<()[s0] -> (100, s0 + 1)>
|
|
|
|
#inline_map_minmax_loop2 = affine_map<()[s0] -> (100, s0 + 1)>
|
2018-08-25 14:38:14 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0, d1)[s0] -> (d0 + d1 + s0)>
|
|
|
|
#bound_map1 = affine_map<(i, j)[s] -> (i + j + s)>
|
2018-08-25 14:38:14 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0, d1) -> (d0 + d1)>
|
|
|
|
#inline_map_loop_bounds2 = affine_map<(d0, d1) -> (d0 + d1)>
|
2018-08-25 14:38:14 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #map{{[0-9]+}} = affine_map<(d0)[s0] -> (d0 + s0, d0 - s0)>
|
|
|
|
#bound_map2 = affine_map<(i)[s] -> (i + s, i - s)>
|
2018-08-25 14:38:14 +08:00
|
|
|
|
2018-10-30 21:11:29 +08:00
|
|
|
// All maps appear in arbitrary order before all sets, in arbitrary order.
|
2019-04-13 01:31:21 +08:00
|
|
|
// CHECK-NOT: Placeholder
|
2018-10-30 21:11:29 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #set{{[0-9]+}} = affine_set<(d0)[s0, s1] : (d0 >= 0, -d0 + s0 >= 0, s0 - 5 == 0, -d0 + s1 + 1 >= 0)>
|
|
|
|
#set0 = affine_set<(i)[N, M] : (i >= 0, -i + N >= 0, N - 5 == 0, -i + M + 1 >= 0)>
|
2018-08-08 05:24:38 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #set{{[0-9]+}} = affine_set<(d0, d1)[s0] : (d0 >= 0, d1 >= 0)>
|
|
|
|
#set1 = affine_set<(d0, d1)[s0] : (d0 >= 0, d1 >= 0)>
|
2018-10-26 13:13:03 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #set{{[0-9]+}} = affine_set<(d0) : (d0 - 1 == 0)>
|
|
|
|
#set2 = affine_set<(d0) : (d0 - 1 == 0)>
|
2018-10-26 13:13:03 +08:00
|
|
|
|
2020-06-12 08:34:35 +08:00
|
|
|
// CHECK-DAG: [[$SET_TRUE:#set[0-9]+]] = affine_set<() : (0 == 0)>
|
2019-02-03 13:01:11 +08:00
|
|
|
|
2020-01-14 05:12:37 +08:00
|
|
|
// CHECK-DAG: #set{{[0-9]+}} = affine_set<(d0)[s0] : (d0 - 2 >= 0, -d0 + 4 >= 0)>
|
2018-08-08 05:24:38 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @foo(i32, i64) -> f32
|
|
|
|
func private @foo(i32, i64) -> f32
|
2018-06-23 01:39:19 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @bar()
|
|
|
|
func private @bar() -> ()
|
2018-06-23 01:39:19 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @baz() -> (i1, index, f32)
|
|
|
|
func private @baz() -> (i1, index, f32)
|
2018-06-23 01:39:19 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @missingReturn()
|
|
|
|
func private @missingReturn()
|
2018-06-23 06:52:02 +08:00
|
|
|
|
2020-12-13 13:24:18 +08:00
|
|
|
// CHECK: func private @int_types(i0, i1, i2, i4, i7, i87) -> (i1, index, i19)
|
|
|
|
func private @int_types(i0, i1, i2, i4, i7, i87) -> (i1, index, i19)
|
2018-06-30 13:08:05 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @sint_types(si2, si4) -> (si7, si1023)
|
|
|
|
func private @sint_types(si2, si4) -> (si7, si1023)
|
2020-01-11 03:48:24 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @uint_types(ui2, ui4) -> (ui7, ui1023)
|
|
|
|
func private @uint_types(ui2, ui4) -> (ui7, ui1023)
|
2020-01-11 03:48:24 +08:00
|
|
|
|
2021-01-15 23:29:37 +08:00
|
|
|
// CHECK: func private @float_types(f80, f128)
|
|
|
|
func private @float_types(f80, f128)
|
2018-06-23 06:52:02 +08:00
|
|
|
|
2021-11-17 22:57:55 +08:00
|
|
|
// CHECK: func private @vectors(vector<f32>, vector<1xf32>, vector<2x4xf32>)
|
|
|
|
func private @vectors(vector<f32>, vector<1 x f32>, vector<2x4xf32>)
|
2018-06-23 06:52:02 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @tensors(tensor<*xf32>, tensor<*xvector<2x4xf32>>, tensor<1x?x4x?x?xi32>, tensor<i8>)
|
|
|
|
func private @tensors(tensor<* x f32>, tensor<* x vector<2x4xf32>>,
|
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
|
|
|
tensor<1x?x4x?x?xi32>, tensor<i8>)
|
2018-06-23 06:52:02 +08:00
|
|
|
|
[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
|
|
|
// CHECK: func private @tensor_encoding(tensor<16x32xf64, "sparse">)
|
|
|
|
func private @tensor_encoding(tensor<16x32xf64, "sparse">)
|
|
|
|
|
2021-12-04 09:09:30 +08:00
|
|
|
// CHECK: func private @large_shape_dimension(tensor<9223372036854775807xf32>)
|
|
|
|
func private @large_shape_dimension(tensor<9223372036854775807xf32>)
|
|
|
|
|
2021-10-11 23:25:14 +08:00
|
|
|
// CHECK: func private @functions((memref<1x?x4x?x?xi32, #map0>, memref<8xi8>) -> (), () -> ())
|
|
|
|
func private @functions((memref<1x?x4x?x?xi32, #map0, 0>, memref<8xi8, #map1, 0>) -> (), ()->())
|
2018-06-24 07:03:42 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @memrefs2(memref<2x4x8xi8, 1>)
|
|
|
|
func private @memrefs2(memref<2x4x8xi8, #map2, 1>)
|
2018-07-17 00:45:22 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @memrefs3(memref<2x4x8xi8>)
|
|
|
|
func private @memrefs3(memref<2x4x8xi8, affine_map<(d0, d1, d2) -> (d0, d1, d2)>>)
|
2018-07-17 00:45:22 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @memrefs_drop_triv_id_inline(memref<2xi8>)
|
|
|
|
func private @memrefs_drop_triv_id_inline(memref<2xi8, affine_map<(d0) -> (d0)>>)
|
2018-10-27 00:07:10 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @memrefs_drop_triv_id_inline0(memref<2xi8>)
|
|
|
|
func private @memrefs_drop_triv_id_inline0(memref<2xi8, affine_map<(d0) -> (d0)>, 0>)
|
2018-10-27 00:07:10 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @memrefs_drop_triv_id_inline1(memref<2xi8, 1>)
|
|
|
|
func private @memrefs_drop_triv_id_inline1(memref<2xi8, affine_map<(d0) -> (d0)>, 1>)
|
2018-10-27 00:07:10 +08:00
|
|
|
|
2021-02-05 21:53:00 +08:00
|
|
|
// Test memref with custom memory space
|
|
|
|
|
|
|
|
// CHECK: func private @memrefs_nomap_nospace(memref<5x6x7xf32>)
|
|
|
|
func private @memrefs_nomap_nospace(memref<5x6x7xf32>)
|
|
|
|
|
|
|
|
// CHECK: func private @memrefs_map_nospace(memref<5x6x7xf32, #map{{[0-9]+}}>)
|
|
|
|
func private @memrefs_map_nospace(memref<5x6x7xf32, #map3>)
|
|
|
|
|
|
|
|
// CHECK: func private @memrefs_nomap_intspace(memref<5x6x7xf32, 3>)
|
|
|
|
func private @memrefs_nomap_intspace(memref<5x6x7xf32, 3>)
|
|
|
|
|
|
|
|
// CHECK: func private @memrefs_map_intspace(memref<5x6x7xf32, #map{{[0-9]+}}, 5>)
|
|
|
|
func private @memrefs_map_intspace(memref<5x6x7xf32, #map3, 5>)
|
|
|
|
|
|
|
|
// CHECK: func private @memrefs_nomap_strspace(memref<5x6x7xf32, "local">)
|
|
|
|
func private @memrefs_nomap_strspace(memref<5x6x7xf32, "local">)
|
|
|
|
|
|
|
|
// CHECK: func private @memrefs_map_strspace(memref<5x6x7xf32, #map{{[0-9]+}}, "private">)
|
|
|
|
func private @memrefs_map_strspace(memref<5x6x7xf32, #map3, "private">)
|
|
|
|
|
|
|
|
// CHECK: func private @memrefs_nomap_dictspace(memref<5x6x7xf32, {memSpace = "special", subIndex = 1 : i64}>)
|
|
|
|
func private @memrefs_nomap_dictspace(memref<5x6x7xf32, {memSpace = "special", subIndex = 1}>)
|
|
|
|
|
|
|
|
// CHECK: func private @memrefs_map_dictspace(memref<5x6x7xf32, #map{{[0-9]+}}, {memSpace = "special", subIndex = 3 : i64}>)
|
|
|
|
func private @memrefs_map_dictspace(memref<5x6x7xf32, #map3, {memSpace = "special", subIndex = 3}>)
|
2019-03-30 13:23:34 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @complex_types(complex<i1>) -> complex<f32>
|
|
|
|
func private @complex_types(complex<i1>) -> complex<f32>
|
2019-03-30 13:23:34 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @memref_with_index_elems(memref<1x?xindex>)
|
|
|
|
func private @memref_with_index_elems(memref<1x?xindex>)
|
2020-07-30 20:02:46 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @memref_with_complex_elems(memref<1x?xcomplex<f32>>)
|
|
|
|
func private @memref_with_complex_elems(memref<1x?xcomplex<f32>>)
|
2020-02-12 16:04:15 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @memref_with_vector_elems(memref<1x?xvector<10xf32>>)
|
|
|
|
func private @memref_with_vector_elems(memref<1x?xvector<10xf32>>)
|
2020-02-12 16:04:15 +08:00
|
|
|
|
2021-06-08 00:33:29 +08:00
|
|
|
// CHECK: func private @memref_with_custom_elem(memref<1x?x!test.memref_element>)
|
|
|
|
func private @memref_with_custom_elem(memref<1x?x!test.memref_element>)
|
|
|
|
|
2021-06-08 00:33:42 +08:00
|
|
|
// CHECK: func private @memref_of_memref(memref<1xmemref<1xf64>>)
|
|
|
|
func private @memref_of_memref(memref<1xmemref<1xf64>>)
|
|
|
|
|
|
|
|
// CHECK: func private @memref_of_unranked_memref(memref<1xmemref<*xf32>>)
|
|
|
|
func private @memref_of_unranked_memref(memref<1xmemref<*xf32>>)
|
|
|
|
|
|
|
|
// CHECK: func private @unranked_memref_of_memref(memref<*xmemref<1xf32>>)
|
|
|
|
func private @unranked_memref_of_memref(memref<*xmemref<1xf32>>)
|
|
|
|
|
|
|
|
// CHECK: func private @unranked_memref_of_unranked_memref(memref<*xmemref<*xi32>>)
|
|
|
|
func private @unranked_memref_of_unranked_memref(memref<*xmemref<*xi32>>)
|
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @unranked_memref_with_complex_elems(memref<*xcomplex<f32>>)
|
|
|
|
func private @unranked_memref_with_complex_elems(memref<*xcomplex<f32>>)
|
2020-02-12 16:04:15 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @unranked_memref_with_index_elems(memref<*xindex>)
|
|
|
|
func private @unranked_memref_with_index_elems(memref<*xindex>)
|
2020-08-08 02:40:58 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK: func private @unranked_memref_with_vector_elems(memref<*xvector<10xf32>>)
|
|
|
|
func private @unranked_memref_with_vector_elems(memref<*xvector<10xf32>>)
|
2020-08-08 02:40:58 +08:00
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-LABEL: func @simpleCFG(%{{.*}}: i32, %{{.*}}: f32) -> i1 {
|
2019-01-03 02:20:00 +08:00
|
|
|
func @simpleCFG(%arg0: i32, %f: f32) -> i1 {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = "foo"() : () -> i64
|
2018-07-19 23:35:28 +08:00
|
|
|
%1 = "foo"() : ()->i64
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: "bar"(%{{.*}}) : (i64) -> (i1, i1, i1)
|
2019-03-29 05:58:52 +08:00
|
|
|
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: return %{{.*}}#1
|
2018-07-23 23:42:19 +08:00
|
|
|
return %2#1 : i1
|
2018-07-19 06:31:25 +08:00
|
|
|
// CHECK: }
|
|
|
|
}
|
2018-06-24 07:03:42 +08:00
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-LABEL: func @simpleCFGUsingBBArgs(%{{.*}}: i32, %{{.*}}: i64) {
|
2019-01-03 02:20:00 +08:00
|
|
|
func @simpleCFGUsingBBArgs(i32, i64) {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb42 (%arg0: i32, %f: i64):
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: "bar"(%{{.*}}) : (i64) -> (i1, i1, i1)
|
2019-03-29 05:58:52 +08:00
|
|
|
%2:3 = "bar"(%f) : (i64) -> (i1,i1,i1)
|
2018-08-02 23:28:20 +08:00
|
|
|
// CHECK: return{{$}}
|
2018-07-23 06:45:24 +08:00
|
|
|
return
|
|
|
|
// CHECK: }
|
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @multiblock() {
|
|
|
|
func @multiblock() {
|
2018-07-15 14:06:24 +08:00
|
|
|
return // CHECK: return
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb1: // CHECK: ^bb1: // no predecessors
|
|
|
|
br ^bb4 // CHECK: br ^bb3
|
|
|
|
^bb2: // CHECK: ^bb2: // pred: ^bb2
|
|
|
|
br ^bb2 // CHECK: br ^bb2
|
|
|
|
^bb4: // CHECK: ^bb3: // pred: ^bb1
|
2018-07-15 14:06:24 +08:00
|
|
|
return // CHECK: return
|
|
|
|
} // CHECK: }
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @emptyMLF() {
|
|
|
|
func @emptyMLF() {
|
2018-07-15 14:06:24 +08:00
|
|
|
return // CHECK: return
|
|
|
|
} // CHECK: }
|
2018-06-29 08:02:32 +08:00
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-LABEL: func @func_with_one_arg(%{{.*}}: i1) -> i2 {
|
2019-01-03 02:20:00 +08:00
|
|
|
func @func_with_one_arg(%c : i1) -> i2 {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = "foo"(%{{.*}}) : (i1) -> i2
|
2018-08-07 02:54:39 +08:00
|
|
|
%b = "foo"(%c) : (i1) -> (i2)
|
2019-07-10 01:40:29 +08:00
|
|
|
return %b : i2 // CHECK: return %{{.*}} : i2
|
2018-08-10 03:28:58 +08:00
|
|
|
} // CHECK: }
|
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-LABEL: func @func_with_two_args(%{{.*}}: f16, %{{.*}}: i8) -> (i1, i32) {
|
2019-01-03 02:20:00 +08:00
|
|
|
func @func_with_two_args(%a : f16, %b : i8) -> (i1, i32) {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}}:2 = "foo"(%{{.*}}, %{{.*}}) : (f16, i8) -> (i1, i32)
|
2019-03-29 05:58:52 +08:00
|
|
|
%c:2 = "foo"(%a, %b) : (f16, i8)->(i1, i32)
|
2019-07-10 01:40:29 +08:00
|
|
|
return %c#0, %c#1 : i1, i32 // CHECK: return %{{.*}}#0, %{{.*}}#1 : i1, i32
|
2018-08-10 03:28:58 +08:00
|
|
|
} // CHECK: }
|
|
|
|
|
2019-02-06 03:47:02 +08:00
|
|
|
// CHECK-LABEL: func @second_order_func() -> (() -> ()) {
|
|
|
|
func @second_order_func() -> (() -> ()) {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-NEXT: %{{.*}} = constant @emptyMLF : () -> ()
|
2019-02-06 03:47:02 +08:00
|
|
|
%c = constant @emptyMLF : () -> ()
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-NEXT: return %{{.*}} : () -> ()
|
2019-02-06 03:47:02 +08:00
|
|
|
return %c : () -> ()
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: func @third_order_func() -> (() -> (() -> ())) {
|
|
|
|
func @third_order_func() -> (() -> (() -> ())) {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-NEXT: %{{.*}} = constant @second_order_func : () -> (() -> ())
|
2019-02-06 03:47:02 +08:00
|
|
|
%c = constant @second_order_func : () -> (() -> ())
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-NEXT: return %{{.*}} : () -> (() -> ())
|
2019-02-06 03:47:02 +08:00
|
|
|
return %c : () -> (() -> ())
|
|
|
|
}
|
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-LABEL: func @identity_functor(%{{.*}}: () -> ()) -> (() -> ()) {
|
2019-02-06 03:47:02 +08:00
|
|
|
func @identity_functor(%a : () -> ()) -> (() -> ()) {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-NEXT: return %{{.*}} : () -> ()
|
2019-02-06 03:47:02 +08:00
|
|
|
return %a : () -> ()
|
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @func_ops_in_loop() {
|
|
|
|
func @func_ops_in_loop() {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = "foo"() : () -> i64
|
2018-07-27 09:09:20 +08:00
|
|
|
%a = "foo"() : ()->i64
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = 1 to 10 {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 10 {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = "doo"() : () -> f32
|
2018-07-27 09:09:20 +08:00
|
|
|
%b = "doo"() : ()->f32
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: "bar"(%{{.*}}, %{{.*}}) : (i64, f32) -> ()
|
2018-07-27 09:09:20 +08:00
|
|
|
"bar"(%a, %b) : (i64, f32) -> ()
|
|
|
|
// CHECK: }
|
|
|
|
}
|
|
|
|
// CHECK: return
|
|
|
|
return
|
|
|
|
// CHECK: }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @loops() {
|
|
|
|
func @loops() {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = 1 to 100 step 2 {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = 1 to 100 step 2 {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = 1 to 200 {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %j = 1 to 200 {
|
2018-07-15 14:06:24 +08:00
|
|
|
} // CHECK: }
|
|
|
|
} // CHECK: }
|
|
|
|
return // CHECK: return
|
|
|
|
} // CHECK: }
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @complex_loops() {
|
|
|
|
func @complex_loops() {
|
2019-07-10 01:40:29 +08:00
|
|
|
affine.for %i1 = 1 to 100 { // CHECK: affine.for %{{.*}} = 1 to 100 {
|
|
|
|
affine.for %j1 = 1 to 100 { // CHECK: affine.for %{{.*}} = 1 to 100 {
|
|
|
|
// CHECK: "foo"(%{{.*}}, %{{.*}}) : (index, index) -> ()
|
2018-10-07 08:21:53 +08:00
|
|
|
"foo"(%i1, %j1) : (index,index) -> ()
|
2018-07-31 06:18:10 +08:00
|
|
|
} // CHECK: }
|
|
|
|
"boo"() : () -> () // CHECK: "boo"() : () -> ()
|
2019-07-10 01:40:29 +08:00
|
|
|
affine.for %j2 = 1 to 10 { // CHECK: affine.for %{{.*}} = 1 to 10 {
|
|
|
|
affine.for %k2 = 1 to 10 { // CHECK: affine.for %{{.*}} = 1 to 10 {
|
2018-07-31 06:18:10 +08:00
|
|
|
"goo"() : () -> () // CHECK: "goo"() : () -> ()
|
|
|
|
} // CHECK: }
|
|
|
|
} // CHECK: }
|
|
|
|
} // CHECK: }
|
|
|
|
return // CHECK: return
|
|
|
|
} // CHECK: }
|
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: func @triang_loop(%{{.*}}: index, %{{.*}}: memref<?x?xi32>) {
|
2019-01-03 02:20:00 +08:00
|
|
|
func @triang_loop(%arg0: index, %arg1: memref<?x?xi32>) {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c = arith.constant 0 : i32 // CHECK: %{{.*}} = arith.constant 0 : i32
|
2019-07-10 01:40:29 +08:00
|
|
|
affine.for %i0 = 1 to %arg0 { // CHECK: affine.for %{{.*}} = 1 to %{{.*}} {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.for %i1 = affine_map<(d0)[]->(d0)>(%i0)[] to %arg0 { // CHECK: affine.for %{{.*}} = #map{{[0-9]+}}(%{{.*}}) to %{{.*}} {
|
2021-02-10 20:53:11 +08:00
|
|
|
memref.store %c, %arg1[%i0, %i1] : memref<?x?xi32> // CHECK: memref.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}]
|
2018-08-25 14:38:14 +08:00
|
|
|
} // CHECK: }
|
|
|
|
} // CHECK: }
|
|
|
|
return // CHECK: return
|
|
|
|
} // CHECK: }
|
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: func @minmax_loop(%{{.*}}: index, %{{.*}}: index, %{{.*}}: memref<100xf32>) {
|
2019-01-03 02:20:00 +08:00
|
|
|
func @minmax_loop(%arg0: index, %arg1: index, %arg2: memref<100xf32>) {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = max #map{{.*}}()[%{{.*}}] to min #map{{.*}}()[%{{.*}}] {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.for %i0 = max affine_map<()[s]->(0,s-1)>()[%arg0] to min affine_map<()[s]->(100,s+1)>()[%arg1] {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: "foo"(%{{.*}}, %{{.*}}) : (memref<100xf32>, index) -> ()
|
2018-10-07 08:21:53 +08:00
|
|
|
"foo"(%arg2, %i0) : (memref<100xf32>, index) -> ()
|
2018-08-25 14:38:14 +08:00
|
|
|
} // CHECK: }
|
|
|
|
return // CHECK: return
|
|
|
|
} // CHECK: }
|
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-LABEL: func @loop_bounds(%{{.*}}: index) {
|
2019-01-03 02:20:00 +08:00
|
|
|
func @loop_bounds(%N : index) {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = "foo"(%{{.*}}) : (index) -> index
|
2018-10-07 08:21:53 +08:00
|
|
|
%s = "foo"(%N) : (index) -> index
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = %{{.*}} to %{{.*}}
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i = %s to %N {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = #map{{[0-9]+}}(%{{.*}}) to 0
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.for %j = affine_map<(d0)[]->(d0)>(%i)[] to 0 step 1 {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = affine.apply #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}]
|
2020-01-14 05:12:37 +08:00
|
|
|
%w1 = affine.apply affine_map<(d0, d1)[s0] -> (d0+d1)> (%i, %j) [%s]
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = affine.apply #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}]
|
2020-01-14 05:12:37 +08:00
|
|
|
%w2 = affine.apply affine_map<(d0, d1)[s0] -> (s0+1)> (%i, %j) [%s]
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}] to #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}] {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.for %k = #bound_map1 (%w1, %i)[%N] to affine_map<(i, j)[s] -> (i + j + s)> (%w2, %j)[%s] {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: "foo"(%{{.*}}, %{{.*}}, %{{.*}}) : (index, index, index) -> ()
|
2018-10-07 08:21:53 +08:00
|
|
|
"foo"(%i, %j, %k) : (index, index, index)->()
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: %{{.*}} = arith.constant 30 : index
|
|
|
|
%c = arith.constant 30 : index
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = affine.apply #map{{.*}}(%{{.*}}, %{{.*}})
|
2020-01-14 05:12:37 +08:00
|
|
|
%u = affine.apply affine_map<(d0, d1)->(d0+d1)> (%N, %c)
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = max #map{{.*}}(%{{.*}})[%{{.*}}] to min #map{{.*}}(%{{.*}})[%{{.*}}] {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %l = max #bound_map2(%i)[%u] to min #bound_map2(%k)[%c] {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: "bar"(%{{.*}}) : (index) -> ()
|
2018-10-07 08:21:53 +08:00
|
|
|
"bar"(%l) : (index) -> ()
|
2018-08-25 14:38:14 +08:00
|
|
|
} // CHECK: }
|
|
|
|
} // CHECK: }
|
|
|
|
} // CHECK: }
|
|
|
|
} // CHECK: }
|
|
|
|
return // CHECK: return
|
|
|
|
} // CHECK: }
|
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-LABEL: func @ifinst(%{{.*}}: index) {
|
2019-01-03 02:20:00 +08:00
|
|
|
func @ifinst(%N: index) {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c = arith.constant 200 : index // CHECK %{{.*}} = arith.constant 200
|
2019-07-10 01:40:29 +08:00
|
|
|
affine.for %i = 1 to 10 { // CHECK affine.for %{{.*}} = 1 to 10 {
|
|
|
|
affine.if #set0(%i)[%N, %c] { // CHECK affine.if #set0(%{{.*}})[%{{.*}}, %{{.*}}] {
|
2021-10-13 07:14:57 +08:00
|
|
|
%x = arith.constant 1 : i32
|
|
|
|
// CHECK: %{{.*}} = arith.constant 1 : i32
|
2019-07-10 01:40:29 +08:00
|
|
|
%y = "add"(%x, %i) : (i32, index) -> i32 // CHECK: %{{.*}} = "add"(%{{.*}}, %{{.*}}) : (i32, index) -> i32
|
|
|
|
%z = "mul"(%y, %y) : (i32, i32) -> i32 // CHECK: %{{.*}} = "mul"(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
|
2019-01-29 13:23:53 +08:00
|
|
|
} else { // CHECK } else {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.if affine_set<(i)[N] : (i - 2 >= 0, 4 - i >= 0)>(%i)[%N] { // CHECK affine.if (#set1(%{{.*}})[%{{.*}}]) {
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: %{{.*}} = arith.constant 1 : index
|
|
|
|
%u = arith.constant 1 : index
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = affine.apply #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}]
|
2020-01-14 05:12:37 +08:00
|
|
|
%w = affine.apply affine_map<(d0,d1)[s0] -> (d0+d1+s0)> (%i, %i) [%u]
|
2019-01-29 13:23:53 +08:00
|
|
|
} else { // CHECK } else {
|
2021-10-13 07:14:57 +08:00
|
|
|
%v = arith.constant 3 : i32 // %c3_i32 = arith.constant 3 : i32
|
2019-01-29 13:23:53 +08:00
|
|
|
}
|
2018-08-08 05:24:38 +08:00
|
|
|
} // CHECK }
|
|
|
|
} // CHECK }
|
|
|
|
return // CHECK return
|
|
|
|
} // CHECK }
|
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-LABEL: func @simple_ifinst(%{{.*}}: index) {
|
2019-01-03 02:20:00 +08:00
|
|
|
func @simple_ifinst(%N: index) {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c = arith.constant 200 : index // CHECK %{{.*}} = arith.constant 200
|
2019-07-10 01:40:29 +08:00
|
|
|
affine.for %i = 1 to 10 { // CHECK affine.for %{{.*}} = 1 to 10 {
|
|
|
|
affine.if #set0(%i)[%N, %c] { // CHECK affine.if #set0(%{{.*}})[%{{.*}}, %{{.*}}] {
|
2021-10-13 07:14:57 +08:00
|
|
|
%x = arith.constant 1 : i32
|
|
|
|
// CHECK: %{{.*}} = arith.constant 1 : i32
|
2019-07-10 01:40:29 +08:00
|
|
|
%y = "add"(%x, %i) : (i32, index) -> i32 // CHECK: %{{.*}} = "add"(%{{.*}}, %{{.*}}) : (i32, index) -> i32
|
|
|
|
%z = "mul"(%y, %y) : (i32, i32) -> i32 // CHECK: %{{.*}} = "mul"(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
|
2018-09-01 13:33:47 +08:00
|
|
|
} // CHECK }
|
|
|
|
} // CHECK }
|
|
|
|
return // CHECK return
|
|
|
|
} // CHECK }
|
2018-07-15 14:06:24 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @attributes() {
|
|
|
|
func @attributes() {
|
2018-07-15 14:06:24 +08:00
|
|
|
// CHECK: "foo"()
|
2018-07-19 06:31:25 +08:00
|
|
|
"foo"(){} : ()->()
|
2018-07-05 11:45:39 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {a = 1 : i64, b = -423 : i64, c = [true, false], d = 1.600000e+01 : f64} : () -> ()
|
|
|
|
"foo"() {a = 1, b = -423, c = [true, false], d = 16.0 } : () -> ()
|
2018-07-05 11:45:39 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {map1 = #map{{[0-9]+}}}
|
|
|
|
"foo"() {map1 = #map1} : () -> ()
|
2018-07-19 07:29:21 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {map2 = #map{{[0-9]+}}}
|
2020-01-14 05:12:37 +08:00
|
|
|
"foo"() {map2 = affine_map<(d0, d1, d2) -> (d0, d1, d2)>} : () -> ()
|
2018-07-19 07:29:21 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {map12 = [#map{{[0-9]+}}, #map{{[0-9]+}}]}
|
|
|
|
"foo"() {map12 = [#map1, #map2]} : () -> ()
|
2018-07-19 07:29:21 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {set1 = #set{{[0-9]+}}}
|
|
|
|
"foo"() {set1 = #set1} : () -> ()
|
2018-10-26 13:13:03 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {set2 = #set{{[0-9]+}}}
|
2020-01-14 05:12:37 +08:00
|
|
|
"foo"() {set2 = affine_set<(d0, d1, d2) : (d0 >= 0, d1 >= 0, d2 - d1 == 0)>} : () -> ()
|
2018-10-26 13:13:03 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {set12 = [#set{{[0-9]+}}, #set{{[0-9]+}}]}
|
|
|
|
"foo"() {set12 = [#set1, #set2]} : () -> ()
|
2018-10-26 13:13:03 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {dictionary = {bool = true, fn = @ifinst}}
|
|
|
|
"foo"() {dictionary = {bool = true, fn = @ifinst}} : () -> ()
|
2019-06-01 00:24:48 +08:00
|
|
|
|
|
|
|
// Check that the dictionary attribute elements are sorted.
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {dictionary = {bar = false, bool = true, fn = @ifinst}}
|
|
|
|
"foo"() {dictionary = {fn = @ifinst, bar = false, bool = true}} : () -> ()
|
2019-06-01 00:24:48 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {d = 1.000000e-09 : f64, func = [], i123 = 7 : i64, if = "foo"} : () -> ()
|
|
|
|
"foo"() {if = "foo", func = [], i123 = 7, d = 1.e-9} : () -> ()
|
2018-07-05 11:45:39 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {fn = @attributes, if = @ifinst} : () -> ()
|
|
|
|
"foo"() {fn = @attributes, if = @ifinst} : () -> ()
|
2019-02-05 23:12:46 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {int = 0 : i42} : () -> ()
|
|
|
|
"foo"() {int = 0 : i42} : () -> ()
|
2018-07-06 00:12:11 +08:00
|
|
|
return
|
2018-07-05 11:45:39 +08:00
|
|
|
}
|
2018-07-21 09:41:34 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @ssa_values() -> (i16, i8) {
|
|
|
|
func @ssa_values() -> (i16, i8) {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}}:2 = "foo"() : () -> (i1, i17)
|
2019-03-29 05:58:52 +08:00
|
|
|
%0:2 = "foo"() : () -> (i1, i17)
|
2018-12-30 03:32:37 +08:00
|
|
|
br ^bb2
|
2018-07-21 09:41:34 +08:00
|
|
|
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb1: // CHECK: ^bb1: // pred: ^bb2
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}}:2 = "baz"(%{{.*}}#1, %{{.*}}#0, %{{.*}}#1) : (f32, i11, i17) -> (i16, i8)
|
2019-03-29 05:58:52 +08:00
|
|
|
%1:2 = "baz"(%2#1, %2#0, %0#1) : (f32, i11, i17) -> (i16, i8)
|
2018-07-25 01:41:30 +08:00
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: return %{{.*}}#0, %{{.*}}#1 : i16, i8
|
2018-07-24 02:56:17 +08:00
|
|
|
return %1#0, %1#1 : i16, i8
|
2018-07-21 09:41:34 +08:00
|
|
|
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb2: // CHECK: ^bb2: // pred: ^bb0
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}}:2 = "bar"(%{{.*}}#0, %{{.*}}#1) : (i1, i17) -> (i11, f32)
|
2019-03-29 05:58:52 +08:00
|
|
|
%2:2 = "bar"(%0#0, %0#1) : (i1, i17) -> (i11, f32)
|
2018-12-30 03:32:37 +08:00
|
|
|
br ^bb1
|
2018-07-23 23:42:19 +08:00
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @bbargs() -> (i16, i8) {
|
|
|
|
func @bbargs() -> (i16, i8) {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}}:2 = "foo"() : () -> (i1, i17)
|
2019-03-29 05:58:52 +08:00
|
|
|
%0:2 = "foo"() : () -> (i1, i17)
|
2018-12-30 03:32:37 +08:00
|
|
|
br ^bb1(%0#1, %0#0 : i17, i1)
|
2018-07-23 23:42:19 +08:00
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
^bb1(%x: i17, %y: i1): // CHECK: ^bb1(%{{.*}}: i17, %{{.*}}: i1):
|
|
|
|
// CHECK: %{{.*}}:2 = "baz"(%{{.*}}, %{{.*}}, %{{.*}}#1) : (i17, i1, i17) -> (i16, i8)
|
2019-03-29 05:58:52 +08:00
|
|
|
%1:2 = "baz"(%x, %y, %0#1) : (i17, i1, i17) -> (i16, i8)
|
2018-07-24 02:56:17 +08:00
|
|
|
return %1#0, %1#1 : i16, i8
|
2018-07-23 23:42:19 +08:00
|
|
|
}
|
2018-07-25 06:01:27 +08:00
|
|
|
|
2019-01-10 04:28:30 +08:00
|
|
|
// CHECK-LABEL: func @verbose_terminators() -> (i1, i17)
|
|
|
|
func @verbose_terminators() -> (i1, i17) {
|
2019-03-29 05:58:52 +08:00
|
|
|
%0:2 = "foo"() : () -> (i1, i17)
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: br ^bb1(%{{.*}}#0, %{{.*}}#1 : i1, i17)
|
2020-03-06 04:48:28 +08:00
|
|
|
"std.br"(%0#0, %0#1)[^bb1] : (i1, i17) -> ()
|
2019-01-10 04:28:30 +08:00
|
|
|
|
|
|
|
^bb1(%x : i1, %y : i17):
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: cond_br %{{.*}}, ^bb2(%{{.*}} : i17), ^bb3(%{{.*}}, %{{.*}} : i1, i17)
|
2020-03-06 04:48:28 +08:00
|
|
|
"std.cond_br"(%x, %y, %x, %y) [^bb2, ^bb3] {operand_segment_sizes = dense<[1, 1, 2]>: vector<3xi32>} : (i1, i17, i1, i17) -> ()
|
2019-01-10 04:28:30 +08:00
|
|
|
|
|
|
|
^bb2(%a : i17):
|
2021-10-13 07:14:57 +08:00
|
|
|
%true = arith.constant true
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: return %{{.*}}, %{{.*}} : i1, i17
|
2019-03-03 10:03:03 +08:00
|
|
|
"std.return"(%true, %a) : (i1, i17) -> ()
|
2019-01-10 04:28:30 +08:00
|
|
|
|
|
|
|
^bb3(%b : i1, %c : i17):
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: return %{{.*}}, %{{.*}} : i1, i17
|
2019-03-03 10:03:03 +08:00
|
|
|
"std.return"(%b, %c) : (i1, i17) -> ()
|
2019-01-10 04:28:30 +08:00
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @condbr_simple
|
|
|
|
func @condbr_simple() -> (i32) {
|
2018-07-25 06:01:27 +08:00
|
|
|
%cond = "foo"() : () -> i1
|
|
|
|
%a = "bar"() : () -> i32
|
|
|
|
%b = "bar"() : () -> i64
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: cond_br %{{.*}}, ^bb1(%{{.*}} : i32), ^bb2(%{{.*}} : i64)
|
2018-12-30 03:32:37 +08:00
|
|
|
cond_br %cond, ^bb1(%a : i32), ^bb2(%b : i64)
|
2018-07-25 06:01:27 +08:00
|
|
|
|
2018-12-30 03:32:37 +08:00
|
|
|
// CHECK: ^bb1({{.*}}: i32): // pred: ^bb0
|
|
|
|
^bb1(%x : i32):
|
|
|
|
br ^bb2(%b: i64)
|
2018-07-25 06:01:27 +08:00
|
|
|
|
2018-12-30 03:32:37 +08:00
|
|
|
// CHECK: ^bb2({{.*}}: i64): // 2 preds: ^bb0, ^bb1
|
|
|
|
^bb2(%y : i64):
|
2018-07-25 06:01:27 +08:00
|
|
|
%z = "foo"() : () -> i32
|
|
|
|
return %z : i32
|
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @condbr_moarargs
|
|
|
|
func @condbr_moarargs() -> (i32) {
|
2018-07-25 06:01:27 +08:00
|
|
|
%cond = "foo"() : () -> i1
|
|
|
|
%a = "bar"() : () -> i32
|
|
|
|
%b = "bar"() : () -> i64
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: cond_br %{{.*}}, ^bb1(%{{.*}}, %{{.*}} : i32, i64), ^bb2(%{{.*}}, %{{.*}}, %{{.*}} : i64, i32, i32)
|
2018-12-30 03:32:37 +08:00
|
|
|
cond_br %cond, ^bb1(%a, %b : i32, i64), ^bb2(%b, %a, %a : i64, i32, i32)
|
2018-07-25 06:01:27 +08:00
|
|
|
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb1(%x : i32, %y : i64):
|
2018-07-25 06:01:27 +08:00
|
|
|
return %x : i32
|
|
|
|
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb2(%x2 : i64, %y2 : i32, %z2 : i32):
|
2018-07-25 06:01:27 +08:00
|
|
|
%z = "foo"() : () -> i32
|
|
|
|
return %z : i32
|
|
|
|
}
|
2018-08-02 01:43:18 +08:00
|
|
|
|
|
|
|
|
|
|
|
// Test pretty printing of constant names.
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @constants
|
|
|
|
func @constants() -> (i32, i23, i23, i1, i1) {
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: %{{.*}} = arith.constant 42 : i32
|
|
|
|
%x = arith.constant 42 : i32
|
|
|
|
// CHECK: %{{.*}} = arith.constant 17 : i23
|
|
|
|
%y = arith.constant 17 : i23
|
2018-08-02 01:43:18 +08:00
|
|
|
|
|
|
|
// This is a redundant definition of 17, the asmprinter gives it a unique name
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: %{{.*}} = arith.constant 17 : i23
|
|
|
|
%z = arith.constant 17 : i23
|
2018-08-02 01:43:18 +08:00
|
|
|
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: %{{.*}} = arith.constant true
|
|
|
|
%t = arith.constant true
|
|
|
|
// CHECK: %{{.*}} = arith.constant false
|
|
|
|
%f = arith.constant false
|
2018-08-03 08:16:58 +08:00
|
|
|
|
2019-02-08 00:36:50 +08:00
|
|
|
// The trick to parse type declarations should not interfere with hex
|
|
|
|
// literals.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: %{{.*}} = arith.constant 3890 : i32
|
|
|
|
%h = arith.constant 0xf32 : i32
|
2019-02-08 00:36:50 +08:00
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: return %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}
|
2018-08-03 08:16:58 +08:00
|
|
|
return %x, %y, %z, %t, %f : i32, i23, i23, i1, i1
|
2018-08-02 01:43:18 +08:00
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @typeattr
|
|
|
|
func @typeattr() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {bar = tensor<*xf32>} : () -> ()
|
|
|
|
"foo"(){bar = tensor<*xf32>} : () -> ()
|
2018-08-03 16:54:46 +08:00
|
|
|
return
|
|
|
|
}
|
2018-08-14 16:16:45 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @stringquote
|
|
|
|
func @stringquote() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {bar = "a\22quoted\22string"} : () -> ()
|
|
|
|
"foo"(){bar = "a\"quoted\"string"} : () -> ()
|
2019-06-28 00:12:19 +08:00
|
|
|
|
|
|
|
// CHECK-NEXT: "typed_string" : !foo.string
|
|
|
|
"foo"(){bar = "typed_string" : !foo.string} : () -> ()
|
2018-08-14 16:16:45 +08:00
|
|
|
return
|
|
|
|
}
|
2018-08-16 00:09:54 +08:00
|
|
|
|
2019-04-26 00:56:09 +08:00
|
|
|
// CHECK-LABEL: func @unitAttrs
|
|
|
|
func @unitAttrs() -> () {
|
2019-10-22 02:01:38 +08:00
|
|
|
// CHECK-NEXT: "foo"() {unitAttr}
|
2019-06-26 10:06:06 +08:00
|
|
|
"foo"() {unitAttr = unit} : () -> ()
|
2019-04-26 00:56:09 +08:00
|
|
|
|
2019-10-22 02:01:38 +08:00
|
|
|
// CHECK-NEXT: "foo"() {unitAttr}
|
2019-04-26 00:56:09 +08:00
|
|
|
"foo"() {unitAttr} : () -> ()
|
2019-10-22 02:01:38 +08:00
|
|
|
|
|
|
|
// CHECK-NEXT: "foo"() {nested = {unitAttr}}
|
|
|
|
"foo"() {nested = {unitAttr}} : () -> ()
|
2019-04-26 00:56:09 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @floatAttrs
|
|
|
|
func @floatAttrs() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo"() {a = 4.000000e+00 : f64, b = 2.000000e+00 : f64, c = 7.100000e+00 : f64, d = -0.000000e+00 : f64} : () -> ()
|
|
|
|
"foo"(){a = 4.0, b = 2.0, c = 7.1, d = -0.0} : () -> ()
|
2018-08-16 00:09:54 +08:00
|
|
|
return
|
2018-08-21 05:37:39 +08:00
|
|
|
}
|
2018-09-19 07:36:26 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @externalfuncattr
|
|
|
|
func private @externalfuncattr() -> ()
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: attributes {dialect.a = "a\22quoted\22string", dialect.b = 4.000000e+00 : f64, dialect.c = tensor<*xf32>}
|
|
|
|
attributes {dialect.a = "a\"quoted\"string", dialect.b = 4.0, dialect.c = tensor<*xf32>}
|
2018-09-19 07:36:26 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @funcattrempty
|
|
|
|
func private @funcattrempty() -> ()
|
2018-09-19 07:36:26 +08:00
|
|
|
attributes {}
|
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @funcattr
|
|
|
|
func private @funcattr() -> ()
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: attributes {dialect.a = "a\22quoted\22string", dialect.b = 4.000000e+00 : f64, dialect.c = tensor<*xf32>}
|
|
|
|
attributes {dialect.a = "a\"quoted\"string", dialect.b = 4.0, dialect.c = tensor<*xf32>} {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2018-09-19 07:36:26 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @funcattrwithblock
|
|
|
|
func @funcattrwithblock() -> ()
|
2018-09-19 07:36:26 +08:00
|
|
|
attributes {} {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2018-09-19 07:36:26 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-label func @funcsimplemap
|
2020-01-14 05:12:37 +08:00
|
|
|
#map_simple0 = affine_map<()[] -> (10)>
|
|
|
|
#map_simple1 = affine_map<()[s0] -> (s0)>
|
|
|
|
#map_non_simple0 = affine_map<(d0)[] -> (d0)>
|
|
|
|
#map_non_simple1 = affine_map<(d0)[s0] -> (d0 + s0)>
|
|
|
|
#map_non_simple2 = affine_map<()[s0, s1] -> (s0 + s1)>
|
|
|
|
#map_non_simple3 = affine_map<()[s0] -> (s0 + 3)>
|
2019-01-03 02:20:00 +08:00
|
|
|
func @funcsimplemap(%arg0: index, %arg1: index) -> () {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i0 = 0 to #map_simple0()[] {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = 0 to 10 {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i1 = 0 to #map_simple1()[%arg1] {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = 0 to %{{.*}} {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i2 = 0 to #map_non_simple0(%i0)[] {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = 0 to #map{{[a-z_0-9]*}}(%{{.*}}) {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i3 = 0 to #map_non_simple1(%i0)[%arg1] {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = 0 to #map{{[a-z_0-9]*}}(%{{.*}})[%{{.*}}] {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i4 = 0 to #map_non_simple2()[%arg1, %arg0] {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = 0 to #map{{[a-z_0-9]*}}()[%{{.*}}, %{{.*}}] {
|
2019-03-26 01:14:34 +08:00
|
|
|
affine.for %i5 = 0 to #map_non_simple3()[%arg0] {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.for %{{.*}} = 0 to #map{{[a-z_0-9]*}}()[%{{.*}}] {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c42_i32 = arith.constant 42 : i32
|
2018-09-26 08:15:54 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-23 01:35:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2018-10-10 23:57:51 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @splattensorattr
|
|
|
|
func @splattensorattr() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2019-07-19 00:24:41 +08:00
|
|
|
// CHECK: "splatBoolTensor"() {bar = dense<false> : tensor<i1>} : () -> ()
|
2019-06-26 10:06:06 +08:00
|
|
|
"splatBoolTensor"(){bar = dense<false> : tensor<i1>} : () -> ()
|
2019-03-19 04:42:55 +08:00
|
|
|
|
2020-03-03 01:18:45 +08:00
|
|
|
// CHECK: "splatUIntTensor"() {bar = dense<222> : tensor<2x1x4xui8>} : () -> ()
|
|
|
|
"splatUIntTensor"(){bar = dense<222> : tensor<2x1x4xui8>} : () -> ()
|
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "splatIntTensor"() {bar = dense<5> : tensor<2x1x4xi32>} : () -> ()
|
|
|
|
"splatIntTensor"(){bar = dense<5> : tensor<2x1x4xi32>} : () -> ()
|
2019-03-19 04:42:55 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "splatFloatTensor"() {bar = dense<-5.000000e+00> : tensor<2x1x4xf32>} : () -> ()
|
|
|
|
"splatFloatTensor"(){bar = dense<-5.0> : tensor<2x1x4xf32>} : () -> ()
|
2019-03-19 04:42:55 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "splatIntVector"() {bar = dense<5> : vector<2x1x4xi64>} : () -> ()
|
|
|
|
"splatIntVector"(){bar = dense<5> : vector<2x1x4xi64>} : () -> ()
|
2019-03-19 04:42:55 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "splatFloatVector"() {bar = dense<-5.000000e+00> : vector<2x1x4xf16>} : () -> ()
|
|
|
|
"splatFloatVector"(){bar = dense<-5.0> : vector<2x1x4xf16>} : () -> ()
|
2019-04-02 01:01:47 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "splatIntScalar"() {bar = dense<5> : tensor<i9>} : () -> ()
|
|
|
|
"splatIntScalar"() {bar = dense<5> : tensor<i9>} : () -> ()
|
|
|
|
// CHECK: "splatFloatScalar"() {bar = dense<-5.000000e+00> : tensor<f16>} : () -> ()
|
|
|
|
"splatFloatScalar"() {bar = dense<-5.0> : tensor<f16>} : () -> ()
|
2018-10-10 23:57:51 +08:00
|
|
|
return
|
|
|
|
}
|
2018-10-19 04:54:44 +08:00
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @densetensorattr
|
|
|
|
func @densetensorattr() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2018-10-19 04:54:44 +08:00
|
|
|
|
|
|
|
// NOTE: The {{\[\[}} syntax is because "[[" confuses FileCheck.
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "fooi3"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi3>} : () -> ()
|
|
|
|
"fooi3"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi3>} : () -> ()
|
|
|
|
// CHECK: "fooi6"() {bar = dense<{{\[\[\[}}5, -6, 1, 2]], {{\[\[}}7, 8, 3, 4]]]> : tensor<2x1x4xi6>} : () -> ()
|
|
|
|
"fooi6"(){bar = dense<[[[5, -6, 1, 2]], [[7, 8, 3, 4]]]> : tensor<2x1x4xi6>} : () -> ()
|
|
|
|
// CHECK: "fooi8"() {bar = dense<5> : tensor<1x1x1xi8>} : () -> ()
|
|
|
|
"fooi8"(){bar = dense<[[[5]]]> : tensor<1x1x1xi8>} : () -> ()
|
|
|
|
// CHECK: "fooi13"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi13>} : () -> ()
|
|
|
|
"fooi13"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi13>} : () -> ()
|
|
|
|
// CHECK: "fooi16"() {bar = dense<-5> : tensor<1x1x1xi16>} : () -> ()
|
|
|
|
"fooi16"(){bar = dense<[[[-5]]]> : tensor<1x1x1xi16>} : () -> ()
|
|
|
|
// CHECK: "fooi23"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi23>} : () -> ()
|
|
|
|
"fooi23"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi23>} : () -> ()
|
|
|
|
// CHECK: "fooi32"() {bar = dense<5> : tensor<1x1x1xi32>} : () -> ()
|
|
|
|
"fooi32"(){bar = dense<[[[5]]]> : tensor<1x1x1xi32>} : () -> ()
|
|
|
|
// CHECK: "fooi33"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi33>} : () -> ()
|
|
|
|
"fooi33"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi33>} : () -> ()
|
|
|
|
// CHECK: "fooi43"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi43>} : () -> ()
|
|
|
|
"fooi43"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi43>} : () -> ()
|
|
|
|
// CHECK: "fooi53"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 2, -1, 2]]]> : tensor<2x1x4xi53>} : () -> ()
|
|
|
|
"fooi53"(){bar = dense<[[[1, -2, 1, 2]], [[0, 2, -1, 2]]]> : tensor<2x1x4xi53>} : () -> ()
|
|
|
|
// CHECK: "fooi64"() {bar = dense<{{\[\[\[}}1, -2, 1, 2]], {{\[\[}}0, 3, -1, 2]]]> : tensor<2x1x4xi64>} : () -> ()
|
|
|
|
"fooi64"(){bar = dense<[[[1, -2, 1, 2]], [[0, 3, -1, 2]]]> : tensor<2x1x4xi64>} : () -> ()
|
|
|
|
// CHECK: "fooi64"() {bar = dense<-5> : tensor<1x1x1xi64>} : () -> ()
|
|
|
|
"fooi64"(){bar = dense<[[[-5]]]> : tensor<1x1x1xi64>} : () -> ()
|
|
|
|
// CHECK: "fooi67"() {bar = dense<{{\[\[\[}}-5, 4, 6, 2]]]> : vector<1x1x4xi67>} : () -> ()
|
|
|
|
"fooi67"(){bar = dense<[[[-5, 4, 6, 2]]]> : vector<1x1x4xi67>} : () -> ()
|
|
|
|
|
2020-07-09 08:44:27 +08:00
|
|
|
// CHECK: "foo2"() {bar = dense<> : tensor<0xi32>} : () -> ()
|
|
|
|
"foo2"(){bar = dense<> : tensor<0xi32>} : () -> ()
|
|
|
|
// CHECK: "foo2"() {bar = dense<> : tensor<1x0xi32>} : () -> ()
|
|
|
|
"foo2"(){bar = dense<> : tensor<1x0xi32>} : () -> ()
|
|
|
|
// CHECK: dense<> : tensor<0x512x512xi32>
|
|
|
|
"foo2"(){bar = dense<> : tensor<0x512x512xi32>} : () -> ()
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo3"() {bar = dense<{{\[\[\[}}5, -6, 1, 2]], {{\[\[}}7, 8, 3, 4]]]> : tensor<2x1x4xi32>} : () -> ()
|
|
|
|
"foo3"(){bar = dense<[[[5, -6, 1, 2]], [[7, 8, 3, 4]]]> : tensor<2x1x4xi32>} : () -> ()
|
|
|
|
|
|
|
|
// CHECK: "float1"() {bar = dense<5.000000e+00> : tensor<1x1x1xf32>} : () -> ()
|
|
|
|
"float1"(){bar = dense<[[[5.0]]]> : tensor<1x1x1xf32>} : () -> ()
|
2020-07-09 08:44:27 +08:00
|
|
|
// CHECK: "float2"() {bar = dense<> : tensor<0xf32>} : () -> ()
|
|
|
|
"float2"(){bar = dense<> : tensor<0xf32>} : () -> ()
|
|
|
|
// CHECK: "float2"() {bar = dense<> : tensor<1x0xf32>} : () -> ()
|
|
|
|
"float2"(){bar = dense<> : tensor<1x0xf32>} : () -> ()
|
2019-06-26 10:06:06 +08:00
|
|
|
|
|
|
|
// CHECK: "bfloat16"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : tensor<2x1x4xbf16>} : () -> ()
|
|
|
|
"bfloat16"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : tensor<2x1x4xbf16>} : () -> ()
|
|
|
|
// CHECK: "float16"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : tensor<2x1x4xf16>} : () -> ()
|
|
|
|
"float16"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : tensor<2x1x4xf16>} : () -> ()
|
|
|
|
// CHECK: "float32"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : tensor<2x1x4xf32>} : () -> ()
|
|
|
|
"float32"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : tensor<2x1x4xf32>} : () -> ()
|
|
|
|
// CHECK: "float64"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : tensor<2x1x4xf64>} : () -> ()
|
|
|
|
"float64"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : tensor<2x1x4xf64>} : () -> ()
|
|
|
|
|
|
|
|
// CHECK: "intscalar"() {bar = dense<1> : tensor<i32>} : () -> ()
|
|
|
|
"intscalar"(){bar = dense<1> : tensor<i32>} : () -> ()
|
|
|
|
// CHECK: "floatscalar"() {bar = dense<5.000000e+00> : tensor<f32>} : () -> ()
|
|
|
|
"floatscalar"(){bar = dense<5.0> : tensor<f32>} : () -> ()
|
2020-04-24 06:47:31 +08:00
|
|
|
|
|
|
|
// CHECK: "index"() {bar = dense<1> : tensor<index>} : () -> ()
|
|
|
|
"index"(){bar = dense<1> : tensor<index>} : () -> ()
|
|
|
|
// CHECK: "index"() {bar = dense<[1, 2]> : tensor<2xindex>} : () -> ()
|
|
|
|
"index"(){bar = dense<[1, 2]> : tensor<2xindex>} : () -> ()
|
2020-05-06 03:39:22 +08:00
|
|
|
|
|
|
|
// CHECK: dense<(1,1)> : tensor<complex<i64>>
|
|
|
|
"complex_attr"(){bar = dense<(1,1)> : tensor<complex<i64>>} : () -> ()
|
|
|
|
// CHECK: dense<[(1,1), (2,2)]> : tensor<2xcomplex<i64>>
|
|
|
|
"complex_attr"(){bar = dense<[(1,1), (2,2)]> : tensor<2xcomplex<i64>>} : () -> ()
|
|
|
|
// CHECK: dense<(1.000000e+00,0.000000e+00)> : tensor<complex<f32>>
|
|
|
|
"complex_attr"(){bar = dense<(1.000000e+00,0.000000e+00)> : tensor<complex<f32>>} : () -> ()
|
|
|
|
// CHECK: dense<[(1.000000e+00,0.000000e+00), (2.000000e+00,2.000000e+00)]> : tensor<2xcomplex<f32>>
|
|
|
|
"complex_attr"(){bar = dense<[(1.000000e+00,0.000000e+00), (2.000000e+00,2.000000e+00)]> : tensor<2xcomplex<f32>>} : () -> ()
|
2018-10-19 04:54:44 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @densevectorattr
|
|
|
|
func @densevectorattr() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
2018-10-19 04:54:44 +08:00
|
|
|
// NOTE: The {{\[\[}} syntax is because "[[" confuses FileCheck.
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "fooi8"() {bar = dense<5> : vector<1x1x1xi8>} : () -> ()
|
|
|
|
"fooi8"(){bar = dense<[[[5]]]> : vector<1x1x1xi8>} : () -> ()
|
|
|
|
// CHECK: "fooi16"() {bar = dense<-5> : vector<1x1x1xi16>} : () -> ()
|
|
|
|
"fooi16"(){bar = dense<[[[-5]]]> : vector<1x1x1xi16>} : () -> ()
|
|
|
|
// CHECK: "foo32"() {bar = dense<5> : vector<1x1x1xi32>} : () -> ()
|
|
|
|
"foo32"(){bar = dense<[[[5]]]> : vector<1x1x1xi32>} : () -> ()
|
|
|
|
// CHECK: "fooi64"() {bar = dense<-5> : vector<1x1x1xi64>} : () -> ()
|
|
|
|
"fooi64"(){bar = dense<[[[-5]]]> : vector<1x1x1xi64>} : () -> ()
|
|
|
|
|
|
|
|
// CHECK: "foo3"() {bar = dense<{{\[\[\[}}5, -6, 1, 2]], {{\[\[}}7, 8, 3, 4]]]> : vector<2x1x4xi32>} : () -> ()
|
|
|
|
"foo3"(){bar = dense<[[[5, -6, 1, 2]], [[7, 8, 3, 4]]]> : vector<2x1x4xi32>} : () -> ()
|
|
|
|
|
|
|
|
// CHECK: "float1"() {bar = dense<5.000000e+00> : vector<1x1x1xf32>} : () -> ()
|
|
|
|
"float1"(){bar = dense<[[[5.0]]]> : vector<1x1x1xf32>} : () -> ()
|
|
|
|
|
|
|
|
// CHECK: "bfloat16"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : vector<2x1x4xbf16>} : () -> ()
|
|
|
|
"bfloat16"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : vector<2x1x4xbf16>} : () -> ()
|
|
|
|
// CHECK: "float16"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : vector<2x1x4xf16>} : () -> ()
|
|
|
|
"float16"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : vector<2x1x4xf16>} : () -> ()
|
|
|
|
// CHECK: "float32"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : vector<2x1x4xf32>} : () -> ()
|
|
|
|
"float32"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : vector<2x1x4xf32>} : () -> ()
|
|
|
|
// CHECK: "float64"() {bar = dense<{{\[\[\[}}-5.000000e+00, 6.000000e+00, 1.000000e+00, 2.000000e+00]], {{\[\[}}7.000000e+00, -8.000000e+00, 3.000000e+00, 4.000000e+00]]]> : vector<2x1x4xf64>} : () -> ()
|
|
|
|
"float64"(){bar = dense<[[[-5.0, 6.0, 1.0, 2.0]], [[7.0, -8.0, 3.0, 4.0]]]> : vector<2x1x4xf64>} : () -> ()
|
2018-10-19 04:54:44 +08:00
|
|
|
return
|
Add support to constant sparse tensor / vector attribute
The SparseElementsAttr uses (COO) Coordinate List encoding to represents a
sparse tensor / vector. Specifically, the coordinates and values are stored as
two dense elements attributes. The first dense elements attribute is a 2-D
attribute with shape [N, ndims], which contains the indices of the elements
with nonzero values in the constant vector/tensor. The second elements
attribute is a 1-D attribute list with shape [N], which supplies the values for
each element in the first elements attribute. ndims is the rank of the
vector/tensor and N is the total nonzero elements.
The syntax is:
`sparse<` (tensor-type | vector-type)`, ` indices-attribute-list, values-attribute-list `>`
Example: a sparse tensor
sparse<vector<3x4xi32>, [[0, 0], [1, 2]], [1, 2]> represents the dense tensor
[[1, 0, 0, 0]
[0, 0, 2, 0]
[0, 0, 0, 0]]
PiperOrigin-RevId: 217764319
2018-10-19 05:02:20 +08:00
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @sparsetensorattr
|
|
|
|
func @sparsetensorattr() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
Add support to constant sparse tensor / vector attribute
The SparseElementsAttr uses (COO) Coordinate List encoding to represents a
sparse tensor / vector. Specifically, the coordinates and values are stored as
two dense elements attributes. The first dense elements attribute is a 2-D
attribute with shape [N, ndims], which contains the indices of the elements
with nonzero values in the constant vector/tensor. The second elements
attribute is a 1-D attribute list with shape [N], which supplies the values for
each element in the first elements attribute. ndims is the rank of the
vector/tensor and N is the total nonzero elements.
The syntax is:
`sparse<` (tensor-type | vector-type)`, ` indices-attribute-list, values-attribute-list `>`
Example: a sparse tensor
sparse<vector<3x4xi32>, [[0, 0], [1, 2]], [1, 2]> represents the dense tensor
[[1, 0, 0, 0]
[0, 0, 2, 0]
[0, 0, 0, 0]]
PiperOrigin-RevId: 217764319
2018-10-19 05:02:20 +08:00
|
|
|
// NOTE: The {{\[\[}} syntax is because "[[" confuses FileCheck.
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "fooi8"() {bar = sparse<0, -2> : tensor<1x1x1xi8>} : () -> ()
|
|
|
|
"fooi8"(){bar = sparse<0, -2> : tensor<1x1x1xi8>} : () -> ()
|
|
|
|
// CHECK: "fooi16"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}2, -1, 5]> : tensor<2x2x2xi16>} : () -> ()
|
|
|
|
"fooi16"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], [2, -1, 5]> : tensor<2x2x2xi16>} : () -> ()
|
2020-07-09 08:44:27 +08:00
|
|
|
// CHECK: "fooi32"() {bar = sparse<> : tensor<1x1xi32>} : () -> ()
|
|
|
|
"fooi32"(){bar = sparse<> : tensor<1x1xi32>} : () -> ()
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "fooi64"() {bar = sparse<0, -1> : tensor<1xi64>} : () -> ()
|
2021-09-21 09:40:04 +08:00
|
|
|
"fooi64"(){bar = sparse<[0], [-1]> : tensor<1xi64>} : () -> ()
|
2020-07-09 08:44:27 +08:00
|
|
|
// CHECK: "foo2"() {bar = sparse<> : tensor<0xi32>} : () -> ()
|
|
|
|
"foo2"(){bar = sparse<> : tensor<0xi32>} : () -> ()
|
|
|
|
// CHECK: "foo3"() {bar = sparse<> : tensor<i32>} : () -> ()
|
|
|
|
"foo3"(){bar = sparse<> : tensor<i32>} : () -> ()
|
2019-06-26 10:06:06 +08:00
|
|
|
|
|
|
|
// CHECK: "foof16"() {bar = sparse<0, -2.000000e+00> : tensor<1x1x1xf16>} : () -> ()
|
|
|
|
"foof16"(){bar = sparse<0, -2.0> : tensor<1x1x1xf16>} : () -> ()
|
|
|
|
// CHECK: "foobf16"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}2.000000e+00, -1.000000e+00, 5.000000e+00]> : tensor<2x2x2xbf16>} : () -> ()
|
|
|
|
"foobf16"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], [2.0, -1.0, 5.0]> : tensor<2x2x2xbf16>} : () -> ()
|
2020-07-09 08:44:27 +08:00
|
|
|
// CHECK: "foof32"() {bar = sparse<> : tensor<1x0x1xf32>} : () -> ()
|
|
|
|
"foof32"(){bar = sparse<> : tensor<1x0x1xf32>} : () -> ()
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foof64"() {bar = sparse<0, -1.000000e+00> : tensor<1xf64>} : () -> ()
|
|
|
|
"foof64"(){bar = sparse<[[0]], [-1.0]> : tensor<1xf64>} : () -> ()
|
2020-07-09 08:44:27 +08:00
|
|
|
// CHECK: "foof320"() {bar = sparse<> : tensor<0xf32>} : () -> ()
|
|
|
|
"foof320"(){bar = sparse<> : tensor<0xf32>} : () -> ()
|
|
|
|
// CHECK: "foof321"() {bar = sparse<> : tensor<f32>} : () -> ()
|
|
|
|
"foof321"(){bar = sparse<> : tensor<f32>} : () -> ()
|
2020-04-25 16:17:09 +08:00
|
|
|
|
|
|
|
// CHECK: "foostr"() {bar = sparse<0, "foo"> : tensor<1x1x1x!unknown<"">>} : () -> ()
|
|
|
|
"foostr"(){bar = sparse<0, "foo"> : tensor<1x1x1x!unknown<"">>} : () -> ()
|
|
|
|
// CHECK: "foostr"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}"a", "b", "c"]> : tensor<2x2x2x!unknown<"">>} : () -> ()
|
|
|
|
"foostr"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], ["a", "b", "c"]> : tensor<2x2x2x!unknown<"">>} : () -> ()
|
Add support to constant sparse tensor / vector attribute
The SparseElementsAttr uses (COO) Coordinate List encoding to represents a
sparse tensor / vector. Specifically, the coordinates and values are stored as
two dense elements attributes. The first dense elements attribute is a 2-D
attribute with shape [N, ndims], which contains the indices of the elements
with nonzero values in the constant vector/tensor. The second elements
attribute is a 1-D attribute list with shape [N], which supplies the values for
each element in the first elements attribute. ndims is the rank of the
vector/tensor and N is the total nonzero elements.
The syntax is:
`sparse<` (tensor-type | vector-type)`, ` indices-attribute-list, values-attribute-list `>`
Example: a sparse tensor
sparse<vector<3x4xi32>, [[0, 0], [1, 2]], [1, 2]> represents the dense tensor
[[1, 0, 0, 0]
[0, 0, 2, 0]
[0, 0, 0, 0]]
PiperOrigin-RevId: 217764319
2018-10-19 05:02:20 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-01-03 02:20:00 +08:00
|
|
|
// CHECK-LABEL: func @sparsevectorattr
|
|
|
|
func @sparsevectorattr() -> () {
|
2018-12-30 03:32:37 +08:00
|
|
|
^bb0:
|
Add support to constant sparse tensor / vector attribute
The SparseElementsAttr uses (COO) Coordinate List encoding to represents a
sparse tensor / vector. Specifically, the coordinates and values are stored as
two dense elements attributes. The first dense elements attribute is a 2-D
attribute with shape [N, ndims], which contains the indices of the elements
with nonzero values in the constant vector/tensor. The second elements
attribute is a 1-D attribute list with shape [N], which supplies the values for
each element in the first elements attribute. ndims is the rank of the
vector/tensor and N is the total nonzero elements.
The syntax is:
`sparse<` (tensor-type | vector-type)`, ` indices-attribute-list, values-attribute-list `>`
Example: a sparse tensor
sparse<vector<3x4xi32>, [[0, 0], [1, 2]], [1, 2]> represents the dense tensor
[[1, 0, 0, 0]
[0, 0, 2, 0]
[0, 0, 0, 0]]
PiperOrigin-RevId: 217764319
2018-10-19 05:02:20 +08:00
|
|
|
// NOTE: The {{\[\[}} syntax is because "[[" confuses FileCheck.
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "fooi8"() {bar = sparse<0, -2> : vector<1x1x1xi8>} : () -> ()
|
|
|
|
"fooi8"(){bar = sparse<0, -2> : vector<1x1x1xi8>} : () -> ()
|
|
|
|
// CHECK: "fooi16"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}2, -1, 5]> : vector<2x2x2xi16>} : () -> ()
|
|
|
|
"fooi16"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], [2, -1, 5]> : vector<2x2x2xi16>} : () -> ()
|
2020-07-09 08:44:27 +08:00
|
|
|
// CHECK: "fooi32"() {bar = sparse<> : vector<1x1xi32>} : () -> ()
|
|
|
|
"fooi32"(){bar = sparse<> : vector<1x1xi32>} : () -> ()
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "fooi64"() {bar = sparse<0, -1> : vector<1xi64>} : () -> ()
|
|
|
|
"fooi64"(){bar = sparse<[[0]], [-1]> : vector<1xi64>} : () -> ()
|
|
|
|
|
|
|
|
// CHECK: "foof16"() {bar = sparse<0, -2.000000e+00> : vector<1x1x1xf16>} : () -> ()
|
|
|
|
"foof16"(){bar = sparse<0, -2.0> : vector<1x1x1xf16>} : () -> ()
|
|
|
|
// CHECK: "foobf16"() {bar = sparse<{{\[\[}}1, 1, 0], {{\[}}0, 1, 0], {{\[}}0, 0, 1]], {{\[}}2.000000e+00, -1.000000e+00, 5.000000e+00]> : vector<2x2x2xbf16>} : () -> ()
|
|
|
|
"foobf16"(){bar = sparse<[[1, 1, 0], [0, 1, 0], [0, 0, 1]], [2.0, -1.0, 5.0]> : vector<2x2x2xbf16>} : () -> ()
|
|
|
|
// CHECK: "foof64"() {bar = sparse<0, -1.000000e+00> : vector<1xf64>} : () -> ()
|
|
|
|
"foof64"(){bar = sparse<0, [-1.0]> : vector<1xf64>} : () -> ()
|
Add support to constant sparse tensor / vector attribute
The SparseElementsAttr uses (COO) Coordinate List encoding to represents a
sparse tensor / vector. Specifically, the coordinates and values are stored as
two dense elements attributes. The first dense elements attribute is a 2-D
attribute with shape [N, ndims], which contains the indices of the elements
with nonzero values in the constant vector/tensor. The second elements
attribute is a 1-D attribute list with shape [N], which supplies the values for
each element in the first elements attribute. ndims is the rank of the
vector/tensor and N is the total nonzero elements.
The syntax is:
`sparse<` (tensor-type | vector-type)`, ` indices-attribute-list, values-attribute-list `>`
Example: a sparse tensor
sparse<vector<3x4xi32>, [[0, 0], [1, 2]], [1, 2]> represents the dense tensor
[[1, 0, 0, 0]
[0, 0, 2, 0]
[0, 0, 0, 0]]
PiperOrigin-RevId: 217764319
2018-10-19 05:02:20 +08:00
|
|
|
return
|
2018-10-26 09:33:42 +08:00
|
|
|
}
|
2018-12-30 05:36:59 +08:00
|
|
|
|
2019-01-08 01:58:34 +08:00
|
|
|
// CHECK-LABEL: func @unknown_dialect_type() -> !bar<""> {
|
|
|
|
func @unknown_dialect_type() -> !bar<""> {
|
|
|
|
// Unregistered dialect 'bar'.
|
|
|
|
// CHECK: "foo"() : () -> !bar<"">
|
|
|
|
%0 = "foo"() : () -> !bar<"">
|
|
|
|
|
2019-04-06 14:56:49 +08:00
|
|
|
// CHECK: "foo"() : () -> !bar.baz
|
2019-01-08 01:58:34 +08:00
|
|
|
%1 = "foo"() : () -> !bar<"baz">
|
|
|
|
|
|
|
|
return %0 : !bar<"">
|
|
|
|
}
|
2018-12-30 05:36:59 +08:00
|
|
|
|
2019-01-08 10:42:04 +08:00
|
|
|
// CHECK-LABEL: func @type_alias() -> i32 {
|
|
|
|
!i32_type_alias = type i32
|
|
|
|
func @type_alias() -> !i32_type_alias {
|
|
|
|
|
|
|
|
// Return a non-aliased i32 type.
|
|
|
|
%0 = "foo"() : () -> i32
|
|
|
|
return %0 : i32
|
|
|
|
}
|
2019-01-26 04:48:25 +08:00
|
|
|
|
2019-02-03 13:01:11 +08:00
|
|
|
// CHECK-LABEL: func @no_integer_set_constraints(
|
|
|
|
func @no_integer_set_constraints() {
|
2020-06-12 08:34:35 +08:00
|
|
|
// CHECK: affine.if [[$SET_TRUE]]() {
|
2020-01-14 05:12:37 +08:00
|
|
|
affine.if affine_set<() : ()> () {
|
2019-02-03 13:01:11 +08:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-01-26 04:48:25 +08:00
|
|
|
// CHECK-LABEL: func @verbose_if(
|
|
|
|
func @verbose_if(%N: index) {
|
2021-10-13 07:14:57 +08:00
|
|
|
%c = arith.constant 200 : index
|
2019-01-26 04:48:25 +08:00
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: affine.if #set{{.*}}(%{{.*}})[%{{.*}}, %{{.*}}] {
|
2019-05-06 16:40:13 +08:00
|
|
|
"affine.if"(%c, %N, %c) ({
|
2019-01-26 04:48:25 +08:00
|
|
|
// CHECK-NEXT: "add"
|
|
|
|
%y = "add"(%c, %N) : (index, index) -> index
|
2020-07-10 03:02:20 +08:00
|
|
|
"affine.yield"() : () -> ()
|
2019-01-29 13:23:53 +08:00
|
|
|
// CHECK-NEXT: } else {
|
2019-05-06 16:40:13 +08:00
|
|
|
}, { // The else region.
|
2019-01-26 04:48:25 +08:00
|
|
|
// CHECK-NEXT: "add"
|
|
|
|
%z = "add"(%c, %c) : (index, index) -> index
|
2020-07-10 03:02:20 +08:00
|
|
|
"affine.yield"() : () -> ()
|
2019-05-06 16:40:13 +08:00
|
|
|
})
|
2019-06-26 10:06:06 +08:00
|
|
|
{ condition = #set0 } : (index, index, index) -> ()
|
2019-05-06 16:40:13 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: func @terminator_with_regions
|
|
|
|
func @terminator_with_regions() {
|
|
|
|
// Combine successors and regions in the same operation.
|
2022-01-18 15:47:25 +08:00
|
|
|
// CHECK: "region"()[^bb1] ({
|
2019-05-06 16:40:13 +08:00
|
|
|
// CHECK: }) : () -> ()
|
|
|
|
"region"()[^bb2] ({}) : () -> ()
|
|
|
|
^bb2:
|
2019-01-26 04:48:25 +08:00
|
|
|
return
|
|
|
|
}
|
2019-02-09 01:52:26 +08:00
|
|
|
|
|
|
|
// CHECK-LABEL: func @unregistered_term
|
|
|
|
func @unregistered_term(%arg0 : i1) -> i1 {
|
2020-03-06 04:48:28 +08:00
|
|
|
// CHECK-NEXT: "unregistered_br"(%{{.*}})[^bb1] : (i1) -> ()
|
|
|
|
"unregistered_br"(%arg0)[^bb1] : (i1) -> ()
|
2019-02-09 01:52:26 +08:00
|
|
|
|
|
|
|
^bb1(%arg1 : i1):
|
|
|
|
return %arg1 : i1
|
|
|
|
}
|
2019-02-27 04:52:51 +08:00
|
|
|
|
2019-03-03 14:34:18 +08:00
|
|
|
// CHECK-LABEL: func @dialect_attrs
|
|
|
|
func @dialect_attrs()
|
2019-11-21 20:24:52 +08:00
|
|
|
// CHECK: attributes {dialect.attr = 10
|
2019-06-26 10:06:06 +08:00
|
|
|
attributes {dialect.attr = 10} {
|
2019-02-27 04:52:51 +08:00
|
|
|
return
|
|
|
|
}
|
2019-02-27 09:11:24 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @_valid.function$name
|
|
|
|
func private @_valid.function$name()
|
2019-03-01 01:30:52 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @external_func_arg_attrs(i32, i1 {dialect.attr = 10 : i64}, i32)
|
|
|
|
func private @external_func_arg_attrs(i32, i1 {dialect.attr = 10 : i64}, i32)
|
2019-03-01 01:30:52 +08:00
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK-LABEL: func @func_arg_attrs(%{{.*}}: i1 {dialect.attr = 10 : i64})
|
2019-06-26 10:06:06 +08:00
|
|
|
func @func_arg_attrs(%arg0: i1 {dialect.attr = 10 : i64}) {
|
2019-03-01 01:30:52 +08:00
|
|
|
return
|
|
|
|
}
|
2019-03-20 01:59:02 +08:00
|
|
|
|
2019-10-19 07:02:56 +08:00
|
|
|
// CHECK-LABEL: func @func_result_attrs({{.*}}) -> (f32 {dialect.attr = 1 : i64})
|
|
|
|
func @func_result_attrs(%arg0: f32) -> (f32 {dialect.attr = 1}) {
|
|
|
|
return %arg0 : f32
|
|
|
|
}
|
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @empty_tuple(tuple<>)
|
|
|
|
func private @empty_tuple(tuple<>)
|
2019-03-20 01:59:02 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @tuple_single_element(tuple<i32>)
|
|
|
|
func private @tuple_single_element(tuple<i32>)
|
2019-03-20 01:59:02 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @tuple_multi_element(tuple<i32, i16, f32>)
|
|
|
|
func private @tuple_multi_element(tuple<i32, i16, f32>)
|
2019-03-20 01:59:02 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @tuple_nested(tuple<tuple<tuple<i32>>>)
|
|
|
|
func private @tuple_nested(tuple<tuple<tuple<i32>>>)
|
2019-03-29 05:58:52 +08:00
|
|
|
|
|
|
|
// CHECK-LABEL: func @pretty_form_multi_result
|
|
|
|
func @pretty_form_multi_result() -> (i16, i16) {
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}}:2 = "foo_div"() : () -> (i16, i16)
|
2019-03-29 05:58:52 +08:00
|
|
|
%quot, %rem = "foo_div"() : () -> (i16, i16)
|
|
|
|
return %quot, %rem : i16, i16
|
|
|
|
}
|
2019-04-06 10:36:42 +08:00
|
|
|
|
2019-10-26 00:33:32 +08:00
|
|
|
// CHECK-LABEL: func @pretty_form_multi_result_groups
|
|
|
|
func @pretty_form_multi_result_groups() -> (i16, i16, i16, i16, i16) {
|
|
|
|
// CHECK: %[[RES:.*]]:5 =
|
|
|
|
// CHECK: return %[[RES]]#0, %[[RES]]#1, %[[RES]]#2, %[[RES]]#3, %[[RES]]#4
|
|
|
|
%group_1:2, %group_2, %group_3:2 = "foo_test"() : () -> (i16, i16, i16, i16, i16)
|
|
|
|
return %group_1#0, %group_1#1, %group_2, %group_3#0, %group_3#1 : i16, i16, i16, i16, i16
|
|
|
|
}
|
|
|
|
|
2019-05-16 00:10:52 +08:00
|
|
|
// CHECK-LABEL: func @pretty_dialect_attribute()
|
|
|
|
func @pretty_dialect_attribute() {
|
2019-10-18 03:23:47 +08:00
|
|
|
// CHECK: "foo.unknown_op"() {foo = #foo.simple_attr} : () -> ()
|
|
|
|
"foo.unknown_op"() {foo = #foo.simple_attr} : () -> ()
|
2019-05-16 00:10:52 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo.unknown_op"() {foo = #foo.complexattr<abcd>} : () -> ()
|
|
|
|
"foo.unknown_op"() {foo = #foo.complexattr<abcd>} : () -> ()
|
2019-05-16 00:10:52 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo.unknown_op"() {foo = #foo.complexattr<abcd<f32>>} : () -> ()
|
|
|
|
"foo.unknown_op"() {foo = #foo.complexattr<abcd<f32>>} : () -> ()
|
2019-05-16 00:10:52 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo.unknown_op"() {foo = #foo.complexattr<abcd<[f]$$[32]>>} : () -> ()
|
|
|
|
"foo.unknown_op"() {foo = #foo.complexattr<abcd<[f]$$[32]>>} : () -> ()
|
2019-05-16 00:10:52 +08:00
|
|
|
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo.unknown_op"() {foo = #foo.dialect<!x@#!@#>} : () -> ()
|
|
|
|
"foo.unknown_op"() {foo = #foo.dialect<!x@#!@#>} : () -> ()
|
2019-05-16 00:10:52 +08:00
|
|
|
|
|
|
|
// Extraneous extra > character can't use the pretty syntax.
|
2019-06-26 10:06:06 +08:00
|
|
|
// CHECK: "foo.unknown_op"() {foo = #foo<"dialect<!x@#!@#>>">} : () -> ()
|
|
|
|
"foo.unknown_op"() {foo = #foo<"dialect<!x@#!@#>>">} : () -> ()
|
2019-05-16 00:10:52 +08:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-04-06 10:36:42 +08:00
|
|
|
// CHECK-LABEL: func @pretty_dialect_type()
|
|
|
|
func @pretty_dialect_type() {
|
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo.simpletype
|
2019-04-06 10:36:42 +08:00
|
|
|
%0 = "foo.unknown_op"() : () -> !foo.simpletype
|
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo.complextype<abcd>
|
2019-04-06 10:36:42 +08:00
|
|
|
%1 = "foo.unknown_op"() : () -> !foo.complextype<abcd>
|
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo.complextype<abcd<f32>>
|
2019-04-06 10:36:42 +08:00
|
|
|
%2 = "foo.unknown_op"() : () -> !foo.complextype<abcd<f32>>
|
2019-04-15 04:41:09 +08:00
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo.complextype<abcd<[f]$$[32]>>
|
2019-04-15 04:41:09 +08:00
|
|
|
%3 = "foo.unknown_op"() : () -> !foo.complextype<abcd<[f]$$[32]>>
|
|
|
|
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo.dialect<!x@#!@#>
|
2019-04-15 04:41:09 +08:00
|
|
|
%4 = "foo.unknown_op"() : () -> !foo.dialect<!x@#!@#>
|
|
|
|
|
|
|
|
// Extraneous extra > character can't use the pretty syntax.
|
2019-07-10 01:40:29 +08:00
|
|
|
// CHECK: %{{.*}} = "foo.unknown_op"() : () -> !foo<"dialect<!x@#!@#>>">
|
2019-04-15 04:41:09 +08:00
|
|
|
%5 = "foo.unknown_op"() : () -> !foo<"dialect<!x@#!@#>>">
|
|
|
|
|
2019-04-06 10:36:42 +08:00
|
|
|
return
|
|
|
|
}
|
2019-04-28 09:35:04 +08:00
|
|
|
|
|
|
|
// CHECK-LABEL: func @none_type
|
|
|
|
func @none_type() {
|
|
|
|
// CHECK: "foo.unknown_op"() : () -> none
|
|
|
|
%none_val = "foo.unknown_op"() : () -> none
|
|
|
|
return
|
|
|
|
}
|
2019-06-04 00:43:22 +08:00
|
|
|
|
|
|
|
// CHECK-LABEL: func @scoped_names
|
|
|
|
func @scoped_names() {
|
|
|
|
// CHECK-NEXT: "foo.region_op"
|
|
|
|
"foo.region_op"() ({
|
|
|
|
// CHECK-NEXT: "foo.unknown_op"
|
|
|
|
%scoped_name = "foo.unknown_op"() : () -> none
|
|
|
|
"foo.terminator"() : () -> ()
|
|
|
|
}, {
|
|
|
|
// CHECK: "foo.unknown_op"
|
|
|
|
%scoped_name = "foo.unknown_op"() : () -> none
|
|
|
|
"foo.terminator"() : () -> ()
|
|
|
|
}) : () -> ()
|
|
|
|
return
|
|
|
|
}
|
2019-06-22 09:27:49 +08:00
|
|
|
|
2019-07-18 07:05:32 +08:00
|
|
|
// CHECK-LABEL: func @dialect_attribute_with_type
|
|
|
|
func @dialect_attribute_with_type() {
|
|
|
|
// CHECK-NEXT: foo = #foo.attr : i32
|
|
|
|
"foo.unknown_op"() {foo = #foo.attr : i32} : () -> ()
|
|
|
|
}
|
2019-07-31 05:05:49 +08:00
|
|
|
|
|
|
|
// CHECK-LABEL: @f16_special_values
|
|
|
|
func @f16_special_values() {
|
|
|
|
// F16 NaNs.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0x7C01 : f16
|
|
|
|
%0 = arith.constant 0x7C01 : f16
|
|
|
|
// CHECK: arith.constant 0x7FFF : f16
|
|
|
|
%1 = arith.constant 0x7FFF : f16
|
|
|
|
// CHECK: arith.constant 0xFFFF : f16
|
|
|
|
%2 = arith.constant 0xFFFF : f16
|
2019-07-31 05:05:49 +08:00
|
|
|
|
|
|
|
// F16 positive infinity.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0x7C00 : f16
|
|
|
|
%3 = arith.constant 0x7C00 : f16
|
2019-10-21 00:44:06 +08:00
|
|
|
// F16 negative infinity.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0xFC00 : f16
|
|
|
|
%4 = arith.constant 0xFC00 : f16
|
2019-07-31 05:05:49 +08:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: @f32_special_values
|
|
|
|
func @f32_special_values() {
|
|
|
|
// F32 signaling NaNs.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0x7F800001 : f32
|
|
|
|
%0 = arith.constant 0x7F800001 : f32
|
|
|
|
// CHECK: arith.constant 0x7FBFFFFF : f32
|
|
|
|
%1 = arith.constant 0x7FBFFFFF : f32
|
2019-07-31 05:05:49 +08:00
|
|
|
|
|
|
|
// F32 quiet NaNs.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0x7FC00000 : f32
|
|
|
|
%2 = arith.constant 0x7FC00000 : f32
|
|
|
|
// CHECK: arith.constant 0xFFFFFFFF : f32
|
|
|
|
%3 = arith.constant 0xFFFFFFFF : f32
|
2019-07-31 05:05:49 +08:00
|
|
|
|
|
|
|
// F32 positive infinity.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0x7F800000 : f32
|
|
|
|
%4 = arith.constant 0x7F800000 : f32
|
2019-07-31 05:05:49 +08:00
|
|
|
// F32 negative infinity.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0xFF800000 : f32
|
|
|
|
%5 = arith.constant 0xFF800000 : f32
|
2019-07-31 05:05:49 +08:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: @f64_special_values
|
|
|
|
func @f64_special_values() {
|
|
|
|
// F64 signaling NaNs.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0x7FF0000000000001 : f64
|
|
|
|
%0 = arith.constant 0x7FF0000000000001 : f64
|
|
|
|
// CHECK: arith.constant 0x7FF8000000000000 : f64
|
|
|
|
%1 = arith.constant 0x7FF8000000000000 : f64
|
2019-07-31 05:05:49 +08:00
|
|
|
|
|
|
|
// F64 quiet NaNs.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0x7FF0000001000000 : f64
|
|
|
|
%2 = arith.constant 0x7FF0000001000000 : f64
|
|
|
|
// CHECK: arith.constant 0xFFF0000001000000 : f64
|
|
|
|
%3 = arith.constant 0xFFF0000001000000 : f64
|
2019-07-31 05:05:49 +08:00
|
|
|
|
2019-10-21 00:44:06 +08:00
|
|
|
// F64 positive infinity.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0x7FF0000000000000 : f64
|
|
|
|
%4 = arith.constant 0x7FF0000000000000 : f64
|
2019-07-31 05:05:49 +08:00
|
|
|
// F64 negative infinity.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0xFFF0000000000000 : f64
|
|
|
|
%5 = arith.constant 0xFFF0000000000000 : f64
|
2019-07-31 05:05:49 +08:00
|
|
|
|
2020-02-07 10:05:32 +08:00
|
|
|
// Check that values that can't be represented with the default format, use
|
|
|
|
// hex instead.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0xC1CDC00000000000 : f64
|
|
|
|
%6 = arith.constant 0xC1CDC00000000000 : f64
|
2020-02-07 10:05:32 +08:00
|
|
|
|
2019-07-31 05:05:49 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-01-15 05:47:21 +08:00
|
|
|
// CHECK-LABEL: @bfloat16_special_values
|
|
|
|
func @bfloat16_special_values() {
|
|
|
|
// bfloat16 signaling NaNs.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0x7F81 : bf16
|
|
|
|
%0 = arith.constant 0x7F81 : bf16
|
|
|
|
// CHECK: arith.constant 0xFF81 : bf16
|
|
|
|
%1 = arith.constant 0xFF81 : bf16
|
2020-01-15 05:47:21 +08:00
|
|
|
|
|
|
|
// bfloat16 quiet NaNs.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0x7FC0 : bf16
|
|
|
|
%2 = arith.constant 0x7FC0 : bf16
|
|
|
|
// CHECK: arith.constant 0xFFC0 : bf16
|
|
|
|
%3 = arith.constant 0xFFC0 : bf16
|
2020-01-15 05:47:21 +08:00
|
|
|
|
|
|
|
// bfloat16 positive infinity.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0x7F80 : bf16
|
|
|
|
%4 = arith.constant 0x7F80 : bf16
|
2020-01-15 05:47:21 +08:00
|
|
|
// bfloat16 negative infinity.
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant 0xFF80 : bf16
|
|
|
|
%5 = arith.constant 0xFF80 : bf16
|
2020-01-15 05:47:21 +08:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-07-31 05:05:49 +08:00
|
|
|
// We want to print floats in exponential notation with 6 significant digits,
|
|
|
|
// but it may lead to precision loss when parsing back, in which case we print
|
|
|
|
// the decimal form instead.
|
|
|
|
// CHECK-LABEL: @f32_potential_precision_loss()
|
|
|
|
func @f32_potential_precision_loss() {
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: arith.constant -1.23697901 : f32
|
|
|
|
%0 = arith.constant -1.23697901 : f32
|
2019-07-31 05:05:49 +08:00
|
|
|
return
|
|
|
|
}
|
2019-07-31 05:24:30 +08:00
|
|
|
|
|
|
|
// CHECK-LABEL: @special_float_values_in_tensors
|
|
|
|
func @special_float_values_in_tensors() {
|
|
|
|
// CHECK: dense<0xFFFFFFFF> : tensor<4x4xf32>
|
|
|
|
"foo"(){bar = dense<0xFFFFFFFF> : tensor<4x4xf32>} : () -> ()
|
|
|
|
// CHECK: dense<[{{\[}}0xFFFFFFFF, 0x7F800000], [0x7FBFFFFF, 0x7F800001]]> : tensor<2x2xf32>
|
|
|
|
"foo"(){bar = dense<[[0xFFFFFFFF, 0x7F800000], [0x7FBFFFFF, 0x7F800001]]> : tensor<2x2xf32>} : () -> ()
|
|
|
|
// CHECK: dense<[0xFFFFFFFF, 0.000000e+00]> : tensor<2xf32>
|
|
|
|
"foo"(){bar = dense<[0xFFFFFFFF, 0.0]> : tensor<2xf32>} : () -> ()
|
|
|
|
|
|
|
|
// CHECK: sparse<[{{\[}}1, 1, 0], [0, 1, 1]], [0xFFFFFFFF, 0x7F800001]>
|
|
|
|
"foo"(){bar = sparse<[[1,1,0],[0,1,1]], [0xFFFFFFFF, 0x7F800001]> : tensor<2x2x2xf32>} : () -> ()
|
|
|
|
}
|
2019-08-20 06:26:43 +08:00
|
|
|
|
|
|
|
// Test parsing of an op with multiple region arguments, and without a
|
|
|
|
// delimiter.
|
|
|
|
|
|
|
|
// CHECK-LABEL: func @op_with_region_args
|
|
|
|
func @op_with_region_args() {
|
2022-01-18 15:47:25 +08:00
|
|
|
// CHECK: "test.polyfor"() ({
|
2019-08-20 06:26:43 +08:00
|
|
|
// CHECK-NEXT: ^bb{{.*}}(%{{.*}}: index, %{{.*}}: index, %{{.*}}: index):
|
|
|
|
test.polyfor %i, %j, %k {
|
|
|
|
"foo"() : () -> ()
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test allowing different name scopes for regions isolated from above.
|
|
|
|
|
|
|
|
// CHECK-LABEL: func @op_with_passthrough_region_args
|
|
|
|
func @op_with_passthrough_region_args() {
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: [[VAL:%.*]] = arith.constant
|
|
|
|
%0 = arith.constant 10 : index
|
2019-08-24 01:35:24 +08:00
|
|
|
|
|
|
|
// CHECK: test.isolated_region [[VAL]] {
|
|
|
|
// CHECK-NEXT: "foo.consumer"([[VAL]]) : (index)
|
|
|
|
// CHECK-NEXT: }
|
2019-08-20 06:26:43 +08:00
|
|
|
test.isolated_region %0 {
|
|
|
|
"foo.consumer"(%0) : (index) -> ()
|
|
|
|
}
|
2019-08-24 01:35:24 +08:00
|
|
|
|
|
|
|
// CHECK: [[VAL:%.*]]:2 = "foo.op"
|
|
|
|
%result:2 = "foo.op"() : () -> (index, index)
|
|
|
|
|
|
|
|
// CHECK: test.isolated_region [[VAL]]#1 {
|
|
|
|
// CHECK-NEXT: "foo.consumer"([[VAL]]#1) : (index)
|
|
|
|
// CHECK-NEXT: }
|
|
|
|
test.isolated_region %result#1 {
|
|
|
|
"foo.consumer"(%result#1) : (index) -> ()
|
|
|
|
}
|
|
|
|
|
2019-08-20 06:26:43 +08:00
|
|
|
return
|
|
|
|
}
|
2019-08-24 01:35:24 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @ptr_to_function() -> !unreg.ptr<() -> ()>
|
|
|
|
func private @ptr_to_function() -> !unreg.ptr<() -> ()>
|
2019-09-04 02:27:00 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @escaped_string_char(i1 {foo.value = "\0A"})
|
|
|
|
func private @escaped_string_char(i1 {foo.value = "\n"})
|
2019-09-18 08:54:54 +08:00
|
|
|
|
2020-12-15 03:53:43 +08:00
|
|
|
// CHECK-LABEL: func @parse_integer_literal_test
|
|
|
|
func @parse_integer_literal_test() {
|
|
|
|
// CHECK: test.parse_integer_literal : 5
|
|
|
|
test.parse_integer_literal : 5
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: func @parse_wrapped_keyword_test
|
|
|
|
func @parse_wrapped_keyword_test() {
|
|
|
|
// CHECK: test.parse_wrapped_keyword foo.keyword
|
|
|
|
test.parse_wrapped_keyword foo.keyword
|
2019-09-18 08:54:54 +08:00
|
|
|
return
|
|
|
|
}
|
2019-10-09 08:44:39 +08:00
|
|
|
|
|
|
|
// CHECK-LABEL: func @"\22_string_symbol_reference\22"
|
|
|
|
func @"\"_string_symbol_reference\""() {
|
|
|
|
// CHECK: ref = @"\22_string_symbol_reference\22"
|
|
|
|
"foo.symbol_reference"() {ref = @"\"_string_symbol_reference\""} : () -> ()
|
|
|
|
return
|
|
|
|
}
|
2019-11-12 10:18:02 +08:00
|
|
|
|
2021-07-05 18:13:36 +08:00
|
|
|
// CHECK-LABEL: func private @parse_opaque_attr_escape
|
|
|
|
func private @parse_opaque_attr_escape() {
|
|
|
|
// CHECK: value = #foo<"\22escaped\\\0A\22">
|
|
|
|
"foo.constant"() {value = #foo<"\"escaped\\\n\"">} : () -> ()
|
|
|
|
}
|
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @string_attr_name
|
2020-03-12 04:22:19 +08:00
|
|
|
// CHECK-SAME: {"0 . 0", nested = {"0 . 0"}}
|
2020-11-14 05:04:53 +08:00
|
|
|
func private @string_attr_name() attributes {"0 . 0", nested = {"0 . 0"}}
|
2020-03-12 04:22:19 +08:00
|
|
|
|
2020-11-14 05:04:53 +08:00
|
|
|
// CHECK-LABEL: func private @nested_reference
|
2019-11-21 20:24:52 +08:00
|
|
|
// CHECK: ref = @some_symbol::@some_nested_symbol
|
2020-11-14 05:04:53 +08:00
|
|
|
func private @nested_reference() attributes {test.ref = @some_symbol::@some_nested_symbol }
|
2019-11-21 02:19:01 +08:00
|
|
|
|
|
|
|
// CHECK-LABEL: func @custom_asm_names
|
2022-01-21 13:45:48 +08:00
|
|
|
func @custom_asm_names() -> (i32, i32, i32, i32, i32, i32) {
|
2019-11-21 02:19:01 +08:00
|
|
|
// CHECK: %[[FIRST:first.*]], %[[MIDDLE:middle_results.*]]:2, %[[LAST:[0-9]+]]
|
|
|
|
%0, %1:2, %2 = "test.asm_interface_op"() : () -> (i32, i32, i32, i32)
|
|
|
|
|
|
|
|
// CHECK: %[[FIRST_2:first.*]], %[[LAST_2:[0-9]+]]
|
|
|
|
%3, %4 = "test.asm_interface_op"() : () -> (i32, i32)
|
|
|
|
|
|
|
|
// CHECK: return %[[FIRST]], %[[MIDDLE]]#0, %[[MIDDLE]]#1, %[[LAST]], %[[FIRST_2]], %[[LAST_2]]
|
2022-01-21 13:45:48 +08:00
|
|
|
return %0, %1#0, %1#1, %2, %3, %4 : i32, i32, i32, i32, i32, i32
|
2019-11-21 02:19:01 +08:00
|
|
|
}
|
Add support for custom op parser/printer hooks to know about result names.
Summary:
This allows the custom parser/printer hooks to do interesting things with
the SSA names. This patch:
- Adds a new 'getResultName' method to OpAsmParser that allows a parser
implementation to get information about its result names, along with
a getNumResults() method that allows op parser impls to know how many
results are expected.
- Adds a OpAsmPrinter::printOperand overload that takes an explicit stream.
- Adds a test.string_attr_pretty_name operation that uses these hooks to
do fancy things with the result name.
Reviewers: rriddle!
Subscribers: mehdi_amini, rriddle, jpienaar, burmako, shauheen, antiagainst, nicolasvasilache, arpith-jacob, mgester, lucyrfox, liufengdb, Joonsoo, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D76205
2020-03-16 08:13:59 +08:00
|
|
|
|
|
|
|
|
|
|
|
// CHECK-LABEL: func @pretty_names
|
|
|
|
|
|
|
|
// This tests the behavior
|
|
|
|
func @pretty_names() {
|
|
|
|
// Simple case, should parse and print as %x being an implied 'name'
|
|
|
|
// attribute.
|
|
|
|
%x = test.string_attr_pretty_name
|
|
|
|
// CHECK: %x = test.string_attr_pretty_name
|
|
|
|
// CHECK-NOT: attributes
|
2020-06-06 08:29:56 +08:00
|
|
|
|
Add support for custom op parser/printer hooks to know about result names.
Summary:
This allows the custom parser/printer hooks to do interesting things with
the SSA names. This patch:
- Adds a new 'getResultName' method to OpAsmParser that allows a parser
implementation to get information about its result names, along with
a getNumResults() method that allows op parser impls to know how many
results are expected.
- Adds a OpAsmPrinter::printOperand overload that takes an explicit stream.
- Adds a test.string_attr_pretty_name operation that uses these hooks to
do fancy things with the result name.
Reviewers: rriddle!
Subscribers: mehdi_amini, rriddle, jpienaar, burmako, shauheen, antiagainst, nicolasvasilache, arpith-jacob, mgester, lucyrfox, liufengdb, Joonsoo, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D76205
2020-03-16 08:13:59 +08:00
|
|
|
// This specifies an explicit name, which should override the result.
|
|
|
|
%YY = test.string_attr_pretty_name attributes { names = ["y"] }
|
|
|
|
// CHECK: %y = test.string_attr_pretty_name
|
|
|
|
// CHECK-NOT: attributes
|
2020-06-06 08:29:56 +08:00
|
|
|
|
Add support for custom op parser/printer hooks to know about result names.
Summary:
This allows the custom parser/printer hooks to do interesting things with
the SSA names. This patch:
- Adds a new 'getResultName' method to OpAsmParser that allows a parser
implementation to get information about its result names, along with
a getNumResults() method that allows op parser impls to know how many
results are expected.
- Adds a OpAsmPrinter::printOperand overload that takes an explicit stream.
- Adds a test.string_attr_pretty_name operation that uses these hooks to
do fancy things with the result name.
Reviewers: rriddle!
Subscribers: mehdi_amini, rriddle, jpienaar, burmako, shauheen, antiagainst, nicolasvasilache, arpith-jacob, mgester, lucyrfox, liufengdb, Joonsoo, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D76205
2020-03-16 08:13:59 +08:00
|
|
|
// Conflicts with the 'y' name, so need an explicit attribute.
|
|
|
|
%0 = "test.string_attr_pretty_name"() { names = ["y"]} : () -> i32
|
|
|
|
// CHECK: %y_0 = test.string_attr_pretty_name attributes {names = ["y"]}
|
|
|
|
|
|
|
|
// Name contains a space.
|
|
|
|
%1 = "test.string_attr_pretty_name"() { names = ["space name"]} : () -> i32
|
|
|
|
// CHECK: %space_name = test.string_attr_pretty_name attributes {names = ["space name"]}
|
|
|
|
|
|
|
|
"unknown.use"(%x, %YY, %0, %1) : (i32, i32, i32, i32) -> ()
|
|
|
|
|
|
|
|
// Multi-result support.
|
|
|
|
|
|
|
|
%a, %b, %c = test.string_attr_pretty_name
|
|
|
|
// CHECK: %a, %b, %c = test.string_attr_pretty_name
|
|
|
|
// CHECK-NOT: attributes
|
|
|
|
|
|
|
|
%q:3, %r = test.string_attr_pretty_name
|
|
|
|
// CHECK: %q, %q_1, %q_2, %r = test.string_attr_pretty_name attributes {names = ["q", "q", "q", "r"]}
|
|
|
|
|
|
|
|
// CHECK: return
|
|
|
|
return
|
|
|
|
}
|
2020-05-14 13:32:21 +08:00
|
|
|
|
2021-08-28 11:03:49 +08:00
|
|
|
|
|
|
|
// This tests the behavior of "default dialect":
|
|
|
|
// operations like `test.default_dialect` can define a default dialect
|
|
|
|
// used in nested region.
|
|
|
|
// CHECK-LABEL: func @default_dialect
|
2021-10-06 10:35:58 +08:00
|
|
|
func @default_dialect(%bool : i1) {
|
2021-08-28 11:03:49 +08:00
|
|
|
test.default_dialect {
|
|
|
|
// The test dialect is the default in this region, the following two
|
|
|
|
// operations are parsed identically.
|
|
|
|
// CHECK-NOT: test.parse_integer_literal
|
|
|
|
parse_integer_literal : 5
|
|
|
|
// CHECK: parse_integer_literal : 6
|
|
|
|
test.parse_integer_literal : 6
|
|
|
|
// Verify that only an op prefix is stripped, not an attribute value for
|
|
|
|
// example.
|
|
|
|
// CHECK: "test.op_with_attr"() {test.attr = "test.value"} : () -> ()
|
|
|
|
"test.op_with_attr"() {test.attr = "test.value"} : () -> ()
|
2021-10-06 10:35:58 +08:00
|
|
|
|
|
|
|
// TODO: remove this after removing the special casing for std in the printer.
|
|
|
|
// Verify that operations in the standard dialect keep the `std.` prefix.
|
|
|
|
// CHECK: std.assert
|
|
|
|
assert %bool, "Assertion"
|
2021-08-28 11:03:49 +08:00
|
|
|
"test.terminator"() : ()->()
|
|
|
|
}
|
2021-10-06 10:35:58 +08:00
|
|
|
// The same operation outside of the region does not have an std. prefix.
|
|
|
|
// CHECK-NOT: std.assert
|
|
|
|
// CHECK: assert
|
|
|
|
assert %bool, "Assertion"
|
2021-08-28 11:03:49 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
[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
|
|
|
// CHECK-LABEL: func @unreachable_dominance_violation_ok
|
2020-05-14 13:32:21 +08:00
|
|
|
func @unreachable_dominance_violation_ok() -> i1 {
|
2021-10-13 07:14:57 +08:00
|
|
|
// CHECK: [[VAL:%.*]] = arith.constant false
|
[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
|
|
|
// CHECK: return [[VAL]] : i1
|
|
|
|
// CHECK: ^bb1: // no predecessors
|
|
|
|
// CHECK: [[VAL2:%.*]]:3 = "bar"([[VAL3:%.*]]) : (i64) -> (i1, i1, i1)
|
|
|
|
// CHECK: br ^bb3
|
|
|
|
// CHECK: ^bb2: // pred: ^bb2
|
|
|
|
// CHECK: br ^bb2
|
|
|
|
// CHECK: ^bb3: // pred: ^bb1
|
|
|
|
// CHECK: [[VAL3]] = "foo"() : () -> i64
|
|
|
|
// CHECK: return [[VAL2]]#1 : i1
|
|
|
|
// CHECK: }
|
2021-10-13 07:14:57 +08:00
|
|
|
%c = arith.constant false
|
[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
|
|
|
return %c : i1
|
|
|
|
^bb1:
|
2020-05-14 13:32:21 +08:00
|
|
|
// %1 is not dominated by it's definition, but block is not reachable.
|
[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
|
|
|
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
|
|
|
|
br ^bb3
|
|
|
|
^bb2:
|
|
|
|
br ^bb2
|
|
|
|
^bb3:
|
|
|
|
%1 = "foo"() : ()->i64
|
|
|
|
return %2#1 : i1
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: func @graph_region_in_hierarchy_ok
|
|
|
|
func @graph_region_in_hierarchy_ok() -> i64 {
|
|
|
|
// CHECK: br ^bb2
|
|
|
|
// CHECK: ^bb1:
|
|
|
|
// CHECK: test.graph_region {
|
|
|
|
// CHECK: [[VAL2:%.*]]:3 = "bar"([[VAL3:%.*]]) : (i64) -> (i1, i1, i1)
|
|
|
|
// CHECK: }
|
|
|
|
// CHECK: br ^bb3
|
|
|
|
// CHECK: ^bb2: // pred: ^bb0
|
|
|
|
// CHECK: [[VAL3]] = "foo"() : () -> i64
|
|
|
|
// CHECK: br ^bb1
|
|
|
|
// CHECK: ^bb3: // pred: ^bb1
|
|
|
|
// CHECK: return [[VAL3]] : i64
|
|
|
|
// CHECK: }
|
|
|
|
br ^bb2
|
|
|
|
^bb1:
|
|
|
|
test.graph_region {
|
|
|
|
// %1 is well-defined here, since bb2 dominates bb1.
|
|
|
|
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
|
|
|
|
}
|
|
|
|
br ^bb4
|
|
|
|
^bb2:
|
|
|
|
%1 = "foo"() : ()->i64
|
|
|
|
br ^bb1
|
|
|
|
^bb4:
|
|
|
|
return %1 : i64
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: func @graph_region_kind
|
|
|
|
func @graph_region_kind() -> () {
|
|
|
|
// CHECK: [[VAL2:%.*]]:3 = "bar"([[VAL3:%.*]]) : (i64) -> (i1, i1, i1)
|
|
|
|
// CHECK: [[VAL3]] = "baz"([[VAL2]]#0) : (i1) -> i64
|
|
|
|
test.graph_region {
|
|
|
|
// %1 OK here in in graph region.
|
|
|
|
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
|
|
|
|
%1 = "baz"(%2#0) : (i1) -> (i64)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: func @graph_region_inside_ssacfg_region
|
|
|
|
func @graph_region_inside_ssacfg_region() -> () {
|
|
|
|
// CHECK: "test.ssacfg_region"
|
|
|
|
// CHECK: [[VAL3:%.*]] = "baz"() : () -> i64
|
|
|
|
// CHECK: test.graph_region {
|
|
|
|
// CHECK: [[VAL2:%.*]]:3 = "bar"([[VAL3]]) : (i64) -> (i1, i1, i1)
|
|
|
|
// CHECK: }
|
|
|
|
// CHECK: [[VAL4:.*]] = "baz"() : () -> i64
|
|
|
|
"test.ssacfg_region"() ({
|
|
|
|
%1 = "baz"() : () -> (i64)
|
|
|
|
test.graph_region {
|
|
|
|
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
|
|
|
|
}
|
|
|
|
%3 = "baz"() : () -> (i64)
|
|
|
|
}) : () -> ()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK-LABEL: func @graph_region_in_graph_region_ok
|
|
|
|
func @graph_region_in_graph_region_ok() -> () {
|
|
|
|
// CHECK: test.graph_region {
|
|
|
|
// CHECK: test.graph_region {
|
|
|
|
// CHECK: [[VAL2:%.*]]:3 = "bar"([[VAL3:%.*]]) : (i64) -> (i1, i1, i1)
|
|
|
|
// CHECK: }
|
|
|
|
// CHECK: [[VAL3]] = "foo"() : () -> i64
|
|
|
|
// CHECK: }
|
|
|
|
test.graph_region {
|
|
|
|
test.graph_region {
|
|
|
|
// %1 is well-defined here since defined in graph region
|
|
|
|
%2:3 = "bar"(%1) : (i64) -> (i1,i1,i1)
|
|
|
|
}
|
|
|
|
%1 = "foo"() : ()->i64
|
|
|
|
"test.terminator"() : ()->()
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// CHECK: test.graph_region {
|
|
|
|
test.graph_region {
|
|
|
|
// CHECK: [[VAL1:%.*]] = "op1"([[VAL3:%.*]]) : (i32) -> i32
|
2022-01-18 15:47:25 +08:00
|
|
|
// CHECK: [[VAL2:%.*]] = "test.ssacfg_region"([[VAL1]], [[VAL2]], [[VAL3]], [[VAL4:%.*]]) ({
|
[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
|
|
|
// CHECK: [[VAL5:%.*]] = "op2"([[VAL1]], [[VAL2]], [[VAL3]], [[VAL4]]) : (i32, i32, i32, i32) -> i32
|
|
|
|
// CHECK: }) : (i32, i32, i32, i32) -> i32
|
|
|
|
// CHECK: [[VAL3]] = "op2"([[VAL1]], [[VAL4]]) : (i32, i32) -> i32
|
|
|
|
// CHECK: [[VAL4]] = "op3"([[VAL1]]) : (i32) -> i32
|
|
|
|
%1 = "op1"(%3) : (i32) -> (i32)
|
|
|
|
%2 = "test.ssacfg_region"(%1, %2, %3, %4) ({
|
|
|
|
%5 = "op2"(%1, %2, %3, %4) :
|
|
|
|
(i32, i32, i32, i32) -> (i32)
|
|
|
|
}) : (i32, i32, i32, i32) -> (i32)
|
|
|
|
%3 = "op2"(%1, %4) : (i32, i32) -> (i32)
|
|
|
|
%4 = "op3"(%1) : (i32) -> (i32)
|
|
|
|
}
|
|
|
|
|
2022-01-18 15:47:25 +08:00
|
|
|
// CHECK: "unregistered_func_might_have_graph_region"() ({
|
[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
|
|
|
// CHECK: [[VAL1:%.*]] = "foo"([[VAL1]], [[VAL2:%.*]]) : (i64, i64) -> i64
|
|
|
|
// CHECK: [[VAL2]] = "bar"([[VAL1]])
|
2022-01-18 15:47:25 +08:00
|
|
|
"unregistered_func_might_have_graph_region"() ({
|
[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
|
|
|
%1 = "foo"(%1, %2) : (i64, i64) -> i64
|
|
|
|
%2 = "bar"(%1) : (i64) -> i64
|
|
|
|
"unregistered_terminator"() : () -> ()
|
|
|
|
}) {sym_name = "unregistered_op_dominance_violation_ok", type = () -> i1} : () -> ()
|
2021-03-23 08:33:03 +08:00
|
|
|
|
|
|
|
// This is an unregister operation, the printing/parsing is handled by the dialect.
|
|
|
|
// CHECK: test.dialect_custom_printer custom_format
|
|
|
|
test.dialect_custom_printer custom_format
|
2021-12-10 08:47:48 +08:00
|
|
|
|
|
|
|
// This is a registered operation with no custom parser and printer, and should
|
|
|
|
// be handled by the dialect.
|
|
|
|
// CHECK: test.dialect_custom_format_fallback custom_format_fallback
|
|
|
|
test.dialect_custom_format_fallback custom_format_fallback
|