1 // RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -canonicalize="test-convergence" | FileCheck %s
2 // RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -canonicalize="test-convergence top-down=0" | FileCheck %s --check-prefix=CHECK-BOTTOM-UP
6 // CHECK-DAG: #[[$MAP0:.*]] = affine_map<(d0) -> (d0 - 1)>
7 // CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0) -> (d0 + 1)>
9 // CHECK-LABEL: func @compose_affine_maps_1dto2d_no_symbols() {
10 func.func @compose_affine_maps_1dto2d_no_symbols() {
11 %0 = memref.alloc() : memref<4x4xf32>
13 affine.for %i0 = 0 to 15 {
16 %x0 = affine.apply affine_map<(d0) -> (d0 - 1)> (%i0)
17 %x1_0 = affine.apply affine_map<(d0, d1) -> (d0)> (%x0, %x0)
18 %x1_1 = affine.apply affine_map<(d0, d1) -> (d1)> (%x0, %x0)
20 // CHECK: %[[I0A:.*]] = affine.apply #[[$MAP0]](%{{.*}})
21 // CHECK-NEXT: %[[V0:.*]] = memref.load %{{.*}}[%[[I0A]], %[[I0A]]]
22 %v0 = memref.load %0[%x1_0, %x1_1] : memref<4x4xf32>
25 %y0 = affine.apply affine_map<(d0) -> (d0 + 1)> (%i0)
26 %y1_0 = affine.apply affine_map<(d0, d1) -> (d0)> (%y0, %y0)
27 %y1_1 = affine.apply affine_map<(d0, d1) -> (d1)> (%y0, %y0)
29 // CHECK-NEXT: %[[I1A:.*]] = affine.apply #[[$MAP1]](%{{.*}})
30 // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I1A]], %[[I1A]]]
31 memref.store %v0, %0[%y1_0, %y1_1] : memref<4x4xf32>
34 %xy_0 = affine.apply affine_map<(d0, d1) -> (d0)> (%x0, %y0)
35 %xy_1 = affine.apply affine_map<(d0, d1) -> (d1)> (%x0, %y0)
37 // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I0A]], %[[I1A]]]
38 memref.store %v0, %0[%xy_0, %xy_1] : memref<4x4xf32>
41 %yx_0 = affine.apply affine_map<(d0, d1) -> (d0)> (%y0, %x0)
42 %yx_1 = affine.apply affine_map<(d0, d1) -> (d1)> (%y0, %x0)
43 // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I1A]], %[[I0A]]]
44 memref.store %v0, %0[%yx_0, %yx_1] : memref<4x4xf32>
51 // CHECK-DAG: #[[$MAP4:.*]] = affine_map<(d0) -> (d0 - 4)>
52 // CHECK-DAG: #[[$MAP7:.*]] = affine_map<(d0) -> (d0 * 2 - 3)>
53 // CHECK-DAG: #[[$MAP7a:.*]] = affine_map<(d0) -> (d0 * 2 + 1)>
55 // CHECK-LABEL: func @compose_affine_maps_1dto2d_with_symbols() {
56 func.func @compose_affine_maps_1dto2d_with_symbols() {
57 %0 = memref.alloc() : memref<4x4xf32>
59 affine.for %i0 = 0 to 15 {
60 // Test load[%x0, %x0] with symbol %c4
61 %c4 = arith.constant 4 : index
62 %x0 = affine.apply affine_map<(d0)[s0] -> (d0 - s0)> (%i0)[%c4]
64 // CHECK: %[[I0:.*]] = affine.apply #[[$MAP4]](%{{.*}})
65 // CHECK-NEXT: %[[V0:.*]] = memref.load %{{.*}}[%[[I0]], %[[I0]]]
66 %v0 = memref.load %0[%x0, %x0] : memref<4x4xf32>
68 // Test load[%x0, %x1] with symbol %c4 captured by '%x0' map.
69 %x1 = affine.apply affine_map<(d0) -> (d0 + 1)> (%i0)
70 %y1 = affine.apply affine_map<(d0, d1) -> (d0+d1)> (%x0, %x1)
71 // CHECK-NEXT: %[[I1:.*]] = affine.apply #[[$MAP7]](%{{.*}})
72 // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I1]], %[[I1]]]
73 memref.store %v0, %0[%y1, %y1] : memref<4x4xf32>
75 // Test store[%x1, %x0] with symbol %c4 captured by '%x0' map.
76 %y2 = affine.apply affine_map<(d0, d1) -> (d0 + d1)> (%x1, %x0)
77 // CHECK-NEXT: %[[I2:.*]] = affine.apply #[[$MAP7]](%{{.*}})
78 // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I2]], %[[I2]]]
79 memref.store %v0, %0[%y2, %y2] : memref<4x4xf32>
81 // Test store[%x2, %x0] with symbol %c4 from '%x0' and %c5 from '%x2'
82 %c5 = arith.constant 5 : index
83 %x2 = affine.apply affine_map<(d0)[s0] -> (d0 + s0)> (%i0)[%c5]
84 %y3 = affine.apply affine_map<(d0, d1) -> (d0 + d1)> (%x2, %x0)
85 // CHECK: %[[I3:.*]] = affine.apply #[[$MAP7a]](%{{.*}})
86 // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I3]], %[[I3]]]
87 memref.store %v0, %0[%y3, %y3] : memref<4x4xf32>
94 // CHECK-DAG: #[[$MAP8:.*]] = affine_map<(d0, d1) -> (d1 + (d0 ceildiv 4) * 4 - (d1 floordiv 4) * 4)>
95 // CHECK-DAG: #[[$MAP8a:.*]] = affine_map<(d0, d1) -> (d1 + (d0 ceildiv 8) * 8 - (d1 floordiv 8) * 8)>
97 // CHECK-LABEL: func @compose_affine_maps_2d_tile
98 func.func @compose_affine_maps_2d_tile(%0: memref<16x32xf32>, %1: memref<16x32xf32>) {
99 %c4 = arith.constant 4 : index
100 %c8 = arith.constant 8 : index
102 affine.for %i0 = 0 to 16 {
103 %x0 = affine.apply affine_map<(d0)[s0] -> (d0 ceildiv s0)> (%i0)[%c4]
104 affine.for %i1 = 0 to 16 {
105 %x1 = affine.apply affine_map<(d0)[s0] -> (d0 ceildiv s0)> (%i1)[%c8]
106 affine.for %i2 = 0 to 16 {
107 %x2 = affine.apply affine_map<(d0)[s0] -> (d0 mod s0)> (%i2)[%c4]
108 affine.for %i3 = 0 to 16 {
109 %x3 = affine.apply affine_map<(d0)[s0] -> (d0 mod s0)> (%i3)[%c8]
111 %x40 = affine.apply affine_map<(d0, d1, d2, d3)[s0, s1] ->
112 ((d0 * s0) + d2)> (%x0, %x1, %x2, %x3)[%c4, %c8]
113 %x41 = affine.apply affine_map<(d0, d1, d2, d3)[s0, s1] ->
114 ((d1 * s1) + d3)> (%x0, %x1, %x2, %x3)[%c4, %c8]
115 // CHECK: %[[I0:.*]] = affine.apply #[[$MAP8]](%{{.*}}, %{{.*}})
116 // CHECK: %[[I1:.*]] = affine.apply #[[$MAP8a]](%{{.*}}, %{{.*}})
117 // CHECK-NEXT: %[[L0:.*]] = memref.load %{{.*}}[%[[I0]], %[[I1]]]
118 %v0 = memref.load %0[%x40, %x41] : memref<16x32xf32>
120 // CHECK-NEXT: memref.store %[[L0]], %{{.*}}[%[[I0]], %[[I1]]]
121 memref.store %v0, %1[%x40, %x41] : memref<16x32xf32>
131 // CHECK-DAG: #[[$MAP4b:.*]] = affine_map<(d0) -> (d0 - 7)>
132 // CHECK-DAG: #[[$MAP9:.*]] = affine_map<(d0) -> (d0 + 3)>
133 // CHECK-DAG: #[[$MAP10:.*]] = affine_map<(d0) -> (d0 * 3)>
134 // CHECK-DAG: #[[$MAP11:.*]] = affine_map<(d0) -> ((d0 + 3) ceildiv 3)>
135 // CHECK-DAG: #[[$MAP12:.*]] = affine_map<(d0) -> (d0 * 7 - 49)>
137 // CHECK-LABEL: func @compose_affine_maps_dependent_loads() {
138 func.func @compose_affine_maps_dependent_loads() {
139 %0 = memref.alloc() : memref<16x32xf32>
140 %1 = memref.alloc() : memref<16x32xf32>
142 affine.for %i0 = 0 to 3 {
143 affine.for %i1 = 0 to 3 {
144 affine.for %i2 = 0 to 3 {
145 %c3 = arith.constant 3 : index
146 %c7 = arith.constant 7 : index
148 %x00 = affine.apply affine_map<(d0, d1, d2)[s0, s1] -> (d0 + s0)>
149 (%i0, %i1, %i2)[%c3, %c7]
150 %x01 = affine.apply affine_map<(d0, d1, d2)[s0, s1] -> (d1 - s1)>
151 (%i0, %i1, %i2)[%c3, %c7]
152 %x02 = affine.apply affine_map<(d0, d1, d2)[s0, s1] -> (d2 * s0)>
153 (%i0, %i1, %i2)[%c3, %c7]
155 // CHECK: %[[I0:.*]] = affine.apply #[[$MAP9]](%{{.*}})
156 // CHECK: %[[I1:.*]] = affine.apply #[[$MAP4b]](%{{.*}})
157 // CHECK: %[[I2:.*]] = affine.apply #[[$MAP10]](%{{.*}})
158 // CHECK-NEXT: %[[V0:.*]] = memref.load %{{.*}}[%[[I0]], %[[I1]]]
159 %v0 = memref.load %0[%x00, %x01] : memref<16x32xf32>
161 // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I0]], %[[I2]]]
162 memref.store %v0, %0[%x00, %x02] : memref<16x32xf32>
165 // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I1]], %[[I0]]]
166 memref.store %v0, %0[%x01, %x00] : memref<16x32xf32>
168 // Swizzle %x00, %x01 and %c3, %c7
169 %x10 = affine.apply affine_map<(d0, d1)[s0, s1] -> (d0 * s1)>
170 (%x01, %x00)[%c3, %c7]
171 %x11 = affine.apply affine_map<(d0, d1)[s0, s1] -> (d1 ceildiv s0)>
172 (%x01, %x00)[%c3, %c7]
174 // CHECK-NEXT: %[[I2A:.*]] = affine.apply #[[$MAP12]](%{{.*}})
175 // CHECK-NEXT: %[[I2B:.*]] = affine.apply #[[$MAP11]](%{{.*}})
176 // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I2A]], %[[I2B]]]
177 memref.store %v0, %0[%x10, %x11] : memref<16x32xf32>
186 // CHECK-DAG: #[[$MAP13A:.*]] = affine_map<(d0) -> ((d0 + 6) ceildiv 8)>
187 // CHECK-DAG: #[[$MAP13B:.*]] = affine_map<(d0) -> ((d0 * 4 - 4) floordiv 3)>
189 // CHECK-LABEL: func @compose_affine_maps_diamond_dependency
190 func.func @compose_affine_maps_diamond_dependency(%arg0: f32, %arg1: memref<4x4xf32>) {
191 affine.for %i0 = 0 to 15 {
192 %a = affine.apply affine_map<(d0) -> (d0 - 1)> (%i0)
193 %b = affine.apply affine_map<(d0) -> (d0 + 7)> (%a)
194 %c = affine.apply affine_map<(d0) -> (d0 * 4)> (%a)
195 %d0 = affine.apply affine_map<(d0, d1) -> (d0 ceildiv 8)> (%b, %c)
196 %d1 = affine.apply affine_map<(d0, d1) -> (d1 floordiv 3)> (%b, %c)
197 // CHECK: %[[I0:.*]] = affine.apply #[[$MAP13A]](%{{.*}})
198 // CHECK: %[[I1:.*]] = affine.apply #[[$MAP13B]](%{{.*}})
199 // CHECK-NEXT: memref.store %arg0, %arg1[%[[I0]], %[[I1]]]
200 memref.store %arg0, %arg1[%d0, %d1] : memref<4x4xf32>
208 // CHECK-DAG: #[[$MAP14:.*]] = affine_map<()[s0, s1] -> ((s0 * 4 + s1 * 4) floordiv s0)>
210 // CHECK-LABEL: func @compose_affine_maps_multiple_symbols
211 func.func @compose_affine_maps_multiple_symbols(%arg0: index, %arg1: index) -> index {
212 %a = affine.apply affine_map<(d0)[s0] -> (s0 + d0)> (%arg0)[%arg1]
213 %c = affine.apply affine_map<(d0) -> (d0 * 4)> (%a)
214 %e = affine.apply affine_map<(d0)[s0] -> (d0 floordiv s0)> (%c)[%arg1]
215 // CHECK: [[I0:.*]] = affine.apply #[[$MAP14]]()[%{{.*}}, %{{.*}}]
221 // CHECK-LABEL: func @arg_used_as_dim_and_symbol
222 func.func @arg_used_as_dim_and_symbol(%arg0: memref<100x100xf32>, %arg1: index, %arg2: f32) -> (memref<100x100xf32, 1>, memref<1xi32>) {
223 %c9 = arith.constant 9 : index
224 %1 = memref.alloc() : memref<100x100xf32, 1>
225 %2 = memref.alloc() : memref<1xi32>
226 affine.for %i0 = 0 to 100 {
227 affine.for %i1 = 0 to 100 {
228 %3 = affine.apply affine_map<(d0, d1)[s0, s1] -> (d1 + s0 + s1)>
229 (%i0, %i1)[%arg1, %c9]
230 %4 = affine.apply affine_map<(d0, d1, d3) -> (d3 - (d0 + d1))>
232 // CHECK: memref.store %arg2, %{{.*}}[%{{.*}}, %{{.*}}]
233 memref.store %arg2, %1[%4, %arg1] : memref<100x100xf32, 1>
236 return %1, %2 : memref<100x100xf32, 1>, memref<1xi32>
241 // CHECK-LABEL: func @trivial_maps
242 func.func @trivial_maps() {
243 // CHECK-NOT: affine.apply
245 %0 = memref.alloc() : memref<10xf32>
246 %c0 = arith.constant 0 : index
247 %cst = arith.constant 0.000000e+00 : f32
248 affine.for %i1 = 0 to 10 {
249 %1 = affine.apply affine_map<()[s0] -> (s0)>()[%c0]
250 memref.store %cst, %0[%1] : memref<10xf32>
251 %2 = memref.load %0[%c0] : memref<10xf32>
253 %3 = affine.apply affine_map<()[] -> (0)>()[]
254 memref.store %cst, %0[%3] : memref<10xf32>
255 memref.store %2, %0[%c0] : memref<10xf32>
262 // CHECK-DAG: #[[$MAP15:.*]] = affine_map<()[s0] -> (s0 - 42)>
264 // CHECK-LABEL: func @partial_fold_map
265 func.func @partial_fold_map(%arg1: index, %arg2: index) -> index {
266 // TODO: Constant fold one index into affine.apply
267 %c42 = arith.constant 42 : index
268 %2 = affine.apply affine_map<(d0, d1) -> (d0 - d1)> (%arg1, %c42)
269 // CHECK: [[X:.*]] = affine.apply #[[$MAP15]]()[%{{.*}}]
275 // CHECK-DAG: #[[$MAP_symbolic_composition_a:.*]] = affine_map<()[s0] -> (s0 * 512)>
277 // CHECK-LABEL: func @symbolic_composition_a(%{{.*}}: index, %{{.*}}: index) -> index {
278 func.func @symbolic_composition_a(%arg0: index, %arg1: index) -> index {
279 %0 = affine.apply affine_map<(d0) -> (d0 * 4)>(%arg0)
280 %1 = affine.apply affine_map<()[s0, s1] -> (8 * s0)>()[%0, %arg0]
281 %2 = affine.apply affine_map<()[s0, s1] -> (16 * s1)>()[%arg1, %1]
282 // CHECK: %{{.*}} = affine.apply #[[$MAP_symbolic_composition_a]]()[%{{.*}}]
288 // CHECK-DAG: #[[$MAP_symbolic_composition_b:.*]] = affine_map<()[s0] -> (s0 * 4)>
290 // CHECK-LABEL: func @symbolic_composition_b(%arg0: index, %arg1: index, %arg2: index, %arg3: index) -> index {
291 func.func @symbolic_composition_b(%arg0: index, %arg1: index, %arg2: index, %arg3: index) -> index {
292 %0 = affine.apply affine_map<(d0) -> (d0)>(%arg0)
293 %1 = affine.apply affine_map<()[s0, s1, s2, s3] -> (s0 + s1 + s2 + s3)>()[%0, %0, %0, %0]
294 // CHECK: %{{.*}} = affine.apply #[[$MAP_symbolic_composition_b]]()[%{{.*}}]
300 // CHECK-DAG: #[[$MAP_symbolic_composition_c:.*]] = affine_map<()[s0, s1] -> (s0 * 3 + s1)>
302 // CHECK-LABEL: func @symbolic_composition_c(%arg0: index, %arg1: index, %arg2: index, %arg3: index) -> index {
303 func.func @symbolic_composition_c(%arg0: index, %arg1: index, %arg2: index, %arg3: index) -> index {
304 %0 = affine.apply affine_map<(d0) -> (d0)>(%arg0)
305 %1 = affine.apply affine_map<(d0) -> (d0)>(%arg1)
306 %2 = affine.apply affine_map<()[s0, s1, s2, s3] -> (s0 + s1 + s2 + s3)>()[%0, %0, %0, %1]
307 // CHECK: %{{.*}} = affine.apply #[[$MAP_symbolic_composition_c]]()[%{{.*}}, %{{.*}}]
313 // CHECK-DAG: #[[$MAP_symbolic_composition_d:.*]] = affine_map<()[s0, s1] -> (s0 * 3 + s1)>
315 // CHECK-LABEL: func @symbolic_composition_d(
316 // CHECK-SAME: %[[ARG0:[0-9a-zA-Z]+]]: index
317 // CHECK-SAME: %[[ARG1:[0-9a-zA-Z]+]]: index
318 func.func @symbolic_composition_d(%arg0: index, %arg1: index, %arg2: index, %arg3: index) -> index {
319 %0 = affine.apply affine_map<(d0) -> (d0)>(%arg0)
320 %1 = affine.apply affine_map<()[s0] -> (s0)>()[%arg1]
321 %2 = affine.apply affine_map<()[s0, s1, s2, s3] -> (s0 + s1 + s2 + s3)>()[%0, %0, %0, %1]
322 // CHECK: %{{.*}} = affine.apply #[[$MAP_symbolic_composition_d]]()[%[[ARG0]], %[[ARG1]]]
328 // CHECK-DAG: #[[$MAP_mix_dims_and_symbols_b:.*]] = affine_map<()[s0, s1] -> (s0 * 42 + s1 + 6)>
330 // CHECK-LABEL: func @mix_dims_and_symbols_b(%arg0: index, %arg1: index) -> index {
331 func.func @mix_dims_and_symbols_b(%arg0: index, %arg1: index) -> index {
332 %a = affine.apply affine_map<(d0)[s0] -> (d0 - 1 + 42 * s0)> (%arg0)[%arg1]
333 %b = affine.apply affine_map<(d0) -> (d0 + 7)> (%a)
334 // CHECK: {{.*}} = affine.apply #[[$MAP_mix_dims_and_symbols_b]]()[%{{.*}}, %{{.*}}]
341 // CHECK-DAG: #[[$MAP_mix_dims_and_symbols_c:.*]] = affine_map<()[s0, s1] -> (s0 * 168 + s1 * 4 - 4)>
343 // CHECK-LABEL: func @mix_dims_and_symbols_c(%arg0: index, %arg1: index) -> index {
344 func.func @mix_dims_and_symbols_c(%arg0: index, %arg1: index) -> index {
345 %a = affine.apply affine_map<(d0)[s0] -> (d0 - 1 + 42 * s0)> (%arg0)[%arg1]
346 %b = affine.apply affine_map<(d0) -> (d0 + 7)> (%a)
347 %c = affine.apply affine_map<(d0) -> (d0 * 4)> (%a)
348 // CHECK: {{.*}} = affine.apply #[[$MAP_mix_dims_and_symbols_c]]()[%{{.*}}, %{{.*}}]
354 // CHECK-DAG: #[[$MAP_mix_dims_and_symbols_d:.*]] = affine_map<()[s0, s1] -> ((s0 * 42 + s1 + 6) ceildiv 8)>
356 // CHECK-LABEL: func @mix_dims_and_symbols_d(%arg0: index, %arg1: index) -> index {
357 func.func @mix_dims_and_symbols_d(%arg0: index, %arg1: index) -> index {
358 %a = affine.apply affine_map<(d0)[s0] -> (d0 - 1 + 42 * s0)> (%arg0)[%arg1]
359 %b = affine.apply affine_map<(d0) -> (d0 + 7)> (%a)
360 %c = affine.apply affine_map<(d0) -> (d0 * 4)> (%a)
361 %d = affine.apply affine_map<()[s0] -> (s0 ceildiv 8)> ()[%b]
362 // CHECK: {{.*}} = affine.apply #[[$MAP_mix_dims_and_symbols_d]]()[%{{.*}}, %{{.*}}]
368 // CHECK-DAG: #[[$MAP_mix_dims_and_symbols_e:.*]] = affine_map<()[s0, s1] -> ((s0 * 168 + s1 * 4 - 4) floordiv 3)>
370 // CHECK-LABEL: func @mix_dims_and_symbols_e(%arg0: index, %arg1: index) -> index {
371 func.func @mix_dims_and_symbols_e(%arg0: index, %arg1: index) -> index {
372 %a = affine.apply affine_map<(d0)[s0] -> (d0 - 1 + 42 * s0)> (%arg0)[%arg1]
373 %b = affine.apply affine_map<(d0) -> (d0 + 7)> (%a)
374 %c = affine.apply affine_map<(d0) -> (d0 * 4)> (%a)
375 %d = affine.apply affine_map<()[s0] -> (s0 ceildiv 8)> ()[%b]
376 %e = affine.apply affine_map<(d0) -> (d0 floordiv 3)> (%c)
377 // CHECK: {{.*}} = affine.apply #[[$MAP_mix_dims_and_symbols_e]]()[%{{.*}}, %{{.*}}]
383 // CHECK-LABEL: func @mix_dims_and_symbols_f(%arg0: index, %arg1: index) -> index {
384 func.func @mix_dims_and_symbols_f(%arg0: index, %arg1: index) -> index {
385 %a = affine.apply affine_map<(d0)[s0] -> (d0 - 1 + 42 * s0)> (%arg0)[%arg1]
386 %b = affine.apply affine_map<(d0) -> (d0 + 7)> (%a)
387 %c = affine.apply affine_map<(d0) -> (d0 * 4)> (%a)
388 %d = affine.apply affine_map<()[s0] -> (s0 ceildiv 8)> ()[%b]
389 %e = affine.apply affine_map<(d0) -> (d0 floordiv 3)> (%c)
390 %f = affine.apply affine_map<(d0, d1)[s0, s1] -> (d0 - s1 + d1 - s0)> (%d, %e)[%e, %d]
391 // CHECK: {{.*}} = arith.constant 0 : index
398 // CHECK-DAG: #[[$MAP_symbolic_composition_b:.*]] = affine_map<()[s0] -> (s0 * 4)>
400 // CHECK-LABEL: func @mix_dims_and_symbols_g(%arg0: index, %arg1: index) -> (index, index, index) {
401 func.func @mix_dims_and_symbols_g(%M: index, %N: index) -> (index, index, index) {
402 %K = affine.apply affine_map<(d0) -> (4*d0)> (%M)
403 %res1 = affine.apply affine_map<()[s0, s1] -> (4 * s0)>()[%N, %K]
404 %res2 = affine.apply affine_map<()[s0, s1] -> (s1)>()[%N, %K]
405 %res3 = affine.apply affine_map<()[s0, s1] -> (1024)>()[%N, %K]
406 // CHECK-DAG: {{.*}} = arith.constant 1024 : index
407 // CHECK-DAG: {{.*}} = affine.apply #[[$MAP_symbolic_composition_b]]()[%{{.*}}]
408 // CHECK-DAG: {{.*}} = affine.apply #[[$MAP_symbolic_composition_b]]()[%{{.*}}]
409 return %res1, %res2, %res3 : index, index, index
414 // CHECK-DAG: #[[$symbolic_semi_affine:.*]] = affine_map<(d0)[s0] -> (d0 floordiv (s0 + 1))>
416 // CHECK-LABEL: func @symbolic_semi_affine(%arg0: index, %arg1: index, %arg2: memref<?xf32>) {
417 func.func @symbolic_semi_affine(%M: index, %N: index, %A: memref<?xf32>) {
418 %f1 = arith.constant 1.0 : f32
419 affine.for %i0 = 1 to 100 {
420 %1 = affine.apply affine_map<()[s0] -> (s0 + 1)> ()[%M]
421 %2 = affine.apply affine_map<(d0)[s0] -> (d0 floordiv s0)> (%i0)[%1]
422 // CHECK-DAG: {{.*}} = affine.apply #[[$symbolic_semi_affine]](%{{.*}})[%{{.*}}]
423 memref.store %f1, %A[%2] : memref<?xf32>
430 // CHECK: #[[$MAP0:.*]] = affine_map<()[s0] -> (0, s0)>
431 // CHECK: #[[$MAP1:.*]] = affine_map<()[s0] -> (100, s0)>
433 // CHECK-LABEL: func @constant_fold_bounds(%arg0: index) {
434 func.func @constant_fold_bounds(%N : index) {
435 // CHECK: arith.constant 3 : index
436 // CHECK-NEXT: "foo"() : () -> index
437 %c9 = arith.constant 9 : index
438 %c1 = arith.constant 1 : index
439 %c2 = arith.constant 2 : index
440 %c3 = affine.apply affine_map<(d0, d1) -> (d0 + d1)> (%c1, %c2)
441 %l = "foo"() : () -> index
443 // CHECK: affine.for %{{.*}} = 5 to 7 {
444 affine.for %i = max affine_map<(d0, d1) -> (0, d0 + d1)> (%c2, %c3) to min affine_map<(d0, d1) -> (d0 - 2, 32*d1)> (%c9, %c1) {
445 "foo"(%i, %c3) : (index, index) -> ()
448 // Bound takes a non-constant argument but can still be folded.
449 // CHECK: affine.for %{{.*}} = 1 to 7 {
450 affine.for %j = max affine_map<(d0) -> (0, 1)> (%N) to min affine_map<(d0, d1) -> (7, 9)> (%N, %l) {
451 "foo"(%j, %c3) : (index, index) -> ()
454 // None of the bounds can be folded.
455 // CHECK: affine.for %{{.*}} = max #[[$MAP0]]()[%{{.*}}] to min #[[$MAP1]]()[%{{.*}}] {
456 affine.for %k = max affine_map<()[s0] -> (0, s0)> ()[%l] to min affine_map<()[s0] -> (100, s0)> ()[%N] {
457 "foo"(%k, %c3) : (index, index) -> ()
464 // CHECK-LABEL: func @fold_empty_loops()
465 func.func @fold_empty_loops() -> index {
466 %c0 = arith.constant 0 : index
467 affine.for %i = 0 to 10 {
469 %res = affine.for %i = 0 to 10 iter_args(%arg = %c0) -> index {
470 affine.yield %arg : index
472 // CHECK-NEXT: %[[zero:.*]] = arith.constant 0
473 // CHECK-NEXT: return %[[zero]]
479 // CHECK-LABEL: func @fold_empty_loop()
480 func.func @fold_empty_loop() -> (index, index) {
481 %c0 = arith.constant 0 : index
482 %c1 = arith.constant 1 : index
483 %c2 = arith.constant 2 : index
484 %res:2 = affine.for %i = 0 to 10 iter_args(%arg0 = %c0, %arg1 = %c1) -> (index, index) {
485 affine.yield %c2, %arg1 : index, index
487 // CHECK-DAG: %[[one:.*]] = arith.constant 1
488 // CHECK-DAG: %[[two:.*]] = arith.constant 2
489 // CHECK-NEXT: return %[[two]], %[[one]]
490 return %res#0, %res#1 : index, index
495 // CHECK-LABEL: func @fold_empty_loops_trip_count_1()
496 func.func @fold_empty_loops_trip_count_1() -> (index, index, index, index) {
497 %c0 = arith.constant 0 : index
498 %c1 = arith.constant 1 : index
499 %c2 = arith.constant 2 : index
500 %res1:2 = affine.for %i = 0 to 1 iter_args(%arg0 = %c2, %arg1 = %c0) -> (index, index) {
501 affine.yield %c1, %arg0 : index, index
503 %res2:2 = affine.for %i = 0 to 2 step 3 iter_args(%arg0 = %c2, %arg1 = %c0) -> (index, index) {
504 affine.yield %arg1, %arg0 : index, index
506 // CHECK-DAG: %[[zero:.*]] = arith.constant 0
507 // CHECK-DAG: %[[one:.*]] = arith.constant 1
508 // CHECK-DAG: %[[two:.*]] = arith.constant 2
509 // CHECK-NEXT: return %[[one]], %[[two]], %[[zero]], %[[two]]
510 return %res1#0, %res1#1, %res2#0, %res2#1 : index, index, index, index
515 // CHECK-LABEL: func @fold_empty_loop_trip_count_0()
516 func.func @fold_empty_loop_trip_count_0() -> (index, index) {
517 %c0 = arith.constant 0 : index
518 %c1 = arith.constant 1 : index
519 %c2 = arith.constant 2 : index
520 %res:2 = affine.for %i = 0 to 0 iter_args(%arg0 = %c2, %arg1 = %c0) -> (index, index) {
521 affine.yield %c1, %arg0 : index, index
523 // CHECK-DAG: %[[zero:.*]] = arith.constant 0
524 // CHECK-DAG: %[[two:.*]] = arith.constant 2
525 // CHECK-NEXT: return %[[two]], %[[zero]]
526 return %res#0, %res#1 : index, index
531 // CHECK-LABEL: func @fold_empty_loop_trip_count_unknown
532 func.func @fold_empty_loop_trip_count_unknown(%in : index) -> (index, index) {
533 %c0 = arith.constant 0 : index
534 %c1 = arith.constant 1 : index
535 %res:2 = affine.for %i = 0 to %in iter_args(%arg0 = %c0, %arg1 = %c1) -> (index, index) {
536 affine.yield %arg0, %arg1 : index, index
538 // CHECK-DAG: %[[zero:.*]] = arith.constant 0
539 // CHECK-DAG: %[[one:.*]] = arith.constant 1
540 // CHECK-NEXT: return %[[zero]], %[[one]]
541 return %res#0, %res#1 : index, index
546 // CHECK-LABEL: func @empty_loops_not_folded_1
547 func.func @empty_loops_not_folded_1(%in : index) -> index {
548 %c0 = arith.constant 0 : index
549 %c1 = arith.constant 1 : index
551 %res = affine.for %i = 0 to %in iter_args(%arg = %c0) -> index {
552 affine.yield %c1 : index
559 // CHECK-LABEL: func @empty_loops_not_folded_2
560 func.func @empty_loops_not_folded_2(%in : index) -> (index, index) {
561 %c0 = arith.constant 0 : index
562 %c1 = arith.constant 1 : index
564 %res:2 = affine.for %i = 0 to %in iter_args(%arg0 = %c0, %arg1 = %c1) -> (index, index) {
565 affine.yield %arg1, %arg0 : index, index
567 return %res#0, %res#1 : index, index
572 // CHECK-LABEL: func @empty_loops_not_folded_3
573 func.func @empty_loops_not_folded_3() -> (index, index) {
574 %c0 = arith.constant 0 : index
575 %c1 = arith.constant 1 : index
577 %res:2 = affine.for %i = 0 to 10 iter_args(%arg0 = %c0, %arg1 = %c1) -> (index, index) {
578 affine.yield %arg1, %arg0 : index, index
580 return %res#0, %res#1 : index, index
585 // CHECK-LABEL: func @zero_iter_loop_not_folded
586 func.func @zero_iter_loop_not_folded() {
587 %A = memref.alloc() : memref<4xf32>
588 affine.for %i = 0 to 0 {
589 %load = affine.load %A[%i] : memref<4xf32>
590 affine.store %load, %A[%i] : memref<4xf32>
592 // CHECK: affine.for {{.*}} = 0 to 0 {
598 // CHECK-LABEL: func @fold_zero_iter_loops
599 // CHECK-SAME: %[[ARG:.*]]: index
600 func.func @fold_zero_iter_loops(%in : index) -> index {
601 %c1 = arith.constant 1 : index
602 %res = affine.for %i = 0 to 0 iter_args(%loop_arg = %in) -> index {
603 %yield = arith.addi %loop_arg, %c1 : index
604 affine.yield %yield : index
606 // CHECK-NEXT: return %[[ARG]]
612 // CHECK-DAG: #[[$SET:.*]] = affine_set<(d0, d1)[s0] : (d0 >= 0, -d0 + 1022 >= 0, d1 >= 0, -d1 + s0 - 2 >= 0)>
614 // CHECK-LABEL: func @canonicalize_affine_if
615 // CHECK-SAME: %[[M:[0-9a-zA-Z]*]]: index,
616 // CHECK-SAME: %[[N:[0-9a-zA-Z]*]]: index)
617 func.func @canonicalize_affine_if(%M : index, %N : index) {
618 %c1022 = arith.constant 1022 : index
619 // Drop unused operand %M, propagate %c1022, and promote %N to symbolic.
620 affine.for %i = 0 to 1024 {
621 affine.for %j = 0 to %N {
622 // CHECK: affine.if #[[$SET]](%{{.*}}, %{{.*}})[%[[N]]]
623 affine.if affine_set<(d0, d1, d2, d3)[s0] : (d1 >= 0, d0 - d1 >= 0, d2 >= 0, d3 - d2 - 2 >= 0)>
624 (%c1022, %i, %j, %N)[%M] {
635 // CHECK-DAG: #[[$SET:.*]] = affine_set<(d0, d1)[s0] : (d0 - 1 >= 0, d1 - 1 == 0, -d0 + s0 + 10 >= 0)>
637 // CHECK-LABEL: func @canonicalize_affine_if_compose_apply
638 // CHECK-SAME: %[[N:.*]]: index
639 func.func @canonicalize_affine_if_compose_apply(%N: index) {
640 %M = affine.apply affine_map<()[s0] -> (s0 + 10)> ()[%N]
641 // CHECK-NEXT: affine.for %[[I:.*]] =
642 affine.for %i = 0 to 1024 {
643 // CHECK-NEXT: affine.for %[[J:.*]] =
644 affine.for %j = 0 to 100 {
645 %j_ = affine.apply affine_map<(d0)[] -> (d0 + 1)> (%j)
646 // CHECK-NEXT: affine.if #[[$SET]](%[[I]], %[[J]])[%[[N]]]
647 affine.if affine_set<(d0, d1)[s0] : (d0 - 1 >= 0, d1 - 2 == 0, -d0 + s0 >= 0)>(%i, %j_)[%M] {
648 "test.foo"() : ()->()
657 // CHECK-DAG: #[[$LBMAP:.*]] = affine_map<()[s0] -> (0, s0)>
658 // CHECK-DAG: #[[$UBMAP:.*]] = affine_map<()[s0] -> (1024, s0 * 2)>
660 // CHECK-LABEL: func @canonicalize_bounds
661 // CHECK-SAME: %[[M:.*]]: index,
662 // CHECK-SAME: %[[N:.*]]: index)
663 func.func @canonicalize_bounds(%M : index, %N : index) {
664 %c0 = arith.constant 0 : index
665 %c1024 = arith.constant 1024 : index
666 // Drop unused operand %N, drop duplicate operand %M, propagate %c1024, and
667 // promote %M to a symbolic one.
668 // CHECK: affine.for %{{.*}} = 0 to min #[[$UBMAP]]()[%[[M]]]
669 affine.for %i = 0 to min affine_map<(d0, d1, d2, d3) -> (d0, d1 + d2)> (%c1024, %M, %M, %N) {
672 // Promote %M to symbolic position.
673 // CHECK: affine.for %{{.*}} = 0 to #{{.*}}()[%[[M]]]
674 affine.for %i = 0 to affine_map<(d0) -> (4 * d0)> (%M) {
677 // Lower bound canonicalize.
678 // CHECK: affine.for %{{.*}} = max #[[$LBMAP]]()[%[[N]]] to %[[M]]
679 affine.for %i = max affine_map<(d0, d1) -> (d0, d1)> (%c0, %N) to %M {
687 // Compose maps into affine load and store ops.
689 // CHECK-LABEL: @compose_into_affine_load_store
690 func.func @compose_into_affine_load_store(%A : memref<1024xf32>, %u : index) {
691 // CHECK: affine.for %[[IV:.*]] = 0 to 1024
692 affine.for %i = 0 to 1024 {
693 // Make sure the unused operand (%u below) gets dropped as well.
694 %idx = affine.apply affine_map<(d0, d1) -> (d0 + 1)> (%i, %u)
695 %0 = affine.load %A[%idx] : memref<1024xf32>
696 affine.store %0, %A[%idx] : memref<1024xf32>
697 // CHECK-NEXT: affine.load %{{.*}}[%[[IV]] + 1]
698 // CHECK-NEXT: affine.store %{{.*}}, %{{.*}}[%[[IV]] + 1]
700 // Map remains the same, but operand changes on composition.
701 %copy = affine.apply affine_map<(d0) -> (d0)> (%i)
702 %1 = affine.load %A[%copy] : memref<1024xf32>
703 "prevent.dce"(%1) : (f32) -> ()
704 // CHECK-NEXT: affine.load %{{.*}}[%[[IV]]]
711 func.func @affine_min(%arg0 : index, %arg1 : index, %arg2 : index) {
712 %c511 = arith.constant 511 : index
713 %c1 = arith.constant 0 : index
714 %0 = affine.min affine_map<(d0)[s0] -> (1000, d0 + 512, s0 + 1)> (%c1)[%c511]
715 "op0"(%0) : (index) -> ()
716 // CHECK: %[[CST:.*]] = arith.constant 512 : index
717 // CHECK-NEXT: "op0"(%[[CST]]) : (index) -> ()
718 // CHECK-NEXT: return
724 func.func @affine_min(%arg0 : index, %arg1 : index, %arg2 : index) {
725 %c3 = arith.constant 3 : index
726 %c20 = arith.constant 20 : index
727 %0 = affine.min affine_map<(d0)[s0] -> (1000, d0 floordiv 4, (s0 mod 5) + 1)> (%c20)[%c3]
728 "op0"(%0) : (index) -> ()
729 // CHECK: %[[CST:.*]] = arith.constant 4 : index
730 // CHECK-NEXT: "op0"(%[[CST]]) : (index) -> ()
731 // CHECK-NEXT: return
737 func.func @affine_max(%arg0 : index, %arg1 : index, %arg2 : index) {
738 %c511 = arith.constant 511 : index
739 %c1 = arith.constant 0 : index
740 %0 = affine.max affine_map<(d0)[s0] -> (1000, d0 + 512, s0 + 1)> (%c1)[%c511]
741 "op0"(%0) : (index) -> ()
742 // CHECK: %[[CST:.*]] = arith.constant 1000 : index
743 // CHECK-NEXT: "op0"(%[[CST]]) : (index) -> ()
744 // CHECK-NEXT: return
750 func.func @affine_max(%arg0 : index, %arg1 : index, %arg2 : index) {
751 %c3 = arith.constant 3 : index
752 %c20 = arith.constant 20 : index
753 %0 = affine.max affine_map<(d0)[s0] -> (1000, d0 floordiv 4, (s0 mod 5) + 1)> (%c20)[%c3]
754 "op0"(%0) : (index) -> ()
755 // CHECK: %[[CST:.*]] = arith.constant 1000 : index
756 // CHECK-NEXT: "op0"(%[[CST]]) : (index) -> ()
757 // CHECK-NEXT: return
763 // CHECK: #[[$MAP:.*]] = affine_map<(d0, d1) -> (d1 - 2, d0)>
765 func.func @affine_min(%arg0: index) {
766 affine.for %i = 0 to %arg0 {
767 affine.for %j = 0 to %arg0 {
768 %c2 = arith.constant 2 : index
769 // CHECK: affine.min #[[$MAP]]
770 %0 = affine.min affine_map<(d0,d1,d2)->(d0, d1 - d2)>(%i, %j, %c2)
771 "consumer"(%0) : (index) -> ()
779 // Reproducer for PR45031. This used to fold into an incorrect map because
780 // symbols were concatenated in the wrong order during map folding. Map
781 // composition places the symbols of the original map before those of the map
782 // it is composed with, e.g. A.compose(B) will first have all symbols of A,
783 // then all symbols of B.
785 #map1 = affine_map<(d0)[s0, s1] -> (d0 * s0 + s1)>
786 #map2 = affine_map<(d0)[s0] -> (1024, -d0 + s0)>
788 // CHECK: #[[$MAP:.*]] = affine_map<()[s0, s1] -> (1024, s0 - s1 * 1024)>
790 // CHECK: func @rep(%[[ARG0:.*]]: index, %[[ARG1:.*]]: index)
791 func.func @rep(%arg0 : index, %arg1 : index) -> index {
792 // CHECK-NOT: arith.constant
793 %c0 = arith.constant 0 : index
794 %c1024 = arith.constant 1024 : index
795 // CHECK-NOT: affine.apply
796 %0 = affine.apply #map1(%arg0)[%c1024, %c0]
798 // CHECK: affine.min #[[$MAP]]()[%[[ARG1]], %[[ARG0]]]
799 %1 = affine.min #map2(%0)[%arg1]
805 // CHECK-DAG: #[[ub:.*]] = affine_map<()[s0] -> (s0 + 2)>
807 func.func @drop_duplicate_bounds(%N : index) {
808 // affine.for %i = max #lb(%arg0) to min #ub(%arg0)
809 affine.for %i = max affine_map<(d0) -> (d0, d0)>(%N) to min affine_map<(d0) -> (d0 + 2, d0 + 2)>(%N) {
817 // Ensure affine.parallel bounds expressions are canonicalized.
819 #map3 = affine_map<(d0) -> (d0 * 5)>
821 // CHECK-LABEL: func @affine_parallel_const_bounds
822 func.func @affine_parallel_const_bounds() {
823 %cst = arith.constant 1.0 : f32
824 %c0 = arith.constant 0 : index
825 %c4 = arith.constant 4 : index
826 %0 = memref.alloc() : memref<4xf32>
827 // CHECK: affine.parallel (%{{.*}}) = (0) to (4)
828 affine.parallel (%i) = (%c0) to (%c0 + %c4) {
829 %1 = affine.apply #map3(%i)
830 // CHECK: affine.parallel (%{{.*}}) = (0) to (%{{.*}} * 5)
831 affine.parallel (%j) = (%c0) to (%1) {
832 affine.store %cst, %0[%j] : memref<4xf32>
840 func.func @compose_affine_maps_div_symbol(%A : memref<i64>, %i0 : index, %i1 : index) {
841 %0 = affine.apply affine_map<()[s0] -> (2 * s0)> ()[%i0]
842 %1 = affine.apply affine_map<()[s0] -> (3 * s0)> ()[%i0]
843 %2 = affine.apply affine_map<(d0)[s0, s1] -> (d0 mod s1 + s0 * s1 + s0 * 4)> (%i1)[%0, %1]
844 %3 = arith.index_cast %2: index to i64
845 memref.store %3, %A[]: memref<i64>
846 affine.for %i2 = 0 to 3 {
847 %4 = affine.apply affine_map<(d0)[s0, s1] -> (d0 ceildiv s1 + s0 + s0 * 3)> (%i2)[%0, %1]
848 %5 = arith.index_cast %4: index to i64
849 memref.store %5, %A[]: memref<i64>
856 // CHECK: #[[MAP:.+]] = affine_map<()[s0, s1] -> (s0 + s1, s0 * s1)>
858 // CHECK: func @deduplicate_affine_min_expressions
859 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)
860 func.func @deduplicate_affine_min_expressions(%i0: index, %i1: index) -> index {
861 // CHECK: affine.min #[[MAP]]()[%[[I0]], %[[I1]]]
862 %0 = affine.min affine_map<()[s0, s1] -> (s0 + s1, s0 * s1, s1 + s0, s0 * s1)> ()[%i0, %i1]
868 // CHECK: #[[MAP:.+]] = affine_map<()[s0, s1] -> (s0 + s1, s0 * s1)>
870 // CHECK: func @deduplicate_affine_max_expressions
871 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)
872 func.func @deduplicate_affine_max_expressions(%i0: index, %i1: index) -> index {
873 // CHECK: affine.max #[[MAP]]()[%[[I0]], %[[I1]]]
874 %0 = affine.max affine_map<()[s0, s1] -> (s0 + s1, s0 * s1, s1 + s0, s0 * s1)> ()[%i0, %i1]
880 // CHECK-DAG: #[[MAP0:.+]] = affine_map<()[s0, s1, s2] -> (-s1 + s2, 16, s0 * 3)>
881 // CHECK-DAG: #[[MAP1:.+]] = affine_map<()[s0, s1, s2] -> (-s0 + s1, -s2 + 5, 16)>
883 // CHECK: func @merge_affine_min_ops
884 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index, %[[I2:.+]]: index, %[[I3:.+]]: index)
885 func.func @merge_affine_min_ops(%i0: index, %i1: index, %i2: index, %i3: index) -> (index, index) {
886 %0 = affine.min affine_map<(d0)[s0] -> (16, d0 - s0)> (%i0)[%i1]
888 // CHECK: affine.min #[[MAP0]]()[%[[I2]], %[[I1]], %[[I0]]]
889 %1 = affine.min affine_map<(d0)[s0] -> (3 * s0, d0)> (%0)[%i2] // Use as dim
890 // CHECK: affine.min #[[MAP1]]()[%[[I1]], %[[I0]], %[[I3]]]
891 %2 = affine.min affine_map<(d0)[s0] -> (s0, 5 - d0)> (%i3)[%0] // Use as symbol
893 return %1, %2: index, index
898 // CHECK: #[[MAP:.+]] = affine_map<()[s0, s1, s2] -> (s2 + 8, s2 * 4, s1 + 16, s1 * 8, s0 + 7)>
900 // CHECK: func @merge_multiple_affine_min_ops
901 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index, %[[I2:.+]]: index)
902 func.func @merge_multiple_affine_min_ops(%i0: index, %i1: index, %i2: index) -> index {
903 %0 = affine.min affine_map<()[s0] -> (s0 + 16, s0 * 8)> ()[%i0]
904 %1 = affine.min affine_map<()[s0] -> (s0 + 8, s0 * 4)> ()[%i1]
905 // CHECK: affine.min #[[MAP]]()[%[[I2]], %[[I0]], %[[I1]]]
906 %2 = affine.min affine_map<()[s0, s1, s2] -> (s0, 7 + s1, s2)> ()[%0, %i2, %1]
912 // CHECK-DAG: #[[MAP:.+]] = affine_map<()[s0, s1] -> (s1 + 16, s1 * 8, s0 * 2)>
914 // CHECK: func @merge_multiple_uses_of_affine_min_ops
915 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)
916 func.func @merge_multiple_uses_of_affine_min_ops(%i0: index, %i1: index) -> index {
917 %0 = affine.min affine_map<()[s0] -> (s0 + 16, s0 * 8)> ()[%i0]
918 // CHECK: affine.min #[[MAP]]()[%[[I1]], %[[I0]]]
919 %2 = affine.min affine_map<()[s0, s1, s2] -> (s0, s1, s2 * 2)> ()[%0, %0, %i1]
925 // CHECK-DAG: #[[MAP0:.+]] = affine_map<()[s0] -> (s0 + 16, s0 * 8)>
926 // CHECK-DAG: #[[MAP1:.+]] = affine_map<()[s0, s1, s2] -> (s2 + 16, s2 * 8, s1 * 2, s0 + 1)>
928 // CHECK: func @merge_mixed_uses_of_affine_min_ops
929 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)
930 func.func @merge_mixed_uses_of_affine_min_ops(%i0: index, %i1: index) -> index {
931 // CHECK: %[[AFFINE:.+]] = affine.min #[[MAP0]]()[%[[I0]]]
932 %0 = affine.min affine_map<()[s0] -> (s0 + 16, s0 * 8)> ()[%i0]
933 // %0 is bound to a symbol that is both a standalone expression and a part
934 // of other expressions.
935 // CHECK: affine.min #[[MAP1]]()[%[[AFFINE]], %[[I1]], %[[I0]]]
936 %2 = affine.min affine_map<()[s0, s1, s2] -> (s0, s1 + 1, s2 * 2)> ()[%0, %0, %i1]
942 // CHECK-LABEL: func @dont_merge_affine_min_if_not_single_dim
943 func.func @dont_merge_affine_min_if_not_single_dim(%i0: index, %i1: index, %i2: index) -> index {
944 // CHECK-COUNT-2: affine.min
945 %0 = affine.min affine_map<()[s0] -> (s0 + 16, s0 * 8)> ()[%i0]
946 %1 = affine.min affine_map<(d0)[s0] -> (s0 + 4, 7 + d0)> (%0)[%i2]
952 // CHECK-LABEL: func @dont_merge_affine_min_if_not_single_sym
953 func.func @dont_merge_affine_min_if_not_single_sym(%i0: index, %i1: index, %i2: index) -> index {
954 // CHECK-COUNT-2: affine.min
955 %0 = affine.min affine_map<()[s0] -> (s0 + 16, s0 * 8)> ()[%i0]
956 %1 = affine.min affine_map<()[s0, s1] -> (s0 + 4, 7 + s1)> ()[%0, %i2]
962 // CHECK-DAG: #[[MAP0:.+]] = affine_map<()[s0, s1, s2] -> (-s1 + s2, 16, s0 * 3)>
963 // CHECK-DAG: #[[MAP1:.+]] = affine_map<()[s0, s1, s2] -> (-s0 + s1, -s2 + 5, 16)>
965 // CHECK: func @merge_affine_max_ops
966 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index, %[[I2:.+]]: index, %[[I3:.+]]: index)
967 func.func @merge_affine_max_ops(%i0: index, %i1: index, %i2: index, %i3: index) -> (index, index) {
968 %0 = affine.max affine_map<(d0)[s0] -> (16, d0 - s0)> (%i0)[%i1]
970 // CHECK: affine.max #[[MAP0]]()[%[[I2]], %[[I1]], %[[I0]]]
971 %1 = affine.max affine_map<(d0)[s0] -> (3 * s0, d0)> (%0)[%i2] // Use as dim
972 // CHECK: affine.max #[[MAP1]]()[%[[I1]], %[[I0]], %[[I3]]]
973 %2 = affine.max affine_map<(d0)[s0] -> (s0, 5 - d0)> (%i3)[%0] // Use as symbol
975 return %1, %2: index, index
980 // CHECK: #[[MAP:.+]] = affine_map<()[s0, s1, s2] -> (s2 + 8, s2 * 4, s1 + 16, s1 * 8, s0 + 7)>
982 // CHECK: func @merge_multiple_affine_max_ops
983 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index, %[[I2:.+]]: index)
984 func.func @merge_multiple_affine_max_ops(%i0: index, %i1: index, %i2: index) -> index {
985 %0 = affine.max affine_map<()[s0] -> (s0 + 16, s0 * 8)> ()[%i0]
986 %1 = affine.max affine_map<()[s0] -> (s0 + 8, s0 * 4)> ()[%i1]
987 // CHECK: affine.max #[[MAP]]()[%[[I2]], %[[I0]], %[[I1]]]
988 %2 = affine.max affine_map<()[s0, s1, s2] -> (s0, 7 + s1, s2)> ()[%0, %i2, %1]
994 // CHECK-DAG: #[[MAP:.+]] = affine_map<()[s0, s1] -> (s1 + 16, s1 * 8, s0 * 2)>
996 // CHECK: func @merge_multiple_uses_of_affine_max_ops
997 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)
998 func.func @merge_multiple_uses_of_affine_max_ops(%i0: index, %i1: index) -> index {
999 %0 = affine.max affine_map<()[s0] -> (s0 + 16, s0 * 8)> ()[%i0]
1000 // CHECK: affine.max #[[MAP]]()[%[[I1]], %[[I0]]]
1001 %2 = affine.max affine_map<()[s0, s1, s2] -> (s0, s1, s2 * 2)> ()[%0, %0, %i1]
1007 // CHECK-DAG: #[[MAP0:.+]] = affine_map<()[s0] -> (s0 + 16, s0 * 8)>
1008 // CHECK-DAG: #[[MAP1:.+]] = affine_map<()[s0, s1, s2] -> (s2 + 16, s2 * 8, s1 * 2, s0 + 1)>
1010 // CHECK: func @merge_mixed_uses_of_affine_max_ops
1011 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)
1012 func.func @merge_mixed_uses_of_affine_max_ops(%i0: index, %i1: index) -> index {
1013 // CHECK: %[[AFFINE:.+]] = affine.max #[[MAP0]]()[%[[I0]]]
1014 %0 = affine.max affine_map<()[s0] -> (s0 + 16, s0 * 8)> ()[%i0]
1015 // %0 is bound to a symbol that is both a standalone expression and a part
1016 // of other expressions.
1017 // CHECK: affine.max #[[MAP1]]()[%[[AFFINE]], %[[I1]], %[[I0]]]
1018 %2 = affine.max affine_map<()[s0, s1, s2] -> (s0, s1 + 1, s2 * 2)> ()[%0, %0, %i1]
1024 // CHECK-LABEL: func @dont_merge_affine_max_if_not_single_dim
1025 func.func @dont_merge_affine_max_if_not_single_dim(%i0: index, %i1: index, %i2: index) -> index {
1026 // CHECK-COUNT-2: affine.max
1027 %0 = affine.max affine_map<()[s0] -> (s0 + 16, s0 * 8)> ()[%i0]
1028 %1 = affine.max affine_map<(d0)[s0] -> (s0 + 4, 7 + d0)> (%0)[%i2]
1034 // CHECK-LABEL: func @dont_merge_affine_max_if_not_single_sym
1035 func.func @dont_merge_affine_max_if_not_single_sym(%i0: index, %i1: index, %i2: index) -> index {
1036 // CHECK-COUNT-2: affine.max
1037 %0 = affine.max affine_map<()[s0] -> (s0 + 16, s0 * 8)> ()[%i0]
1038 %1 = affine.max affine_map<()[s0, s1] -> (s0 + 4, 7 + s1)> ()[%0, %i2]
1044 // Ensure bounding maps of affine.for are composed.
1046 // CHECK-DAG: #[[$MAP0]] = affine_map<()[s0] -> (s0 - 2)>
1047 // CHECK-DAG: #[[$MAP1]] = affine_map<()[s0] -> (s0 + 2)>
1049 // CHECK-LABEL: func @compose_affine_for_bounds
1050 // CHECK-SAME: %[[N:.*]]: index)
1051 // CHECK: affine.for %{{.*}} = #[[$MAP0]]()[%[[N]]] to #[[$MAP1]]()[%[[N]]] {
1053 func.func @compose_affine_for_bounds(%N: index) {
1054 %u = affine.apply affine_map<(d0) -> (d0 + 2)>(%N)
1055 %l = affine.apply affine_map<(d0) -> (d0 - 2)>(%N)
1056 affine.for %i = %l to %u {
1064 // Compose maps into affine.vector_load / affine.vector_store
1066 // CHECK-LABEL: func @compose_into_affine_vector_load_vector_store
1067 // CHECK: affine.for %[[IV:.*]] = 0 to 1024
1068 // CHECK-NEXT: affine.vector_load %{{.*}}[%[[IV]] + 1]
1069 // CHECK-NEXT: affine.vector_store %{{.*}}, %{{.*}}[%[[IV]] + 1]
1070 // CHECK-NEXT: affine.vector_load %{{.*}}[%[[IV]]]
1071 func.func @compose_into_affine_vector_load_vector_store(%A : memref<1024xf32>, %u : index) {
1072 affine.for %i = 0 to 1024 {
1073 // Make sure the unused operand (%u below) gets dropped as well.
1074 %idx = affine.apply affine_map<(d0, d1) -> (d0 + 1)> (%i, %u)
1075 %0 = affine.vector_load %A[%idx] : memref<1024xf32>, vector<8xf32>
1076 affine.vector_store %0, %A[%idx] : memref<1024xf32>, vector<8xf32>
1078 // Map remains the same, but operand changes on composition.
1079 %copy = affine.apply affine_map<(d0) -> (d0)> (%i)
1080 %1 = affine.vector_load %A[%copy] : memref<1024xf32>, vector<8xf32>
1081 "prevent.dce"(%1) : (vector<8xf32>) -> ()
1088 // CHECK-LABEL: func @no_fold_of_store
1089 // CHECK: %[[cst:.+]] = memref.cast %arg
1090 // CHECK: affine.store %[[cst]]
1091 func.func @no_fold_of_store(%arg : memref<32xi8>, %holder: memref<memref<?xi8>>) {
1092 %0 = memref.cast %arg : memref<32xi8> to memref<?xi8>
1093 affine.store %0, %holder[] : memref<memref<?xi8>>
1099 // CHECK-DAG: #[[$MAP0:.+]] = affine_map<()[s0] -> (s0 + 16)>
1100 // CHECK-DAG: #[[$MAP1:.+]] = affine_map<()[s0] -> (s0 * 4)>
1102 // CHECK: func @canonicalize_single_min_max
1103 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)
1104 func.func @canonicalize_single_min_max(%i0: index, %i1: index) -> (index, index) {
1105 // CHECK-NOT: affine.min
1106 // CHECK-NEXT: affine.apply #[[$MAP0]]()[%[[I0]]]
1107 %0 = affine.min affine_map<()[s0] -> (s0 + 16)> ()[%i0]
1109 // CHECK-NOT: affine.max
1110 // CHECK-NEXT: affine.apply #[[$MAP1]]()[%[[I1]]]
1111 %1 = affine.min affine_map<()[s0] -> (s0 * 4)> ()[%i1]
1113 return %0, %1: index, index
1118 // CHECK: #[[$MAP:.+]] = affine_map<()[s0, s1] -> (32, s1 + 16, s0 + s1)>
1120 // CHECK-LABEL: func @canonicalize_multi_min_max
1121 // CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)
1122 func.func @canonicalize_multi_min_max(%i0: index, %i1: index) -> (index, index) {
1123 // CHECK-NEXT: affine.min #[[$MAP]]()[%[[I0]], %[[I1]]]
1124 %0 = affine.min affine_map<()[s0, s1] -> (s0 + s1, s1 + 16, 32)> ()[%i0, %i1]
1126 // CHECK-NEXT: affine.max #[[$MAP]]()[%[[I0]], %[[I1]]]
1127 %1 = affine.max affine_map<()[s0, s1] -> (s0 + s1, 32, s1 + 16)> ()[%i0, %i1]
1129 return %0, %1: index, index
1135 memref.global "private" constant @__constant_1x5x1xf32 : memref<1x5x1xf32> = dense<[[[6.250000e-02], [2.500000e-01], [3.750000e-01], [2.500000e-01], [6.250000e-02]]]>
1136 memref.global "private" constant @__constant_32x64xf32 : memref<32x64xf32> = dense<0.000000e+00>
1137 // CHECK-LABEL: func @fold_const_init_global_memref
1138 func.func @fold_const_init_global_memref() -> (f32, f32) {
1139 %m = memref.get_global @__constant_1x5x1xf32 : memref<1x5x1xf32>
1140 %v0 = affine.load %m[0, 0, 0] : memref<1x5x1xf32>
1141 %v1 = affine.load %m[0, 1, 0] : memref<1x5x1xf32>
1142 return %v0, %v1 : f32, f32
1143 // CHECK-DAG: %[[C0:.*]] = arith.constant 6.250000e-02 : f32
1144 // CHECK-DAG: %[[C1:.*]] = arith.constant 2.500000e-01 : f32
1145 // CHECK-NEXT: return %[[C0]], %[[C1]]
1148 // CHECK-LABEL: func @fold_const_splat_global
1149 func.func @fold_const_splat_global() -> memref<32x64xf32> {
1150 // CHECK-NEXT: %[[CST:.*]] = arith.constant 0.000000e+00 : f32
1151 %m = memref.get_global @__constant_32x64xf32 : memref<32x64xf32>
1152 %s = memref.alloc() : memref<32x64xf32>
1153 affine.for %i = 0 to 32 {
1154 affine.for %j = 0 to 64 {
1155 %v = affine.load %m[%i, %j] : memref<32x64xf32>
1156 affine.store %v, %s[%i, %j] : memref<32x64xf32>
1157 // CHECK: affine.store %[[CST]], %{{.*}}
1160 return %s: memref<32x64xf32>
1166 // Simplification of maps exploiting operand info.
1168 // CHECK: #[[$MAP_SIMPLER:.*]] = affine_map<(d0, d1) -> (((d0 + d1) mod 458313) floordiv 227)>
1170 // CHECK-LABEL: func @simplify_with_operands
1171 func.func @simplify_with_operands(%N: index, %A: memref<?x32xf32>) {
1172 // CHECK-NEXT: affine.for %[[I:.*]] = 0 to %{{.*}}
1173 affine.for %i = 0 to %N step 32 {
1174 // CHECK-NEXT: affine.for %[[II:.*]] = 0 to 32
1175 affine.for %ii = 0 to 32 {
1176 // %ii is less than 32 and %i divides 32.
1177 // CHECK: affine.load %{{.*}}[0, 0]
1178 %x = affine.load %A[%ii floordiv 32, %i mod 32] : memref<?x32xf32>
1179 "test.foo"(%x) : (f32) -> ()
1181 // %i is aligned at 32 boundary and %ii < 32.
1182 // CHECK: affine.load %{{.*}}[%[[I]] floordiv 32, %[[II]] mod 16]
1183 %a = affine.load %A[(%i + %ii) floordiv 32, (%i + %ii) mod 16] : memref<?x32xf32>
1184 "test.foo"(%a) : (f32) -> ()
1185 // CHECK: affine.load %{{.*}}[%[[I]] floordiv 64, (%[[I]] + %[[II]]) mod 64]
1186 %b = affine.load %A[(%i + %ii) floordiv 64, (%i + %ii) mod 64] : memref<?x32xf32>
1187 "test.foo"(%b) : (f32) -> ()
1188 // CHECK: affine.load %{{.*}}[(%[[I]] + %[[II]]) floordiv 16, %[[II]] mod 16]
1189 %c = affine.load %A[(%i + %ii) floordiv 16, (%i + %ii) mod 16] : memref<?x32xf32>
1190 "test.foo"(%c) : (f32) -> ()
1194 // Should not simplify.
1195 affine.for %i = -1 to 32 {
1196 // CHECK: affine.load %{{.*}}[%{{.*}} floordiv {{.*}}, %{{.*}} mod {{.*}}] :
1197 %x = affine.load %A[%i floordiv 32, %i mod 32] : memref<?x32xf32>
1198 "test.foo"(%x) : (f32) -> ()
1201 affine.for %arg0 = 0 to %N step 128 {
1202 affine.for %arg4 = 0 to 32 step 32 {
1203 affine.for %arg5 = 0 to 128 {
1204 // CHECK: affine.apply #[[$MAP_SIMPLER]]
1205 %x = affine.apply affine_map<(d0, d1, d2) -> (((d0 + d2) mod 458313) floordiv 227 + d1 floordiv 256)>(%arg0, %arg4, %arg5)
1206 "test.foo"(%x) : (index) -> ()
1214 // CHECK-LABEL: func @simplify_div_mod_with_operands
1215 func.func @simplify_div_mod_with_operands(%N: index, %A: memref<64xf32>, %unknown: index) {
1216 // CHECK: affine.for %[[I:.*]] = 0 to 32
1217 %cst = arith.constant 1.0 : f32
1218 affine.for %i = 0 to 32 {
1219 // CHECK: affine.store %{{.*}}, %{{.*}}[0]
1220 affine.store %cst, %A[%i floordiv 32] : memref<64xf32>
1221 // CHECK: affine.store %{{.*}}, %{{.*}}[1]
1222 affine.store %cst, %A[(%i + 1) ceildiv 32] : memref<64xf32>
1223 // CHECK: affine.store %{{.*}}, %{{.*}}[%[[I]]]
1224 affine.store %cst, %A[%i mod 32] : memref<64xf32>
1225 // CHECK: affine.store %{{.*}}, %{{.*}}[0]
1226 affine.store %cst, %A[2 * %i floordiv 64] : memref<64xf32>
1227 // CHECK: affine.store %{{.*}}, %{{.*}}[0]
1228 affine.store %cst, %A[(%i mod 16) floordiv 16] : memref<64xf32>
1230 // The ones below can't be simplified.
1231 affine.store %cst, %A[%i floordiv 16] : memref<64xf32>
1232 affine.store %cst, %A[%i mod 16] : memref<64xf32>
1233 affine.store %cst, %A[(%i mod 16) floordiv 15] : memref<64xf32>
1234 affine.store %cst, %A[%i mod 31] : memref<64xf32>
1235 // CHECK: affine.store %{{.*}}, %{{.*}}[%{{.*}} floordiv 16] : memref<64xf32>
1236 // CHECK-NEXT: affine.store %{{.*}}, %{{.*}}[%{{.*}} mod 16] : memref<64xf32>
1237 // CHECK-NEXT: affine.store %{{.*}}, %{{.*}}[(%{{.*}} mod 16) floordiv 15] : memref<64xf32>
1238 // CHECK-NEXT: affine.store %{{.*}}, %{{.*}}[%{{.*}} mod 31] : memref<64xf32>
1241 affine.for %i = -8 to 32 {
1242 // Can't be simplified.
1243 // CHECK: affine.store %{{.*}}, %{{.*}}[%{{.*}} floordiv 32] : memref<64xf32>
1244 affine.store %cst, %A[%i floordiv 32] : memref<64xf32>
1245 // CHECK: affine.store %{{.*}}, %{{.*}}[%{{.*}} mod 32] : memref<64xf32>
1246 affine.store %cst, %A[%i mod 32] : memref<64xf32>
1247 // floordiv rounds toward -inf; (%i - 96) floordiv 64 will be -2.
1248 // CHECK: affine.store %{{.*}}, %{{.*}}[0] : memref<64xf32>
1249 affine.store %cst, %A[2 + (%i - 96) floordiv 64] : memref<64xf32>
1252 // CHECK: affine.for %[[II:.*]] = 8 to 16
1253 affine.for %i = 8 to 16 {
1254 // CHECK: affine.store %{{.*}}, %{{.*}}[1] : memref<64xf32>
1255 affine.store %cst, %A[%i floordiv 8] : memref<64xf32>
1256 // CHECK: affine.store %{{.*}}, %{{.*}}[2] : memref<64xf32>
1257 affine.store %cst, %A[(%i + 1) ceildiv 8] : memref<64xf32>
1258 // CHECK: affine.store %{{.*}}, %{{.*}}[%[[II]] mod 8] : memref<64xf32>
1259 affine.store %cst, %A[%i mod 8] : memref<64xf32>
1260 // CHECK: affine.store %{{.*}}, %{{.*}}[%[[II]]] : memref<64xf32>
1261 affine.store %cst, %A[%i mod 32] : memref<64xf32>
1262 // Upper bound on the mod 32 expression will be 15.
1263 // CHECK: affine.store %{{.*}}, %{{.*}}[0] : memref<64xf32>
1264 affine.store %cst, %A[(%i mod 32) floordiv 16] : memref<64xf32>
1265 // Lower bound on the mod 16 expression will be 8.
1266 // CHECK: affine.store %{{.*}}, %{{.*}}[1] : memref<64xf32>
1267 affine.store %cst, %A[(%i mod 16) floordiv 8] : memref<64xf32>
1268 // CHECK: affine.store %{{.*}}, %{{.*}}[0] : memref<64xf32>
1269 affine.store %cst, %A[(%unknown mod 16) floordiv 16] : memref<64xf32>
1276 #map0 = affine_map<(d0) -> (32, d0 * -32 + 32)>
1277 #map1 = affine_map<(d0) -> (32, d0 * -32 + 64)>
1278 #map3 = affine_map<(d0) -> (16, d0 * -16 + 32)>
1280 // CHECK-DAG: #[[$SIMPLE_MAP:.*]] = affine_map<()[s0] -> (3, s0)>
1281 // CHECK-DAG: #[[$SIMPLE_MAP_MAX:.*]] = affine_map<()[s0] -> (5, s0)>
1282 // CHECK-DAG: #[[$SIMPLIFIED_MAP:.*]] = affine_map<(d0, d1) -> (-9, d0 * 4 - d1 * 4)>
1283 // CHECK-DAG: #[[$FLOORDIV:.*]] = affine_map<(d0) -> (d0 floordiv 2)>
1285 // CHECK-LABEL: func @simplify_min_max_bounds_simple
1286 func.func @simplify_min_max_bounds_simple(%M: index) {
1288 // CHECK-NEXT: affine.for %{{.*}} = 0 to min #[[$SIMPLE_MAP]]
1289 affine.for %i = 0 to min affine_map<(d0) -> (3, 5, d0)>(%M) {
1290 "test.foo"() : () -> ()
1293 // CHECK: affine.for %{{.*}} = 0 to min #[[$SIMPLE_MAP]]
1294 affine.for %i = 0 to min affine_map<(d0) -> (3, 3, d0)>(%M) {
1295 "test.foo"() : () -> ()
1298 // CHECK: affine.for %{{.*}} = max #[[$SIMPLE_MAP_MAX]]
1299 affine.for %i = max affine_map<(d0) -> (3, 5, d0)>(%M) to 10 {
1300 "test.foo"() : () -> ()
1303 // CHECK: affine.for %{{.*}} = max #[[$SIMPLE_MAP_MAX]]
1304 affine.for %i = max affine_map<(d0) -> (5, 5, d0)>(%M) to 10 {
1305 "test.foo"() : () -> ()
1311 // CHECK-LABEL: func @simplify_bounds_tiled
1312 func.func @simplify_bounds_tiled() {
1313 affine.for %arg5 = 0 to 1 {
1314 affine.for %arg6 = 0 to 2 {
1315 affine.for %arg8 = 0 to min #map0(%arg5) step 16 {
1316 affine.for %arg9 = 0 to min #map1(%arg6) step 16 {
1317 affine.for %arg10 = 0 to 2 {
1318 affine.for %arg12 = 0 to min #map3(%arg10) step 16 {
1319 "test.foo"() : () -> ()
1326 // CHECK: affine.for
1327 // CHECK-NEXT: affine.for
1328 // CHECK-NEXT: affine.for %{{.*}} = 0 to 32 step 16
1329 // CHECK-NEXT: affine.for %{{.*}} = 0 to 32 step 16
1330 // CHECK-NEXT: affine.for %{{.*}} = 0 to 2
1331 // CHECK-NEXT: affine.for %{{.*}} = 0 to 16 step 16
1336 // CHECK-LABEL: func @simplify_min_max_multi_expr
1337 func.func @simplify_min_max_multi_expr() {
1339 // CHECK: affine.for
1340 affine.for %i = 0 to 2 {
1341 // CHECK: affine.for %{{.*}} = 5 to
1342 affine.for %j = max affine_map<(d0) -> (5, 4 * d0)> (%i) to affine_map<(d0) -> (4 * d0 + 3)>(%i) {
1343 "test.foo"() : () -> ()
1347 // Expressions with multiple operands.
1348 // CHECK: affine.for
1349 affine.for %i = 0 to 2 {
1350 // CHECK: affine.for
1351 affine.for %j = 0 to 4 {
1352 // The first upper bound expression will not be lower than -9. So, it's redundant.
1353 // CHECK-NEXT: affine.for %{{.*}} = -10 to -9
1354 affine.for %k = -10 to min affine_map<(d0, d1) -> (4 * d0 - 3 * d1, -9)>(%i, %j) {
1355 "test.foo"() : () -> ()
1360 // One expression is redundant but not the others.
1361 // CHECK: affine.for
1362 affine.for %i = 0 to 2 {
1363 // CHECK: affine.for
1364 affine.for %j = 0 to 4 {
1365 // The first upper bound expression will not be lower than -9. So, it's redundant.
1366 // CHECK-NEXT: affine.for %{{.*}} = -10 to min #[[$SIMPLIFIED_MAP]]
1367 affine.for %k = -10 to min affine_map<(d0, d1) -> (4 * d0 - 3 * d1, -9, 4 * d0 - 4 * d1)>(%i, %j) {
1368 "test.foo"() : () -> ()
1373 // CHECK: affine.for %{{.*}} = 0 to 1
1374 affine.for %i = 0 to 2 {
1375 affine.for %j = max affine_map<(d0) -> (d0 floordiv 2, 0)>(%i) to 1 {
1376 "test.foo"() : () -> ()
1380 // The constant bound is redundant here.
1381 // CHECK: affine.for %{{.*}} = #[[$FLOORDIV]](%{{.*}} to 10
1382 affine.for %i = 0 to 8 {
1383 affine.for %j = max affine_map<(d0) -> (d0 floordiv 2, 0)>(%i) to 10 {
1384 "test.foo"() : () -> ()
1391 // CHECK-LABEL: func @no_simplify_min_max
1392 func.func @no_simplify_min_max(%M: index) {
1393 // Negative test cases.
1394 // CHECK: affine.for
1395 affine.for %i = 0 to 4 {
1396 // CHECK-NEXT: affine.for %{{.*}} = 0 to min
1397 affine.for %j = 0 to min affine_map<(d0) -> (2 * d0, 2)>(%i) {
1398 "test.foo"() : () -> ()
1400 // CHECK: affine.for %{{.*}} = 0 to min {{.*}}(%{{.*}})[%{{.*}}]
1401 affine.for %j = 0 to min affine_map<(d0)[s0] -> (d0, s0)>(%i)[%M] {
1402 "test.foo"() : () -> ()
1411 // CHECK: #[[$map:.*]] = affine_map<()[s0] -> (s0 * ((-s0 + 40961) ceildiv 512))>
1412 // CHECK-BOTTOM-UP: #[[$map:.*]] = affine_map<()[s0] -> (s0 * ((-s0 + 40961) ceildiv 512))>
1413 // CHECK-LABEL: func @regression_do_not_perform_invalid_replacements
1414 // CHECK-BOTTOM-UP-LABEL: func @regression_do_not_perform_invalid_replacements
1415 func.func @regression_do_not_perform_invalid_replacements(%arg0: index) {
1416 // Dim must be promoted to sym before combining both maps.
1417 // CHECK: %[[apply:.*]] = affine.apply #[[$map]]()[%{{.*}}]
1418 // CHECK-BOTTOM-UP: %[[apply:.*]] = affine.apply #[[$map]]()[%{{.*}}]
1419 %0 = affine.apply affine_map<(d0) -> (-d0 + 40961)>(%arg0)
1420 %1 = affine.apply affine_map<(d0)[s0] -> (d0 * (s0 ceildiv 512))>(%arg0)[%0]
1421 // CHECK: "test.foo"(%[[apply]])
1422 // CHECK-BOTTOM-UP: "test.foo"(%[[apply]])
1423 "test.foo"(%1) : (index) -> ()
1428 // CHECK-LABEL: func @min.oneval(%arg0: index)
1429 func.func @min.oneval(%arg0: index) -> index {
1430 %min = affine.min affine_map<()[s0] -> (s0)> ()[%arg0]
1431 // CHECK: return %arg0 : index
1436 // CHECK-LABEL: func @max.oneval(%arg0: index)
1437 func.func @max.oneval(%arg0: index) -> index {
1438 %max = affine.max affine_map<()[s0] -> (s0)> ()[%arg0]
1439 // CHECK: return %arg0 : index
1445 // CHECK-LABEL: func @mod_of_mod(
1446 // CHECK: %[[c0:.*]] = arith.constant 0
1447 // CHECK: return %[[c0]], %[[c0]]
1448 func.func @mod_of_mod(%lb: index, %ub: index, %step: index) -> (index, index) {
1449 // Simplify: (ub - ub % step) % step == 0
1450 %0 = affine.apply affine_map<()[s0, s1] -> ((s0 - (s0 mod s1)) mod s1)> ()[%ub, %step]
1451 // Simplify: (ub - (ub - lb) % step - lb) % step == 0
1452 %1 = affine.apply affine_map<()[s0, s1, s2] -> ((s0 - ((s0 - s2) mod s1) - s2) mod s1)> ()[%ub, %step, %lb]
1453 return %0, %1 : index, index
1458 // CHECK-LABEL: func.func @prefetch_canonicalize
1459 // CHECK-SAME: ([[PARAM_0_:%.+]]: memref<512xf32>) {
1460 func.func @prefetch_canonicalize(%arg0: memref<512xf32>) -> () {
1461 // CHECK: affine.for [[I_0_:%.+]] = 0 to 8 {
1462 affine.for %arg3 = 0 to 8 {
1463 %1 = affine.apply affine_map<()[s0] -> (s0 * 64)>()[%arg3]
1464 // CHECK: affine.prefetch [[PARAM_0_]][symbol([[I_0_]]) * 64], read, locality<3>, data : memref<512xf32>
1465 affine.prefetch %arg0[%1], read, locality<3>, data : memref<512xf32>
1472 // CHECK-LABEL: @delinearize_fold_constant
1473 // CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index
1474 // CHECK-DAG: %[[C2:.+]] = arith.constant 2 : index
1475 // CHECK-NOT: affine.delinearize_index
1476 // CHECK: return %[[C1]], %[[C1]], %[[C2]]
1477 func.func @delinearize_fold_constant() -> (index, index, index) {
1478 %c22 = arith.constant 22 : index
1479 %0:3 = affine.delinearize_index %c22 into (2, 3, 5) : index, index, index
1480 return %0#0, %0#1, %0#2 : index, index, index
1485 // CHECK-LABEL: @delinearize_fold_negative_constant
1486 // CHECK-DAG: %[[C_2:.+]] = arith.constant -2 : index
1487 // CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index
1488 // CHECK-DAG: %[[C3:.+]] = arith.constant 3 : index
1489 // CHECK-NOT: affine.delinearize_index
1490 // CHECK: return %[[C_2]], %[[C1]], %[[C3]]
1491 func.func @delinearize_fold_negative_constant() -> (index, index, index) {
1492 %c_22 = arith.constant -22 : index
1493 %0:3 = affine.delinearize_index %c_22 into (2, 3, 5) : index, index, index
1494 return %0#0, %0#1, %0#2 : index, index, index
1499 // CHECK-LABEL: @delinearize_fold_negative_constant_no_outer_bound
1500 // CHECK-DAG: %[[C_2:.+]] = arith.constant -2 : index
1501 // CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index
1502 // CHECK-DAG: %[[C3:.+]] = arith.constant 3 : index
1503 // CHECK-NOT: affine.delinearize_index
1504 // CHECK: return %[[C_2]], %[[C1]], %[[C3]]
1505 func.func @delinearize_fold_negative_constant_no_outer_bound() -> (index, index, index) {
1506 %c_22 = arith.constant -22 : index
1507 %0:3 = affine.delinearize_index %c_22 into (3, 5) : index, index, index
1508 return %0#0, %0#1, %0#2 : index, index, index
1513 // CHECK-LABEL: @delinearize_dont_fold_constant_dynamic_basis
1514 // CHECK-DAG: %[[C22:.+]] = arith.constant 22 : index
1515 // CHECK: %[[RET:.+]]:3 = affine.delinearize_index %[[C22]]
1516 // CHECK: return %[[RET]]#0, %[[RET]]#1, %[[RET]]#2
1517 func.func @delinearize_dont_fold_constant_dynamic_basis(%arg0: index) -> (index, index, index) {
1518 %c22 = arith.constant 22 : index
1519 %0:3 = affine.delinearize_index %c22 into (2, %arg0, 5) : index, index, index
1520 return %0#0, %0#1, %0#2 : index, index, index
1525 func.func @drop_unit_basis_in_delinearize(%arg0 : index, %arg1 : index, %arg2 : index) ->
1526 (index, index, index, index, index, index) {
1527 %c1 = arith.constant 1 : index
1528 %0:6 = affine.delinearize_index %arg0 into (1, %arg1, 1, 1, %arg2, %c1)
1529 : index, index, index, index, index, index
1530 return %0#0, %0#1, %0#2, %0#3, %0#4, %0#5 : index, index, index, index, index, index
1532 // CHECK-LABEL: func @drop_unit_basis_in_delinearize(
1533 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1534 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1535 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index)
1536 // CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index
1537 // CHECK-DAG: %[[DELINEARIZE:.+]]:2 = affine.delinearize_index %[[ARG0]] into (%[[ARG1]], %[[ARG2]])
1538 // CHECK: return %[[C0]], %[[DELINEARIZE]]#0, %[[C0]], %[[C0]], %[[DELINEARIZE]]#1, %[[C0]]
1542 func.func @drop_unit_basis_in_delinearize_no_outer_bound(%arg0 : index, %arg1 : index, %arg2 : index) ->
1543 (index, index, index, index, index, index) {
1544 %c1 = arith.constant 1 : index
1545 %0:6 = affine.delinearize_index %arg0 into (%arg1, 1, 1, %arg2, %c1)
1546 : index, index, index, index, index, index
1547 return %0#0, %0#1, %0#2, %0#3, %0#4, %0#5 : index, index, index, index, index, index
1549 // CHECK-LABEL: func @drop_unit_basis_in_delinearize_no_outer_bound(
1550 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1551 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1552 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index)
1553 // CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index
1554 // CHECK-DAG: %[[DELINEARIZE:.+]]:3 = affine.delinearize_index %[[ARG0]] into (%[[ARG1]], %[[ARG2]])
1555 // CHECK: return %[[DELINEARIZE]]#0, %[[DELINEARIZE]]#1, %[[C0]], %[[C0]], %[[DELINEARIZE]]#2, %[[C0]]
1559 func.func @drop_all_unit_bases(%arg0 : index) -> (index, index) {
1560 %0:2 = affine.delinearize_index %arg0 into (1, 1) : index, index
1561 return %0#0, %0#1 : index, index
1563 // CHECK-LABEL: func @drop_all_unit_bases(
1564 // CHECK-SAME: %[[ARG0:.+]]: index)
1565 // CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index
1566 // CHECK-NOT: affine.delinearize_index
1567 // CHECK: return %[[C0]], %[[C0]]
1571 func.func @drop_all_unit_bases_no_outer_bound(%arg0 : index) -> (index, index, index) {
1572 %0:3 = affine.delinearize_index %arg0 into (1, 1) : index, index, index
1573 return %0#0, %0#1, %0#2 : index, index, index
1575 // CHECK-LABEL: func @drop_all_unit_bases_no_outer_bound(
1576 // CHECK-SAME: %[[ARG0:.+]]: index)
1577 // CHECK-DAG: %[[C0:.+]] = arith.constant 0 : index
1578 // CHECK-NOT: affine.delinearize_index
1579 // CHECK: return %[[ARG0]], %[[C0]], %[[C0]]
1583 func.func @drop_single_loop_delinearize(%arg0 : index, %arg1 : index) -> index {
1584 %c0 = arith.constant 0 : index
1585 %c1 = arith.constant 1 : index
1586 %2 = scf.for %iv = %c0 to %arg1 step %c1 iter_args(%arg2 = %c0) -> index {
1587 %0 = affine.delinearize_index %iv into (%arg1) : index
1588 %1 = "some_use"(%arg2, %0) : (index, index) -> (index)
1589 scf.yield %1 : index
1593 // CHECK-LABEL: func @drop_single_loop_delinearize(
1594 // CHECK-SAME: %[[ARG0:.+]]: index)
1595 // CHECK: scf.for %[[IV:[a-zA-Z0-9]+]] =
1596 // CHECK-NOT: affine.delinearize_index
1597 // CHECK: "some_use"(%{{.+}}, %[[IV]])
1601 // CHECK-LABEL: func @delinearize_non_induction_variable
1602 // CHECK-NOT: affine.delinearize
1603 func.func @delinearize_non_induction_variable(%arg0: memref<?xi32>, %i : index, %t0 : index, %t1 : index, %t2 : index) -> index {
1604 %1 = affine.apply affine_map<(d0)[s0, s1, s2] -> (d0 + s0 + s1 * 64 + s2 * 128)>(%i)[%t0, %t1, %t2]
1605 %2 = affine.delinearize_index %1 into (1024) : index
1611 // CHECK-LABEL: func @delinearize_non_loop_like
1612 // CHECK-NOT: affine.delinearize
1613 func.func @delinearize_non_loop_like(%arg0: memref<?xi32>, %i : index) -> index {
1614 %2 = affine.delinearize_index %i into (1024) : index
1620 // CHECK-LABEL: func @delinearize_empty_basis
1621 // CHECK-SAME: (%[[ARG0:.+]]: index)
1622 // CHECK-NOT: affine.delinearize
1623 // CHECK: return %[[ARG0]]
1624 func.func @delinearize_empty_basis(%arg0: index) -> index {
1625 %0 = affine.delinearize_index %arg0 into () : index
1631 // CHECK-LABEL: @linearize_fold_constants
1632 // CHECK-DAG: %[[C22:.+]] = arith.constant 22 : index
1633 // CHECK-NOT: affine.linearize
1634 // CHECK: return %[[C22]]
1635 func.func @linearize_fold_constants() -> index {
1636 %c2 = arith.constant 2 : index
1637 %c1 = arith.constant 1 : index
1639 %ret = affine.linearize_index [%c1, %c1, %c2] by (2, 3, 5) : index
1645 // CHECK-LABEL: @linearize_fold_constants_no_outer_bound
1646 // CHECK-DAG: %[[C22:.+]] = arith.constant 22 : index
1647 // CHECK-NOT: affine.linearize
1648 // CHECK: return %[[C22]]
1649 func.func @linearize_fold_constants_no_outer_bound() -> index {
1650 %c2 = arith.constant 2 : index
1651 %c1 = arith.constant 1 : index
1653 %ret = affine.linearize_index [%c1, %c1, %c2] by (3, 5) : index
1659 // CHECK-LABEL: @linearize_fold_empty_basis
1660 // CHECK-SAME: (%[[ARG0:.+]]: index)
1661 // CHECK-NOT: affine.linearize
1662 // CHECK: return %[[ARG0]]
1663 func.func @linearize_fold_empty_basis(%arg0: index) -> index {
1664 %ret = affine.linearize_index [%arg0] by () : index
1670 // CHECK-LABEL: @linearize_fold_only_outer_bound
1671 // CHECK-SAME: (%[[ARG0:.+]]: index)
1672 // CHECK-NOT: affine.linearize
1673 // CHECK: return %[[ARG0]]
1674 func.func @linearize_fold_only_outer_bound(%arg0: index) -> index {
1675 %ret = affine.linearize_index [%arg0] by (2) : index
1681 // CHECK-LABEL: @linearize_dont_fold_dynamic_basis
1682 // CHECK: %[[RET:.+]] = affine.linearize_index
1683 // CHECK: return %[[RET]]
1684 func.func @linearize_dont_fold_dynamic_basis(%arg0: index) -> index {
1685 %c2 = arith.constant 2 : index
1686 %c1 = arith.constant 1 : index
1688 %ret = affine.linearize_index [%c1, %c1, %c2] by (2, %arg0, 5) : index
1694 // CHECK-LABEL: func @cancel_delinearize_linearize_disjoint_exact(
1695 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1696 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1697 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index,
1698 // CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]: index,
1699 // CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]: index)
1700 // CHECK: return %[[ARG0]], %[[ARG1]], %[[ARG2]]
1701 func.func @cancel_delinearize_linearize_disjoint_exact(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) -> (index, index, index) {
1702 %0 = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by (%arg3, 4, %arg4) : index
1703 %1:3 = affine.delinearize_index %0 into (%arg3, 4, %arg4)
1704 : index, index, index
1705 return %1#0, %1#1, %1#2 : index, index, index
1710 // CHECK-LABEL: func @cancel_delinearize_linearize_disjoint_linearize_extra_bound(
1711 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1712 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1713 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index,
1714 // CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]: index,
1715 // CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]: index)
1716 // CHECK: return %[[ARG0]], %[[ARG1]], %[[ARG2]]
1717 func.func @cancel_delinearize_linearize_disjoint_linearize_extra_bound(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) -> (index, index, index) {
1718 %0 = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by (4, %arg4) : index
1719 %1:3 = affine.delinearize_index %0 into (4, %arg4)
1720 : index, index, index
1721 return %1#0, %1#1, %1#2 : index, index, index
1726 // CHECK-LABEL: func @cancel_delinearize_linearize_disjoint_delinearize_extra_bound(
1727 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1728 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1729 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index,
1730 // CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]: index,
1731 // CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]: index)
1732 // CHECK: return %[[ARG0]], %[[ARG1]], %[[ARG2]]
1733 func.func @cancel_delinearize_linearize_disjoint_delinearize_extra_bound(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) -> (index, index, index) {
1734 %0 = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by (4, %arg4) : index
1735 %1:3 = affine.delinearize_index %0 into (%arg3, 4, %arg4)
1736 : index, index, index
1737 return %1#0, %1#1, %1#2 : index, index, index
1742 // Without `disjoint`, the cancelation isn't guaranteed to be the identity.
1743 // CHECK-LABEL: func @no_cancel_delinearize_linearize_exact(
1744 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1745 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1746 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index,
1747 // CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]: index,
1748 // CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]: index)
1749 // CHECK: %[[LIN:.+]] = affine.linearize_index [%[[ARG0]], %[[ARG1]], %[[ARG2]]] by (%[[ARG3]], 4, %[[ARG4]])
1750 // CHECK: %[[DELIN:.+]]:3 = affine.delinearize_index %[[LIN]] into (%[[ARG3]], 4, %[[ARG4]])
1751 // CHECK: return %[[DELIN]]#0, %[[DELIN]]#1, %[[DELIN]]#2
1752 func.func @no_cancel_delinearize_linearize_exact(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) -> (index, index, index) {
1753 %0 = affine.linearize_index [%arg0, %arg1, %arg2] by (%arg3, 4, %arg4) : index
1754 %1:3 = affine.delinearize_index %0 into (%arg3, 4, %arg4)
1755 : index, index, index
1756 return %1#0, %1#1, %1#2 : index, index, index
1761 // These don't cancel because the delinearize and linearize have a different basis.
1762 // CHECK-LABEL: func @no_cancel_delinearize_linearize_different_basis(
1763 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1764 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1765 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index,
1766 // CHECK-SAME: %[[ARG3:[a-zA-Z0-9]+]]: index,
1767 // CHECK-SAME: %[[ARG4:[a-zA-Z0-9]+]]: index)
1768 // CHECK: %[[LIN:.+]] = affine.linearize_index [%[[ARG0]], %[[ARG1]], %[[ARG2]]] by (%[[ARG3]], 4, %[[ARG4]])
1769 // CHECK: %[[DELIN:.+]]:3 = affine.delinearize_index %[[LIN]] into (%[[ARG3]], 8, %[[ARG4]])
1770 // CHECK: return %[[DELIN]]#0, %[[DELIN]]#1, %[[DELIN]]#2
1771 func.func @no_cancel_delinearize_linearize_different_basis(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) -> (index, index, index) {
1772 %0 = affine.linearize_index [%arg0, %arg1, %arg2] by (%arg3, 4, %arg4) : index
1773 %1:3 = affine.delinearize_index %0 into (%arg3, 8, %arg4)
1774 : index, index, index
1775 return %1#0, %1#1, %1#2 : index, index, index
1780 // CHECK-LABEL: @linearize_unit_basis_disjoint
1781 // CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index, %[[arg2:.+]]: index, %[[arg3:.+]]: index)
1782 // CHECK: %[[ret:.+]] = affine.linearize_index disjoint [%[[arg0]], %[[arg2]]] by (3, %[[arg3]]) : index
1783 // CHECK: return %[[ret]]
1784 func.func @linearize_unit_basis_disjoint(%arg0: index, %arg1: index, %arg2: index, %arg3: index) -> index {
1785 %ret = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by (3, 1, %arg3) : index
1791 // CHECK-LABEL: @linearize_unit_basis_disjoint_no_outer_bound
1792 // CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index, %[[arg2:.+]]: index, %[[arg3:.+]]: index)
1793 // CHECK: %[[ret:.+]] = affine.linearize_index disjoint [%[[arg0]], %[[arg2]]] by (%[[arg3]]) : index
1794 // CHECK: return %[[ret]]
1795 func.func @linearize_unit_basis_disjoint_no_outer_bound(%arg0: index, %arg1: index, %arg2: index, %arg3: index) -> index {
1796 %ret = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by (1, %arg3) : index
1802 // CHECK-LABEL: @linearize_unit_basis_zero
1803 // CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index, %[[arg2:.+]]: index)
1804 // CHECK: %[[ret:.+]] = affine.linearize_index [%[[arg0]], %[[arg1]]] by (3, %[[arg2]]) : index
1805 // CHECK: return %[[ret]]
1806 func.func @linearize_unit_basis_zero(%arg0: index, %arg1: index, %arg2: index) -> index {
1807 %c0 = arith.constant 0 : index
1808 %ret = affine.linearize_index [%arg0, %c0, %arg1] by (3, 1, %arg2) : index
1814 // CHECK-LABEL: @linearize_all_zero_unit_basis
1815 // CHECK: arith.constant 0 : index
1816 // CHECK-NOT: affine.linearize_index
1817 func.func @linearize_all_zero_unit_basis() -> index {
1818 %c0 = arith.constant 0 : index
1819 %ret = affine.linearize_index [%c0, %c0] by (1, 1) : index
1825 // CHECK-LABEL: @linearize_one_element_basis
1826 // CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index)
1827 // CHECK-NOT: affine.linearize_index
1828 // CHECK: return %[[arg0]]
1829 func.func @linearize_one_element_basis(%arg0: index, %arg1: index) -> index {
1830 %ret = affine.linearize_index [%arg0] by (%arg1) : index
1836 // CHECK-LABEL: func @cancel_linearize_denearize_exact(
1837 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1838 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1839 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index)
1840 // CHECK: return %[[ARG0]]
1841 func.func @cancel_linearize_denearize_exact(%arg0: index, %arg1: index, %arg2: index) -> index {
1842 %0:3 = affine.delinearize_index %arg0 into (%arg1, 4, %arg2) : index, index, index
1843 %1 = affine.linearize_index [%0#0, %0#1, %0#2] by (%arg1, 4, %arg2) : index
1849 // CHECK-LABEL: func @cancel_linearize_denearize_linearize_extra_bound(
1850 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1851 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1852 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index)
1853 // CHECK: return %[[ARG0]]
1854 func.func @cancel_linearize_denearize_linearize_extra_bound(%arg0: index, %arg1: index, %arg2: index) -> index {
1855 %0:3 = affine.delinearize_index %arg0 into (4, %arg2) : index, index, index
1856 %1 = affine.linearize_index [%0#0, %0#1, %0#2] by (%arg1, 4, %arg2) : index
1862 // CHECK-LABEL: func @cancel_linearize_denearize_delinearize_extra_bound(
1863 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1864 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1865 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index)
1866 // CHECK: return %[[ARG0]]
1867 func.func @cancel_linearize_denearize_delinearize_extra_bound(%arg0: index, %arg1: index, %arg2: index) -> index {
1868 %0:3 = affine.delinearize_index %arg0 into (%arg1, 4, %arg2) : index, index, index
1869 %1 = affine.linearize_index [%0#0, %0#1, %0#2] by (4, %arg2) : index
1875 // Don't cancel because the values from the delinearize aren't used in order
1876 // CHECK-LABEL: func @no_cancel_linearize_denearize_permuted(
1877 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1878 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1879 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index)
1880 // CHECK: %[[DELIN:.+]]:3 = affine.delinearize_index %[[ARG0]] into (%[[ARG1]], 4, %[[ARG2]])
1881 // CHECK: %[[LIN:.+]] = affine.linearize_index [%[[DELIN]]#0, %[[DELIN]]#2, %[[DELIN]]#1] by (%[[ARG1]], 4, %[[ARG2]])
1882 // CHECK: return %[[LIN]]
1883 func.func @no_cancel_linearize_denearize_permuted(%arg0: index, %arg1: index, %arg2: index) -> index {
1884 %0:3 = affine.delinearize_index %arg0 into (%arg1, 4, %arg2) : index, index, index
1885 %1 = affine.linearize_index [%0#0, %0#2, %0#1] by (%arg1, 4, %arg2) : index
1891 // Won't cancel because the linearize and delinearize are using a different basis
1892 // CHECK-LABEL: func @no_cancel_linearize_denearize_different_basis(
1893 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1894 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index,
1895 // CHECK-SAME: %[[ARG2:[a-zA-Z0-9]+]]: index)
1896 // CHECK: %[[DELIN:.+]]:3 = affine.delinearize_index %[[ARG0]] into (%[[ARG1]], 4, %[[ARG2]])
1897 // CHECK: %[[LIN:.+]] = affine.linearize_index [%[[DELIN]]#0, %[[DELIN]]#1, %[[DELIN]]#2] by (%[[ARG1]], 8, %[[ARG2]])
1898 // CHECK: return %[[LIN]]
1899 func.func @no_cancel_linearize_denearize_different_basis(%arg0: index, %arg1: index, %arg2: index) -> index {
1900 %0:3 = affine.delinearize_index %arg0 into (%arg1, 4, %arg2) : index, index, index
1901 %1 = affine.linearize_index [%0#0, %0#1, %0#2] by (%arg1, 8, %arg2) : index
1907 // CHECK-LABEL: func @affine_leading_zero(
1908 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1909 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index)
1910 // CHECK: %[[RET:.+]] = affine.linearize_index [%[[ARG0]], %[[ARG1]]] by (3, 5)
1911 // CHECK: return %[[RET]]
1912 func.func @affine_leading_zero(%arg0: index, %arg1: index) -> index {
1913 %c0 = arith.constant 0 : index
1914 %ret = affine.linearize_index [%c0, %arg0, %arg1] by (2, 3, 5) : index
1920 // CHECK-LABEL: func @affine_leading_zero_no_outer_bound(
1921 // CHECK-SAME: %[[ARG0:[a-zA-Z0-9]+]]: index,
1922 // CHECK-SAME: %[[ARG1:[a-zA-Z0-9]+]]: index)
1923 // CHECK: %[[RET:.+]] = affine.linearize_index [%[[ARG0]], %[[ARG1]]] by (3, 5)
1924 // CHECK: return %[[RET]]
1925 func.func @affine_leading_zero_no_outer_bound(%arg0: index, %arg1: index) -> index {
1926 %c0 = arith.constant 0 : index
1927 %ret = affine.linearize_index [%c0, %arg0, %arg1] by (3, 5) : index