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:.*]] = arith.constant 0 : index
24// CHECK-DAG:     %[[c1:.*]] = arith.constant 1 : index
25// CHECK-DAG:     %[[c8000:.*]] = arith.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:               arith.mulf
32// CHECK:               arith.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:.*]] = arith.constant 0 : index
46// CHECK-DAG:     %[[c5:.*]] = arith.constant 5 : index
47// CHECK-DAG:     %[[c6:.*]] = arith.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:.*]] = arith.constant 0 : index
65// CHECK-DAG:     %[[c2:.*]] = arith.constant 2 : index
66// CHECK-DAG:     %[[c3:.*]] = arith.constant 3 : index
67// CHECK-DAG:     %[[c4:.*]] = arith.constant 4 : index
68// CHECK-DAG:     %[[c20:.*]] = arith.constant 20 : index
69// CHECK-DAG:     %[[c30:.*]] = arith.constant 30 : index
70// CHECK-DAG:     %[[c40:.*]] = arith.constant 40 : index
71// CHECK-DAG:     %[[c200:.*]] = arith.constant 200 : index
72// CHECK-DAG:     %[[c300:.*]] = arith.constant 300 : index
73// CHECK-DAG:     %[[c400:.*]] = arith.constant 400 : index
74// CHECK-DAG:     %[[c2000:.*]] = arith.constant 2000 : index
75// CHECK-DAG:     %[[c3000:.*]] = arith.constant 3000 : index
76// CHECK-DAG:     %[[c4000:.*]] = arith.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 = arith.mulf %a, %b: f32
114      %e = arith.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
128func @matvec_perm(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
129             %x: memref<?xf32, offset: ?, strides: [1]>,
130             %y: memref<?xf32, offset: ?, strides: [1]>) {
131  linalg.matvec {__internal_linalg_transform__ = "__with_perm__"}
132    ins(%A, %x: memref<?x?xf32, offset: ?, strides: [?, 1]>,
133                memref<?xf32, offset: ?, strides: [1]>)
134   outs(%y: memref<?xf32, offset: ?, strides: [1]>)
135  return
136}
137// CHECK-LABEL: func @matvec_perm
138// CHECK-DAG:     %[[c0:.*]] = arith.constant 0 : index
139// CHECK-DAG:     %[[c5:.*]] = arith.constant 5 : index
140// CHECK-DAG:     %[[c6:.*]] = arith.constant 6 : index
141// CHECK:         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c6]]
142// CHECK:           scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c5]]
143// CHECK:             linalg.matvec
144// CHECK:               ins({{.*}}: memref<?x?xf32, #[[$STRIDED_2D_u_1]]>, memref<?xf32, #[[$STRIDED_1D]]>)
145// CHECK:              outs({{.*}}: memref<?xf32, #[[$STRIDED_1D]]>)
146
147func @matmul_perm(%A: memref<?x?xf32, offset: ?, strides: [?, 1]>,
148             %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
149             %C: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
150  linalg.matmul {__internal_linalg_transform__ = "__with_perm__"}
151    ins(%A, %B: memref<?x?xf32, offset: ?, strides: [?, 1]>,
152                memref<?x?xf32, offset: ?, strides: [?, 1]>)
153   outs(%C : memref<?x?xf32, offset: ?, strides: [?, 1]>)
154  return
155}
156// CHECK-LABEL: func @matmul_perm
157// CHECK-DAG:     %[[c0:.*]] = arith.constant 0 : index
158// CHECK-DAG:     %[[c20:.*]] = arith.constant 20 : index
159// CHECK-DAG:     %[[c30:.*]] = arith.constant 30 : index
160// CHECK-DAG:     %[[c40:.*]] = arith.constant 40 : index
161// CHECK-DAG:     %[[c200:.*]] = arith.constant 200 : index
162// CHECK-DAG:     %[[c300:.*]] = arith.constant 300 : index
163// CHECK-DAG:     %[[c400:.*]] = arith.constant 400 : index
164// CHECK-DAG:     %[[c2000:.*]] = arith.constant 2000 : index
165// CHECK-DAG:     %[[c3000:.*]] = arith.constant 3000 : index
166// CHECK-DAG:     %[[c4000:.*]] = arith.constant 4000 : index
167// CHECK:         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c3000]] {
168// CHECK:           scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c4000]] {
169// CHECK:             scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c2000]] {
170// CHECK:               scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c300]] {
171// CHECK:                 scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c200]] {
172// CHECK:                   scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c400]] {
173// CHECK:                     scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c20]] {
174// CHECK:                       scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c30]] {
175// CHECK:                         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c40]] {
176// CHECK:                                 linalg.matmul
177// CHECK:                                  ins({{.*}}: memref<?x?xf32, #[[$STRIDED_2D_u_1]]>, memref<?x?xf32, #[[$STRIDED_2D_u_1]]>)
178// CHECK:                                   outs({{.*}}: memref<?x?xf32, #[[$STRIDED_2D_u_1]]>)
179
180func @promote_subview_matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
181                             %arg1: memref<?x?xf32, offset: ?, strides: [?, 1]>,
182                             %arg2: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
183  %c2000 = arith.constant 2000 : index
184  %c3000 = arith.constant 3000 : index
185  %c4000 = arith.constant 4000 : index
186  %c0 = arith.constant 0 : index
187  %c1 = arith.constant 1 : index
188  %0 = memref.dim %arg0, %c0 : memref<?x?xf32, offset: ?, strides: [?, 1]>
189  %1 = memref.dim %arg0, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
190  %2 = memref.dim %arg1, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
191  scf.for %arg3 = %c0 to %0 step %c2000 {
192    scf.for %arg4 = %c0 to %2 step %c3000 {
193      scf.for %arg5 = %c0 to %1 step %c4000 {
194        %3 = memref.subview %arg0[%arg3, %arg5][%c2000, %c4000][%c1, %c1] :
195             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
196        %4 = memref.subview %arg1[%arg5, %arg4][%c4000, %c3000][%c1, %c1] :
197             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
198        %5 = memref.subview %arg2[%arg3, %arg4][%c2000, %c3000][%c1, %c1] :
199             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
200        linalg.matmul {__internal_linalg_transform__ = "_promote_views_"}
201          ins(%3, %4: memref<?x?xf32, offset: ?, strides: [?, ?]>,
202                      memref<?x?xf32, offset: ?, strides: [?, ?]>)
203         outs(%5: memref<?x?xf32, offset: ?, strides: [?, ?]>)
204      }
205    }
206  }
207  return
208}
209// CHECK-LABEL: func @promote_subview_matmul
210// CHECK-DAG:     %[[c0:.*]] = arith.constant 0 : index
211// CHECK-DAG:     %[[c2000:.*]] = arith.constant 2000 : index
212// CHECK-DAG:     %[[c3000:.*]] = arith.constant 3000 : index
213// CHECK-DAG:     %[[c4000:.*]] = arith.constant 4000 : index
214// CHECK:         scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c2000]] {
215// CHECK:           scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c3000]] {
216// CHECK:             scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c4000]] {
217// CHECK:               %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
218// CHECK:               %[[s1:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
219// CHECK:               %[[s2:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
220// CHECK:               %[[a0:.*]] = memref.alloc() : memref<32000000xi8>
221// CHECK:               %[[v0:.*]] = memref.view %[[a0]]{{.*}} : memref<32000000xi8> to memref<?x?xf32>
222// CHECK:               %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1]
223// CHECK-SAME:            memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
224// CHECK:               %[[a1:.*]] = memref.alloc() : memref<48000000xi8>
225// CHECK:               %[[v1:.*]] = memref.view %[[a1]]{{.*}} : memref<48000000xi8> to memref<?x?xf32>
226// CHECK:               %[[l1:.*]] = memref.subview %[[v1]][0, 0] [%{{.*}}, %{{.*}}] [1, 1]
227// CHECK-SAME:            memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
228// CHECK:               %[[a2:.*]] = memref.alloc() : memref<24000000xi8>
229// CHECK:               %[[v2:.*]] = memref.view %[[a2]]{{.*}} : memref<24000000xi8> to memref<?x?xf32>
230// CHECK:               %[[l2:.*]] = memref.subview %[[v2]][0, 0] [%{{.*}}, %{{.*}}] [1, 1]
231// CHECK-SAME:            memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
232// CHECK:               memref.copy %[[s0]], %[[l0]] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
233// CHECK:               memref.copy %[[s1]], %[[l1]] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
234// CHECK:               memref.copy %[[s2]], %[[l2]] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
235// CHECK:               linalg.matmul
236// CHECK-SAME:                 ins(%[[v0]], %[[v1]] : memref<?x?xf32>, memref<?x?xf32>)
237// CHECK-SAME:                outs(%[[v2]] : memref<?x?xf32>)
238
239func @promote_first_subview_matmul(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>,
240                             %arg1: memref<?x?xf32, offset: ?, strides: [?, 1]>,
241                             %arg2: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
242  %c2000 = arith.constant 2000 : index
243  %c3000 = arith.constant 3000 : index
244  %c4000 = arith.constant 4000 : index
245  %c0 = arith.constant 0 : index
246  %c1 = arith.constant 1 : index
247  %0 = memref.dim %arg0, %c0 : memref<?x?xf32, offset: ?, strides: [?, 1]>
248  %1 = memref.dim %arg0, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
249  %2 = memref.dim %arg1, %c1 : memref<?x?xf32, offset: ?, strides: [?, 1]>
250  scf.for %arg3 = %c0 to %0 step %c2000 {
251    scf.for %arg4 = %c0 to %2 step %c3000 {
252      scf.for %arg5 = %c0 to %1 step %c4000 {
253        %3 = memref.subview %arg0[%arg3, %arg5][%c2000, %c4000][%c1, %c1] :
254             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
255        %4 = memref.subview %arg1[%arg5, %arg4][%c4000, %c3000][%c1, %c1] :
256             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
257        %5 = memref.subview %arg2[%arg3, %arg4][%c2000, %c3000][%c1, %c1] :
258             memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
259        linalg.matmul {__internal_linalg_transform__ = "_promote_first_view_"}
260          ins(%3, %4: memref<?x?xf32, offset: ?, strides: [?, ?]>,
261                      memref<?x?xf32, offset: ?, strides: [?, ?]>)
262         outs(%5: memref<?x?xf32, offset: ?, strides: [?, ?]>)
263      }
264    }
265  }
266  return
267}
268// CHECK-LABEL: func @promote_first_subview_matmul
269// CHECK-DAG:     %[[c0:.*]] = arith.constant 0 : index
270// CHECK-DAG:     %[[c2000:.*]] = arith.constant 2000 : index
271// CHECK-DAG:     %[[c3000:.*]] = arith.constant 3000 : index
272// CHECK-DAG:     %[[c4000:.*]] = arith.constant 4000 : index
273// CHECK:   scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c2000]] {
274// CHECK:     scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c3000]] {
275// CHECK:       scf.for {{.*}} = %[[c0]] to {{.*}} step %[[c4000]] {
276// CHECK:         %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
277// CHECK:         %[[s1:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
278// CHECK:         %[[s2:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
279// CHECK:         %[[a0:.*]] = memref.alloc() : memref<32000000xi8>
280// CHECK:         %[[v0:.*]] = memref.view %[[a0]]{{.*}} : memref<32000000xi8> to memref<?x?xf32>
281// CHECK:         %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
282// CHECK-NOT:     memref.alloc
283// CHECK-NOT:     memref.view
284// CHECK-NOT:     memref.subview
285// CHECK:         memref.copy %[[s0]], %[[l0]] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
286// CHECK-NOT:     memref.copy
287// CHECK:         linalg.matmul
288// CHECK-SAME:           ins(%[[v0]], %[[s1]] : memref<?x?xf32>, memref<?x?xf32, #[[$STRIDED_2D]]>)
289// CHECK-SAME:          outs(%[[s2]] : memref<?x?xf32, #[[$STRIDED_2D]]>)
290
291func @aligned_promote_fill(%arg0: memref<?x?xf32, offset: ?, strides: [?, 1]>) {
292  %c2000 = arith.constant 2000 : index
293  %c4000 = arith.constant 4000 : index
294  %c0 = arith.constant 0 : index
295  %c1 = arith.constant 1 : index
296  %cf = arith.constant 1.0 : f32
297  %3 = memref.subview %arg0[%c0, %c0][%c2000, %c4000][%c1, %c1] :
298 	 memref<?x?xf32, offset: ?, strides: [?, 1]> to memref<?x?xf32, offset: ?, strides: [?, ?]>
299  linalg.fill { __internal_linalg_transform__ = "_promote_views_aligned_"}
300   ins(%cf : f32) outs(%3 : memref<?x?xf32, offset: ?, strides: [?, ?]>)
301  return
302}
303// CHECK-LABEL: func @aligned_promote_fill
304// CHECK:	  %[[cf:.*]] = arith.constant {{.*}} : f32
305// CHECK:         %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
306// CHECK:         %[[a0:.*]] = memref.alloc() {alignment = 32 : i64} : memref<32000000xi8>
307// CHECK:         %[[v0:.*]] = memref.view %[[a0]]{{.*}} : memref<32000000xi8> to memref<?x?xf32>
308// CHECK:         %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xf32> to memref<?x?xf32, #[[$STRIDED_2D_u_1]]>
309// CHECK:         linalg.fill ins({{.*}} : f32) outs(%[[v0]] : memref<?x?xf32>)
310// CHECK:         memref.copy %[[s0]], %[[l0]] : memref<?x?xf32, #map{{.*}}> to memref<?x?xf32, #map{{.*}}>
311// CHECK:         linalg.fill ins(%[[cf]] : f32) outs(%[[v0]] : memref<?x?xf32>)
312
313func @aligned_promote_fill_complex(%arg0: memref<?x?xcomplex<f32>, offset: ?, strides: [?, 1]>) {
314  %c2000 = arith.constant 2000 : index
315  %c4000 = arith.constant 4000 : index
316  %c0 = arith.constant 0 : index
317  %c1 = arith.constant 1 : index
318  %cf = arith.constant 1.0 : f32
319  %cc = complex.create %cf, %cf : complex<f32>
320  %3 = memref.subview %arg0[%c0, %c0][%c2000, %c4000][%c1, %c1] :
321 	 memref<?x?xcomplex<f32>, offset: ?, strides: [?, 1]> to memref<?x?xcomplex<f32>, offset: ?, strides: [?, ?]>
322  linalg.fill { __internal_linalg_transform__ = "_promote_views_aligned_"}
323   ins(%cc : complex<f32>) outs(%3 : memref<?x?xcomplex<f32>, offset: ?, strides: [?, ?]>)
324  return
325}
326// CHECK-LABEL: func @aligned_promote_fill_complex
327// CHECK:	  %[[cc:.*]] = complex.create {{.*}} : complex<f32>
328// CHECK:         %[[s0:.*]] = memref.subview {{.*}}: memref<?x?xcomplex<f32>, #map{{.*}}> to memref<?x?xcomplex<f32>, #map{{.*}}>
329// CHECK:         %[[a0:.*]] = memref.alloc() {alignment = 32 : i64} : memref<64000000xi8>
330// CHECK:         %[[v0:.*]] = memref.view %[[a0]]{{.*}} : memref<64000000xi8> to memref<?x?xcomplex<f32>>
331// CHECK:         %[[l0:.*]] = memref.subview %[[v0]][0, 0] [%{{.*}}, %{{.*}}] [1, 1] : memref<?x?xcomplex<f32>> to memref<?x?xcomplex<f32>, #[[$STRIDED_2D_u_1]]>
332// CHECK:         linalg.fill ins({{.*}} : complex<f32>) outs(%[[v0]] : memref<?x?xcomplex<f32>>)
333// CHECK:         memref.copy %[[s0]], %[[l0]] : memref<?x?xcomplex<f32>, #map{{.*}}> to memref<?x?xcomplex<f32>, #map{{.*}}>
334// CHECK:         linalg.fill ins(%[[cc]] : complex<f32>) outs(%[[v0]] : memref<?x?xcomplex<f32>>)
335
336func @tile_permute_parallel_loop(%arg0: memref<?x?xf32>,
337                                 %arg1: memref<?x?xf32>,
338                                 %arg2: memref<?x?xf32>) {
339  linalg.matmul {__internal_linalg_transform__ = "par__with_perm__"}
340    ins(%arg0, %arg1: memref<?x?xf32>, memref<?x?xf32>)
341   outs(%arg2: memref<?x?xf32>)
342  return
343}
344// CHECK-LABEL: func @tile_permute_parallel_loop
345//  CHECK-SAME:   %[[ARG0:[a-zA-Z0-9_]+]]: memref<?x?xf32>
346//  CHECK-SAME:   %[[ARG1:[a-zA-Z0-9_]+]]: memref<?x?xf32>
347//  CHECK-SAME:   %[[ARG2:[a-zA-Z0-9_]+]]: memref<?x?xf32>
348//   CHECK-DAG:   %[[C16:.*]] = arith.constant 16 : index
349//   CHECK-DAG:   %[[C8:.*]] = arith.constant 8 : index
350//   CHECK-DAG:   %[[C4:.*]] = arith.constant 4 : index
351//   CHECK-DAG:   %[[C0:.*]] = arith.constant 0 : index
352//   CHECK-DAG:   %[[D0:.*]] = memref.dim %[[ARG0]], %c0
353//   CHECK-DAG:   %[[D1:.*]] = memref.dim %[[ARG0]], %c1
354//   CHECK-DAG:   %[[D2:.*]] = memref.dim %[[ARG1]], %c1
355//       CHECK:   scf.parallel (%{{.*}}) = (%[[C0]]) to (%[[D2]]) step (%[[C8]])
356//       CHECK:     scf.for %{{.*}} = %[[C0]] to %[[D1]] step %[[C4]]
357//       CHECK:       scf.parallel (%{{.*}}) = (%[[C0]]) to (%[[D0]]) step (%[[C16]])
358