1// RUN: mlir-opt -test-linalg-decompose-ops -cse -split-input-file %s | FileCheck %s
2// RUN: mlir-opt -test-linalg-decompose-ops -cse -canonicalize -split-input-file %s | FileCheck %s --check-prefix=CANONICALIZECHECK
3
4func.func @simple_op(%arg0 : tensor<?x?xf32>, %arg1 : tensor<?xf32>, %arg2 : tensor<?xf32>)
5    -> (tensor<?x?xf32>, tensor<?x?xf32>) {
6  %c0 = arith.constant 0 : index
7  %c1 = arith.constant 1 : index
8  %d0 = tensor.dim %arg0, %c0 : tensor<?x?xf32>
9  %d1 = tensor.dim %arg0, %c1 : tensor<?x?xf32>
10  %init1 = linalg.init_tensor [%d1, %d0] : tensor<?x?xf32>
11  %init2 = linalg.init_tensor [%d0, %d1] : tensor<?x?xf32>
12  %result:2 = linalg.generic {
13    indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> (d0)>,
14                     affine_map<(d0, d1) -> (d1)>, affine_map<(d0, d1) -> (d1, d0)>,
15                     affine_map<(d0, d1) -> (d0, d1)>],
16    iterator_types = ["parallel", "parallel"]}
17    ins(%arg0, %arg1, %arg2 : tensor<?x?xf32>, tensor<?xf32>, tensor<?xf32>)
18    outs(%init1, %init2 : tensor<?x?xf32>, tensor<?x?xf32>) {
19    ^bb0(%b0 : f32, %b1 : f32, %b2 : f32, %b3 : f32, %b4 : f32) :
20      %0 = arith.addf %b0, %b1 : f32
21      %1 = arith.mulf %0, %b2 : f32
22      linalg.yield %0, %1 : f32, f32
23    } -> (tensor<?x?xf32>, tensor<?x?xf32>)
24  return %result#0, %result#1 : tensor<?x?xf32>, tensor<?x?xf32>
25}
26//  CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1) -> (d0, d1)>
27//  CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1) -> (d0)>
28//  CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d1)>
29//  CHECK-DAG: #[[MAP3:.+]] = affine_map<(d0, d1) -> (d1, d0)>
30//      CHECK: func @simple_op(
31// CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: tensor<?x?xf32>
32// CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: tensor<?xf32>
33// CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: tensor<?xf32>
34//  CHECK-DAG:   %[[C0:.+]] = arith.constant 0 : index
35//  CHECK-DAG:   %[[C1:.+]] = arith.constant 1 : index
36//  CHECK-DAG:   %[[D0:.+]] = tensor.dim %[[ARG0]], %[[C0]]
37//  CHECK-DAG:   %[[D1:.+]] = tensor.dim %[[ARG0]], %[[C1]]
38//  CHECK-DAG:   %[[INIT1:.+]] = linalg.init_tensor [%[[D1]], %[[D0]]]
39//  CHECK-DAG:   %[[INIT2:.+]] = linalg.init_tensor [%[[D0]], %[[D1]]]
40//  CHECK-DAG:   %[[GENERIC1:.+]]:3 = linalg.generic
41// CHECK-SAME:       [#[[MAP0]], #[[MAP1]], #[[MAP2]], #[[MAP3]], #[[MAP0]], #[[MAP3]]]
42// CHECK-SAME:       ["parallel", "parallel"]
43// CHECK-SAME:       ins(%[[ARG0]], %[[ARG1]], %[[ARG2]] :
44// CHECK-SAME:       outs(%[[INIT1]], %[[INIT2]], %[[INIT1]] :
45// CHECK-NEXT:   ^bb0(
46// CHECK-SAME:       %[[B0:[a-zA-Z0-9]+]]: f32
47// CHECK-SAME:       %[[B1:[a-zA-Z0-9]+]]: f32
48// CHECK-SAME:       %[[B2:[a-zA-Z0-9]+]]: f32
49// CHECK-SAME:       %[[B3:[a-zA-Z0-9]+]]: f32
50// CHECK-SAME:       %[[B4:[a-zA-Z0-9]+]]: f32
51// CHECK-SAME:       %[[B5:[a-zA-Z0-9]+]]: f32):
52// CHECK-NEXT:     %[[S0:.+]] = arith.addf %[[B0]], %[[B1]]
53// CHECK-NEXT:     linalg.yield %[[S0]], %{{[a-zA-Z0-9]+}}, %[[S0]]
54//      CHECK:   %[[GENERIC2:.+]]:2 = linalg.generic
55// CHECK-SAME:       [#[[MAP0]], #[[MAP1]], #[[MAP2]], #[[MAP3]], #[[MAP3]], #[[MAP0]]]
56// CHECK-SAME:       ["parallel", "parallel"]
57// CHECK-SAME:       ins(%[[ARG0]], %[[ARG1]], %[[ARG2]], %[[GENERIC1]]#2 :
58// CHECK-SAME:       outs(%[[INIT1]], %[[INIT2]] :
59// CHECK-NEXT:   ^bb0(
60// CHECK-SAME:       %[[B6:[a-zA-Z0-9]+]]: f32
61// CHECK-SAME:       %[[B7:[a-zA-Z0-9]+]]: f32
62// CHECK-SAME:       %[[B8:[a-zA-Z0-9]+]]: f32
63// CHECK-SAME:       %[[B9:[a-zA-Z0-9]+]]: f32
64// CHECK-SAME:       %[[B10:[a-zA-Z0-9]+]]: f32
65// CHECK-SAME:       %[[B11:[a-zA-Z0-9]+]]: f32):
66// CHECK-NEXT:     %[[S1:.+]] = arith.mulf %[[B9]], %[[B8]]
67// CHECK-NEXT:     linalg.yield %[[B9]], %[[S1]]
68//      CHECK:   return %[[GENERIC1]]#0, %[[GENERIC2]]#1
69
70// With cse + canonicalization
71
72//  CANONICALIZECHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1) -> (d0, d1)>
73//  CANONICALIZECHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1) -> (d0)>
74//  CANONICALIZECHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d1, d0)>
75//  CANONICALIZECHECK-DAG: #[[MAP3:.+]] = affine_map<(d0, d1) -> (d1)>
76//      CANONICALIZECHECK: func @simple_op(
77// CANONICALIZECHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: tensor<?x?xf32>
78// CANONICALIZECHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: tensor<?xf32>
79// CANONICALIZECHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: tensor<?xf32>
80//  CANONICALIZECHECK-DAG:   %[[C0:.+]] = arith.constant 0 : index
81//  CANONICALIZECHECK-DAG:   %[[C1:.+]] = arith.constant 1 : index
82//  CANONICALIZECHECK-DAG:   %[[D0:.+]] = tensor.dim %[[ARG0]], %[[C0]]
83//  CANONICALIZECHECK-DAG:   %[[D1:.+]] = tensor.dim %[[ARG0]], %[[C1]]
84//  CANONICALIZECHECK-DAG:   %[[INIT1:.+]] = linalg.init_tensor [%[[D1]], %[[D0]]]
85//  CANONICALIZECHECK-DAG:   %[[INIT2:.+]] = linalg.init_tensor [%[[D0]], %[[D1]]]
86//  CANONICALIZECHECK-DAG:   %[[GENERIC1:.+]] = linalg.generic
87// CANONICALIZECHECK-SAME:       [#[[MAP0]], #[[MAP1]], #[[MAP2]]]
88// CANONICALIZECHECK-SAME:       ["parallel", "parallel"]
89// CANONICALIZECHECK-SAME:       ins(%[[ARG0]], %[[ARG1]] :
90// CANONICALIZECHECK-SAME:       outs(%[[INIT1]] :
91// CANONICALIZECHECK-NEXT:   ^bb0(
92// CANONICALIZECHECK-SAME:       %[[B0:[a-zA-Z0-9]+]]: f32
93// CANONICALIZECHECK-SAME:       %[[B1:[a-zA-Z0-9]+]]: f32
94// CANONICALIZECHECK-SAME:       %[[B2:[a-zA-Z0-9]+]]: f32):
95// CANONICALIZECHECK-NEXT:     %[[S0:.+]] = arith.addf %[[B0]], %[[B1]]
96// CANONICALIZECHECK-NEXT:     linalg.yield %[[S0]]
97//      CANONICALIZECHECK:   %[[GENERIC2:.+]] = linalg.generic
98// CANONICALIZECHECK-SAME:       [#[[MAP3]], #[[MAP2]], #[[MAP0]]]
99// CANONICALIZECHECK-SAME:       ["parallel", "parallel"]
100// CANONICALIZECHECK-SAME:       ins(%[[ARG2]], %[[GENERIC1]] :
101// CANONICALIZECHECK-SAME:       outs(%[[INIT2]] :
102// CANONICALIZECHECK-NEXT:   ^bb0(
103// CANONICALIZECHECK-SAME:       %[[B3:[a-zA-Z0-9]+]]: f32
104// CANONICALIZECHECK-SAME:       %[[B4:[a-zA-Z0-9]+]]: f32
105// CANONICALIZECHECK-SAME:       %[[B5:[a-zA-Z0-9]+]]: f32):
106// CANONICALIZECHECK-NEXT:     %[[S1:.+]] = arith.mulf %[[B4]], %[[B3]]
107// CANONICALIZECHECK-NEXT:     linalg.yield %[[S1]]
108//      CANONICALIZECHECK:   return %[[GENERIC1]], %[[GENERIC2]]
109
110
111// -----
112
113func.func @simple_op_permuted_outputs(%arg0 : tensor<?x?xf32>, %arg1 : tensor<?xf32>, %arg2 : tensor<?xf32>)
114    -> (tensor<?x?xf32>, tensor<?x?xf32>, tensor<?x?xf32>) {
115  %c0 = arith.constant 0 : index
116  %c1 = arith.constant 1 : index
117  %d0 = tensor.dim %arg0, %c0 : tensor<?x?xf32>
118  %d1 = tensor.dim %arg0, %c1 : tensor<?x?xf32>
119  %init1 = linalg.init_tensor [%d1, %d0] : tensor<?x?xf32>
120  %init2 = linalg.init_tensor [%d0, %d1] : tensor<?x?xf32>
121  %result:3 = linalg.generic {
122    indexing_maps = [affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> (d0)>,
123                     affine_map<(d0, d1) -> (d1)>, affine_map<(d0, d1) -> (d1, d0)>,
124                     affine_map<(d0, d1) -> (d0, d1)>, affine_map<(d0, d1) -> (d0, d1)>],
125    iterator_types = ["parallel", "parallel"]}
126    ins(%arg0, %arg1, %arg2 : tensor<?x?xf32>, tensor<?xf32>, tensor<?xf32>)
127    outs(%init1, %init2, %init2 : tensor<?x?xf32>, tensor<?x?xf32>, tensor<?x?xf32>) {
128    ^bb0(%b0 : f32, %b1 : f32, %b2 : f32, %b3 : f32, %b4 : f32, %b5 : f32) :
129      %0 = arith.addf %b0, %b1 : f32
130      %1 = arith.mulf %0, %b2 : f32
131      linalg.yield %0, %1, %0 : f32, f32, f32
132    } -> (tensor<?x?xf32>, tensor<?x?xf32>, tensor<?x?xf32>)
133  return %result#0, %result#1, %result#2 : tensor<?x?xf32>, tensor<?x?xf32>, tensor<?x?xf32>
134}
135//  CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1) -> (d0, d1)>
136//  CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1) -> (d0)>
137//  CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d1)>
138//  CHECK-DAG: #[[MAP3:.+]] = affine_map<(d0, d1) -> (d1, d0)>
139//      CHECK: func @simple_op_permuted_outputs(
140// CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: tensor<?x?xf32>
141// CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: tensor<?xf32>
142// CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: tensor<?xf32>
143//  CHECK-DAG:   %[[C0:.+]] = arith.constant 0 : index
144//  CHECK-DAG:   %[[C1:.+]] = arith.constant 1 : index
145//  CHECK-DAG:   %[[D0:.+]] = tensor.dim %[[ARG0]], %[[C0]]
146//  CHECK-DAG:   %[[D1:.+]] = tensor.dim %[[ARG0]], %[[C1]]
147//  CHECK-DAG:   %[[INIT1:.+]] = linalg.init_tensor [%[[D1]], %[[D0]]]
148//  CHECK-DAG:   %[[INIT2:.+]] = linalg.init_tensor [%[[D0]], %[[D1]]]
149//  CHECK-DAG:   %[[GENERIC1:.+]]:4 = linalg.generic
150// CHECK-SAME:       [#[[MAP0]], #[[MAP1]], #[[MAP2]], #[[MAP3]], #[[MAP0]], #[[MAP0]], #[[MAP0]]]
151// CHECK-SAME:       ["parallel", "parallel"]
152// CHECK-SAME:       ins(%[[ARG0]], %[[ARG1]], %[[ARG2]] :
153// CHECK-SAME:       outs(%[[INIT1]], %[[INIT2]], %[[INIT2]], %[[INIT2]] :
154// CHECK-NEXT:   ^bb0(
155// CHECK-SAME:       %[[B0:[a-zA-Z0-9]+]]: f32
156// CHECK-SAME:       %[[B1:[a-zA-Z0-9]+]]: f32
157// CHECK-SAME:       %[[B2:[a-zA-Z0-9]+]]: f32
158// CHECK-SAME:       %[[B3:[a-zA-Z0-9]+]]: f32
159// CHECK-SAME:       %[[B4:[a-zA-Z0-9]+]]: f32
160// CHECK-SAME:       %[[B5:[a-zA-Z0-9]+]]: f32
161// CHECK-SAME:       %[[B6:[a-zA-Z0-9]+]]: f32):
162// CHECK-NEXT:     %[[S0:.+]] = arith.addf %[[B0]], %[[B1]]
163// CHECK-NEXT:     linalg.yield %[[S0]], %{{[a-zA-Z0-9]+}}, %[[S0]]
164//      CHECK:   %[[GENERIC2:.+]]:3 = linalg.generic
165// CHECK-SAME:       [#[[MAP0]], #[[MAP1]], #[[MAP2]], #[[MAP0]], #[[MAP3]], #[[MAP0]], #[[MAP0]]]
166// CHECK-SAME:       ["parallel", "parallel"]
167// CHECK-SAME:       ins(%[[ARG0]], %[[ARG1]], %[[ARG2]], %[[GENERIC1]]#3 :
168// CHECK-SAME:       outs(%[[INIT1]], %[[INIT2]], %[[INIT2]] :
169// CHECK-NEXT:   ^bb0(
170// CHECK-SAME:       %[[B7:[a-zA-Z0-9]+]]: f32
171// CHECK-SAME:       %[[B8:[a-zA-Z0-9]+]]: f32
172// CHECK-SAME:       %[[B9:[a-zA-Z0-9]+]]: f32
173// CHECK-SAME:       %[[B10:[a-zA-Z0-9]+]]: f32
174// CHECK-SAME:       %[[B11:[a-zA-Z0-9]+]]: f32
175// CHECK-SAME:       %[[B12:[a-zA-Z0-9]+]]: f32):
176// CHECK-NEXT:     %[[S1:.+]] = arith.mulf %[[B10]], %[[B9]]
177// CHECK-NEXT:     linalg.yield %[[B10]], %[[S1]], %[[B10]]
178//      CHECK:   return %[[GENERIC1]]#0, %[[GENERIC2]]#1, %[[GENERIC1]]#2
179
180//  CANONICALIZECHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1) -> (d0, d1)>
181//  CANONICALIZECHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1) -> (d0)>
182//  CANONICALIZECHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d1, d0)>
183//  CANONICALIZECHECK-DAG: #[[MAP3:.+]] = affine_map<(d0, d1) -> (d1)>
184//      CANONICALIZECHECK: func @simple_op_permuted_outputs(
185// CANONICALIZECHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: tensor<?x?xf32>
186// CANONICALIZECHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: tensor<?xf32>
187// CANONICALIZECHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: tensor<?xf32>
188//  CANONICALIZECHECK-DAG:   %[[C0:.+]] = arith.constant 0 : index
189//  CANONICALIZECHECK-DAG:   %[[C1:.+]] = arith.constant 1 : index
190//  CANONICALIZECHECK-DAG:   %[[D0:.+]] = tensor.dim %[[ARG0]], %[[C0]]
191//  CANONICALIZECHECK-DAG:   %[[D1:.+]] = tensor.dim %[[ARG0]], %[[C1]]
192//  CANONICALIZECHECK-DAG:   %[[INIT1:.+]] = linalg.init_tensor [%[[D1]], %[[D0]]]
193//  CANONICALIZECHECK-DAG:   %[[INIT2:.+]] = linalg.init_tensor [%[[D0]], %[[D1]]]
194//  CANONICALIZECHECK-DAG:   %[[GENERIC1:.+]]:2 = linalg.generic
195// CANONICALIZECHECK-SAME:       [#[[MAP0]], #[[MAP1]], #[[MAP2]], #[[MAP0]]]
196// CANONICALIZECHECK-SAME:       ["parallel", "parallel"]
197// CANONICALIZECHECK-SAME:       ins(%[[ARG0]], %[[ARG1]] :
198// CANONICALIZECHECK-SAME:       outs(%[[INIT1]], %[[INIT2]] :
199// CANONICALIZECHECK-NEXT:   ^bb0(
200// CANONICALIZECHECK-SAME:       %[[B0:[a-zA-Z0-9]+]]: f32
201// CANONICALIZECHECK-SAME:       %[[B1:[a-zA-Z0-9]+]]: f32
202// CANONICALIZECHECK-SAME:       %[[B2:[a-zA-Z0-9]+]]: f32):
203// CANONICALIZECHECK-NEXT:     %[[S0:.+]] = arith.addf %[[B0]], %[[B1]]
204// CANONICALIZECHECK-NEXT:     linalg.yield %[[S0]], %[[S0]]
205//      CANONICALIZECHECK:   %[[GENERIC2:.+]] = linalg.generic
206// CANONICALIZECHECK-SAME:       [#[[MAP3]], #[[MAP0]], #[[MAP0]]]
207// CANONICALIZECHECK-SAME:       ["parallel", "parallel"]
208// CANONICALIZECHECK-SAME:       ins(%[[ARG2]], %[[GENERIC1]]#1 :
209// CANONICALIZECHECK-SAME:       outs(%[[INIT2]] :
210// CANONICALIZECHECK-NEXT:   ^bb0(
211// CANONICALIZECHECK-SAME:       %[[B4:[a-zA-Z0-9]+]]: f32
212// CANONICALIZECHECK-SAME:       %[[B5:[a-zA-Z0-9]+]]: f32
213// CANONICALIZECHECK-SAME:       %[[B6:[a-zA-Z0-9]+]]: f32):
214// CANONICALIZECHECK-NEXT:     %[[S1:.+]] = arith.mulf %[[B5]], %[[B4]]
215// CANONICALIZECHECK-NEXT:     linalg.yield %[[S1]]
216//      CANONICALIZECHECK:   return %[[GENERIC1]]#0, %[[GENERIC2]], %[[GENERIC1]]#1
217
218// -----
219
220#map0 = affine_map<(d0, d1) -> (d0, d1)>
221#map1 = affine_map<(d0, d1) -> (d0)>
222#map2 = affine_map<(d0, d1) -> (d1, d0)>
223func.func @multi_statement(%arg0 : tensor<10x20xf32>, %arg1 : tensor<10xi32>) -> tensor<20x10xf64> {
224  %init = linalg.init_tensor [20, 10] : tensor<20x10xf64>
225  %0 = linalg.generic {
226    indexing_maps = [#map0, #map1, #map2],
227    iterator_types = ["parallel", "parallel"]}
228    ins(%arg0, %arg1 : tensor<10x20xf32>, tensor<10xi32>)
229    outs(%init : tensor<20x10xf64>) {
230    ^bb0(%b0 : f32, %b1 : i32, %b2 : f64):
231      %1 = arith.sitofp %b1 : i32 to f64
232      %2 = arith.extf %b0 : f32 to f64
233      %3 = arith.addf %1, %2 : f64
234      linalg.yield %3 : f64
235    } -> tensor<20x10xf64>
236  return %0 : tensor<20x10xf64>
237}
238
239//  CHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1) -> (d0, d1)>
240//  CHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1) -> (d0)>
241//  CHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d1, d0)>
242//      CHECK: func @multi_statement(
243// CHECK-SAME:     %[[ARG0:.+]]: tensor<10x20xf32>
244// CHECK-SAME:     %[[ARG1:.+]]: tensor<10xi32>)
245//  CHECK-DAG:   %[[INIT0:.+]] = linalg.init_tensor [20, 10] : tensor<20x10xf64>
246//  CHECK-DAG:   %[[INIT1:.+]] = linalg.init_tensor [10, 20] : tensor<10x20xf64>
247//      CHECK:   %[[GENERIC0:.+]]:2 = linalg.generic
248// CHECK-SAME:       indexing_maps = [#[[MAP0]], #[[MAP1]], #[[MAP2]], #[[MAP0]]]
249// CHECK-SAME:       iterator_types = ["parallel", "parallel"]
250// CHECK-SAME:       ins(%[[ARG0]], %[[ARG1]] :
251// CHECK-SAME:       outs(%[[INIT0]], %[[INIT1]] :
252// CHECK-NEXT:     ^bb0(
253// CHECK-SAME:         %[[B0:.+]]: f32
254// CHECK-SAME:         %[[B1:.+]]: i32
255// CHECK-SAME:         %[[B2:[a-zA-Z0-9]+]]: f64
256// CHECK-SAME:         %[[B3:.+]]: f64
257// CHECK-NEXT:       %[[S0:.+]] = arith.sitofp %[[B1]] : i32 to f64
258// CHECK-NEXT:       linalg.yield %{{.+}}, %[[S0]]
259//      CHECK:   %[[GENERIC1:.+]]:2 = linalg.generic
260// CHECK-SAME:       indexing_maps = [#[[MAP0]], #[[MAP1]], #[[MAP0]], #[[MAP2]], #[[MAP0]]]
261// CHECK-SAME:       iterator_types = ["parallel", "parallel"]
262// CHECK-SAME:       ins(%[[ARG0]], %[[ARG1]], %[[GENERIC0]]#1 :
263// CHECK-SAME:       outs(%[[INIT0]], %[[INIT1]] :
264// CHECK-NEXT:     ^bb0(
265// CHECK-SAME:         %[[B4:.+]]: f32
266// CHECK-SAME:         %[[B5:.+]]: i32
267// CHECK-SAME:         %[[B6:[a-zA-Z0-9]+]]: f64
268// CHECK-SAME:         %[[B7:[a-zA-Z0-9]+]]: f64
269// CHECK-SAME:         %[[B8:.+]]: f64
270// CHECK-NEXT:       %[[S1:.+]] = arith.extf %[[B4]] : f32 to f64
271// CHECK-NEXT:       linalg.yield %{{.+}}, %[[S1]]
272//      CHECK:   %[[GENERIC2:.+]] = linalg.generic
273// CHECK-SAME:       indexing_maps = [#[[MAP0]], #[[MAP1]], #[[MAP0]], #[[MAP0]], #[[MAP2]]]
274// CHECK-SAME:       iterator_types = ["parallel", "parallel"]
275// CHECK-SAME:       ins(%[[ARG0]], %[[ARG1]], %[[GENERIC0]]#1, %[[GENERIC1]]#1 :
276// CHECK-SAME:       outs(%[[INIT0]] :
277// CHECK-NEXT:     ^bb0(
278// CHECK-SAME:         %[[B9:.+]]: f32
279// CHECK-SAME:         %[[B10:.+]]: i32
280// CHECK-SAME:         %[[B11:[a-zA-Z0-9]+]]: f64
281// CHECK-SAME:         %[[B12:[a-zA-Z0-9]+]]: f64
282// CHECK-SAME:         %[[B13:.+]]: f64
283// CHECK-NEXT:       %[[S2:.+]] = arith.addf %[[B11]], %[[B12]] : f64
284// CHECK-NEXT:       linalg.yield %[[S2]]
285//      CHECK:   return %[[GENERIC2]]
286
287//  CANONICALIZECHECK-DAG: #[[MAP0:.+]] = affine_map<(d0, d1) -> (d0)>
288//  CANONICALIZECHECK-DAG: #[[MAP1:.+]] = affine_map<(d0, d1) -> (d0, d1)>
289//  CANONICALIZECHECK-DAG: #[[MAP2:.+]] = affine_map<(d0, d1) -> (d1, d0)>
290//      CANONICALIZECHECK: func @multi_statement(
291// CANONICALIZECHECK-SAME:     %[[ARG0:.+]]: tensor<10x20xf32>
292// CANONICALIZECHECK-SAME:     %[[ARG1:.+]]: tensor<10xi32>)
293//  CANONICALIZECHECK-DAG:   %[[INIT0:.+]] = linalg.init_tensor [20, 10] : tensor<20x10xf64>
294//  CANONICALIZECHECK-DAG:   %[[INIT1:.+]] = linalg.init_tensor [10, 20] : tensor<10x20xf64>
295//      CANONICALIZECHECK:   %[[GENERIC0:.+]] = linalg.generic
296// CANONICALIZECHECK-SAME:       indexing_maps = [#[[MAP0]], #[[MAP1]]]
297// CANONICALIZECHECK-SAME:       iterator_types = ["parallel", "parallel"]
298// CANONICALIZECHECK-SAME:       ins(%[[ARG1]] :
299// CANONICALIZECHECK-SAME:       outs(%[[INIT1]] :
300// CANONICALIZECHECK-NEXT:     ^bb0(
301// CANONICALIZECHECK-SAME:         %[[B0:.+]]: i32
302// CANONICALIZECHECK-SAME:         %[[B1:.+]]: f64
303// CANONICALIZECHECK-NEXT:       %[[S0:.+]] = arith.sitofp %[[B0]] : i32 to f64
304// CANONICALIZECHECK-NEXT:       linalg.yield %[[S0]]
305//      CANONICALIZECHECK:   %[[GENERIC1:.+]] = linalg.generic
306// CANONICALIZECHECK-SAME:       indexing_maps = [#[[MAP1]], #[[MAP1]]]
307// CANONICALIZECHECK-SAME:       iterator_types = ["parallel", "parallel"]
308// CANONICALIZECHECK-SAME:       ins(%[[ARG0]] :
309// CANONICALIZECHECK-SAME:       outs(%[[INIT1]] :
310// CANONICALIZECHECK-NEXT:     ^bb0(
311// CANONICALIZECHECK-SAME:         %[[B2:.+]]: f32
312// CANONICALIZECHECK-SAME:         %[[B3:.+]]: f64
313// CANONICALIZECHECK-NEXT:       %[[S1:.+]] = arith.extf %[[B2]] : f32 to f64
314// CANONICALIZECHECK-NEXT:       linalg.yield %[[S1]]
315//      CANONICALIZECHECK:   %[[GENERIC2:.+]] = linalg.generic
316// CANONICALIZECHECK-SAME:       indexing_maps = [#[[MAP1]], #[[MAP1]], #[[MAP2]]]
317// CANONICALIZECHECK-SAME:       iterator_types = ["parallel", "parallel"]
318// CANONICALIZECHECK-SAME:       ins(%[[GENERIC0]], %[[GENERIC1]] :
319// CANONICALIZECHECK-SAME:       outs(%[[INIT0]] :
320// CANONICALIZECHECK-NEXT:     ^bb0(
321// CANONICALIZECHECK-SAME:         %[[B4:[a-zA-Z0-9]+]]: f64
322// CANONICALIZECHECK-SAME:         %[[B5:[a-zA-Z0-9]+]]: f64
323// CANONICALIZECHECK-SAME:         %[[B6:.+]]: f64
324// CANONICALIZECHECK-NEXT:       %[[S2:.+]] = arith.addf %[[B4]], %[[B5]] : f64
325// CANONICALIZECHECK-NEXT:       linalg.yield %[[S2]]
326//      CANONICALIZECHECK:   return %[[GENERIC2]]
327