1// RUN: mlir-opt %s | mlir-opt | FileCheck %s
2
3// CHECK-LABEL: func @vector_transfer_ops(
4func @vector_transfer_ops(%arg0: memref<?x?xf32>,
5                          %arg1 : memref<?x?xvector<4x3xf32>>,
6                          %arg2 : memref<?x?xvector<4x3xi32>>) {
7  // CHECK: %[[C3:.*]] = constant 3 : index
8  %c3 = constant 3 : index
9  %cst = constant 3.0 : f32
10  %f0 = constant 0.0 : f32
11  %c0 = constant 0 : i32
12  %vf0 = splat %f0 : vector<4x3xf32>
13  %v0 = splat %c0 : vector<4x3xi32>
14
15  //
16  // CHECK: vector.transfer_read
17  %0 = vector.transfer_read %arg0[%c3, %c3], %f0 {permutation_map = affine_map<(d0, d1)->(d0)>} : memref<?x?xf32>, vector<128xf32>
18  // CHECK: vector.transfer_read
19  %1 = vector.transfer_read %arg0[%c3, %c3], %f0 {permutation_map = affine_map<(d0, d1)->(d1, d0)>} : memref<?x?xf32>, vector<3x7xf32>
20  // CHECK: vector.transfer_read
21  %2 = vector.transfer_read %arg0[%c3, %c3], %cst {permutation_map = affine_map<(d0, d1)->(d0)>} : memref<?x?xf32>,  vector<128xf32>
22  // CHECK: vector.transfer_read
23  %3 = vector.transfer_read %arg0[%c3, %c3], %cst {permutation_map = affine_map<(d0, d1)->(d1)>} : memref<?x?xf32>,  vector<128xf32>
24  // CHECK: vector.transfer_read %{{.*}}[%[[C3]], %[[C3]]], %{{.*}} : memref<?x?xvector<4x3xf32>>, vector<1x1x4x3xf32>
25  %4 = vector.transfer_read %arg1[%c3, %c3], %vf0 {permutation_map = affine_map<(d0, d1)->(d0, d1)>} : memref<?x?xvector<4x3xf32>>, vector<1x1x4x3xf32>
26  // CHECK: vector.transfer_read %{{.*}}[%[[C3]], %[[C3]]], %{{.*}} {masked = [true, false]} : memref<?x?xvector<4x3xf32>>, vector<1x1x4x3xf32>
27  %5 = vector.transfer_read %arg1[%c3, %c3], %vf0 {masked = [true, false]} : memref<?x?xvector<4x3xf32>>, vector<1x1x4x3xf32>
28  // CHECK: vector.transfer_read %{{.*}}[%[[C3]], %[[C3]]], %{{.*}} : memref<?x?xvector<4x3xi32>>, vector<5x24xi8>
29  %6 = vector.transfer_read %arg2[%c3, %c3], %v0 : memref<?x?xvector<4x3xi32>>, vector<5x24xi8>
30
31
32  // CHECK: vector.transfer_write
33  vector.transfer_write %0, %arg0[%c3, %c3] {permutation_map = affine_map<(d0, d1)->(d0)>} : vector<128xf32>, memref<?x?xf32>
34  // CHECK: vector.transfer_write
35  vector.transfer_write %1, %arg0[%c3, %c3] {permutation_map = affine_map<(d0, d1)->(d1, d0)>} : vector<3x7xf32>, memref<?x?xf32>
36  // CHECK: vector.transfer_write %{{.*}}, %{{.*}}[%[[C3]], %[[C3]]] : vector<1x1x4x3xf32>, memref<?x?xvector<4x3xf32>>
37  vector.transfer_write %4, %arg1[%c3, %c3] {permutation_map = affine_map<(d0, d1)->(d0, d1)>} : vector<1x1x4x3xf32>, memref<?x?xvector<4x3xf32>>
38  // CHECK: vector.transfer_write %{{.*}}, %{{.*}}[%[[C3]], %[[C3]]] : vector<1x1x4x3xf32>, memref<?x?xvector<4x3xf32>>
39  vector.transfer_write %5, %arg1[%c3, %c3] {masked = [true, true]} : vector<1x1x4x3xf32>, memref<?x?xvector<4x3xf32>>
40  // CHECK: vector.transfer_write %{{.*}}, %{{.*}}[%[[C3]], %[[C3]]] : vector<5x24xi8>, memref<?x?xvector<4x3xi32>>
41  vector.transfer_write %6, %arg2[%c3, %c3] : vector<5x24xi8>, memref<?x?xvector<4x3xi32>>
42
43  return
44}
45
46
47// CHECK-LABEL: func @vector_transfer_ops_tensor(
48func @vector_transfer_ops_tensor(%arg0: tensor<?x?xf32>,
49                          %arg1 : tensor<?x?xvector<4x3xf32>>,
50                          %arg2 : tensor<?x?xvector<4x3xi32>>) ->
51  (tensor<?x?xf32>, tensor<?x?xf32>, tensor<?x?xvector<4x3xf32>>,
52   tensor<?x?xvector<4x3xf32>>, tensor<?x?xvector<4x3xi32>>){
53  // CHECK: %[[C3:.*]] = constant 3 : index
54  %c3 = constant 3 : index
55  %cst = constant 3.0 : f32
56  %f0 = constant 0.0 : f32
57  %c0 = constant 0 : i32
58  %vf0 = splat %f0 : vector<4x3xf32>
59  %v0 = splat %c0 : vector<4x3xi32>
60
61  //
62  // CHECK: vector.transfer_read
63  %0 = vector.transfer_read %arg0[%c3, %c3], %f0 {permutation_map = affine_map<(d0, d1)->(d0)>} : tensor<?x?xf32>, vector<128xf32>
64  // CHECK: vector.transfer_read
65  %1 = vector.transfer_read %arg0[%c3, %c3], %f0 {permutation_map = affine_map<(d0, d1)->(d1, d0)>} : tensor<?x?xf32>, vector<3x7xf32>
66  // CHECK: vector.transfer_read
67  %2 = vector.transfer_read %arg0[%c3, %c3], %cst {permutation_map = affine_map<(d0, d1)->(d0)>} : tensor<?x?xf32>,  vector<128xf32>
68  // CHECK: vector.transfer_read
69  %3 = vector.transfer_read %arg0[%c3, %c3], %cst {permutation_map = affine_map<(d0, d1)->(d1)>} : tensor<?x?xf32>,  vector<128xf32>
70  // CHECK: vector.transfer_read %{{.*}}[%[[C3]], %[[C3]]], %{{.*}} : tensor<?x?xvector<4x3xf32>>, vector<1x1x4x3xf32>
71  %4 = vector.transfer_read %arg1[%c3, %c3], %vf0 {permutation_map = affine_map<(d0, d1)->(d0, d1)>} : tensor<?x?xvector<4x3xf32>>, vector<1x1x4x3xf32>
72  // CHECK: vector.transfer_read %{{.*}}[%[[C3]], %[[C3]]], %{{.*}} {masked = [true, false]} : tensor<?x?xvector<4x3xf32>>, vector<1x1x4x3xf32>
73  %5 = vector.transfer_read %arg1[%c3, %c3], %vf0 {masked = [true, false]} : tensor<?x?xvector<4x3xf32>>, vector<1x1x4x3xf32>
74  // CHECK: vector.transfer_read %{{.*}}[%[[C3]], %[[C3]]], %{{.*}} : tensor<?x?xvector<4x3xi32>>, vector<5x24xi8>
75  %6 = vector.transfer_read %arg2[%c3, %c3], %v0 : tensor<?x?xvector<4x3xi32>>, vector<5x24xi8>
76
77
78  // CHECK: vector.transfer_write
79  %7 = vector.transfer_write %0, %arg0[%c3, %c3] {permutation_map = affine_map<(d0, d1)->(d0)>} : vector<128xf32>, tensor<?x?xf32>
80  // CHECK: vector.transfer_write
81  %8 = vector.transfer_write %1, %arg0[%c3, %c3] {permutation_map = affine_map<(d0, d1)->(d1, d0)>} : vector<3x7xf32>, tensor<?x?xf32>
82  // CHECK: vector.transfer_write %{{.*}}, %{{.*}}[%[[C3]], %[[C3]]] : vector<1x1x4x3xf32>, tensor<?x?xvector<4x3xf32>>
83  %9 = vector.transfer_write %4, %arg1[%c3, %c3] {permutation_map = affine_map<(d0, d1)->(d0, d1)>} : vector<1x1x4x3xf32>, tensor<?x?xvector<4x3xf32>>
84  // CHECK: vector.transfer_write %{{.*}}, %{{.*}}[%[[C3]], %[[C3]]] : vector<1x1x4x3xf32>, tensor<?x?xvector<4x3xf32>>
85  %10 = vector.transfer_write %5, %arg1[%c3, %c3] {masked = [true, true]} : vector<1x1x4x3xf32>, tensor<?x?xvector<4x3xf32>>
86  // CHECK: vector.transfer_write %{{.*}}, %{{.*}}[%[[C3]], %[[C3]]] : vector<5x24xi8>, tensor<?x?xvector<4x3xi32>>
87  %11 = vector.transfer_write %6, %arg2[%c3, %c3] : vector<5x24xi8>, tensor<?x?xvector<4x3xi32>>
88
89  return %7, %8, %9, %10, %11 :
90    tensor<?x?xf32>, tensor<?x?xf32>,  tensor<?x?xvector<4x3xf32>>,
91    tensor<?x?xvector<4x3xf32>>, tensor<?x?xvector<4x3xi32>>
92}
93
94// CHECK-LABEL: @vector_broadcast
95func @vector_broadcast(%a: f32, %b: vector<16xf32>, %c: vector<1x16xf32>, %d: vector<8x1xf32>) -> vector<8x16xf32> {
96  // CHECK: vector.broadcast %{{.*}} : f32 to vector<16xf32>
97  %0 = vector.broadcast %a : f32 to vector<16xf32>
98  // CHECK-NEXT: vector.broadcast %{{.*}} : vector<16xf32> to vector<8x16xf32>
99  %1 = vector.broadcast %b : vector<16xf32> to vector<8x16xf32>
100  // CHECK-NEXT: vector.broadcast %{{.*}} : vector<1x16xf32> to vector<8x16xf32>
101  %2 = vector.broadcast %c : vector<1x16xf32> to vector<8x16xf32>
102  // CHECK-NEXT: vector.broadcast %{{.*}} : vector<8x1xf32> to vector<8x16xf32>
103  %3 = vector.broadcast %d : vector<8x1xf32> to vector<8x16xf32>
104  return %3 : vector<8x16xf32>
105}
106
107// CHECK-LABEL: @shuffle1D
108func @shuffle1D(%a: vector<2xf32>, %b: vector<4xf32>) -> vector<2xf32> {
109  // CHECK: vector.shuffle %{{.*}}, %{{.*}}[0, 1, 2, 3] : vector<2xf32>, vector<2xf32>
110  %1 = vector.shuffle %a, %a[0, 1, 2, 3] : vector<2xf32>, vector<2xf32>
111  // CHECK-NEXT: vector.shuffle %{{.*}}, %{{.*}}[0, 1, 2] : vector<4xf32>, vector<4xf32>
112  %2 = vector.shuffle %1, %b[0, 1, 2] : vector<4xf32>, vector<4xf32>
113  // CHECK-NEXT: vector.shuffle %{{.*}}, %{{.*}}[0, 6] : vector<3xf32>, vector<4xf32>
114  %3 = vector.shuffle %2, %b[0, 6] : vector<3xf32>, vector<4xf32>
115  return %3 : vector<2xf32>
116}
117
118// CHECK-LABEL: @shuffle2D
119func @shuffle2D(%a: vector<1x4xf32>, %b: vector<2x4xf32>) -> vector<3x4xf32> {
120  // CHECK: vector.shuffle %{{.*}}, %{{.*}}[0, 1, 2] : vector<1x4xf32>, vector<2x4xf32>
121  %1 = vector.shuffle %a, %b[0, 1, 2] : vector<1x4xf32>, vector<2x4xf32>
122  return %1 : vector<3x4xf32>
123}
124
125// CHECK-LABEL: @extract_element
126func @extract_element(%a: vector<16xf32>) -> f32 {
127  // CHECK:      %[[C15:.*]] = constant 15 : i32
128  %c = constant 15 : i32
129  // CHECK-NEXT: vector.extractelement %{{.*}}[%[[C15]] : i32] : vector<16xf32>
130  %1 = vector.extractelement %a[%c : i32] : vector<16xf32>
131  return %1 : f32
132}
133
134// CHECK-LABEL: @extract
135func @extract(%arg0: vector<4x8x16xf32>) -> (vector<8x16xf32>, vector<16xf32>, f32) {
136  // CHECK: vector.extract {{.*}}[3] : vector<4x8x16xf32>
137  %1 = vector.extract %arg0[3] : vector<4x8x16xf32>
138  // CHECK-NEXT: vector.extract {{.*}}[3, 3] : vector<4x8x16xf32>
139  %2 = vector.extract %arg0[3, 3] : vector<4x8x16xf32>
140  // CHECK-NEXT: vector.extract {{.*}}[3, 3, 3] : vector<4x8x16xf32>
141  %3 = vector.extract %arg0[3, 3, 3] : vector<4x8x16xf32>
142  return %1, %2, %3 : vector<8x16xf32>, vector<16xf32>, f32
143}
144
145// CHECK-LABEL: @insert_element
146func @insert_element(%a: f32, %b: vector<16xf32>) -> vector<16xf32> {
147  // CHECK:      %[[C15:.*]] = constant 15 : i32
148  %c = constant 15 : i32
149  // CHECK-NEXT: vector.insertelement %{{.*}}, %{{.*}}[%[[C15]] : i32] : vector<16xf32>
150  %1 = vector.insertelement %a, %b[%c : i32] : vector<16xf32>
151  return %1 : vector<16xf32>
152}
153
154// CHECK-LABEL: @insert
155func @insert(%a: f32, %b: vector<16xf32>, %c: vector<8x16xf32>, %res: vector<4x8x16xf32>) -> vector<4x8x16xf32> {
156  // CHECK: vector.insert %{{.*}}, %{{.*}}[3] : vector<8x16xf32> into vector<4x8x16xf32>
157  %1 = vector.insert %c, %res[3] : vector<8x16xf32> into vector<4x8x16xf32>
158  // CHECK: vector.insert %{{.*}}, %{{.*}}[3, 3] : vector<16xf32> into vector<4x8x16xf32>
159  %2 = vector.insert %b, %res[3, 3] : vector<16xf32> into vector<4x8x16xf32>
160  // CHECK: vector.insert %{{.*}}, %{{.*}}[3, 3, 3] : f32 into vector<4x8x16xf32>
161  %3 = vector.insert %a, %res[3, 3, 3] : f32 into vector<4x8x16xf32>
162  return %3 : vector<4x8x16xf32>
163}
164
165// CHECK-LABEL: @outerproduct
166func @outerproduct(%arg0: vector<4xf32>, %arg1: vector<8xf32>, %arg2: vector<4x8xf32>) -> vector<4x8xf32> {
167  // CHECK: vector.outerproduct {{.*}} : vector<4xf32>, vector<8xf32>
168  %0 = vector.outerproduct %arg0, %arg1 : vector<4xf32>, vector<8xf32>
169  // CHECK: vector.outerproduct {{.*}}, {{.*}}, {{.*}} : vector<4xf32>, vector<8xf32>
170  %1 = vector.outerproduct %arg0, %arg1, %arg2 : vector<4xf32>, vector<8xf32>
171  return %1 : vector<4x8xf32>
172}
173
174// CHECK-LABEL: @insert_strided_slice
175func @insert_strided_slice(%a: vector<4x4xf32>, %b: vector<4x8x16xf32>) {
176  // CHECK: vector.insert_strided_slice %{{.*}}, %{{.*}} {offsets = [2, 2, 2], strides = [1, 1]} : vector<4x4xf32> into vector<4x8x16xf32>
177  %1 = vector.insert_strided_slice %a, %b {offsets = [2, 2, 2], strides = [1, 1]} : vector<4x4xf32> into vector<4x8x16xf32>
178  return
179}
180
181// CHECK-LABEL: @extract_strided_slice
182func @extract_strided_slice(%arg0: vector<4x8x16xf32>) -> vector<2x2x16xf32> {
183  // CHECK: vector.extract_strided_slice %{{.*}} {offsets = [2, 2], sizes = [2, 2], strides = [1, 1]} : vector<4x8x16xf32>
184  %1 = vector.extract_strided_slice %arg0 {offsets = [2, 2], sizes = [2, 2], strides = [1, 1]} : vector<4x8x16xf32> to vector<2x2x16xf32>
185  return %1: vector<2x2x16xf32>
186}
187
188#contraction_to_scalar_accesses = [
189  affine_map<(i) -> (i)>,
190  affine_map<(i) -> (i)>,
191  affine_map<(i) -> ()>
192]
193#contraction_to_scalar_trait = {
194  indexing_maps = #contraction_to_scalar_accesses,
195  iterator_types = ["reduction"]
196}
197// CHECK-LABEL: @contraction_to_scalar
198func @contraction_to_scalar(%arg0: vector<10xf32>, %arg1: vector<10xf32>) -> f32 {
199  // CHECK:      %[[C0:.*]] = constant 0.000000e+00 : f32
200  %f0 = constant 0.0: f32
201  // CHECK:      %[[X:.*]] = vector.contract {indexing_maps = [#{{.*}}, #{{.*}}, #{{.*}}], iterator_types = ["reduction"], kind = #vector.kind<add>} %{{.*}}, %{{.*}}, %[[C0]] : vector<10xf32>, vector<10xf32> into f32
202  %0 = vector.contract #contraction_to_scalar_trait %arg0, %arg1, %f0
203    : vector<10xf32>, vector<10xf32> into f32
204  // CHECK:      return %[[X]] : f32
205  return %0 : f32
206}
207
208#contraction_to_scalar_max_accesses = [
209  affine_map<(i) -> (i)>,
210  affine_map<(i) -> (i)>,
211  affine_map<(i) -> ()>
212]
213#contraction_to_scalar_max_trait = {
214  indexing_maps = #contraction_to_scalar_max_accesses,
215  iterator_types = ["reduction"],
216  kind = #vector.kind<max>
217}
218// CHECK-LABEL: @contraction_to_scalar_with_max
219func @contraction_to_scalar_with_max(%arg0: vector<10xf32>, %arg1: vector<10xf32>) -> f32 {
220  // CHECK:      %[[C0:.*]] = constant 0.000000e+00 : f32
221  %f0 = constant 0.0: f32
222  // CHECK:      %[[X:.*]] = vector.contract {indexing_maps = [#{{.*}}, #{{.*}}, #{{.*}}], iterator_types = ["reduction"], kind = #vector.kind<max>} %{{.*}}, %{{.*}}, %[[C0]] : vector<10xf32>, vector<10xf32> into f32
223  %0 = vector.contract #contraction_to_scalar_max_trait %arg0, %arg1, %f0
224    : vector<10xf32>, vector<10xf32> into f32
225  // CHECK:      return %[[X]] : f32
226  return %0 : f32
227}
228
229#contraction_accesses0 = [
230  affine_map<(b0, f0, f1, c0, c1) -> (c0, b0, c1, f0)>,
231  affine_map<(b0, f0, f1, c0, c1) -> (b0, c1, c0, f1)>,
232  affine_map<(b0, f0, f1, c0, c1) -> (b0, f0, f1)>
233]
234#contraction_trait0 = {
235  indexing_maps = #contraction_accesses0,
236  iterator_types = ["parallel", "parallel", "parallel", "reduction", "reduction"]
237}
238#contraction_accesses1 = [              // 7,  8, 16, 15
239  affine_map<(f0, f1, f2, f3, c0, c1) -> (c0, f0, c1, f2)>,
240                                        // 8, 16,  7,  5
241  affine_map<(f0, f1, f2, f3, c0, c1) -> (f1, c1, c0, f3)>,
242                                        // 8,  8, 15,  5
243  affine_map<(f0, f1, f2, f3, c0, c1) -> (f0, f1, f2, f3)>
244]
245#iterator_types1 = ["parallel", "parallel", "parallel", "parallel", "reduction",
246                    "reduction"]
247#contraction_trait1 = {
248  indexing_maps = #contraction_accesses1,
249  iterator_types = #iterator_types1
250}
251#contraction_trait2 = {
252  indexing_maps = #contraction_accesses1,
253  iterator_types = #iterator_types1,
254  kind = #vector.kind<max>
255}
256// CHECK-LABEL: @contraction
257func @contraction(%arg0 : vector<7x8x16x15xf32>, %arg1 : vector<8x16x7x5xf32>,
258                  %arg2 : vector<8x15x5xf32>, %arg3 : vector<8x8x15x5xf32>,
259                  %arg4 : vector<7x8x16x15xf16>, %arg5 : vector<8x16x7x5xf16>) {
260  // Test contraction with batch and contracting dims.
261  // CHECK: vector.contract {indexing_maps = [#{{.*}}, #{{.*}}, #{{.*}}], iterator_types = ["parallel", "parallel", "parallel", "reduction", "reduction"], kind = #vector.kind<add>} {{.*}}, {{.*}}, {{.*}} : vector<7x8x16x15xf32>, vector<8x16x7x5xf32> into vector<8x15x5xf32>
262  %0 = vector.contract #contraction_trait0 %arg0, %arg1, %arg2
263      : vector<7x8x16x15xf32>, vector<8x16x7x5xf32> into vector<8x15x5xf32>
264  // Test contraction with only contracting dims. In this case the lhs/rhs
265  // dimension of size 8 will be considered a parallel dim for lhs/rhs and will
266  // appear twice in the output.
267  // CHECK: vector.contract {indexing_maps = [#{{.*}}, #{{.*}}, #{{.*}}], iterator_types = ["parallel", "parallel", "parallel", "parallel", "reduction", "reduction"], kind = #vector.kind<add>} {{.*}}, {{.*}}, {{.*}} : vector<7x8x16x15xf32>, vector<8x16x7x5xf32> into vector<8x8x15x5xf32>
268  %1 = vector.contract #contraction_trait1 %arg0, %arg1, %arg3
269      : vector<7x8x16x15xf32>, vector<8x16x7x5xf32> into vector<8x8x15x5xf32>
270  // Test contraction with optional vector mask arguments.
271  %lhs_mask = vector.constant_mask [7, 8, 16, 15] : vector<7x8x16x15xi1>
272  %rhs_mask = vector.constant_mask [8, 16, 7, 5] : vector<8x16x7x5xi1>
273  // CHECK: vector.contract {indexing_maps = [#{{.*}}, #{{.*}}, #{{.*}}], iterator_types = ["parallel", "parallel", "parallel", "parallel", "reduction", "reduction"], kind = #vector.kind<add>} {{.*}}, {{.*}}, {{.*}}, {{.*}}, {{.*}} : vector<7x8x16x15xf32>, vector<8x16x7x5xf32> into vector<8x8x15x5xf32>
274  %2 = vector.contract #contraction_trait1 %arg0, %arg1, %arg3, %lhs_mask,
275                                           %rhs_mask
276      : vector<7x8x16x15xf32>, vector<8x16x7x5xf32> into vector<8x8x15x5xf32>
277  // Test contraction with mixed type.
278  // CHECK: vector.contract {indexing_maps = [#{{.*}}, #{{.*}}, #{{.*}}], iterator_types = ["parallel", "parallel", "parallel", "parallel", "reduction", "reduction"], kind = #vector.kind<add>} {{.*}}, {{.*}}, {{.*}} : vector<7x8x16x15xf16>, vector<8x16x7x5xf16> into vector<8x8x15x5xf32>
279  %3 = vector.contract #contraction_trait1 %arg4, %arg5, %arg3
280      : vector<7x8x16x15xf16>, vector<8x16x7x5xf16> into vector<8x8x15x5xf32>
281  // Test contraction with "max" instead of "add".
282  // CHECK: vector.contract {indexing_maps = [#{{.*}}, #{{.*}}, #{{.*}}], iterator_types = ["parallel", "parallel", "parallel", "parallel", "reduction", "reduction"], kind = #vector.kind<max>} {{.*}}, {{.*}}, {{.*}} : vector<7x8x16x15xf32>, vector<8x16x7x5xf32> into vector<8x8x15x5xf32>
283  %4 = vector.contract #contraction_trait2 %arg0, %arg1, %arg3
284      : vector<7x8x16x15xf32>, vector<8x16x7x5xf32> into vector<8x8x15x5xf32>
285  return
286}
287
288// CHECK-LABEL: @create_vector_mask
289func @create_vector_mask() {
290  // CHECK:      %[[C2:.*]] = constant 2 : index
291  %c2 = constant 2 : index
292  // CHECK-NEXT: %[[C3:.*]] = constant 3 : index
293  %c3 = constant 3 : index
294  // CHECK-NEXT: vector.create_mask %[[C3]], %[[C2]] : vector<4x3xi1>
295  %0 = vector.create_mask %c3, %c2 : vector<4x3xi1>
296
297  return
298}
299
300// CHECK-LABEL: @constant_vector_mask
301func @constant_vector_mask() {
302  // CHECK: vector.constant_mask [3, 2] : vector<4x3xi1>
303  %0 = vector.constant_mask [3, 2] : vector<4x3xi1>
304  return
305}
306
307// CHECK-LABEL: @extract_slices
308func @extract_slices(%arg0 : vector<4x2xf32>)
309  -> (tuple<vector<2x2xf32>, vector<2x2xf32>>) {
310  // CHECK: vector.extract_slices %{{.*}}, [2, 2], [1, 1] : vector<4x2xf32> into tuple<vector<2x2xf32>, vector<2x2xf32>>
311  %0 = vector.extract_slices %arg0, [2, 2], [1, 1]
312    : vector<4x2xf32> into tuple<vector<2x2xf32>, vector<2x2xf32>>
313  %1 = vector.tuple_get %0, 0 : tuple<vector<2x2xf32>, vector<2x2xf32>>
314  %2 = vector.tuple_get %0, 1 : tuple<vector<2x2xf32>, vector<2x2xf32>>
315  %3 = vector.tuple %1, %2 : vector<2x2xf32>, vector<2x2xf32>
316  return %3 : tuple<vector<2x2xf32>, vector<2x2xf32>>
317}
318
319// CHECK-LABEL: @insert_slices
320func @insert_slices(%arg0 : tuple<vector<2x2xf32>, vector<2x2xf32>>)
321  -> (vector<4x2xf32>) {
322  // CHECK: vector.insert_slices %{{.*}}, [2, 2], [1, 1] : tuple<vector<2x2xf32>, vector<2x2xf32>> into vector<4x2xf32>
323  %0 = vector.insert_slices %arg0, [2, 2], [1, 1]
324    : tuple<vector<2x2xf32>, vector<2x2xf32>> into vector<4x2xf32>
325  return %0 : vector<4x2xf32>
326}
327
328// CHECK-LABEL: @vector_print
329func @vector_print(%arg0: vector<8x4xf32>) {
330  // CHECK: vector.print %{{.*}} : vector<8x4xf32>
331  vector.print %arg0 : vector<8x4xf32>
332  return
333}
334
335// CHECK-LABEL: @reshape
336func @reshape(%arg0 : vector<3x2x4xf32>) -> (vector<2x3x4xf32>) {
337  // CHECK:      %[[C2:.*]] = constant 2 : index
338  %c2 = constant 2 : index
339  // CHECK:      %[[C3:.*]] = constant 3 : index
340  %c3 = constant 3 : index
341  // CHECK:      %[[C6:.*]] = constant 6 : index
342  %c6 = constant 6 : index
343  // CHECK:      %[[C9:.*]] = constant 9 : index
344  %c9 = constant 9 : index
345  // CHECK: vector.reshape %{{.*}}, [%[[C3]], %[[C6]]], [%[[C2]], %[[C9]]], [4] : vector<3x2x4xf32> to vector<2x3x4xf32>
346  %1 = vector.reshape %arg0, [%c3, %c6], [%c2, %c9], [4]
347    : vector<3x2x4xf32> to vector<2x3x4xf32>
348
349  return %1 : vector<2x3x4xf32>
350}
351
352// CHECK-LABEL: @shape_cast
353func @shape_cast(%arg0 : vector<5x1x3x2xf32>,
354                 %arg1 : tuple<vector<5x4x2xf32>, vector<3x4x2xf32>>,
355                 %arg2 : vector<8x1xf32>,
356                 %arg3 : vector<16x1x1xf32>)
357  -> (vector<15x2xf32>, tuple<vector<20x2xf32>, vector<12x2xf32>>, vector<8xf32>, vector<16xf32>, vector<16x1xf32>) {
358
359  // CHECK: vector.shape_cast %{{.*}} : vector<5x1x3x2xf32> to vector<15x2xf32>
360  %0 = vector.shape_cast %arg0 : vector<5x1x3x2xf32> to vector<15x2xf32>
361
362  // CHECK-NEXT: vector.shape_cast %{{.*}} : tuple<vector<5x4x2xf32>, vector<3x4x2xf32>> to tuple<vector<20x2xf32>, vector<12x2xf32>>
363  %1 = vector.shape_cast %arg1 : tuple<vector<5x4x2xf32>, vector<3x4x2xf32>> to
364                                 tuple<vector<20x2xf32>, vector<12x2xf32>>
365
366  // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<8x1xf32> to vector<8xf32>
367  %2 = vector.shape_cast %arg2 : vector<8x1xf32> to vector<8xf32>
368
369  // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<16x1x1xf32> to vector<16xf32>
370  %3 = vector.shape_cast %arg3 : vector<16x1x1xf32> to vector<16xf32>
371
372  // CHECK-NEXT: vector.shape_cast %{{.*}} : vector<16x1x1xf32> to vector<16x1xf32>
373  %4 = vector.shape_cast %arg3 : vector<16x1x1xf32> to vector<16x1xf32>
374
375  return %0, %1, %2, %3, %4 : vector<15x2xf32>, tuple<vector<20x2xf32>, vector<12x2xf32>>, vector<8xf32>, vector<16xf32>, vector<16x1xf32>
376}
377
378// CHECK-LABEL: @bitcast
379func @bitcast(%arg0 : vector<5x1x3x2xf32>,
380                 %arg1 : vector<8x1xi32>,
381                 %arg2 : vector<16x1x8xi8>)
382  -> (vector<5x1x3x4xf16>, vector<5x1x3x8xi8>, vector<8x4xi8>, vector<8x1xf32>, vector<16x1x2xi32>, vector<16x1x4xi16>) {
383
384  // CHECK: vector.bitcast %{{.*}} : vector<5x1x3x2xf32> to vector<5x1x3x4xf16>
385  %0 = vector.bitcast %arg0 : vector<5x1x3x2xf32> to vector<5x1x3x4xf16>
386
387  // CHECK-NEXT: vector.bitcast %{{.*}} : vector<5x1x3x2xf32> to vector<5x1x3x8xi8>
388  %1 = vector.bitcast %arg0 : vector<5x1x3x2xf32> to vector<5x1x3x8xi8>
389
390  // CHECK-NEXT: vector.bitcast %{{.*}} : vector<8x1xi32> to vector<8x4xi8>
391  %2 = vector.bitcast %arg1 : vector<8x1xi32> to vector<8x4xi8>
392
393  // CHECK-NEXT: vector.bitcast %{{.*}} : vector<8x1xi32> to vector<8x1xf32>
394  %3 = vector.bitcast %arg1 : vector<8x1xi32> to vector<8x1xf32>
395
396  // CHECK-NEXT: vector.bitcast %{{.*}} : vector<16x1x8xi8> to vector<16x1x2xi32>
397  %4 = vector.bitcast %arg2 : vector<16x1x8xi8> to vector<16x1x2xi32>
398
399  // CHECK-NEXT: vector.bitcast %{{.*}} : vector<16x1x8xi8> to vector<16x1x4xi16>
400  %5 = vector.bitcast %arg2 : vector<16x1x8xi8> to vector<16x1x4xi16>
401
402  return %0, %1, %2, %3, %4, %5 : vector<5x1x3x4xf16>, vector<5x1x3x8xi8>, vector<8x4xi8>, vector<8x1xf32>, vector<16x1x2xi32>, vector<16x1x4xi16>
403}
404
405// CHECK-LABEL: @vector_fma
406func @vector_fma(%a: vector<8xf32>, %b: vector<8x4xf32>) {
407  // CHECK: vector.fma %{{.*}} : vector<8xf32>
408  vector.fma %a, %a, %a : vector<8xf32>
409  // CHECK: vector.fma %{{.*}} : vector<8x4xf32>
410  vector.fma %b, %b, %b : vector<8x4xf32>
411  return
412}
413
414// CHECK-LABEL: @reduce_fp
415func @reduce_fp(%arg0: vector<16xf32>, %arg1: f32) -> f32 {
416  // CHECK:    vector.reduction "add", %{{.*}} : vector<16xf32> into f32
417  vector.reduction "add", %arg0 : vector<16xf32> into f32
418  // CHECK:    vector.reduction "add", %{{.*}}, %{{.*}} : vector<16xf32> into f32
419  vector.reduction "add", %arg0, %arg1 : vector<16xf32> into f32
420  // CHECK:    vector.reduction "mul", %{{.*}} : vector<16xf32> into f32
421  vector.reduction "mul", %arg0 : vector<16xf32> into f32
422  // CHECK:    vector.reduction "mul", %{{.*}}, %{{.*}} : vector<16xf32> into f32
423  vector.reduction "mul", %arg0, %arg1 : vector<16xf32> into f32
424  // CHECK:    vector.reduction "min", %{{.*}} : vector<16xf32> into f32
425  vector.reduction "min", %arg0 : vector<16xf32> into f32
426  // CHECK:    %[[X:.*]] = vector.reduction "max", %{{.*}} : vector<16xf32> into f32
427  %0 = vector.reduction "max", %arg0 : vector<16xf32> into f32
428  // CHECK:    return %[[X]] : f32
429  return %0 : f32
430}
431
432// CHECK-LABEL: @reduce_int
433func @reduce_int(%arg0: vector<16xi32>) -> i32 {
434  // CHECK:    vector.reduction "add", %{{.*}} : vector<16xi32> into i32
435  vector.reduction "add", %arg0 : vector<16xi32> into i32
436  // CHECK:    vector.reduction "mul", %{{.*}} : vector<16xi32> into i32
437  vector.reduction "mul", %arg0 : vector<16xi32> into i32
438  // CHECK:    vector.reduction "min", %{{.*}} : vector<16xi32> into i32
439  vector.reduction "min", %arg0 : vector<16xi32> into i32
440  // CHECK:    vector.reduction "max", %{{.*}} : vector<16xi32> into i32
441  vector.reduction "max", %arg0 : vector<16xi32> into i32
442  // CHECK:    vector.reduction "and", %{{.*}} : vector<16xi32> into i32
443  vector.reduction "and", %arg0 : vector<16xi32> into i32
444  // CHECK:    vector.reduction "or", %{{.*}} : vector<16xi32> into i32
445  vector.reduction "or", %arg0 : vector<16xi32> into i32
446  // CHECK:    %[[X:.*]] = vector.reduction "xor", %{{.*}} : vector<16xi32> into i32
447  %0 = vector.reduction "xor", %arg0 : vector<16xi32> into i32
448  // CHECK:    return %[[X]] : i32
449  return %0 : i32
450}
451
452// CHECK-LABEL: @transpose_fp
453func @transpose_fp(%arg0: vector<3x7xf32>) -> vector<7x3xf32> {
454  // CHECK: %[[X:.*]] = vector.transpose %{{.*}}, [1, 0] : vector<3x7xf32> to vector<7x3xf32>
455  %0 = vector.transpose %arg0, [1, 0] : vector<3x7xf32> to vector<7x3xf32>
456  // CHECK: return %[[X]] : vector<7x3xf32>
457  return %0 : vector<7x3xf32>
458}
459
460// CHECK-LABEL: @transpose_int
461func @transpose_int(%arg0: vector<11x7x3x2xi32>) -> vector<2x11x7x3xi32> {
462  // CHECK: %[[X:.*]] = vector.transpose %{{.*}}, [3, 0, 1, 2] : vector<11x7x3x2xi32> to vector<2x11x7x3xi32>
463  %0 = vector.transpose %arg0, [3, 0, 1, 2] : vector<11x7x3x2xi32> to vector<2x11x7x3xi32>
464  // CHECK: return %[[X]] : vector<2x11x7x3xi32>
465  return %0 : vector<2x11x7x3xi32>
466}
467
468// CHECK-LABEL: @flat_transpose_fp
469func @flat_transpose_fp(%arg0: vector<16xf32>) -> vector<16xf32> {
470  // CHECK: %[[X:.*]] = vector.flat_transpose %{{.*}} {columns = 4 : i32, rows = 4 : i32} : vector<16xf32> -> vector<16xf32>
471  %0 = vector.flat_transpose %arg0 { rows = 4: i32, columns = 4: i32 } : vector<16xf32> -> vector<16xf32>
472  // CHECK: return %[[X]] : vector<16xf32>
473  return %0 : vector<16xf32>
474}
475
476// CHECK-LABEL: @flat_transpose_int
477func @flat_transpose_int(%arg0: vector<16xi32>) -> vector<16xi32> {
478  // CHECK: %[[X:.*]] = vector.flat_transpose %{{.*}} {columns = 8 : i32, rows = 2 : i32} : vector<16xi32> -> vector<16xi32>
479  %0 = vector.flat_transpose %arg0 { rows = 2: i32, columns = 8: i32 } : vector<16xi32> -> vector<16xi32>
480  // CHECK: return %[[X]] : vector<16xi32>
481  return %0 : vector<16xi32>
482}
483
484// CHECK-LABEL: @vector_load_and_store_1d_scalar_memref
485func @vector_load_and_store_1d_scalar_memref(%memref : memref<200x100xf32>,
486                                             %i : index, %j : index) {
487  // CHECK: %[[ld:.*]] = vector.load %{{.*}}[%{{.*}}] : memref<200x100xf32>, vector<8xf32>
488  %0 = vector.load %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>
489  // CHECK: vector.store %[[ld]], %{{.*}}[%{{.*}}] : memref<200x100xf32>, vector<8xf32>
490  vector.store %0, %memref[%i, %j] : memref<200x100xf32>, vector<8xf32>
491  return
492}
493
494// CHECK-LABEL: @vector_load_and_store_1d_vector_memref
495func @vector_load_and_store_1d_vector_memref(%memref : memref<200x100xvector<8xf32>>,
496                                             %i : index, %j : index) {
497  // CHECK: %[[ld:.*]] = vector.load %{{.*}}[%{{.*}}] : memref<200x100xvector<8xf32>>, vector<8xf32>
498  %0 = vector.load %memref[%i, %j] : memref<200x100xvector<8xf32>>, vector<8xf32>
499  // CHECK: vector.store %[[ld]], %{{.*}}[%{{.*}}] : memref<200x100xvector<8xf32>>, vector<8xf32>
500  vector.store %0, %memref[%i, %j] : memref<200x100xvector<8xf32>>, vector<8xf32>
501  return
502}
503
504// CHECK-LABEL: @vector_load_and_store_out_of_bounds
505func @vector_load_and_store_out_of_bounds(%memref : memref<7xf32>) {
506  %c0 = constant 0 : index
507  // CHECK: %[[ld:.*]] = vector.load %{{.*}}[%{{.*}}] : memref<7xf32>, vector<8xf32>
508  %0 = vector.load %memref[%c0] : memref<7xf32>, vector<8xf32>
509  // CHECK: vector.store %[[ld]], %{{.*}}[%{{.*}}] : memref<7xf32>, vector<8xf32>
510  vector.store %0, %memref[%c0] : memref<7xf32>, vector<8xf32>
511  return
512}
513
514// CHECK-LABEL: @vector_load_and_store_2d_scalar_memref
515func @vector_load_and_store_2d_scalar_memref(%memref : memref<200x100xf32>,
516                                             %i : index, %j : index) {
517  // CHECK: %[[ld:.*]] = vector.load %{{.*}}[%{{.*}}] : memref<200x100xf32>, vector<4x8xf32>
518  %0 = vector.load %memref[%i, %j] : memref<200x100xf32>, vector<4x8xf32>
519  // CHECK: vector.store %[[ld]], %{{.*}}[%{{.*}}] : memref<200x100xf32>, vector<4x8xf32>
520  vector.store %0, %memref[%i, %j] : memref<200x100xf32>, vector<4x8xf32>
521  return
522}
523
524// CHECK-LABEL: @vector_load_and_store_2d_vector_memref
525func @vector_load_and_store_2d_vector_memref(%memref : memref<200x100xvector<4x8xf32>>,
526                                             %i : index, %j : index) {
527  // CHECK: %[[ld:.*]] = vector.load %{{.*}}[%{{.*}}] : memref<200x100xvector<4x8xf32>>, vector<4x8xf32>
528  %0 = vector.load %memref[%i, %j] : memref<200x100xvector<4x8xf32>>, vector<4x8xf32>
529  // CHECK: vector.store %[[ld]], %{{.*}}[%{{.*}}] : memref<200x100xvector<4x8xf32>>, vector<4x8xf32>
530  vector.store %0, %memref[%i, %j] : memref<200x100xvector<4x8xf32>>, vector<4x8xf32>
531  return
532}
533
534// CHECK-LABEL: @masked_load_and_store
535func @masked_load_and_store(%base: memref<?xf32>, %mask: vector<16xi1>, %passthru: vector<16xf32>) {
536  %c0 = constant 0 : index
537  // CHECK: %[[X:.*]] = vector.maskedload %{{.*}}[%{{.*}}], %{{.*}}, %{{.*}} : memref<?xf32>, vector<16xi1>, vector<16xf32> into vector<16xf32>
538  %0 = vector.maskedload %base[%c0], %mask, %passthru : memref<?xf32>, vector<16xi1>, vector<16xf32> into vector<16xf32>
539  // CHECK: vector.maskedstore %{{.*}}[%{{.*}}], %{{.*}}, %[[X]] : memref<?xf32>, vector<16xi1>, vector<16xf32>
540  vector.maskedstore %base[%c0], %mask, %0 : memref<?xf32>, vector<16xi1>, vector<16xf32>
541  return
542}
543
544// CHECK-LABEL: @gather_and_scatter
545func @gather_and_scatter(%base: memref<?xf32>, %indices: vector<16xi32>, %mask: vector<16xi1>, %pass_thru: vector<16xf32>) {
546  // CHECK: %[[X:.*]] = vector.gather %{{.*}}[%{{.*}}], %{{.*}}, %{{.*}} : memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32> into vector<16xf32>
547  %0 = vector.gather %base[%indices], %mask, %pass_thru : memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32> into vector<16xf32>
548  // CHECK: vector.scatter %{{.*}}[%{{.*}}], %{{.*}}, %[[X]] : memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32>
549  vector.scatter %base[%indices], %mask, %0 : memref<?xf32>, vector<16xi32>, vector<16xi1>, vector<16xf32>
550  return
551}
552
553// CHECK-LABEL: @expand_and_compress
554func @expand_and_compress(%base: memref<?xf32>, %mask: vector<16xi1>, %pass_thru: vector<16xf32>) {
555  %c0 = constant 0 : index
556  // CHECK: %[[X:.*]] = vector.expandload %{{.*}}[{{.*}}], %{{.*}}, %{{.*}} : memref<?xf32>, vector<16xi1>, vector<16xf32> into vector<16xf32>
557  %0 = vector.expandload %base[%c0], %mask, %pass_thru : memref<?xf32>, vector<16xi1>, vector<16xf32> into vector<16xf32>
558  // CHECK: vector.compressstore %{{.*}}[{{.*}}], %{{.*}}, %[[X]] : memref<?xf32>, vector<16xi1>, vector<16xf32>
559  vector.compressstore %base[%c0], %mask, %0 : memref<?xf32>, vector<16xi1>, vector<16xf32>
560  return
561}
562
563// CHECK-LABEL: @extract_insert_map
564func @extract_insert_map(%v: vector<32xf32>, %v2: vector<16x32xf32>,
565  %id0 : index, %id1 : index) -> (vector<32xf32>, vector<16x32xf32>) {
566  // CHECK: %[[V:.*]] = vector.extract_map %{{.*}}[%{{.*}}] : vector<32xf32> to vector<2xf32>
567  %vd = vector.extract_map %v[%id0] : vector<32xf32> to vector<2xf32>
568  // CHECK: %[[V1:.*]] = vector.extract_map %{{.*}}[%{{.*}}, %{{.*}}] : vector<16x32xf32> to vector<4x2xf32>
569  %vd2 = vector.extract_map %v2[%id0, %id1] : vector<16x32xf32> to vector<4x2xf32>
570  // CHECK: %[[R:.*]] = vector.insert_map %[[V]], %{{.*}}[%{{.*}}] : vector<2xf32> into vector<32xf32>
571  %r = vector.insert_map %vd, %v[%id0] : vector<2xf32> into vector<32xf32>
572  // CHECK: %[[R1:.*]] = vector.insert_map %[[V1]], %{{.*}}[%{{.*}}, %{{.*}}] : vector<4x2xf32> into vector<16x32xf32>
573  %r2 = vector.insert_map %vd2, %v2[%id0, %id1] : vector<4x2xf32> into vector<16x32xf32>
574  // CHECK: return %[[R]], %[[R1]] : vector<32xf32>, vector<16x32xf32>
575  return %r, %r2 : vector<32xf32>, vector<16x32xf32>
576}
577
578