1// RUN: mlir-opt %s -test-linalg-transform-patterns=test-patterns | FileCheck %s
2
3// CHECK-DAG: #[[$STRIDED_1D:.*]] = affine_map<(d0)[s0] -> (d0 + s0)>
4// Map corresponding to a 2D memory access where the stride along the last dim is known to be 1.
5// CHECK-DAG: #[[$STRIDED_2D_u_1:.*]] = affine_map<(d0, d1)[s0, s1] -> (d0 * s1 + s0 + d1)>
6// Map corresponding to a 2D memory access where the stride along all dims are unknown.
7// CHECK-DAG: #[[$STRIDED_2D:.*]] = affine_map<(d0, d1)[s0, s1, s2] -> (d0 * s1 + s0 + d1 * s2)>
8// CHECK-DAG: #[[$kn:.*]] = affine_map<(d0, d1, d2) -> (d2, d1)>
9// CHECK-DAG: #[[$nm:.*]] = affine_map<(d0, d1, d2) -> (d1, d0)>
10// CHECK-DAG: #[[$km:.*]] = affine_map<(d0, d1, d2) -> (d2, d0)>
11
12func @dot(%x: memref<?xf32, offset: ?, strides: [1]>,
13          %y: memref<?xf32, offset: ?, strides: [1]>,
14          %v: memref<f32>) {
15  linalg.dot { __internal_linalg_transform__ = "MEM" }
16    ins(%x, %y: memref<?xf32, offset: ?, strides: [1]>,
17                memref<?xf32, offset: ?, strides: [1]>)
18    outs(%v: memref<f32>)
19
20  return
21}
22// CHECK-LABEL: func @dot
23// CHECK-DAG:     %[[c0:.*]] = constant 0 : index
24// CHECK-DAG:     %[[c1:.*]] = constant 1 : index
25// CHECK-DAG:     %[[c8000:.*]] = constant 8000 : index
26// CHECK:         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c8000]] {
27// CHECK:             scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c1]] {
28// CHECK:               load
29// CHECK:               load
30// CHECK:               load
31// CHECK:               mulf
32// CHECK:               addf
33// CHECK:               store
34
35func @matvec(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
36             %x: memref<?xf32, offset: ?, strides: [1]>,
37             %y: memref<?xf32, offset: ?, strides: [1]>) {
38  linalg.matvec
39    ins(%A, %x: memref<?x?xf32, offset: ?, strides: [?, 1]>,
40                memref<?xf32, offset: ?, strides: [1]>)
41    outs(%y: memref<?xf32, offset: ?, strides: [1]>)
42  return
43}
44// CHECK-LABEL: func @matvec
45// CHECK-DAG:     %[[c0:.*]] = constant 0 : index
46// CHECK-DAG:     %[[c5:.*]] = constant 5 : index
47// CHECK-DAG:     %[[c6:.*]] = constant 6 : index
48// CHECK:         scf.parallel {{.*}} step (%[[c5]])
49// CHECK:           scf.for {{.*}} step %[[c6]]
50// CHECK:             linalg.matvec
51// CHECK:               ins({{.*}}, {{.*}}: memref<?x?xf32, #[[$STRIDED_2D_u_1]]>, memref<?xf32, #[[$STRIDED_1D]]>)
52// CHECK:              outs({{.*}}: memref<?xf32, #[[$STRIDED_1D]]>)
53
54func @matmul(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
55             %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
56             %C: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
57  linalg.matmul { __internal_linalg_transform__ = "MEM" }
58    ins(%A, %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
59                memref<?x?xf32, offset: ?, strides: [?, 1]>)
60    outs(%C: memref<?x?xf32, offset: ?, strides: [?, 1]>)
61  return
62}
63// CHECK-LABEL: func @matmul
64// CHECK-DAG:     %[[c0:.*]] = constant 0 : index
65// CHECK-DAG:     %[[c2:.*]] = constant 2 : index
66// CHECK-DAG:     %[[c3:.*]] = constant 3 : index
67// CHECK-DAG:     %[[c4:.*]] = constant 4 : index
68// CHECK-DAG:     %[[c20:.*]] = constant 20 : index
69// CHECK-DAG:     %[[c30:.*]] = constant 30 : index
70// CHECK-DAG:     %[[c40:.*]] = constant 40 : index
71// CHECK-DAG:     %[[c200:.*]] = constant 200 : index
72// CHECK-DAG:     %[[c300:.*]] = constant 300 : index
73// CHECK-DAG:     %[[c400:.*]] = constant 400 : index
74// CHECK-DAG:     %[[c2000:.*]] = constant 2000 : index
75// CHECK-DAG:     %[[c3000:.*]] = constant 3000 : index
76// CHECK-DAG:     %[[c4000:.*]] = constant 4000 : index
77// CHECK:         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c2000]] {
78// CHECK:           scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c3000]] {
79// CHECK:             scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c4000]] {
80// CHECK:               scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c200]] {
81// CHECK:                 scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c300]] {
82// CHECK:                   scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c400]] {
83// CHECK:                     scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c20]] {
84// CHECK:                       scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c30]] {
85// CHECK:                         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c40]] {
86// CHECK:                           scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c2]] {
87// CHECK:                             scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c3]] {
88// CHECK:                               scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c4]] {
89// CHECK:                                 linalg.matmul
90// CHECK:                                   ins({{.*}}, {{.*}}: memref<?x?xf32, #[[$STRIDED_2D_u_1]]>, memref<?x?xf32, #[[$STRIDED_2D_u_1]]>)
91// CHECK:                                  outs({{.*}}: memref<?x?xf32, #[[$STRIDED_2D_u_1]]>)
92
93#matmul_accesses = [
94  affine_map<(m, n, k) -> (m, k)>,
95  affine_map<(m, n, k) -> (k, n)>,
96  affine_map<(m, n, k) -> (m, n)>
97]
98#generic_matmul_trait = {
99  args_in = 2,
100  args_out = 1,
101  indexing_maps = #matmul_accesses,
102  library_call = "linalg_matmul",
103  iterator_types = ["parallel", "parallel", "reduction"]
104}
105func @permute_generic(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
106           %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
107           %C: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
108  linalg.generic #generic_matmul_trait
109    ins(%A, %B : memref<?x?xf32, offset: ?, strides: [?, 1]>,
110                 memref<?x?xf32, offset: ?, strides: [?, 1]>)
111   outs(%C : memref<?x?xf32, offset: ?, strides: [?, 1]>) {
112    ^bb(%a: f32, %b: f32, %c: f32):
113      %d = mulf %a, %b: f32
114      %e = addf %c, %d: f32
115      linalg.yield %e: f32
116  }
117  return
118}
119// CHECK-LABEL:  func @permute_generic
120// CHECK:        linalg.generic {
121// CHECK-SAME:   indexing_maps = [#[[$kn]], #[[$nm]], #[[$km]]],
122// CHECK-SAME:   iterator_types = ["parallel", "reduction", "parallel"],
123// CHECK-SAME:   library_call = "linalg_matmul"}
124// CHECK:          memref<?x?xf32, #[[$STRIDED_2D_u_1]]>,
125// CHECK-SAME:     memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
126// CHECK-SAME:     memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
127
128#indexed_matmul_trait = {
129  args_in = 2,
130  args_out = 1,
131  indexing_maps = #matmul_accesses,
132  library_call = "linalg_matmul_indexed",
133  iterator_types = ["parallel", "parallel", "reduction"]
134}
135func @permute_generic_indexed(
136    %A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
137    %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
138    %C: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
139  linalg.indexed_generic #indexed_matmul_trait
140    ins(%A, %B : memref<?x?xf32, offset: ?, strides: [?, 1]>,
141                 memref<?x?xf32, offset: ?, strides: [?, 1]>)
142   outs(%C : memref<?x?xf32, offset: ?, strides: [?, 1]>) {
143    ^bb(%i: index, %j: index, %k: index, %a: f32, %b: f32, %c: f32):
144      %d = mulf %a, %b: f32
145      %e = addf %c, %d: f32
146      linalg.yield %e: f32
147  }
148  return
149}
150// CHECK-LABEL:  func @permute_generic_indexed
151// CHECK:        linalg.indexed_generic {
152// CHECK-SAME:     indexing_maps = [#[[$kn]], #[[$nm]], #[[$km]]],
153// CHECK-SAME:     iterator_types = ["parallel", "reduction", "parallel"],
154// CHECK-SAME:     library_call = "linalg_matmul_indexed"}
155// CHECK:            memref<?x?xf32, #[[$STRIDED_2D_u_1]]>,
156// CHECK-SAME:       memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
157// CHECK-SAME:       memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
158
159func @matvec_perm(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
160             %x: memref<?xf32, offset: ?, strides: [1]>,
161             %y: memref<?xf32, offset: ?, strides: [1]>) {
162  linalg.matvec {__internal_linalg_transform__ = "__with_perm__"}
163    ins(%A, %x: memref<?x?xf32, offset: ?, strides: [?, 1]>,
164                memref<?xf32, offset: ?, strides: [1]>)
165   outs(%y: memref<?xf32, offset: ?, strides: [1]>)
166  return
167}
168// CHECK-LABEL: func @matvec_perm
169// CHECK-DAG:     %[[c0:.*]] = constant 0 : index
170// CHECK-DAG:     %[[c5:.*]] = constant 5 : index
171// CHECK-DAG:     %[[c6:.*]] = constant 6 : index
172// CHECK:         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c6]]
173// CHECK:           scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c5]]
174// CHECK:             linalg.matvec
175// CHECK:               ins({{.*}}, {{.*}}: memref<?x?xf32, #[[$STRIDED_2D_u_1]]>, memref<?xf32, #[[$STRIDED_1D]]>)
176// CHECK:              outs({{.*}}: memref<?xf32, #[[$STRIDED_1D]]>)
177
178func @matmul_perm(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
179             %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
180             %C: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
181  linalg.matmul {__internal_linalg_transform__ = "__with_perm__"}
182    ins(%A, %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
183                memref<?x?xf32, offset: ?, strides: [?, 1]>)
184   outs(%C : memref<?x?xf32, offset: ?, strides: [?, 1]>)
185  return
186}
187// CHECK-LABEL: func @matmul_perm
188// CHECK-DAG:     %[[c0:.*]] = constant 0 : index
189// CHECK-DAG:     %[[c20:.*]] = constant 20 : index
190// CHECK-DAG:     %[[c30:.*]] = constant 30 : index
191// CHECK-DAG:     %[[c40:.*]] = constant 40 : index
192// CHECK-DAG:     %[[c200:.*]] = constant 200 : index
193// CHECK-DAG:     %[[c300:.*]] = constant 300 : index
194// CHECK-DAG:     %[[c400:.*]] = constant 400 : index
195// CHECK-DAG:     %[[c2000:.*]] = constant 2000 : index
196// CHECK-DAG:     %[[c3000:.*]] = constant 3000 : index
197// CHECK-DAG:     %[[c4000:.*]] = constant 4000 : index
198// CHECK:         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c3000]] {
199// CHECK:           scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c4000]] {
200// CHECK:             scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c2000]] {
201// CHECK:               scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c300]] {
202// CHECK:                 scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c200]] {
203// CHECK:                   scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c400]] {
204// CHECK:                     scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c20]] {
205// CHECK:                       scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c30]] {
206// CHECK:                         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c40]] {
207// CHECK:                                 linalg.matmul
208// CHECK:                                  ins({{.*}}, {{.*}}: memref<?x?xf32, #[[$STRIDED_2D_u_1]]>, memref<?x?xf32, #[[$STRIDED_2D_u_1]]>)
209// CHECK:                                   outs({{.*}}: memref<?x?xf32, #[[$STRIDED_2D_u_1]]>)
210
211func @promote_subview_matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
212                             %arg1: memref<?x?xf32, offset: ?, strides: [?, 1]>,
213                             %arg2: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
214  %c2000 = constant 2000 : index
215  %c3000 = constant 3000 : index
216  %c4000 = constant 4000 : index
217  %c0 = constant 0 : index
218  %c1 = constant 1 : index
219  %0 = memref.dim %arg0, %c0 : memref<?x?xf32, offset: ?, strides: [?, 1]>
220  %1 = memref.dim %arg0, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
221  %2 = memref.dim %arg1, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
222  scf.for %arg3 = %c0 to %0 step %c2000 {
223    scf.for %arg4 = %c0 to %2 step %c3000 {
224      scf.for %arg5 = %c0 to %1 step %c4000 {
225        %3 = memref.subview %arg0[%arg3, %arg5][%c2000, %c4000][%c1, %c1] :
226             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
227        %4 = memref.subview %arg1[%arg5, %arg4][%c4000, %c3000][%c1, %c1] :
228             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
229        %5 = memref.subview %arg2[%arg3, %arg4][%c2000, %c3000][%c1, %c1] :
230             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
231        linalg.matmul {__internal_linalg_transform__ = "_promote_views_"}
232          ins(%3, %4: memref<?x?xf32, offset: ?, strides: [?, ?]>,
233                      memref<?x?xf32, offset: ?, strides: [?, ?]>)
234         outs(%5: memref<?x?xf32, offset: ?, strides: [?, ?]>)
235      }
236    }
237  }
238  return
239}
240// CHECK-LABEL: func @promote_subview_matmul
241// CHECK-DAG:     %[[c0:.*]] = constant 0 : index
242// CHECK-DAG:     %[[c2000:.*]] = constant 2000 : index
243// CHECK-DAG:     %[[c3000:.*]] = constant 3000 : index
244// CHECK-DAG:     %[[c4000:.*]] = constant 4000 : index
245// CHECK:         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c2000]] {
246// CHECK:           scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c3000]] {
247// CHECK:             scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c4000]] {
248// CHECK:               %[[s0:.*]] = memref.subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
249// CHECK:               %[[s1:.*]] = memref.subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
250// CHECK:               %[[s2:.*]] = memref.subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
251// CHECK:               %[[a0:.*]] = memref.alloc({{%.*}}) : memref<?xi8>
252// CHECK:               %[[v0:.*]] = memref.view %[[a0]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
253// CHECK:               %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1]
254// CHECK-SAME:            memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
255// CHECK:               %[[a1:.*]] = memref.alloc({{%.*}}) : memref<?xi8>
256// CHECK:               %[[v1:.*]] = memref.view %[[a1]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
257// CHECK:               %[[l1:.*]] = memref.subview %[[v1]][0, 0] [%{{.*}}, %{{.*}}] [1, 1]
258// CHECK-SAME:            memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
259// CHECK:               %[[a2:.*]] = memref.alloc({{%.*}}) : memref<?xi8>
260// CHECK:               %[[v2:.*]] = memref.view %[[a2]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
261// CHECK:               %[[l2:.*]] = memref.subview %[[v2]][0, 0] [%{{.*}}, %{{.*}}] [1, 1]
262// CHECK-SAME:            memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
263// CHECK:               linalg.copy(%[[s0]], %[[l0]]) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>
264// CHECK:               linalg.copy(%[[s1]], %[[l1]]) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>
265// CHECK:               linalg.copy(%[[s2]], %[[l2]]) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>
266// CHECK:               linalg.matmul
267// CHECK-SAME:                 ins(%[[v0]], %[[v1]] : memref<?x?xf32>, memref<?x?xf32>)
268// CHECK-SAME:                outs(%[[v2]] : memref<?x?xf32>)
269
270func @promote_first_subview_matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
271                             %arg1: memref<?x?xf32, offset: ?, strides: [?, 1]>,
272                             %arg2: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
273  %c2000 = constant 2000 : index
274  %c3000 = constant 3000 : index
275  %c4000 = constant 4000 : index
276  %c0 = constant 0 : index
277  %c1 = constant 1 : index
278  %0 = memref.dim %arg0, %c0 : memref<?x?xf32, offset: ?, strides: [?, 1]>
279  %1 = memref.dim %arg0, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
280  %2 = memref.dim %arg1, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
281  scf.for %arg3 = %c0 to %0 step %c2000 {
282    scf.for %arg4 = %c0 to %2 step %c3000 {
283      scf.for %arg5 = %c0 to %1 step %c4000 {
284        %3 = memref.subview %arg0[%arg3, %arg5][%c2000, %c4000][%c1, %c1] :
285             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
286        %4 = memref.subview %arg1[%arg5, %arg4][%c4000, %c3000][%c1, %c1] :
287             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
288        %5 = memref.subview %arg2[%arg3, %arg4][%c2000, %c3000][%c1, %c1] :
289             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
290        linalg.matmul {__internal_linalg_transform__ = "_promote_first_view_"}
291          ins(%3, %4: memref<?x?xf32, offset: ?, strides: [?, ?]>,
292                      memref<?x?xf32, offset: ?, strides: [?, ?]>)
293         outs(%5: memref<?x?xf32, offset: ?, strides: [?, ?]>)
294      }
295    }
296  }
297  return
298}
299// CHECK-LABEL: func @promote_first_subview_matmul
300// CHECK-DAG:     %[[c0:.*]] = constant 0 : index
301// CHECK-DAG:     %[[c2000:.*]] = constant 2000 : index
302// CHECK-DAG:     %[[c3000:.*]] = constant 3000 : index
303// CHECK-DAG:     %[[c4000:.*]] = constant 4000 : index
304// CHECK:   scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c2000]] {
305// CHECK:     scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c3000]] {
306// CHECK:       scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c4000]] {
307// CHECK:         %[[s0:.*]] = memref.subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
308// CHECK:         %[[s1:.*]] = memref.subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
309// CHECK:         %[[s2:.*]] = memref.subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
310// CHECK:         %[[a0:.*]] = memref.alloc({{%.*}}) : memref<?xi8>
311// CHECK:         %[[v0:.*]] = memref.view %[[a0]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
312// CHECK:         %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
313// CHECK-NOT:     %{{.*}} = memref.alloc({{%.*}}) : memref<?xi8>
314// CHECK-NOT:     %{{.*}} = memref.view %{{.*}}[{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
315// CHECK-NOT:     %{{.*}} = memref.subview %{{.*}}[0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
316// CHECK-NOT:     %{{.*}} = memref.alloc({{%.*}}) : memref<?xi8>
317// CHECK-NOT:     %{{.*}} = memref.view %{{.*}}[{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
318// CHECK-NOT:     %{{.*}} = memref.subview %{{.*}}[0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
319// CHECK:         linalg.copy(%[[s0]], %[[l0]]) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>
320// CHECK-NOT:     linalg.copy(%[[s1]], %{{.*}}) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>
321// CHECK-NOT:     linalg.copy(%[[s2]], %{{.*}}) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>^
322// CHECK:         linalg.matmul
323// CHECK-SAME:           ins(%[[v0]], %[[s1]] : memref<?x?xf32>, memref<?x?xf32, #[[$STRIDED_2D]]>)
324// CHECK-SAME:          outs(%[[s2]] : memref<?x?xf32, #[[$STRIDED_2D]]>)
325
326func @aligned_promote_fill(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
327  %c2000 = constant 2000 : index
328  %c4000 = constant 4000 : index
329  %c0 = constant 0 : index
330  %c1 = constant 1 : index
331  %cf = constant 1.0 : f32
332  %3 = memref.subview %arg0[%c0, %c0][%c2000, %c4000][%c1, %c1] :
333 	 memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
334  linalg.fill(%3, %cf) { __internal_linalg_transform__ = "_promote_views_aligned_"}
335  	:  memref<?x?xf32, offset: ?, strides: [?, ?]>, f32
336  return
337}
338// CHECK-LABEL: func @aligned_promote_fill
339// CHECK:	  %[[cf:.*]] = constant {{.*}} : f32
340// CHECK:         %[[s0:.*]] = memref.subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
341// CHECK:         %[[a0:.*]] = memref.alloc({{%.*}}) {alignment = 32 : i64} : memref<?xi8>
342// CHECK:         %[[v0:.*]] = memref.view %[[a0]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xf32>
343// CHECK:         %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
344// CHECK:         linalg.fill(%[[v0]], {{%.*}}) : memref<?x?xf32>, f32
345// CHECK:         linalg.copy(%[[s0]], %[[l0]]) : memref<?x?xf32, #map{{.*}}>, memref<?x?xf32, #map{{.*}}>
346// CHECK:         linalg.fill(%[[v0]], %[[cf]]) : memref<?x?xf32>, f32
347
348func @aligned_promote_fill_complex(%arg0: memref<?x?xcomplex<f32>, offset: ?, strides: [?, 1]>) {
349  %c2000 = constant 2000 : index
350  %c4000 = constant 4000 : index
351  %c0 = constant 0 : index
352  %c1 = constant 1 : index
353  %cf = constant 1.0 : f32
354  %cc = complex.create %cf, %cf : complex<f32>
355  %3 = memref.subview %arg0[%c0, %c0][%c2000, %c4000][%c1, %c1] :
356 	 memref<?x?xcomplex<f32>, offset: ?, strides: [?, 1]> to memref<?x?xcomplex<f32>, offset: ?, strides: [?, ?]>
357  linalg.fill(%3, %cc) { __internal_linalg_transform__ = "_promote_views_aligned_"}
358  	:  memref<?x?xcomplex<f32>, offset: ?, strides: [?, ?]>, complex<f32>
359  return
360}
361// CHECK-LABEL: func @aligned_promote_fill_complex
362// CHECK:	  %[[cc:.*]] = complex.create {{.*}} : complex<f32>
363// CHECK:         %[[s0:.*]] = memref.subview {{%.*}}[{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] [{{%.*}}, {{%.*}}] : memref<?x?xcomplex<f32>, #map{{.*}}> to memref<?x?xcomplex<f32>, #map{{.*}}>
364// CHECK:         %[[a0:.*]] = memref.alloc({{%.*}}) {alignment = 32 : i64} : memref<?xi8>
365// CHECK:         %[[v0:.*]] = memref.view %[[a0]][{{.*}}][{{%.*}}, {{%.*}}] : memref<?xi8> to memref<?x?xcomplex<f32>>
366// CHECK:         %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xcomplex<f32>> to memref<?x?xcomplex<f32>, #[[$STRIDED_2D_u_1]]>
367// CHECK:         linalg.fill(%[[v0]], {{%.*}}) : memref<?x?xcomplex<f32>>, complex<f32>
368// CHECK:         linalg.copy(%[[s0]], %[[l0]]) : memref<?x?xcomplex<f32>, #map{{.*}}>, memref<?x?xcomplex<f32>, #map{{.*}}>
369// CHECK:         linalg.fill(%[[v0]], %[[cc]]) : memref<?x?xcomplex<f32>>, complex<f32>
370
371func @tile_permute_parallel_loop(%arg0: memref<?x?xf32>,
372                                 %arg1: memref<?x?xf32>,
373                                 %arg2: memref<?x?xf32>) {
374  linalg.matmul {__internal_linalg_transform__ = "par__with_perm__"}
375    ins(%arg0, %arg1: memref<?x?xf32>, memref<?x?xf32>)
376   outs(%arg2: memref<?x?xf32>)
377  return
378}
379// CHECK-LABEL: func @tile_permute_parallel_loop
380//  CHECK-SAME:   %[[ARG0:[a-zA-Z0-9_]+]]: memref<?x?xf32>
381//  CHECK-SAME:   %[[ARG1:[a-zA-Z0-9_]+]]: memref<?x?xf32>
382//  CHECK-SAME:   %[[ARG2:[a-zA-Z0-9_]+]]: memref<?x?xf32>
383//   CHECK-DAG:   %[[C16:.*]] = constant 16 : index
384//   CHECK-DAG:   %[[C8:.*]] = constant 8 : index
385//   CHECK-DAG:   %[[C4:.*]] = constant 4 : index
386//   CHECK-DAG:   %[[C0:.*]] = constant 0 : index
387//   CHECK-DAG:   %[[D0:.*]] = memref.dim %[[ARG0]], %c0
388//   CHECK-DAG:   %[[D1:.*]] = memref.dim %[[ARG0]], %c1
389//   CHECK-DAG:   %[[D2:.*]] = memref.dim %[[ARG1]], %c1
390//       CHECK:   scf.parallel (%{{.*}}) = (%[[C0]]) to (%[[D2]]) step (%[[C8]])
391//       CHECK:     scf.for %{{.*}} = %[[C0]] to %[[D1]] step %[[C4]]
392//       CHECK:       scf.parallel (%{{.*}}) = (%[[C0]]) to (%[[D0]]) step (%[[C16]])
393