brintos

brintos / llvm-project-archived public Read only

0
0
Text · 94.5 KiB · 1169cd1 Raw
2404 lines · plain
1// RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -canonicalize="test-convergence" | FileCheck %s2// RUN: mlir-opt -allow-unregistered-dialect %s -split-input-file -canonicalize="test-convergence top-down=0" | FileCheck %s --check-prefix=CHECK-BOTTOM-UP3 4// -----5 6// CHECK-DAG: #[[$MAP0:.*]] = affine_map<(d0) -> (d0 - 1)>7// CHECK-DAG: #[[$MAP1:.*]] = affine_map<(d0) -> (d0 + 1)>8 9// CHECK-LABEL: func @compose_affine_maps_1dto2d_no_symbols() {10func.func @compose_affine_maps_1dto2d_no_symbols() {11  %0 = memref.alloc() : memref<4x4xf32>12 13  affine.for %i0 = 0 to 15 {14    // Test load[%x, %x]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)19 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>23 24    // Test store[%y, %y]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)28 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>32 33    // Test store[%x, %y]34    %xy_0 = affine.apply affine_map<(d0, d1) -> (d0)> (%x0, %y0)35    %xy_1 = affine.apply affine_map<(d0, d1) -> (d1)> (%x0, %y0)36 37    // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I0A]], %[[I1A]]]38    memref.store %v0, %0[%xy_0, %xy_1] : memref<4x4xf32>39 40    // Test store[%y, %x]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>45  }46  return47}48 49// -----50 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)>54 55// CHECK-LABEL: func @compose_affine_maps_1dto2d_with_symbols() {56func.func @compose_affine_maps_1dto2d_with_symbols() {57  %0 = memref.alloc() : memref<4x4xf32>58 59  affine.for %i0 = 0 to 15 {60    // Test load[%x0, %x0] with symbol %c461    %c4 = arith.constant 4 : index62    %x0 = affine.apply affine_map<(d0)[s0] -> (d0 - s0)> (%i0)[%c4]63 64    // CHECK: %[[I0:.*]] = affine.apply #[[$MAP4]](%{{.*}})65    // CHECK-NEXT: %[[V0:.*]] = memref.load %{{.*}}[%[[I0]], %[[I0]]]66    %v0 = memref.load %0[%x0, %x0] : memref<4x4xf32>67 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>74 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>80 81    // Test store[%x2, %x0] with symbol %c4 from '%x0' and %c5 from '%x2'82    %c5 = arith.constant 5 : index83    %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>88  }89  return90}91 92// -----93 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)>96 97// CHECK-LABEL: func @compose_affine_maps_2d_tile98func.func @compose_affine_maps_2d_tile(%0: memref<16x32xf32>, %1: memref<16x32xf32>) {99  %c4 = arith.constant 4 : index100  %c8 = arith.constant 8 : index101 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]110 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>119 120          // CHECK-NEXT: memref.store %[[L0]], %{{.*}}[%[[I0]], %[[I1]]]121          memref.store %v0, %1[%x40, %x41] : memref<16x32xf32>122        }123      }124    }125  }126  return127}128 129// -----130 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)>136 137// CHECK-LABEL: func @compose_affine_maps_dependent_loads() {138func.func @compose_affine_maps_dependent_loads() {139  %0 = memref.alloc() : memref<16x32xf32>140  %1 = memref.alloc() : memref<16x32xf32>141 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 : index146        %c7 = arith.constant 7 : index147 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]154 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>160 161        // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I0]], %[[I2]]]162        memref.store %v0, %0[%x00, %x02] : memref<16x32xf32>163 164        // Swizzle %i0, %i1165        // CHECK-NEXT: memref.store %[[V0]], %{{.*}}[%[[I1]], %[[I0]]]166        memref.store %v0, %0[%x01, %x00] : memref<16x32xf32>167 168        // Swizzle %x00, %x01 and %c3, %c7169        %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]173 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>178      }179    }180  }181  return182}183 184// -----185 186// CHECK-DAG: #[[$MAP13A:.*]] = affine_map<(d0) -> ((d0 + 6) ceildiv 8)>187// CHECK-DAG: #[[$MAP13B:.*]] = affine_map<(d0) -> ((d0 * 4 - 4) floordiv 3)>188 189// CHECK-LABEL: func @compose_affine_maps_diamond_dependency190func.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>201  }202 203  return204}205 206// -----207 208// CHECK-DAG: #[[$MAP14:.*]] = affine_map<()[s0, s1] -> ((s0 * 4 + s1 * 4) floordiv s0)>209 210// CHECK-LABEL: func @compose_affine_maps_multiple_symbols211func.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]]()[%{{.*}}, %{{.*}}]216  return %e : index217}218 219// -----220 221// CHECK-LABEL: func @arg_used_as_dim_and_symbol222func.func @arg_used_as_dim_and_symbol(%arg0: memref<100x100xf32>, %arg1: index, %arg2: f32) -> (memref<100x100xf32, 1>, memref<1xi32>) {223  %c9 = arith.constant 9 : index224  %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))>231        (%arg1, %c9, %3)232      // CHECK: memref.store %arg2, %{{.*}}[%{{.*}}, %{{.*}}]233      memref.store %arg2, %1[%4, %arg1] : memref<100x100xf32, 1>234    }235  }236  return %1, %2 : memref<100x100xf32, 1>, memref<1xi32>237}238 239// -----240 241// CHECK-LABEL: func @trivial_maps242func.func @trivial_maps() {243  // CHECK-NOT: affine.apply244 245  %0 = memref.alloc() : memref<10xf32>246  %c0 = arith.constant 0 : index247  %cst = arith.constant 0.000000e+00 : f32248  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>252 253    %3 = affine.apply affine_map<()[] -> (0)>()[]254    memref.store %cst, %0[%3] : memref<10xf32>255    memref.store %2, %0[%c0] : memref<10xf32>256  }257  return258}259 260// -----261 262// CHECK-DAG: #[[$MAP15:.*]] = affine_map<()[s0] -> (s0 - 42)>263 264// CHECK-LABEL: func @partial_fold_map265func.func @partial_fold_map(%arg1: index, %arg2: index) -> index {266  // TODO: Constant fold one index into affine.apply267  %c42 = arith.constant 42 : index268  %2 = affine.apply affine_map<(d0, d1) -> (d0 - d1)> (%arg1, %c42)269  // CHECK: [[X:.*]] = affine.apply #[[$MAP15]]()[%{{.*}}]270  return %2 : index271}272 273// -----274 275// CHECK-DAG: #[[$MAP_symbolic_composition_a:.*]] = affine_map<()[s0] -> (s0 * 512)>276 277// CHECK-LABEL: func @symbolic_composition_a(%{{.*}}: index, %{{.*}}: index) -> index {278func.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]]()[%{{.*}}]283  return %2 : index284}285 286// -----287 288// CHECK-DAG: #[[$MAP_symbolic_composition_b:.*]] = affine_map<()[s0] -> (s0 * 4)>289 290// CHECK-LABEL: func @symbolic_composition_b(%arg0: index, %arg1: index, %arg2: index, %arg3: index) -> index {291func.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]]()[%{{.*}}]295  return %1 : index296}297 298// -----299 300// CHECK-DAG: #[[$MAP_symbolic_composition_c:.*]] = affine_map<()[s0, s1] -> (s0 * 3 + s1)>301 302// CHECK-LABEL: func @symbolic_composition_c(%arg0: index, %arg1: index, %arg2: index, %arg3: index) -> index {303func.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]]()[%{{.*}}, %{{.*}}]308  return %2 : index309}310 311// -----312 313// CHECK-DAG: #[[$MAP_symbolic_composition_d:.*]] = affine_map<()[s0, s1] -> (s0 * 3 + s1)>314 315// CHECK-LABEL: func @symbolic_composition_d(316//  CHECK-SAME:   %[[ARG0:[0-9a-zA-Z]+]]: index317//  CHECK-SAME:   %[[ARG1:[0-9a-zA-Z]+]]: index318func.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]]]323  return %2 : index324}325 326// -----327 328// CHECK-DAG: #[[$MAP_mix_dims_and_symbols_b:.*]] = affine_map<()[s0, s1] -> (s0 * 42 + s1 + 6)>329 330// CHECK-LABEL: func @mix_dims_and_symbols_b(%arg0: index, %arg1: index) -> index {331func.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]]()[%{{.*}}, %{{.*}}]335 336  return %b : index337}338 339// -----340 341// CHECK-DAG: #[[$MAP_mix_dims_and_symbols_c:.*]] = affine_map<()[s0, s1] -> (s0 * 168 + s1 * 4 - 4)>342 343// CHECK-LABEL: func @mix_dims_and_symbols_c(%arg0: index, %arg1: index) -> index {344func.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]]()[%{{.*}}, %{{.*}}]349  return %c : index350}351 352// -----353 354// CHECK-DAG: #[[$MAP_mix_dims_and_symbols_d:.*]] = affine_map<()[s0, s1] -> ((s0 * 42 + s1 + 6) ceildiv 8)>355 356// CHECK-LABEL: func @mix_dims_and_symbols_d(%arg0: index, %arg1: index) -> index {357func.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]]()[%{{.*}}, %{{.*}}]363  return %d : index364}365 366// -----367 368// CHECK-DAG: #[[$MAP_mix_dims_and_symbols_e:.*]] = affine_map<()[s0, s1] -> ((s0 * 168 + s1 * 4 - 4) floordiv 3)>369 370// CHECK-LABEL: func @mix_dims_and_symbols_e(%arg0: index, %arg1: index) -> index {371func.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]]()[%{{.*}}, %{{.*}}]378  return %e : index379}380 381// -----382 383// CHECK-LABEL: func @mix_dims_and_symbols_f(%arg0: index, %arg1: index) -> index {384func.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 : index392 393  return %f : index394}395 396// -----397 398// CHECK-DAG: #[[$MAP_symbolic_composition_b:.*]] = affine_map<()[s0] -> (s0 * 4)>399 400// CHECK-LABEL: func @mix_dims_and_symbols_g(%arg0: index, %arg1: index) -> (index, index, index) {401func.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 : index407  // CHECK-DAG: {{.*}} = affine.apply #[[$MAP_symbolic_composition_b]]()[%{{.*}}]408  // CHECK-DAG: {{.*}} = affine.apply #[[$MAP_symbolic_composition_b]]()[%{{.*}}]409  return %res1, %res2, %res3 : index, index, index410}411 412// -----413 414// CHECK-DAG: #[[$symbolic_semi_affine:.*]] = affine_map<(d0)[s0] -> (d0 floordiv (s0 + 1))>415 416// CHECK-LABEL: func @symbolic_semi_affine(%arg0: index, %arg1: index, %arg2: memref<?xf32>) {417func.func @symbolic_semi_affine(%M: index, %N: index, %A: memref<?xf32>) {418  %f1 = arith.constant 1.0 : f32419  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>424  }425  return426}427 428// -----429 430// CHECK: #[[$MAP0:.*]] = affine_map<()[s0] -> (0, s0)>431// CHECK: #[[$MAP1:.*]] = affine_map<()[s0] -> (100, s0)>432 433// CHECK-LABEL:  func @constant_fold_bounds(%arg0: index) {434func.func @constant_fold_bounds(%N : index) {435  // CHECK:      arith.constant 3 : index436  // CHECK-NEXT: "foo"() : () -> index437  %c9 = arith.constant 9 : index438  %c1 = arith.constant 1 : index439  %c2 = arith.constant 2 : index440  %c3 = affine.apply affine_map<(d0, d1) -> (d0 + d1)> (%c1, %c2)441  %l = "foo"() : () -> index442 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) -> ()446  }447 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) -> ()452  }453 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) -> ()458  }459  return460}461 462// -----463 464// CHECK-LABEL:  func @fold_empty_loops()465func.func @fold_empty_loops() -> index {466  %c0 = arith.constant 0 : index467  affine.for %i = 0 to 10 {468  }469  %res = affine.for %i = 0 to 10 iter_args(%arg = %c0) -> index {470    affine.yield %arg : index471  }472  // CHECK-NEXT: %[[zero:.*]] = arith.constant 0473  // CHECK-NEXT: return %[[zero]]474  return %res : index475}476 477// -----478 479// CHECK-LABEL:  func @fold_empty_loop()480func.func @fold_empty_loop() -> (index, index) {481  %c0 = arith.constant 0 : index482  %c1 = arith.constant 1 : index483  %c2 = arith.constant 2 : index484  %res:2 = affine.for %i = 0 to 10 iter_args(%arg0 = %c0, %arg1 = %c1) -> (index, index) {485    affine.yield %c2, %arg1 : index, index486  }487  // CHECK-DAG: %[[one:.*]] = arith.constant 1488  // CHECK-DAG: %[[two:.*]] = arith.constant 2489  // CHECK-NEXT: return %[[two]], %[[one]]490  return %res#0, %res#1 : index, index491}492 493// -----494 495// CHECK-LABEL:  func @fold_empty_loops_trip_count_1()496func.func @fold_empty_loops_trip_count_1() -> (index, index, index, index) {497  %c0 = arith.constant 0 : index498  %c1 = arith.constant 1 : index499  %c2 = arith.constant 2 : index500  %res1:2 = affine.for %i = 0 to 1 iter_args(%arg0 = %c2, %arg1 = %c0) -> (index, index) {501    affine.yield %c1, %arg0 : index, index502  }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, index505  }506  // CHECK-DAG: %[[zero:.*]] = arith.constant 0507  // CHECK-DAG: %[[one:.*]] = arith.constant 1508  // CHECK-DAG: %[[two:.*]] = arith.constant 2509  // CHECK-NEXT: return %[[one]], %[[two]], %[[zero]], %[[two]]510  return %res1#0, %res1#1, %res2#0, %res2#1 : index, index, index, index511}512 513// -----514 515// CHECK-LABEL:  func @fold_empty_loop_trip_count_0()516func.func @fold_empty_loop_trip_count_0() -> (index, index) {517  %c0 = arith.constant 0 : index518  %c1 = arith.constant 1 : index519  %c2 = arith.constant 2 : index520  %res:2 = affine.for %i = 0 to 0 iter_args(%arg0 = %c2, %arg1 = %c0) -> (index, index) {521    affine.yield %c1, %arg0 : index, index522  }523  // CHECK-DAG: %[[zero:.*]] = arith.constant 0524  // CHECK-DAG: %[[two:.*]] = arith.constant 2525  // CHECK-NEXT: return %[[two]], %[[zero]]526  return %res#0, %res#1 : index, index527}528 529// -----530 531// CHECK-LABEL:  func @fold_empty_loop_trip_count_unknown532func.func @fold_empty_loop_trip_count_unknown(%in : index) -> (index, index) {533  %c0 = arith.constant 0 : index534  %c1 = arith.constant 1 : index535  %res:2 = affine.for %i = 0 to %in iter_args(%arg0 = %c0, %arg1 = %c1) -> (index, index) {536    affine.yield %arg0, %arg1 : index, index537  }538  // CHECK-DAG: %[[zero:.*]] = arith.constant 0539  // CHECK-DAG: %[[one:.*]] = arith.constant 1540  // CHECK-NEXT: return %[[zero]], %[[one]]541  return %res#0, %res#1 : index, index542}543 544// -----545 546// CHECK-LABEL:  func @empty_loops_not_folded_1547func.func @empty_loops_not_folded_1(%in : index) -> index {548  %c0 = arith.constant 0 : index549  %c1 = arith.constant 1 : index550  // CHECK: affine.for551  %res = affine.for %i = 0 to %in iter_args(%arg = %c0) -> index {552    affine.yield %c1 : index553  }554  return %res : index555}556 557// -----558 559// CHECK-LABEL:  func @empty_loops_not_folded_2560func.func @empty_loops_not_folded_2(%in : index) -> (index, index) {561  %c0 = arith.constant 0 : index562  %c1 = arith.constant 1 : index563  // CHECK: affine.for564  %res:2 = affine.for %i = 0 to %in iter_args(%arg0 = %c0, %arg1 = %c1) -> (index, index) {565    affine.yield %arg1, %arg0 : index, index566  }567  return %res#0, %res#1 : index, index568}569 570// -----571 572// CHECK-LABEL:  func @empty_loops_not_folded_3573func.func @empty_loops_not_folded_3() -> (index, index) {574  %c0 = arith.constant 0 : index575  %c1 = arith.constant 1 : index576  // CHECK: affine.for577  %res:2 = affine.for %i = 0 to 10 iter_args(%arg0 = %c0, %arg1 = %c1) -> (index, index) {578    affine.yield %arg1, %arg0 : index, index579  }580  return %res#0, %res#1 : index, index581}582 583// -----584 585// CHECK-LABEL:  func @zero_iter_loop_not_folded586func.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>591  }592  // CHECK:   affine.for {{.*}} = 0 to 0 {593  return594}595 596// -----597 598// CHECK-LABEL:  func @fold_zero_iter_loops599// CHECK-SAME: %[[ARG:.*]]: index600func.func @fold_zero_iter_loops(%in : index) -> index {601  %c1 = arith.constant 1 : index602  %res = affine.for %i = 0 to 0 iter_args(%loop_arg = %in) -> index {603    %yield = arith.addi %loop_arg, %c1 : index604    affine.yield %yield : index605  }606  // CHECK-NEXT: return %[[ARG]]607  return %res : index608}609 610// -----611 612// CHECK-DAG: #[[$SET:.*]] = affine_set<(d0, d1)[s0] : (d0 >= 0, -d0 + 1022 >= 0, d1 >= 0, -d1 + s0 - 2 >= 0)>613 614// CHECK-LABEL: func @canonicalize_affine_if615//  CHECK-SAME:   %[[M:[0-9a-zA-Z]*]]: index,616//  CHECK-SAME:   %[[N:[0-9a-zA-Z]*]]: index)617func.func @canonicalize_affine_if(%M : index, %N : index) {618  %c1022 = arith.constant 1022 : index619  // 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] {625        "foo"() : () -> ()626      }627      "bar"() : () -> ()628    }629  }630  return631}632 633// -----634 635// CHECK-DAG: #[[$SET:.*]] = affine_set<(d0, d1)[s0] : (d0 - 1 >= 0, d1 - 1 == 0, -d0 + s0 + 10 >= 0)>636 637// CHECK-LABEL: func @canonicalize_affine_if_compose_apply638// CHECK-SAME:   %[[N:.*]]: index639func.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"() : ()->()649      }650    }651  }652  return653}654 655// -----656 657// CHECK-DAG: #[[$LBMAP:.*]] = affine_map<()[s0] -> (0, s0)>658// CHECK-DAG: #[[$UBMAP:.*]] = affine_map<()[s0] -> (1024, s0 * 2)>659 660// CHECK-LABEL: func @canonicalize_bounds661// CHECK-SAME: %[[M:.*]]: index,662// CHECK-SAME: %[[N:.*]]: index)663func.func @canonicalize_bounds(%M : index, %N : index) {664  %c0 = arith.constant 0 : index665  %c1024 = arith.constant 1024 : index666  // Drop unused operand %N, drop duplicate operand %M, propagate %c1024, and667  // 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) {670    "foo"() : () -> ()671  }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) {675    "foo"() : () -> ()676  }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 {680    "foo"() : () -> ()681  }682  return683}684 685// -----686 687// Compose maps into affine load and store ops.688 689// CHECK-LABEL: @compose_into_affine_load_store690func.func @compose_into_affine_load_store(%A : memref<1024xf32>, %u : index) {691  // CHECK: affine.for %[[IV:.*]] = 0 to 1024692  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]699 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]]]705  }706  return707}708 709// -----710 711func.func @affine_min(%arg0 : index, %arg1 : index, %arg2 : index) {712  %c511 = arith.constant 511 : index713  %c1 = arith.constant 0 : index714  %0 = affine.min affine_map<(d0)[s0] -> (1000, d0 + 512, s0 + 1)> (%c1)[%c511]715  "op0"(%0) : (index) -> ()716  // CHECK:       %[[CST:.*]] = arith.constant 512 : index717  // CHECK-NEXT:  "op0"(%[[CST]]) : (index) -> ()718  // CHECK-NEXT:  return719  return720}721 722// -----723 724func.func @affine_min(%arg0 : index, %arg1 : index, %arg2 : index) {725  %c3 = arith.constant 3 : index726  %c20 = arith.constant 20 : index727  %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 : index730  // CHECK-NEXT:  "op0"(%[[CST]]) : (index) -> ()731  // CHECK-NEXT:  return732  return733}734 735// -----736 737func.func @affine_max(%arg0 : index, %arg1 : index, %arg2 : index) {738  %c511 = arith.constant 511 : index739  %c1 = arith.constant 0 : index740  %0 = affine.max affine_map<(d0)[s0] -> (1000, d0 + 512, s0 + 1)> (%c1)[%c511]741  "op0"(%0) : (index) -> ()742  // CHECK:       %[[CST:.*]] = arith.constant 1000 : index743  // CHECK-NEXT:  "op0"(%[[CST]]) : (index) -> ()744  // CHECK-NEXT:  return745  return746}747 748// -----749 750func.func @affine_max(%arg0 : index, %arg1 : index, %arg2 : index) {751  %c3 = arith.constant 3 : index752  %c20 = arith.constant 20 : index753  %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 : index756  // CHECK-NEXT:  "op0"(%[[CST]]) : (index) -> ()757  // CHECK-NEXT:  return758  return759}760 761// -----762 763// CHECK: #[[$MAP:.*]] = affine_map<(d0, d1) -> (d1 - 2, d0)>764 765func.func @affine_min(%arg0: index) {766  affine.for %i = 0 to %arg0 {767    affine.for %j = 0 to %arg0 {768      %c2 = arith.constant 2 : index769      // CHECK: affine.min #[[$MAP]]770      %0 = affine.min affine_map<(d0,d1,d2)->(d0, d1 - d2)>(%i, %j, %c2)771      "consumer"(%0) : (index) -> ()772    }773  }774  return775}776 777// -----778 779// Reproducer for PR45031. This used to fold into an incorrect map because780// symbols were concatenated in the wrong order during map folding. Map781// composition places the symbols of the original map before those of the map782// it is composed with, e.g. A.compose(B) will first have all symbols of A,783// then all symbols of B.784 785#map1 = affine_map<(d0)[s0, s1] -> (d0 * s0 + s1)>786#map2 = affine_map<(d0)[s0] -> (1024, -d0 + s0)>787 788// CHECK: #[[$MAP:.*]] = affine_map<()[s0, s1] -> (1024, s0 - s1 * 1024)>789 790// CHECK: func @rep(%[[ARG0:.*]]: index, %[[ARG1:.*]]: index)791func.func @rep(%arg0 : index, %arg1 : index) -> index {792  // CHECK-NOT: arith.constant793  %c0 = arith.constant 0 : index794  %c1024 = arith.constant 1024 : index795  // CHECK-NOT: affine.apply796  %0 = affine.apply #map1(%arg0)[%c1024, %c0]797 798  // CHECK: affine.min #[[$MAP]]()[%[[ARG1]], %[[ARG0]]]799  %1 = affine.min #map2(%0)[%arg1]800  return %1 : index801}802 803// -----804 805// CHECK-DAG: #[[ub:.*]] = affine_map<()[s0] -> (s0 + 2)>806 807func.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) {810    "foo"() : () -> ()811  }812  return813}814 815// -----816 817// Ensure affine.parallel bounds expressions are canonicalized.818 819#map3 = affine_map<(d0) -> (d0 * 5)>820 821// CHECK-LABEL: func @affine_parallel_const_bounds822func.func @affine_parallel_const_bounds() {823  %cst = arith.constant 1.0 : f32824  %c0 = arith.constant 0 : index825  %c4 = arith.constant 4 : index826  %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>833    }834  }835  return836}837 838// -----839 840func.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 i64845  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 i64849    memref.store %5, %A[]: memref<i64>850  }851  return852}853 854// -----855 856// CHECK: #[[MAP:.+]] = affine_map<()[s0, s1] -> (s0 + s1, s0 * s1)>857 858// CHECK: func @deduplicate_affine_min_expressions859// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)860func.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]863  return %0: index864}865 866// -----867 868// CHECK: #[[MAP:.+]] = affine_map<()[s0, s1] -> (s0 + s1, s0 * s1)>869 870// CHECK: func @deduplicate_affine_max_expressions871// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)872func.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]875  return %0: index876}877 878// -----879 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)>882 883// CHECK: func @merge_affine_min_ops884// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index, %[[I2:.+]]: index, %[[I3:.+]]: index)885func.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]887 888 // CHECK: affine.min #[[MAP0]]()[%[[I2]], %[[I1]], %[[I0]]]889  %1 = affine.min affine_map<(d0)[s0] -> (3 * s0, d0)> (%0)[%i2] // Use as dim890 // CHECK: affine.min #[[MAP1]]()[%[[I1]], %[[I0]], %[[I3]]]891  %2 = affine.min affine_map<(d0)[s0] -> (s0, 5 - d0)> (%i3)[%0] // Use as symbol892 893  return %1, %2: index, index894}895 896// -----897 898// CHECK: #[[MAP:.+]] = affine_map<()[s0, s1, s2] -> (s2 + 8, s2 * 4, s1 + 16, s1 * 8, s0 + 7)>899 900// CHECK: func @merge_multiple_affine_min_ops901// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index, %[[I2:.+]]: index)902func.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]907  return %2: index908}909 910// -----911 912// CHECK-DAG: #[[MAP:.+]] = affine_map<()[s0, s1] -> (s1 + 16, s1 * 8, s0 * 2)>913 914// CHECK: func @merge_multiple_uses_of_affine_min_ops915// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)916func.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]920  return %2: index921}922 923// -----924 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)>927 928// CHECK: func @merge_mixed_uses_of_affine_min_ops929// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)930func.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 part934  // 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]937  return %2: index938}939 940// -----941 942// CHECK-LABEL: func @dont_merge_affine_min_if_not_single_dim943func.func @dont_merge_affine_min_if_not_single_dim(%i0: index, %i1: index, %i2: index) -> index {944  // CHECK-COUNT-2: affine.min945  %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]947  return %1: index948}949 950// -----951 952// CHECK-LABEL: func @dont_merge_affine_min_if_not_single_sym953func.func @dont_merge_affine_min_if_not_single_sym(%i0: index, %i1: index, %i2: index) -> index {954  // CHECK-COUNT-2: affine.min955  %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]957  return %1: index958}959 960// -----961 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)>964 965// CHECK: func @merge_affine_max_ops966// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index, %[[I2:.+]]: index, %[[I3:.+]]: index)967func.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]969 970 // CHECK: affine.max #[[MAP0]]()[%[[I2]], %[[I1]], %[[I0]]]971  %1 = affine.max affine_map<(d0)[s0] -> (3 * s0, d0)> (%0)[%i2] // Use as dim972 // CHECK: affine.max #[[MAP1]]()[%[[I1]], %[[I0]], %[[I3]]]973  %2 = affine.max affine_map<(d0)[s0] -> (s0, 5 - d0)> (%i3)[%0] // Use as symbol974 975  return %1, %2: index, index976}977 978// -----979 980// CHECK: #[[MAP:.+]] = affine_map<()[s0, s1, s2] -> (s2 + 8, s2 * 4, s1 + 16, s1 * 8, s0 + 7)>981 982// CHECK: func @merge_multiple_affine_max_ops983// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index, %[[I2:.+]]: index)984func.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]989  return %2: index990}991 992// -----993 994// CHECK-DAG: #[[MAP:.+]] = affine_map<()[s0, s1] -> (s1 + 16, s1 * 8, s0 * 2)>995 996// CHECK: func @merge_multiple_uses_of_affine_max_ops997// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)998func.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]1002  return %2: index1003}1004 1005// -----1006 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)>1009 1010// CHECK: func @merge_mixed_uses_of_affine_max_ops1011// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)1012func.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 part1016  // 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]1019  return %2: index1020}1021 1022// -----1023 1024// CHECK-LABEL: func @dont_merge_affine_max_if_not_single_dim1025func.func @dont_merge_affine_max_if_not_single_dim(%i0: index, %i1: index, %i2: index) -> index {1026  // CHECK-COUNT-2: affine.max1027  %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]1029  return %1: index1030}1031 1032// -----1033 1034// CHECK-LABEL: func @dont_merge_affine_max_if_not_single_sym1035func.func @dont_merge_affine_max_if_not_single_sym(%i0: index, %i1: index, %i2: index) -> index {1036  // CHECK-COUNT-2: affine.max1037  %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]1039  return %1: index1040}1041 1042// -----1043 1044// Ensure bounding maps of affine.for are composed.1045 1046// CHECK-DAG: #[[$MAP0]] = affine_map<()[s0] -> (s0 - 2)>1047// CHECK-DAG: #[[$MAP1]] = affine_map<()[s0] -> (s0 + 2)>1048 1049// CHECK-LABEL: func @compose_affine_for_bounds1050// CHECK-SAME:   %[[N:.*]]: index)1051// CHECK: affine.for %{{.*}} = #[[$MAP0]]()[%[[N]]] to #[[$MAP1]]()[%[[N]]] {1052 1053func.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 {1057    "foo"() : () -> ()1058  }1059  return1060}1061 1062// -----1063 1064// Compose maps into affine.vector_load / affine.vector_store1065 1066// CHECK-LABEL: func @compose_into_affine_vector_load_vector_store1067// CHECK: affine.for %[[IV:.*]] = 0 to 10241068// CHECK-NEXT: affine.vector_load %{{.*}}[%[[IV]] + 1]1069// CHECK-NEXT: affine.vector_store %{{.*}}, %{{.*}}[%[[IV]] + 1]1070// CHECK-NEXT: affine.vector_load %{{.*}}[%[[IV]]]1071func.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>1077 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>) -> ()1082  }1083  return1084}1085 1086// -----1087 1088// CHECK-LABEL: func @no_fold_of_store1089//  CHECK:   %[[cst:.+]] = memref.cast %arg1090//  CHECK:   affine.store %[[cst]]1091func.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>>1094  return1095}1096 1097// -----1098 1099// CHECK-DAG: #[[$MAP0:.+]] = affine_map<()[s0] -> (s0 + 16)>1100// CHECK-DAG: #[[$MAP1:.+]] = affine_map<()[s0] -> (s0 * 4)>1101 1102// CHECK: func @canonicalize_single_min_max1103// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)1104func.func @canonicalize_single_min_max(%i0: index, %i1: index) -> (index, index) {1105  // CHECK-NOT: affine.min1106  // CHECK-NEXT: affine.apply #[[$MAP0]]()[%[[I0]]]1107  %0 = affine.min affine_map<()[s0] -> (s0 + 16)> ()[%i0]1108 1109  // CHECK-NOT: affine.max1110  // CHECK-NEXT: affine.apply #[[$MAP1]]()[%[[I1]]]1111  %1 = affine.min affine_map<()[s0] -> (s0 * 4)> ()[%i1]1112 1113  return %0, %1: index, index1114}1115 1116// -----1117 1118// CHECK: #[[$MAP:.+]] = affine_map<()[s0, s1] -> (32, s1 + 16, s0 + s1)>1119 1120// CHECK-LABEL: func @canonicalize_multi_min_max1121// CHECK-SAME: (%[[I0:.+]]: index, %[[I1:.+]]: index)1122func.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]1125 1126  // CHECK-NEXT: affine.max #[[$MAP]]()[%[[I0]], %[[I1]]]1127  %1 = affine.max affine_map<()[s0, s1] -> (s0 + s1, 32, s1 + 16)> ()[%i0, %i1]1128 1129  return %0, %1: index, index1130}1131 1132// -----1133 1134module {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_memref1138  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, f321143    // CHECK-DAG: %[[C0:.*]] = arith.constant 6.250000e-02 : f321144    // CHECK-DAG: %[[C1:.*]] = arith.constant 2.500000e-01 : f321145    // CHECK-NEXT: return %[[C0]], %[[C1]]1146  }1147 1148  // CHECK-LABEL: func @fold_const_splat_global1149  func.func @fold_const_splat_global() -> memref<32x64xf32> {1150    // CHECK-NEXT: %[[CST:.*]] = arith.constant 0.000000e+00 : f321151    %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]], %{{.*}}1158      }1159    }1160    return %s: memref<32x64xf32>1161  }1162}1163 1164// -----1165 1166// Simplification of maps exploiting operand info.1167 1168// CHECK: #[[$MAP_SIMPLER:.*]] = affine_map<(d0, d1) -> (((d0 + d1) mod 458313) floordiv 227)>1169 1170// CHECK-LABEL: func @simplify_with_operands1171func.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 321175    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) -> ()1180 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) -> ()1191    }1192  }1193 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) -> ()1199  }1200 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) -> ()1207      }1208    }1209  }1210 1211  return1212}1213 1214// CHECK-LABEL: func @simplify_div_mod_with_operands1215func.func @simplify_div_mod_with_operands(%N: index, %A: memref<64xf32>, %unknown: index) {1216  // CHECK: affine.for %[[I:.*]] = 0 to 321217  %cst = arith.constant 1.0 : f321218  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>1229 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>1239  }1240 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>1250  }1251 1252  // CHECK: affine.for %[[II:.*]] = 8 to 161253  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>1270  }1271  return1272}1273 1274// -----1275 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)>1279 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)>1284 1285// CHECK-LABEL: func @simplify_min_max_bounds_simple1286func.func @simplify_min_max_bounds_simple(%M: index) {1287 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"() : () -> ()1291  }1292 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"() : () -> ()1296  }1297 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"() : () -> ()1301  }1302 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"() : () -> ()1306  }1307 1308  return1309}1310 1311// CHECK-LABEL: func @simplify_bounds_tiled1312func.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"() : () -> ()1320            }1321          }1322        }1323      }1324    }1325  }1326  // CHECK:      affine.for1327  // CHECK-NEXT:   affine.for1328  // CHECK-NEXT:     affine.for %{{.*}} = 0 to 32 step 161329  // CHECK-NEXT:       affine.for %{{.*}} = 0 to 32 step 161330  // CHECK-NEXT:         affine.for %{{.*}} = 0 to 21331  // CHECK-NEXT:           affine.for %{{.*}} = 0 to 16 step 161332 1333  return1334}1335 1336// CHECK-LABEL: func @simplify_min_max_multi_expr1337func.func @simplify_min_max_multi_expr() {1338  // Lower bound max.1339  // CHECK: affine.for1340  affine.for %i = 0 to 2 {1341    // CHECK: affine.for %{{.*}} = 5 to1342    affine.for %j = max affine_map<(d0) -> (5, 4 * d0)> (%i) to affine_map<(d0) -> (4 * d0 + 3)>(%i) {1343      "test.foo"() : () -> ()1344    }1345  }1346 1347  // Expressions with multiple operands.1348  // CHECK: affine.for1349  affine.for %i = 0 to 2 {1350    // CHECK: affine.for1351    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 -91354      affine.for %k = -10 to min affine_map<(d0, d1) -> (4 * d0 - 3 * d1, -9)>(%i, %j) {1355        "test.foo"() : () -> ()1356      }1357    }1358  }1359 1360  // One expression is redundant but not the others.1361  // CHECK: affine.for1362  affine.for %i = 0 to 2 {1363    // CHECK: affine.for1364    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"() : () -> ()1369      }1370    }1371  }1372 1373  // CHECK: affine.for %{{.*}} = 0 to 11374  affine.for %i = 0 to 2 {1375    affine.for %j = max affine_map<(d0) -> (d0 floordiv 2, 0)>(%i) to 1 {1376      "test.foo"() : () -> ()1377    }1378  }1379 1380  // The constant bound is redundant here.1381  // CHECK: affine.for %{{.*}} = #[[$FLOORDIV]](%{{.*}} to 101382  affine.for %i = 0 to 8 {1383    affine.for %j = max affine_map<(d0) -> (d0 floordiv 2, 0)>(%i) to 10 {1384      "test.foo"() : () -> ()1385    }1386  }1387 1388  return1389}1390 1391// CHECK-LABEL: func @no_simplify_min_max1392func.func @no_simplify_min_max(%M: index) {1393  // Negative test cases.1394  // CHECK: affine.for1395  affine.for %i = 0 to 4 {1396    // CHECK-NEXT: affine.for %{{.*}} = 0 to min1397    affine.for %j = 0 to min affine_map<(d0) -> (2 * d0, 2)>(%i) {1398      "test.foo"() : () -> ()1399    }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"() : () -> ()1403    }1404  }1405 1406  return1407}1408 1409// -----1410 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_replacements1414// CHECK-BOTTOM-UP-LABEL: func @regression_do_not_perform_invalid_replacements1415func.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) -> ()1424  return1425}1426 1427// -----1428// CHECK-LABEL: func @min.oneval(%arg0: index)1429func.func @min.oneval(%arg0: index) -> index {1430  %min = affine.min affine_map<()[s0] -> (s0)> ()[%arg0]1431  // CHECK: return %arg0 : index1432  return %min: index1433}1434 1435// -----1436// CHECK-LABEL: func @max.oneval(%arg0: index)1437func.func @max.oneval(%arg0: index) -> index {1438  %max = affine.max affine_map<()[s0] -> (s0)> ()[%arg0]1439  // CHECK: return %arg0 : index1440  return %max: index1441}1442 1443// -----1444 1445// CHECK-LABEL: func @mod_of_mod(1446//       CHECK:   %[[c0:.*]] = arith.constant 01447//       CHECK:   return %[[c0]], %[[c0]]1448func.func @mod_of_mod(%lb: index, %ub: index, %step: index) -> (index, index) {1449  // Simplify: (ub - ub % step) % step == 01450  %0 = affine.apply affine_map<()[s0, s1] -> ((s0 - (s0 mod s1)) mod s1)> ()[%ub, %step]1451  // Simplify: (ub - (ub - lb) % step - lb) % step == 01452  %1 = affine.apply affine_map<()[s0, s1, s2] -> ((s0 - ((s0 - s2) mod s1) - s2) mod s1)> ()[%ub, %step, %lb]1453  return %0, %1 : index, index1454}1455 1456// -----1457 1458// CHECK-LABEL:  func.func @prefetch_canonicalize1459// CHECK-SAME:   ([[PARAM_0_:%.+]]: memref<512xf32>) {1460func.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<(d0) -> (d0 * 64)>(%arg3)1464    // CHECK: affine.prefetch [[PARAM_0_]][[[I_0_]] * 64], read, locality<3>, data : memref<512xf32>1465    affine.prefetch %arg0[%1], read, locality<3>, data : memref<512xf32>1466  }1467  return1468}1469 1470// -----1471 1472// CHECK-LABEL: @delinearize_fold_constant1473// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index1474// CHECK-DAG: %[[C2:.+]] = arith.constant 2 : index1475// CHECK-NOT: affine.delinearize_index1476// CHECK: return %[[C1]], %[[C1]], %[[C2]]1477func.func @delinearize_fold_constant() -> (index, index, index) {1478  %c22 = arith.constant 22 : index1479  %0:3 = affine.delinearize_index %c22 into (2, 3, 5) : index, index, index1480  return %0#0, %0#1, %0#2 : index, index, index1481}1482 1483// -----1484 1485// CHECK-LABEL: @delinearize_fold_negative_constant1486// CHECK-DAG: %[[C_2:.+]] = arith.constant -2 : index1487// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index1488// CHECK-DAG: %[[C3:.+]] = arith.constant 3 : index1489// CHECK-NOT: affine.delinearize_index1490// CHECK: return %[[C_2]], %[[C1]], %[[C3]]1491func.func @delinearize_fold_negative_constant() -> (index, index, index) {1492  %c_22 = arith.constant -22 : index1493  %0:3 = affine.delinearize_index %c_22 into (2, 3, 5) : index, index, index1494  return %0#0, %0#1, %0#2 : index, index, index1495}1496 1497// -----1498 1499// CHECK-LABEL: @delinearize_fold_negative_constant_no_outer_bound1500// CHECK-DAG: %[[C_2:.+]] = arith.constant -2 : index1501// CHECK-DAG: %[[C1:.+]] = arith.constant 1 : index1502// CHECK-DAG: %[[C3:.+]] = arith.constant 3 : index1503// CHECK-NOT: affine.delinearize_index1504// CHECK: return %[[C_2]], %[[C1]], %[[C3]]1505func.func @delinearize_fold_negative_constant_no_outer_bound() -> (index, index, index) {1506  %c_22 = arith.constant -22 : index1507  %0:3 = affine.delinearize_index %c_22 into (3, 5) : index, index, index1508  return %0#0, %0#1, %0#2 : index, index, index1509}1510 1511// -----1512 1513// CHECK-LABEL: @delinearize_dont_fold_constant_dynamic_basis1514// CHECK-DAG: %[[C22:.+]] = arith.constant 22 : index1515// CHECK: %[[RET:.+]]:3 = affine.delinearize_index %[[C22]]1516// CHECK: return %[[RET]]#0, %[[RET]]#1, %[[RET]]#21517func.func @delinearize_dont_fold_constant_dynamic_basis(%arg0: index) -> (index, index, index) {1518  %c22 = arith.constant 22 : index1519  %0:3 = affine.delinearize_index %c22 into (2, %arg0, 5) : index, index, index1520  return %0#0, %0#1, %0#2 : index, index, index1521}1522 1523// -----1524 1525func.func @drop_unit_basis_in_delinearize(%arg0 : index, %arg1 : index, %arg2 : index) ->1526    (index, index, index, index, index, index) {1527  %c1 = arith.constant 1 : index1528  %0:6 = affine.delinearize_index %arg0 into (1, %arg1, 1, 1, %arg2, %c1)1529      : index, index, index, index, index, index1530  return %0#0, %0#1, %0#2, %0#3, %0#4, %0#5 : index, index, index, index, index, index1531}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 : index1537//   CHECK-DAG:   %[[DELINEARIZE:.+]]:2 = affine.delinearize_index %[[ARG0]] into (%[[ARG1]], %[[ARG2]])1538//       CHECK:   return %[[C0]], %[[DELINEARIZE]]#0, %[[C0]], %[[C0]], %[[DELINEARIZE]]#1, %[[C0]]1539 1540// -----1541 1542func.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 : index1545  %0:6 = affine.delinearize_index %arg0 into (%arg1, 1, 1, %arg2, %c1)1546      : index, index, index, index, index, index1547  return %0#0, %0#1, %0#2, %0#3, %0#4, %0#5 : index, index, index, index, index, index1548}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 : index1554//   CHECK-DAG:   %[[DELINEARIZE:.+]]:3 = affine.delinearize_index %[[ARG0]] into (%[[ARG1]], %[[ARG2]])1555//       CHECK:   return %[[DELINEARIZE]]#0, %[[DELINEARIZE]]#1, %[[C0]], %[[C0]], %[[DELINEARIZE]]#2, %[[C0]]1556 1557// -----1558 1559func.func @drop_all_unit_bases(%arg0 : index) -> (index, index) {1560  %0:2 = affine.delinearize_index %arg0 into (1, 1) : index, index1561  return %0#0, %0#1 : index, index1562}1563// CHECK-LABEL: func @drop_all_unit_bases(1564//  CHECK-SAME:     %[[ARG0:.+]]: index)1565//   CHECK-DAG:   %[[C0:.+]] = arith.constant 0 : index1566//   CHECK-NOT:   affine.delinearize_index1567//       CHECK:   return %[[C0]], %[[C0]]1568 1569// -----1570 1571func.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, index1573  return %0#0, %0#1, %0#2 : index, index, index1574}1575// CHECK-LABEL: func @drop_all_unit_bases_no_outer_bound(1576//  CHECK-SAME:     %[[ARG0:.+]]: index)1577//   CHECK-DAG:   %[[C0:.+]] = arith.constant 0 : index1578//   CHECK-NOT:   affine.delinearize_index1579//       CHECK:   return %[[ARG0]], %[[C0]], %[[C0]]1580 1581// -----1582 1583func.func @drop_single_loop_delinearize(%arg0 : index, %arg1 : index) -> index {1584  %c0 = arith.constant 0 : index1585  %c1 = arith.constant 1 : index1586  %2 = scf.for %iv = %c0 to %arg1 step %c1 iter_args(%arg2 = %c0) -> index {1587    %0 = affine.delinearize_index %iv into (%arg1) : index1588    %1 = "some_use"(%arg2, %0) : (index, index) -> (index)1589    scf.yield %1 : index1590  }1591  return %2 : index1592}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_index1597//       CHECK:     "some_use"(%{{.+}}, %[[IV]])1598 1599// -----1600 1601// CHECK-LABEL: func @delinearize_non_induction_variable1602// CHECK-NOT: affine.delinearize1603func.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) : index1606  return %2 : index1607}1608 1609// -----1610 1611// CHECK-LABEL: func @delinearize_non_loop_like1612// CHECK-NOT: affine.delinearize1613func.func @delinearize_non_loop_like(%arg0: memref<?xi32>, %i : index) -> index {1614  %2 = affine.delinearize_index %i into (1024) : index1615  return %2 : index1616}1617 1618// -----1619 1620// CHECK-LABEL: func @delinearize_empty_basis1621// CHECK-SAME: (%[[ARG0:.+]]: index)1622// CHECK-NOT: affine.delinearize1623// CHECK: return %[[ARG0]]1624func.func @delinearize_empty_basis(%arg0: index) -> index {1625  %0 = affine.delinearize_index %arg0 into () : index1626  return %0 : index1627}1628 1629// -----1630 1631// CHECK-LABEL: @linearize_fold_constants1632// CHECK-DAG: %[[C22:.+]] = arith.constant 22 : index1633// CHECK-NOT: affine.linearize1634// CHECK: return %[[C22]]1635func.func @linearize_fold_constants() -> index {1636  %c2 = arith.constant 2 : index1637  %c1 = arith.constant 1 : index1638 1639  %ret = affine.linearize_index [%c1, %c1, %c2] by (2, 3, 5) : index1640  return %ret : index1641}1642 1643// -----1644 1645// CHECK-LABEL: @linearize_fold_constants_no_outer_bound1646// CHECK-DAG: %[[C22:.+]] = arith.constant 22 : index1647// CHECK-NOT: affine.linearize1648// CHECK: return %[[C22]]1649func.func @linearize_fold_constants_no_outer_bound() -> index {1650  %c2 = arith.constant 2 : index1651  %c1 = arith.constant 1 : index1652 1653  %ret = affine.linearize_index [%c1, %c1, %c2] by (3, 5) : index1654  return %ret : index1655}1656 1657// -----1658 1659// CHECK-LABEL: @linearize_fold_empty_basis1660// CHECK-SAME: (%[[ARG0:.+]]: index)1661// CHECK-NOT: affine.linearize1662// CHECK: return %[[ARG0]]1663func.func @linearize_fold_empty_basis(%arg0: index) -> index {1664  %ret = affine.linearize_index [%arg0] by () : index1665  return %ret : index1666}1667 1668// -----1669 1670// CHECK-LABEL: @linearize_fold_only_outer_bound1671// CHECK-SAME: (%[[ARG0:.+]]: index)1672// CHECK-NOT: affine.linearize1673// CHECK: return %[[ARG0]]1674func.func @linearize_fold_only_outer_bound(%arg0: index) -> index {1675  %ret = affine.linearize_index [%arg0] by (2) : index1676  return %ret : index1677}1678 1679// -----1680 1681// CHECK-LABEL: @linearize_dont_fold_dynamic_basis1682// CHECK: %[[RET:.+]] = affine.linearize_index1683// CHECK: return %[[RET]]1684func.func @linearize_dont_fold_dynamic_basis(%arg0: index) -> index {1685  %c2 = arith.constant 2 : index1686  %c1 = arith.constant 1 : index1687 1688  %ret = affine.linearize_index [%c1, %c1, %c2] by (2, %arg0, 5) : index1689  return %ret : index1690}1691 1692// -----1693 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]]1701func.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) : index1703  %1:3 = affine.delinearize_index %0 into (%arg3, 4, %arg4)1704      : index, index, index1705  return %1#0, %1#1, %1#2 : index, index, index1706}1707 1708// -----1709 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]]1717func.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) : index1719  %1:3 = affine.delinearize_index %0 into (4, %arg4)1720      : index, index, index1721  return %1#0, %1#1, %1#2 : index, index, index1722}1723 1724// -----1725 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]]1733func.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) : index1735  %1:3 = affine.delinearize_index %0 into (%arg3, 4, %arg4)1736      : index, index, index1737  return %1#0, %1#1, %1#2 : index, index, index1738}1739 1740// -----1741 1742// CHECK-LABEL: func @cancel_delinearize_linearize_disjoint_partial(1743//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1744//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,1745//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index,1746//  CHECK-SAME:     %[[ARG3:[a-zA-Z0-9]+]]: index,1747//  CHECK-SAME:     %[[ARG4:[a-zA-Z0-9]+]]: index)1748//       CHECK:     %[[LIN:.+]] = affine.linearize_index disjoint [%[[ARG0]], %[[ARG1]]] by (%[[ARG3]], 4) : index1749//       CHECK:     %[[DELIN:.+]]:2 = affine.delinearize_index %[[LIN]] into (8) : index, index1750//       CHECK:     return %[[DELIN]]#0, %[[DELIN]]#1, %[[ARG2]]1751func.func @cancel_delinearize_linearize_disjoint_partial(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) -> (index, index, index) {1752  %0 = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by (%arg3, 4, %arg4) : index1753  %1:3 = affine.delinearize_index %0 into (8, %arg4)1754      : index, index, index1755  return %1#0, %1#1, %1#2 : index, index, index1756}1757 1758// -----1759 1760// Without `disjoint`, the cancelation isn't guaranteed to be the identity.1761// CHECK-LABEL: func @no_cancel_delinearize_linearize_exact(1762//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1763//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,1764//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index,1765//  CHECK-SAME:     %[[ARG3:[a-zA-Z0-9]+]]: index,1766//  CHECK-SAME:     %[[ARG4:[a-zA-Z0-9]+]]: index)1767//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[ARG0]], %[[ARG1]], %[[ARG2]]] by (%[[ARG3]], 4, %[[ARG4]])1768//       CHECK:     %[[DELIN:.+]]:3 = affine.delinearize_index %[[LIN]] into (%[[ARG3]], 4, %[[ARG4]])1769//       CHECK:     return %[[DELIN]]#0, %[[DELIN]]#1, %[[DELIN]]#21770func.func @no_cancel_delinearize_linearize_exact(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) -> (index, index, index) {1771  %0 = affine.linearize_index [%arg0, %arg1, %arg2] by (%arg3, 4, %arg4) : index1772  %1:3 = affine.delinearize_index %0 into (%arg3, 4, %arg4)1773      : index, index, index1774  return %1#0, %1#1, %1#2 : index, index, index1775}1776 1777// -----1778 1779// These don't cancel because the delinearize and linearize have a different basis.1780// CHECK-LABEL: func @no_cancel_delinearize_linearize_different_basis(1781//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1782//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,1783//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index,1784//  CHECK-SAME:     %[[ARG3:[a-zA-Z0-9]+]]: index,1785//  CHECK-SAME:     %[[ARG4:[a-zA-Z0-9]+]]: index)1786//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[ARG0]], %[[ARG1]], %[[ARG2]]] by (%[[ARG3]], 4, %[[ARG4]])1787//       CHECK:     %[[DELIN:.+]]:3 = affine.delinearize_index %[[LIN]] into (%[[ARG3]], 8, %[[ARG4]])1788//       CHECK:     return %[[DELIN]]#0, %[[DELIN]]#1, %[[DELIN]]#21789func.func @no_cancel_delinearize_linearize_different_basis(%arg0: index, %arg1: index, %arg2: index, %arg3: index, %arg4: index) -> (index, index, index) {1790  %0 = affine.linearize_index [%arg0, %arg1, %arg2] by (%arg3, 4, %arg4) : index1791  %1:3 = affine.delinearize_index %0 into (%arg3, 8, %arg4)1792      : index, index, index1793  return %1#0, %1#1, %1#2 : index, index, index1794}1795 1796// -----1797 1798// CHECK-LABEL: func @split_delinearize_spanning_final_part1799//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1800//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,1801//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index)1802//       CHECK:     %[[LIN:.+]] = affine.linearize_index disjoint [%[[ARG0]], %[[ARG1]]] by (2, 4)1803//       CHECK:     %[[DELIN1:.+]]:2 = affine.delinearize_index %[[LIN]] into (2)1804//       CHECK:     %[[DELIN2:.+]]:2 = affine.delinearize_index %[[ARG2]] into (8, 8)1805//       CHECK:     return %[[DELIN1]]#0, %[[DELIN1]]#1, %[[DELIN2]]#0, %[[DELIN2]]#11806func.func @split_delinearize_spanning_final_part(%arg0: index, %arg1: index, %arg2: index) -> (index, index, index, index) {1807  %0 = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by (2, 4, 64) : index1808  %1:4 = affine.delinearize_index %0 into (2, 8, 8)1809      : index, index, index, index1810  return %1#0, %1#1, %1#2, %1#3 : index, index, index, index1811}1812 1813// -----1814 1815// CHECK-LABEL: func @split_delinearize_spanning_final_part_and_cancel1816//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1817//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,1818//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index)1819//       CHECK:     %[[DELIN:.+]]:2 = affine.delinearize_index %[[ARG2]] into (8, 8)1820//       CHECK:     return %[[ARG0]], %[[ARG1]], %[[DELIN]]#0, %[[DELIN]]#11821func.func @split_delinearize_spanning_final_part_and_cancel(%arg0: index, %arg1: index, %arg2: index) -> (index, index, index, index) {1822  %0 = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by (2, 4, 64) : index1823  %1:4 = affine.delinearize_index %0 into (2, 4, 8, 8)1824      : index, index, index, index1825  return %1#0, %1#1, %1#2, %1#3 : index, index, index, index1826}1827 1828// -----1829 1830// The delinearize basis doesn't match the last basis element before1831// overshooting it, don't simplify.1832// CHECK-LABEL: func @dont_split_delinearize_overshooting_target1833//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1834//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,1835//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index)1836//       CHECK:     %[[LIN:.+]] = affine.linearize_index disjoint [%[[ARG0]], %[[ARG1]], %[[ARG2]]] by (2, 4, 64)1837//       CHECK:     %[[DELIN:.+]]:4 = affine.delinearize_index %[[LIN]] into (2, 16, 8)1838//       CHECK:     return %[[DELIN]]#0, %[[DELIN]]#1, %[[DELIN]]#2, %[[DELIN]]#31839func.func @dont_split_delinearize_overshooting_target(%arg0: index, %arg1: index, %arg2: index) -> (index, index, index, index) {1840  %0 = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by (2, 4, 64) : index1841  %1:4 = affine.delinearize_index %0 into (2, 16, 8)1842      : index, index, index, index1843  return %1#0, %1#1, %1#2, %1#3 : index, index, index, index1844}1845 1846// -----1847 1848// The delinearize basis doesn't fully multiply to the final basis element.1849// CHECK-LABEL: func @dont_split_delinearize_undershooting_target1850//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1851//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index)1852//       CHECK:     %[[LIN:.+]] = affine.linearize_index disjoint [%[[ARG0]], %[[ARG1]]] by (2, 64)1853//       CHECK:     %[[DELIN:.+]]:3 = affine.delinearize_index %[[LIN]] into (4, 8)1854//       CHECK:     return %[[DELIN]]#0, %[[DELIN]]#11855func.func @dont_split_delinearize_undershooting_target(%arg0: index, %arg1: index) -> (index, index, index) {1856  %0 = affine.linearize_index disjoint [%arg0, %arg1] by (2, 64) : index1857  %1:3 = affine.delinearize_index %0 into (4, 8)1858      : index, index, index1859  return %1#0, %1#1, %1#2 : index, index, index1860}1861 1862// -----1863 1864// CHECK-LABEL: @linearize_unit_basis_disjoint1865// CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index, %[[arg2:.+]]: index, %[[arg3:.+]]: index)1866// CHECK: %[[ret:.+]] = affine.linearize_index disjoint [%[[arg0]], %[[arg2]]] by (3, %[[arg3]]) : index1867// CHECK: return %[[ret]]1868func.func @linearize_unit_basis_disjoint(%arg0: index, %arg1: index, %arg2: index, %arg3: index) -> index {1869  %ret = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by (3, 1, %arg3) : index1870  return %ret : index1871}1872 1873// -----1874 1875// CHECK-LABEL: @linearize_unit_basis_disjoint_no_outer_bound1876// CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index, %[[arg2:.+]]: index, %[[arg3:.+]]: index)1877// CHECK: %[[ret:.+]] = affine.linearize_index disjoint [%[[arg0]], %[[arg2]]] by (%[[arg3]]) : index1878// CHECK: return %[[ret]]1879func.func @linearize_unit_basis_disjoint_no_outer_bound(%arg0: index, %arg1: index, %arg2: index, %arg3: index) -> index {1880  %ret = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by (1, %arg3) : index1881  return %ret : index1882}1883 1884// -----1885 1886// CHECK-LABEL: @linearize_unit_basis_zero1887// CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index, %[[arg2:.+]]: index)1888// CHECK: %[[ret:.+]] = affine.linearize_index [%[[arg0]], %[[arg1]]] by (3, %[[arg2]]) : index1889// CHECK: return %[[ret]]1890func.func @linearize_unit_basis_zero(%arg0: index, %arg1: index, %arg2: index) -> index {1891  %c0 = arith.constant 0 : index1892  %ret = affine.linearize_index [%arg0, %c0, %arg1] by (3, 1, %arg2) : index1893  return %ret : index1894}1895 1896// -----1897 1898// CHECK-LABEL: @linearize_all_zero_unit_basis1899// CHECK: arith.constant 0 : index1900// CHECK-NOT: affine.linearize_index1901func.func @linearize_all_zero_unit_basis() -> index {1902  %c0 = arith.constant 0 : index1903  %ret = affine.linearize_index [%c0, %c0] by (1, 1) : index1904  return %ret : index1905}1906 1907// -----1908 1909// CHECK-LABEL: @linearize_one_element_basis1910// CHECK-SAME: (%[[arg0:.+]]: index, %[[arg1:.+]]: index)1911// CHECK-NOT: affine.linearize_index1912// CHECK: return %[[arg0]]1913func.func @linearize_one_element_basis(%arg0: index, %arg1: index) -> index {1914  %ret = affine.linearize_index [%arg0] by (%arg1) : index1915  return %ret : index1916}1917 1918// -----1919 1920// CHECK-LABEL: func @cancel_linearize_delinearize_exact(1921//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1922//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,1923//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index)1924//       CHECK:     return %[[ARG0]]1925func.func @cancel_linearize_delinearize_exact(%arg0: index, %arg1: index, %arg2: index) -> index {1926  %0:3 = affine.delinearize_index %arg0 into (%arg1, 4, %arg2) : index, index, index1927  %1 = affine.linearize_index [%0#0, %0#1, %0#2] by (%arg1, 4, %arg2) : index1928  return %1 : index1929}1930 1931// -----1932 1933// CHECK-LABEL: func @cancel_linearize_delinearize_linearize_extra_bound(1934//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1935//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,1936//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index)1937//       CHECK:     return %[[ARG0]]1938func.func @cancel_linearize_delinearize_linearize_extra_bound(%arg0: index, %arg1: index, %arg2: index) -> index {1939  %0:3 = affine.delinearize_index %arg0 into (4, %arg2) : index, index, index1940  %1 = affine.linearize_index [%0#0, %0#1, %0#2] by (%arg1, 4, %arg2) : index1941  return %1 : index1942}1943 1944// -----1945 1946// CHECK-LABEL: func @cancel_linearize_delinearize_delinearize_extra_bound(1947//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1948//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,1949//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index)1950//       CHECK:     return %[[ARG0]]1951func.func @cancel_linearize_delinearize_delinearize_extra_bound(%arg0: index, %arg1: index, %arg2: index) -> index {1952  %0:3 = affine.delinearize_index %arg0 into (%arg1, 4, %arg2) : index, index, index1953  %1 = affine.linearize_index [%0#0, %0#1, %0#2] by (4, %arg2) : index1954  return %1 : index1955}1956 1957// -----1958 1959// CHECK-LABEL: func @cancel_linearize_delinearize_head(1960//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1961//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index)1962//       CHECK:     %[[DELIN:.+]]:2 = affine.delinearize_index %[[ARG0]] into (12, 8)1963//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[DELIN]]#0, %[[ARG1]]] by (12, 16)1964//       CHECK:     return %[[LIN]]1965func.func @cancel_linearize_delinearize_head(%arg0: index, %arg1: index) -> index {1966  %0:3 = affine.delinearize_index %arg0 into (3, 4, 8) : index, index, index1967  %1 = affine.linearize_index [%0#0, %0#1, %arg1] by (3, 4, 16) : index1968  return %1 : index1969}1970 1971// -----1972 1973// CHECK-LABEL: func @cancel_linearize_delinearize_head_delinearize_unbounded(1974//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1975//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index)1976//       CHECK:     %[[DELIN:.+]]:2 = affine.delinearize_index %[[ARG0]] into (12, 8)1977//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[DELIN]]#0, %[[ARG1]]] by (12, 16)1978//       CHECK:     return %[[LIN]]1979func.func @cancel_linearize_delinearize_head_delinearize_unbounded(%arg0: index, %arg1: index) -> index {1980  %0:3 = affine.delinearize_index %arg0 into (4, 8) : index, index, index1981  %1 = affine.linearize_index [%0#0, %0#1, %arg1] by (3, 4, 16) : index1982  return %1 : index1983}1984 1985// -----1986 1987// CHECK-LABEL: func @cancel_linearize_delinearize_head_linearize_unbounded(1988//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,1989//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index)1990//       CHECK:     %[[DELIN:.+]]:2 = affine.delinearize_index %[[ARG0]] into (8)1991//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[DELIN]]#0, %[[ARG1]]] by (16)1992//       CHECK:     return %[[LIN]]1993func.func @cancel_linearize_delinearize_head_linearize_unbounded(%arg0: index, %arg1: index) -> index {1994  %0:3 = affine.delinearize_index %arg0 into (3, 4, 8) : index, index, index1995  %1 = affine.linearize_index [%0#0, %0#1, %arg1] by (4, 16) : index1996  return %1 : index1997}1998 1999// -----2000 2001// CHECK-LABEL: func @cancel_linearize_delinearize_head_both_unbounded(2002//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2003//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index)2004//       CHECK:     %[[DELIN:.+]]:2 = affine.delinearize_index %[[ARG0]] into (8)2005//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[DELIN]]#0, %[[ARG1]]] by (16)2006//       CHECK:     return %[[LIN]]2007func.func @cancel_linearize_delinearize_head_both_unbounded(%arg0: index, %arg1: index) -> index {2008  %0:3 = affine.delinearize_index %arg0 into (4, 8) : index, index, index2009  %1 = affine.linearize_index [%0#0, %0#1, %arg1] by (4, 16) : index2010  return %1 : index2011}2012 2013// -----2014 2015// CHECK-LABEL: func @cancel_linearize_delinearize_tail(2016//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2017//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index)2018//       CHECK:     %[[DELIN:.+]]:2 = affine.delinearize_index %[[ARG0]] into (3, 32)2019//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[ARG1]], %[[DELIN]]#1] by (5, 32)2020//       CHECK:     return %[[LIN]]2021func.func @cancel_linearize_delinearize_tail(%arg0: index, %arg1: index) -> index {2022  %0:3 = affine.delinearize_index %arg0 into (3, 4, 8) : index, index, index2023  %1 = affine.linearize_index [%arg1, %0#1, %0#2] by (5, 4, 8) : index2024  return %1 : index2025}2026 2027// -----2028 2029// CHECK-LABEL: func @cancel_linearize_delinearize_middle_exact(2030//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2031//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,2032//  CHECK-SAME:     %[[ARG2:[a-zA-z0-9]+]]: index)2033//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[ARG1]], %[[ARG0]], %[[ARG2]]] by (9, 30, 7)2034//       CHECK:     return %[[LIN]]2035func.func @cancel_linearize_delinearize_middle_exact(%arg0: index, %arg1: index, %arg2: index) -> index {2036  %0:3 = affine.delinearize_index %arg0 into (2, 3, 5) : index, index, index2037  %1 = affine.linearize_index [%arg1, %0#0, %0#1, %0#2, %arg2] by (9, 2, 3, 5, 7) : index2038  return %1 : index2039}2040 2041// -----2042 2043// CHECK: #[[$MAP:.+]] = affine_map<()[s0, s1] -> ((s0 * s1) * 16)>2044 2045// CHECK-LABEL: func @cancel_linearize_delinearize_middle_exact_dynamic_basis(2046//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2047//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,2048//  CHECK-SAME:     %[[ARG2:[a-zA-z0-9]+]]: index)2049//       CHECK:     %[[C1:.+]] = arith.constant 1 : index2050//       CHECK:     %[[SIZEPROD:.+]] = affine.apply #[[$MAP]]()[%[[ARG1]], %[[ARG2]]]2051//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[C1]], %[[ARG0]], %[[C1]]] by (3, %[[SIZEPROD]], 4)2052//       CHECK:     return %[[LIN]]2053func.func @cancel_linearize_delinearize_middle_exact_dynamic_basis(%arg0: index, %arg1: index, %arg2: index) -> index {2054  %c1 = arith.constant 1 : index2055  %0:4 = affine.delinearize_index %arg0 into (2, %arg1, %arg2, 8) : index, index, index, index2056  %1 = affine.linearize_index [%c1, %0#0, %0#1, %0#2, %0#3, %c1] by (3, 2, %arg1, %arg2, 8, 4) : index2057  return %1 : index2058}2059 2060// -----2061 2062// CHECK-LABEL: func @cancel_linearize_delinearize_middle_exact_delinearize_unbounded_disjoint(2063//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2064//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,2065//  CHECK-SAME:     %[[ARG2:[a-zA-z0-9]+]]: index)2066//       CHECK:     %[[LIN:.+]] = affine.linearize_index disjoint [%[[ARG1]], %[[ARG0]], %[[ARG2]]] by (9, 30, 7)2067//       CHECK:     return %[[LIN]]2068func.func @cancel_linearize_delinearize_middle_exact_delinearize_unbounded_disjoint(%arg0: index, %arg1: index, %arg2: index) -> index {2069  %0:3 = affine.delinearize_index %arg0 into (3, 5) : index, index, index2070  %1 = affine.linearize_index disjoint [%arg1, %0#0, %0#1, %0#2, %arg2] by (9, 2, 3, 5, 7) : index2071  return %1 : index2072}2073 2074// -----2075 2076// Unlike in the test above, the linerize indices aren't asserted to be disjoint, so2077// we can't know if the `2` from the basis is a correct bound.2078// CHECK-LABEL: func @dont_cancel_linearize_delinearize_middle_exact_delinearize_unbounded(2079//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2080//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,2081//  CHECK-SAME:     %[[ARG2:[a-zA-z0-9]+]]: index)2082//       CHECK:     %[[DELIN:.+]]:2 = affine.delinearize_index %[[ARG0]] into (3)2083//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[ARG1]], %[[DELIN]]#0, %[[DELIN]]#1, %[[ARG2]]] by (9, 2, 3, 7)2084//       CHECK:     return %[[LIN]]2085 2086func.func @dont_cancel_linearize_delinearize_middle_exact_delinearize_unbounded(%arg0: index, %arg1: index, %arg2: index) -> index {2087  %0:2 = affine.delinearize_index %arg0 into (3) : index, index2088  %1 = affine.linearize_index [%arg1, %0#0, %0#1, %arg2] by (9, 2, 3, 7) : index2089  return %1 : index2090}2091 2092// -----2093 2094// The presence of a `disjoint` here tells us that the "unbounded" term on the2095// delinearization can't have been above 2.2096// CHECK-LABEL: func @cancel_linearize_delinearize_middle_delinearize_unbounded_disjoint_implied_bound(2097//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2098//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,2099//  CHECK-SAME:     %[[ARG2:[a-zA-z0-9]+]]: index)2100//       CHECK:     %[[DELIN:.+]]:2 = affine.delinearize_index %[[ARG0]] into (6, 5)2101//       CHECK:     %[[LIN:.+]] = affine.linearize_index disjoint [%[[ARG1]], %[[DELIN]]#0, %[[ARG2]]] by (9, 6, 7)2102//       CHECK:     return %[[LIN]]2103func.func @cancel_linearize_delinearize_middle_delinearize_unbounded_disjoint_implied_bound(%arg0: index, %arg1: index, %arg2: index) -> index {2104  %0:3 = affine.delinearize_index %arg0 into (3, 5) : index, index, index2105  %1 = affine.linearize_index disjoint [%arg1, %0#0, %0#1, %arg2] by (9, 2, 3, 7) : index2106  return %1 : index2107}2108 2109// -----2110 2111// CHECK-LABEL: func @cancel_linearize_delinearize_multiple_matches(2112//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2113//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index)2114//       CHECK:     %[[C0:.+]] = arith.constant 02115//       CHECK:     %[[DELIN:.+]]:4 = affine.delinearize_index %[[ARG0]] into (4, 16, 4, 64)2116//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[ARG1]], %[[DELIN]]#1, %[[C0]], %[[DELIN]]#3] by (4, 16, 4, 64)2117//       CHECK:     return %[[LIN]]2118func.func @cancel_linearize_delinearize_multiple_matches(%arg0: index, %arg1: index) -> index {2119  %c0 = arith.constant 0 : index2120  %0:7 = affine.delinearize_index %arg0 into (4, 4, 4, 4, 4, 4, 4) : index, index, index, index, index, index, index2121  %1 = affine.linearize_index [%arg1, %0#1, %0#2, %c0, %0#4, %0#5, %0#6] by (4, 4, 4, 4, 4, 4, 4) : index2122  return %1 : index2123}2124 2125// -----2126 2127// CHECK-LABEL: func @cancel_linearize_delinearize_multiple_delinearizes(2128//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2129//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index)2130//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[ARG0]], %[[ARG1]]] by (32, 32)2131//       CHECK:     return %[[LIN]]2132func.func @cancel_linearize_delinearize_multiple_delinearizes(%arg0: index, %arg1: index) -> index {2133  %0:2 = affine.delinearize_index %arg0 into (4, 8) : index, index2134  %1:2 = affine.delinearize_index %arg1 into (2, 16) : index, index2135  %2 = affine.linearize_index [%0#0, %0#1, %1#0, %1#1] by (4, 8, 2, 16) : index2136  return %2 : index2137}2138 2139// -----2140 2141// Don't cancel because the values from the delinearize aren't used in order2142// CHECK-LABEL: func @no_cancel_linearize_delinearize_permuted(2143//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2144//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,2145//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index)2146//       CHECK:     %[[DELIN:.+]]:3 = affine.delinearize_index %[[ARG0]] into (%[[ARG1]], 4, %[[ARG2]])2147//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[DELIN]]#0, %[[DELIN]]#2, %[[DELIN]]#1] by (%[[ARG1]], %[[ARG2]], 4)2148//       CHECK:     return %[[LIN]]2149func.func @no_cancel_linearize_delinearize_permuted(%arg0: index, %arg1: index, %arg2: index) -> index {2150  %0:3 = affine.delinearize_index %arg0 into (%arg1, 4, %arg2) : index, index, index2151  %1 = affine.linearize_index [%0#0, %0#2, %0#1] by (%arg1, %arg2, 4) : index2152  return %1 : index2153}2154 2155// -----2156 2157// CHECK: #[[$MAP:.+]] = affine_map<()[s0] -> (s0 * 3)>2158// But these cancel because they're a contiguous segment2159// CHECK-LABEL: func @partial_cancel_linearize_delinearize_not_fully_permuted(2160//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2161//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,2162//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index)2163//       CHECK:     %[[SIZEPROD:.+]] = affine.apply #[[$MAP]]()[%[[ARG2]]]2164//       CHECK:     %[[DELIN:.+]]:3 = affine.delinearize_index %[[ARG0]] into (%[[ARG1]], 4, %[[SIZEPROD]])2165//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[DELIN]]#0, %[[DELIN]]#2, %[[DELIN]]#1] by (%[[ARG1]], %[[SIZEPROD]], 4)2166//       CHECK:     return %[[LIN]]2167func.func @partial_cancel_linearize_delinearize_not_fully_permuted(%arg0: index, %arg1: index, %arg2: index) -> index {2168  %0:4 = affine.delinearize_index %arg0 into (%arg1, 4, %arg2, 3) : index, index, index, index2169  %1 = affine.linearize_index [%0#0, %0#2, %0#3, %0#1] by (%arg1, %arg2, 3, 4) : index2170  return %1 : index2171}2172 2173// -----2174 2175// Ensure we don't get SSA errors when creating new `affine.delinearize` operations.2176// CHECK-LABEL: func @cancel_linearize_delinearize_placement2177// CHECK-SAME: (%[[ARG0:.+]]: index)2178// CHECK: %[[C0:.+]] = arith.constant 0 : index2179// CHECK: %[[NEW_DELIN:.+]]:2 = affine.delinearize_index %[[ARG0]] into (8, 32) : index, index2180// CHECK-NEXT: %[[DELIN_PART:.+]]:2 = affine.delinearize_index %[[NEW_DELIN]]#1 into (8, 4) : index, index2181// CHECK-NEXT: %[[L1:.+]] = affine.linearize_index disjoint [%[[DELIN_PART]]#1, %[[NEW_DELIN]]#0, %[[C0]], %[[C0]]] by (4, 8, 4, 8)2182// CHECK-NEXT: %[[L2:.+]] = affine.linearize_index disjoint [%[[NEW_DELIN]]#1, %[[C0]], %[[C0]]] by (32, 8, 4)2183// CHECK-NEXT: %[[L3:.+]] = affine.linearize_index disjoint [%[[DELIN_PART]]#0, %[[NEW_DELIN]]#0, %[[C0]], %[[C0]]] by (8, 8, 4, 4)2184// CHECK-NEXT: return %[[L1]], %[[L2]], %[[L3]]2185func.func @cancel_linearize_delinearize_placement(%arg0: index) -> (index, index, index) {2186  %c0 = arith.constant 0 : index2187  %0:3 = affine.delinearize_index %arg0 into (8, 8, 4) : index, index, index2188  %1 = affine.linearize_index disjoint [%0#2, %0#0, %c0, %c0] by (4, 8, 4, 8) : index2189  %2 = affine.linearize_index disjoint [%0#1, %0#2, %c0, %c0] by (8, 4, 8, 4) : index2190  %3 = affine.linearize_index disjoint [%0#1, %0#0, %c0, %c0] by (8, 8, 4, 4) : index2191  return %1, %2, %3 : index, index, index2192}2193 2194// -----2195 2196// Won't cancel because the linearize and delinearize are using a different basis2197// CHECK-LABEL: func @no_cancel_linearize_delinearize_different_basis(2198//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2199//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index,2200//  CHECK-SAME:     %[[ARG2:[a-zA-Z0-9]+]]: index)2201//       CHECK:     %[[DELIN:.+]]:3 = affine.delinearize_index %[[ARG0]] into (%[[ARG1]], 4, %[[ARG2]])2202//       CHECK:     %[[LIN:.+]] = affine.linearize_index [%[[DELIN]]#0, %[[DELIN]]#1, %[[DELIN]]#2] by (%[[ARG1]], 8, %[[ARG2]])2203//       CHECK:     return %[[LIN]]2204func.func @no_cancel_linearize_delinearize_different_basis(%arg0: index, %arg1: index, %arg2: index) -> index {2205  %0:3 = affine.delinearize_index %arg0 into (%arg1, 4, %arg2) : index, index, index2206  %1 = affine.linearize_index [%0#0, %0#1, %0#2] by (%arg1, 8, %arg2) : index2207  return %1 : index2208}2209 2210// -----2211 2212// CHECK-LABEL: func @affine_leading_zero(2213//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2214//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index)2215//       CHECK:     %[[RET:.+]] = affine.linearize_index [%[[ARG0]], %[[ARG1]]] by (3, 5)2216//       CHECK:     return %[[RET]]2217func.func @affine_leading_zero(%arg0: index, %arg1: index) -> index {2218  %c0 = arith.constant 0 : index2219  %ret = affine.linearize_index [%c0, %arg0, %arg1] by (2, 3, 5) : index2220  return %ret : index2221}2222 2223// -----2224 2225// CHECK-LABEL: func @affine_leading_zero_no_outer_bound(2226//  CHECK-SAME:     %[[ARG0:[a-zA-Z0-9]+]]: index,2227//  CHECK-SAME:     %[[ARG1:[a-zA-Z0-9]+]]: index)2228//       CHECK:     %[[RET:.+]] = affine.linearize_index [%[[ARG0]], %[[ARG1]]] by (3, 5)2229//       CHECK:     return %[[RET]]2230func.func @affine_leading_zero_no_outer_bound(%arg0: index, %arg1: index) -> index {2231  %c0 = arith.constant 0 : index2232  %ret = affine.linearize_index [%c0, %arg0, %arg1] by (3, 5) : index2233  return %ret : index2234}2235 2236// -----2237 2238// CHECK-LABEL: func @delin_apply_cancel_exact2239// CHECK-SAME: (%[[ARG0:.+]]: index, %[[ARG1:.+]]: memref<?xindex>)2240// CHECK-COUNT-6: memref.store %[[ARG0]], %[[ARG1]][%[[ARG0]]]2241// CHECK-NOT: memref.store2242// CHECK: return2243func.func @delin_apply_cancel_exact(%arg0:  index, %arg1: memref<?xindex>) {2244  %a:3 = affine.delinearize_index %arg0 into (4, 5) : index, index, index2245  %b:3 = affine.delinearize_index %arg0 into (3, 4, 5) : index, index, index2246  %c:2 = affine.delinearize_index %arg0 into (20) : index, index2247 2248  %t1 = affine.apply affine_map<()[s0, s1, s2] -> (s0 + s1 * 5 + s2 * 20)>()[%a#2, %a#1, %a#0]2249  memref.store %t1, %arg1[%t1] : memref<?xindex>2250 2251  %t2 = affine.apply affine_map<()[s0, s1, s2] -> (s0 + s2 * 20 + s1 * 5)>()[%a#2, %a#1, %a#0]2252  memref.store %t2, %arg1[%t2] : memref<?xindex>2253 2254  %t3 = affine.apply affine_map<()[s0, s1, s2] -> (s1 * 20 + s2 * 5 + s0)>()[%a#2, %a#0, %a#1]2255  memref.store %t3, %arg1[%t3] : memref<?xindex>2256 2257  %t4 = affine.apply affine_map<()[s0, s1, s2] -> (s0 + s1 * 5 + s2 * 20)>()[%b#2, %b#1, %b#0]2258  memref.store %t4, %arg1[%t4] : memref<?xindex>2259 2260  %t5 = affine.apply affine_map<()[s0, s1] -> (s0 + s1 * 20)>()[%c#1, %c#0]2261  memref.store %t5, %arg1[%t5] : memref<?xindex>2262 2263  %t6 = affine.apply affine_map<()[s0, s1] -> (s1 * 20 + s0)>()[%c#1, %c#0]2264  memref.store %t6, %arg1[%t5] : memref<?xindex>2265 2266  return2267}2268 2269// -----2270 2271// CHECK-LABEL: func @delin_apply_cancel_exact_dim2272// CHECK: affine.for %[[arg1:.+]] = 0 to 2562273// CHECK: memref.store %[[arg1]]2274// CHECK: return2275func.func @delin_apply_cancel_exact_dim(%arg0: memref<?xindex>) {2276  affine.for %arg1 = 0 to 256 {2277    %a:3 = affine.delinearize_index %arg1 into (2, 2, 64) : index, index, index2278    %i = affine.apply affine_map<(d0, d1, d2) -> (d0 + d1 * 128 + d2 * 64)>(%a#2, %a#0, %a#1)2279    memref.store %i, %arg0[%i] : memref<?xindex>2280  }2281  return2282}2283 2284// -----2285 2286// CHECK-DAG: #[[$MAP:.+]] = affine_map<()[s0] -> (s0 + 512)>2287// CHECK-LABEL: func @delin_apply_cancel_const_term2288// CHECK-SAME: (%[[ARG0:.+]]: index, %[[ARG1:.+]]: memref<?xindex>)2289// CHECK: affine.apply #[[$MAP]]()[%[[ARG0]]]2290// CHECK: return2291func.func @delin_apply_cancel_const_term(%arg0:  index, %arg1: memref<?xindex>) {2292  %a:3 = affine.delinearize_index %arg0 into (2, 2, 64) : index, index, index2293 2294  %t1 = affine.apply affine_map<()[s0, s1, s2] -> (s0 + s1 * 128 + s2 * 64 + 512)>()[%a#2, %a#0, %a#1]2295  memref.store %t1, %arg1[%t1] : memref<?xindex>2296 2297  return2298}2299 2300// -----2301 2302// CHECK-DAG: #[[$MAP:.+]] = affine_map<()[s0, s1] -> (s0 + s1 + 512)>2303// CHECK-LABEL: func @delin_apply_cancel_var_term2304// CHECK-SAME: (%[[ARG0:.+]]: index, %[[ARG1:.+]]: memref<?xindex>, %[[ARG2:.+]]: index)2305// CHECK: affine.apply #[[$MAP]]()[%[[ARG2]], %[[ARG0]]]2306// CHECK: return2307func.func @delin_apply_cancel_var_term(%arg0:  index, %arg1: memref<?xindex>, %arg2: index) {2308  %a:3 = affine.delinearize_index %arg0 into (2, 2, 64) : index, index, index2309 2310  %t1 = affine.apply affine_map<()[s0, s1, s2, s3] -> (s0 + s1 * 128 + s2 * 64 + s3 + 512)>()[%a#2, %a#0, %a#1, %arg2]2311  memref.store %t1, %arg1[%t1] : memref<?xindex>2312 2313  return2314}2315 2316// -----2317 2318// CHECK-DAG: #[[$MAP:.+]] = affine_map<()[s0] -> (s0 * 2 + s0 ceildiv 4)>2319// CHECK-LABEL: func @delin_apply_cancel_nested_exprs2320// CHECK-SAME: (%[[ARG0:.+]]: index, %[[ARG1:.+]]: memref<?xindex>)2321// CHECK: affine.apply #[[$MAP]]()[%[[ARG0]]]2322// CHECK: return2323func.func @delin_apply_cancel_nested_exprs(%arg0:  index, %arg1: memref<?xindex>) {2324  %a:2 = affine.delinearize_index %arg0 into (20) : index, index2325 2326  %t1 = affine.apply affine_map<()[s0, s1] -> ((s0 + s1 * 20) ceildiv 4 + (s1 * 20 + s0) * 2)>()[%a#1, %a#0]2327  memref.store %t1, %arg1[%t1] : memref<?xindex>2328 2329  return2330}2331 2332// -----2333 2334// CHECK-DAG: #[[$MAP:.+]] = affine_map<()[s0, s1] -> (s0 + s1)>2335// CHECK-LABEL: func @delin_apply_cancel_preserve_rotation2336// CHECK-SAME: (%[[ARG0:.+]]: index, %[[ARG1:.+]]: memref<?xindex>)2337// CHECK: %[[A:.+]]:2 = affine.delinearize_index %[[ARG0]] into (20)2338// CHECK: affine.apply #[[$MAP]]()[%[[A]]#1, %[[ARG0]]]2339// CHECK: return2340func.func @delin_apply_cancel_preserve_rotation(%arg0:  index, %arg1: memref<?xindex>) {2341  %a:2 = affine.delinearize_index %arg0 into (20) : index, index2342 2343  %t1 = affine.apply affine_map<()[s0, s1] -> (s0 + s1 * 20 + s0)>()[%a#1, %a#0]2344  memref.store %t1, %arg1[%t1] : memref<?xindex>2345 2346  return2347}2348 2349// -----2350 2351// CHECK-DAG: #[[$MAP:.+]] = affine_map<()[s0, s1] -> (s0 + s1 * 5)>2352// CHECK-LABEL: func @delin_apply_dont_cancel_partial2353// CHECK-SAME: (%[[ARG0:.+]]: index, %[[ARG1:.+]]: memref<?xindex>)2354// CHECK: %[[A:.+]]:3 = affine.delinearize_index %[[ARG0]] into (3, 4, 5)2355// CHECK: affine.apply #[[$MAP]]()[%[[A]]#2, %[[A]]#1]2356// CHECK: return2357func.func @delin_apply_dont_cancel_partial(%arg0:  index, %arg1: memref<?xindex>) {2358  %a:3 = affine.delinearize_index %arg0 into (3, 4, 5) : index, index, index2359 2360  %t1 = affine.apply affine_map<()[s0, s1] -> (s0 + s1 * 5)>()[%a#2, %a#1]2361  memref.store %t1, %arg1[%t1] : memref<?xindex>2362 2363  return2364}2365 2366// -----2367 2368// CHECK-LABEL: @cst_value_to_cst_attr_basis_delinearize_index2369// CHECK-SAME:    (%[[ARG0:.*]]: index)2370// CHECK:         %[[RET:.*]]:3 = affine.delinearize_index %[[ARG0]] into (3, 4, 2) : index, index2371// CHECK:         return %[[RET]]#0, %[[RET]]#1, %[[RET]]#2 : index, index, index2372func.func @cst_value_to_cst_attr_basis_delinearize_index(%arg0 : index) ->2373    (index, index, index) {2374  %c4 = arith.constant 4 : index2375  %c3 = arith.constant 3 : index2376  %c2 = arith.constant 2 : index2377  %0:3 = affine.delinearize_index %arg0 into (%c3, %c4, %c2)2378      : index, index, index2379  return %0#0, %0#1, %0#2 : index, index, index2380}2381 2382// -----2383 2384// CHECK-LABEL: @cst_value_to_cst_attr_basis_linearize_index2385// CHECK-SAME:    (%[[ARG0:.*]]: index, %[[ARG1:.*]]: index, %[[ARG2:.*]]: index)2386// CHECK:         %[[RET:.*]] = affine.linearize_index disjoint [%[[ARG0]], %[[ARG1]], %[[ARG2]]] by (2, 3, 4) : index2387// CHECK:         return %[[RET]] : index2388func.func @cst_value_to_cst_attr_basis_linearize_index(%arg0 : index, %arg1 : index, %arg2 : index) ->2389    (index) {2390  %c4 = arith.constant 4 : index2391  %c2 = arith.constant 2 : index2392  %0 = affine.linearize_index disjoint [%arg0, %arg1, %arg2] by  (%c2, 3, %c4) : index2393  return %0 : index2394}2395 2396// CHECK-LABEL: func @for_empty_body_folder_iv_yield2397func.func @for_empty_body_folder_iv_yield() -> index {2398  %c18 = arith.constant 18 : index2399  %10 = affine.for %arg3 = 0 to 114 iter_args(%arg4 = %c18) -> (index) {2400    affine.yield %arg3 : index2401  }2402  return %10 : index2403}2404