brintos

brintos / llvm-project-archived public Read only

0
0
Text · 54.7 KiB · 1ea4251 Raw
1579 lines · plain
1// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline='builtin.module(func.func(affine-loop-fusion))' -split-input-file | FileCheck %s2 3// Part II of fusion tests in  mlir/test/Transforms/loop-fusion=2.mlir.4// Part III of fusion tests in mlir/test/Transforms/loop-fusion-3.mlir5// Part IV of fusion tests in mlir/test/Transforms/loop-fusion-4.mlir6 7// TODO: Add more tests:8// *) Add nested fusion test cases when non-constant loop bound support is9//    added to iteration domain in dependence check.10// *) Add a test w/ floordiv/ceildiv/mod when supported in dependence check.11// *) Add tests which check fused computation slice indexing and loop bounds.12// TODO: Test clean up: move memref allocs to func args.13 14// -----15 16// CHECK-LABEL: func @should_fuse_raw_dep_for_locality() {17func.func @should_fuse_raw_dep_for_locality() {18  %m = memref.alloc() : memref<10xf32>19  %cf7 = arith.constant 7.0 : f3220 21  affine.for %i0 = 0 to 10 {22    affine.store %cf7, %m[%i0] : memref<10xf32>23  }24  affine.for %i1 = 0 to 10 {25    %v0 = affine.load %m[%i1] : memref<10xf32>26  }27  // CHECK:      affine.for %{{.*}} = 0 to 10 {28  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>29  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>30  // CHECK-NEXT: }31  // CHECK-NEXT: return32  return33}34 35// -----36 37// CHECK-LABEL: func @should_fuse_reduction_to_pointwise() {38func.func @should_fuse_reduction_to_pointwise() {39  %a = memref.alloc() : memref<10x10xf32>40  %b = memref.alloc() : memref<10xf32>41  %c = memref.alloc() : memref<10xf32>42 43  %cf7 = arith.constant 7.0 : f3244 45  affine.for %i0 = 0 to 10 {46    affine.for %i1 = 0 to 10 {47      %v0 = affine.load %b[%i0] : memref<10xf32>48      %v1 = affine.load %a[%i0, %i1] : memref<10x10xf32>49      %v3 = arith.addf %v0, %v1 : f3250      affine.store %v3, %b[%i0] : memref<10xf32>51    }52  }53  affine.for %i2 = 0 to 10 {54    %v4 = affine.load %b[%i2] : memref<10xf32>55    affine.store %v4, %c[%i2] : memref<10xf32>56  }57 58  // Should fuse in entire inner loop on %i1 from source loop nest, as %i159  // is not used in the access function of the store/load on %b.60  // CHECK:       affine.for %{{.*}} = 0 to 10 {61  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 10 {62  // CHECK-NEXT:      affine.load %{{.*}}[0] : memref<1xf32>63  // CHECK-NEXT:      affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<10x10xf32>64  // CHECK-NEXT:      arith.addf %{{.*}}, %{{.*}} : f3265  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>66  // CHECK-NEXT:    }67  // CHECK-NEXT:    affine.load %{{.*}}[0] : memref<1xf32>68  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>69  // CHECK-NEXT:  }70  // CHECK-NEXT:  return71  return72}73 74// -----75 76// CHECK-DAG: [[$MAP_SHIFT_MINUS_ONE_R1:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> (d0 - 1)>77// CHECK-DAG: [[$MAP_SHIFT_D0_BY_ONE:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> (d0 + 1)>78// CHECK-DAG: [[$MAP_SHIFT_D1_BY_ONE:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> (d1 + 1)>79 80// CHECK-LABEL: func @should_fuse_loop_nests_with_shifts() {81func.func @should_fuse_loop_nests_with_shifts() {82  %a = memref.alloc() : memref<10x10xf32>83  %cf7 = arith.constant 7.0 : f3284 85  affine.for %i0 = 0 to 9 {86    affine.for %i1 = 0 to 9 {87      affine.store %cf7, %a[%i0 + 1, %i1 + 1] : memref<10x10xf32>88    }89  }90  affine.for %i2 = 1 to 10 {91    affine.for %i3 = 1 to 10 {92      %v0 = affine.load %a[%i2, %i3] : memref<10x10xf32>93    }94  }95 96  // Source slice affine apply sequence:97  // *) First two affine apply's map from the dst to src iteration space.98  // *) Third affine apply is access function around src store.99  // *) Fourth affine apply shifts the stores access function by '-1', because100  //    of the offset induced by reducing the memref shape from 10x10 to 9x9.101  // *) Fifth affine apply shifts the loads access function by '-1', because102  //    of the offset induced by reducing the memref shape from 10x10 to 9x9.103  // NOTE: Should create a private memref with reduced shape 9x9xf32.104  // CHECK:      affine.for %{{.*}} = 1 to 10 {105  // CHECK-NEXT:   affine.for %{{.*}} = 1 to 10 {106  // CHECK-NEXT:     %[[I:.*]] = affine.apply [[$MAP_SHIFT_MINUS_ONE_R1]](%{{.*}})107  // CHECK-NEXT:     %[[J:.*]] = affine.apply [[$MAP_SHIFT_MINUS_ONE_R1]](%{{.*}})108  // CHECK-NEXT:     affine.apply [[$MAP_SHIFT_D0_BY_ONE]](%[[I]], %[[J]])109  // CHECK-NEXT:     affine.apply [[$MAP_SHIFT_D1_BY_ONE]](%[[I]], %[[J]])110  // CHECK-NEXT:     affine.store %{{.*}}, %{{.*}}[0, 0] : memref<1x1xf32>111  // CHECK-NEXT:     affine.load %{{.*}}[0, 0] : memref<1x1xf32>112  // CHECK-NEXT:   }113  // CHECK-NEXT: }114  // CHECK-NEXT: return115  return116}117 118// -----119 120// CHECK-LABEL: func @should_fuse_loop_nest() {121func.func @should_fuse_loop_nest() {122  %a = memref.alloc() : memref<10x10xf32>123  %b = memref.alloc() : memref<10x10xf32>124  %cf7 = arith.constant 7.0 : f32125 126  affine.for %i0 = 0 to 10 {127    affine.for %i1 = 0 to 10 {128      affine.store %cf7, %a[%i0, %i1] : memref<10x10xf32>129    }130  }131  affine.for %i2 = 0 to 10 {132    affine.for %i3 = 0 to 10 {133      %v0 = affine.load %a[%i3, %i2] : memref<10x10xf32>134      affine.store %v0, %b[%i2, %i3] : memref<10x10xf32>135    }136  }137  affine.for %i4 = 0 to 10 {138    affine.for %i5 = 0 to 10 {139      %v1 = affine.load %b[%i4, %i5] : memref<10x10xf32>140    }141  }142  // Expecting private memref for '%a' first, then private memref for '%b'.143  // CHECK-DAG:  [[NEWA:%[0-9a-zA-Z_]+]] = memref.alloc() : memref<1x1xf32>144  // CHECK-DAG:  [[NEWB:%[0-9a-zA-Z_]+]] = memref.alloc() : memref<1x1xf32>145  // CHECK:      affine.for %{{.*}} = 0 to 10 {146  // CHECK-NEXT:   affine.for %{{.*}} = 0 to 10 {147  // CHECK-NEXT:     affine.store %{{.*}}, [[NEWA]][0, 0] : memref<1x1xf32>148  // CHECK-NEXT:     affine.load [[NEWA]][0, 0] : memref<1x1xf32>149  // CHECK-NEXT:     affine.store %{{.*}}, [[NEWB]][0, 0] : memref<1x1xf32>150  // CHECK-NEXT:     affine.load [[NEWB]][0, 0] : memref<1x1xf32>151  // CHECK-NEXT:   }152  // CHECK-NEXT: }153  // CHECK-NEXT: return154  return155}156 157// -----158 159// CHECK-LABEL: func @should_fuse_across_intermediate_loop_with_no_deps() {160func.func @should_fuse_across_intermediate_loop_with_no_deps() {161  %a = memref.alloc() : memref<10xf32>162  %b = memref.alloc() : memref<10xf32>163  %c = memref.alloc() : memref<10xf32>164 165  %cf7 = arith.constant 7.0 : f32166 167  affine.for %i0 = 0 to 10 {168    %v0 = affine.load %a[%i0] : memref<10xf32>169    affine.store %v0, %b[%i0] : memref<10xf32>170  }171  affine.for %i1 = 0 to 10 {172    affine.store %cf7, %c[%i1] : memref<10xf32>173  }174  affine.for %i2 = 0 to 10 {175    %v1 = affine.load %b[%i2] : memref<10xf32>176  }177 178  // Should fuse first loop (past second loop with no dependences) into third.179  // Note that fusion creates a private memref '%2' for the fused loop nest.180  // CHECK:      affine.for %{{.*}} = 0 to 10 {181  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>182  // CHECK-NEXT: }183  // CHECK:      affine.for %{{.*}} = 0 to 10 {184  // CHECK-NEXT:   affine.load %{{.*}}[%{{.*}}] : memref<10xf32>185  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>186  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>187  // CHECK-NEXT: }188  // CHECK-NEXT: return189  return190}191 192// -----193 194// CHECK-LABEL: func @should_fuse_all_loops() {195func.func @should_fuse_all_loops() {196  %a = memref.alloc() : memref<10xf32>197  %b = memref.alloc() : memref<10xf32>198  %cf7 = arith.constant 7.0 : f32199 200  // Set up flow dependences from first and second loops to third.201  affine.for %i0 = 0 to 10 {202    affine.store %cf7, %a[%i0] : memref<10xf32>203  }204  affine.for %i1 = 0 to 10 {205    affine.store %cf7, %b[%i1] : memref<10xf32>206  }207  affine.for %i2 = 0 to 10 {208    %v0 = affine.load %a[%i2] : memref<10xf32>209    %v1 = affine.load %b[%i2] : memref<10xf32>210  }211 212  // Should fuse first and second loops into third.213  // Expecting private memref for '%a' first, then private memref for '%b'.214  // CHECK-DAG: [[NEWA:%[0-9a-zA-Z_]+]] = memref.alloc() : memref<1xf32>215  // CHECK-DAG: [[NEWB:%[0-9a-zA-Z_]+]] = memref.alloc() : memref<1xf32>216  // CHECK:      affine.for %{{.*}} = 0 to 10 {217  // CHECK-NEXT:   affine.store %{{.*}}, [[NEWA]][0] : memref<1xf32>218  // CHECK-NEXT:   affine.store %{{.*}}, [[NEWB]][0] : memref<1xf32>219  // CHECK-NEXT:   affine.load [[NEWA]][0] : memref<1xf32>220  // CHECK-NEXT:   affine.load [[NEWB]][0] : memref<1xf32>221  // CHECK-NEXT: }222  // CHECK-NEXT: return223  return224}225 226// -----227 228// CHECK-LABEL: func @should_fuse_first_and_second_loops() {229func.func @should_fuse_first_and_second_loops() {230  %a = memref.alloc() : memref<10xf32>231  %b = memref.alloc() : memref<10xf32>232  %c = memref.alloc() : memref<10xf32>233 234  %cf7 = arith.constant 7.0 : f32235 236  affine.for %i0 = 0 to 10 {237    affine.store %cf7, %a[%i0] : memref<10xf32>238  }239  affine.for %i1 = 0 to 10 {240    %v0 = affine.load %a[%i1] : memref<10xf32>241    affine.store %cf7, %b[%i1] : memref<10xf32>242  }243  affine.for %i2 = 0 to 10 {244    %v1 = affine.load %c[%i2] : memref<10xf32>245  }246 247  // Should fuse first loop into the second (last loop should not be fused).248  // Should create private memref '%2' for fused scf.249  // CHECK:      affine.for %{{.*}} = 0 to 10 {250  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>251  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>252  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>253  // CHECK-NEXT: }254  // CHECK:      affine.for %{{.*}} = 0 to 10 {255  // CHECK-NEXT:   affine.load %{{.*}}[%{{.*}}] : memref<10xf32>256  // CHECK-NEXT: }257  // CHECK-NEXT: return258 259  return260}261 262// -----263 264// CHECK-LABEL: func @should_not_fuse_would_create_cycle() {265func.func @should_not_fuse_would_create_cycle() {266  %a = memref.alloc() : memref<10xf32>267  %b = memref.alloc() : memref<10xf32>268  %c = memref.alloc() : memref<10xf32>269 270  %cf7 = arith.constant 7.0 : f32271 272  // Set up the following dependences:273  // 1) loop0 -> loop1 on memref '%{{.*}}'274  // 2) loop0 -> loop2 on memref '%{{.*}}'275  // 3) loop1 -> loop2 on memref '%{{.*}}'276  affine.for %i0 = 0 to 10 {277    %v0 = affine.load %a[%i0] : memref<10xf32>278    affine.store %cf7, %b[%i0] : memref<10xf32>279  }280  affine.for %i1 = 0 to 10 {281    affine.store %cf7, %a[%i1] : memref<10xf32>282    %v1 = affine.load %c[%i1] : memref<10xf32>283  }284  affine.for %i2 = 0 to 10 {285    %v2 = affine.load %b[%i2] : memref<10xf32>286    affine.store %cf7, %c[%i2] : memref<10xf32>287  }288  // Should not fuse: fusing loop first loop into last would create a cycle.289  // CHECK:      affine.for %{{.*}} = 0 to 10 {290  // CHECK-NEXT:   affine.load %{{.*}}[%{{.*}}] : memref<10xf32>291  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>292  // CHECK-NEXT: }293  // CHECK:      affine.for %{{.*}} = 0 to 10 {294  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>295  // CHECK-NEXT:   affine.load %{{.*}}[%{{.*}}] : memref<10xf32>296  // CHECK-NEXT: }297  // CHECK:      affine.for %{{.*}} = 0 to 10 {298  // CHECK-NEXT:   affine.load %{{.*}}[%{{.*}}] : memref<10xf32>299  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>300  // CHECK-NEXT: }301  // CHECK-NEXT: return302  return303}304 305// -----306 307// CHECK-LABEL: func @should_fuse_producer_consumer() {308func.func @should_fuse_producer_consumer() {309  %m = memref.alloc() : memref<10xf32>310  %cf7 = arith.constant 7.0 : f32311 312  affine.for %i0 = 0 to 10 {313    affine.store %cf7, %m[%i0] : memref<10xf32>314  }315  affine.for %i1 = 0 to 10 {316    affine.store %cf7, %m[%i1] : memref<10xf32>317  }318  affine.for %i2 = 0 to 10 {319    %v1 = affine.load %m[%i2] : memref<10xf32>320  }321  // Fusing loop %i0 to %i2 would violate the WAW dependence between %i0 and322  // %i1, but OK to fuse %i1 into %i2.323  // TODO: When the fusion pass is run to a fixed-point, it should324  // fuse all three of these loop nests.325  // CHECK:      memref.alloc() : memref<1xf32>326  // CHECK:      affine.for %{{.*}} = 0 to 10 {327  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>328  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>329  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>330  // CHECK-NEXT: }331  // CHECK-NEXT: return332  return333}334 335// -----336 337// CHECK-LABEL: func @should_fuse_and_move_to_preserve_war_dep() {338func.func @should_fuse_and_move_to_preserve_war_dep() {339  %a = memref.alloc() : memref<10xf32>340  %b = memref.alloc() : memref<10xf32>341  %cf7 = arith.constant 7.0 : f32342 343  affine.for %i0 = 0 to 10 {344    %v0 = affine.load %a[%i0] : memref<10xf32>345    affine.store %v0, %b[%i0] : memref<10xf32>346  }347  affine.for %i1 = 0 to 10 {348    affine.store %cf7, %a[%i1] : memref<10xf32>349  }350  affine.for %i2 = 0 to 10 {351    %v1 = affine.load %b[%i2] : memref<10xf32>352  }353  // Loops '%i1' and '%i2' have no dependences. We can fuse a slice of '%i0'354  // into '%i2' if we move the fused loop nest before '%i1', which preserves355  // the WAR dependence from load '%a' in '%i0' to the store '%a' in loop '%i1'.356  // CHECK:       affine.for %{{.*}} = 0 to 10 {357  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>358  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>359  // CHECK-NEXT:    affine.load %{{.*}}[0] : memref<1xf32>360  // CHECK-NEXT:  }361  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 10 {362  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>363  // CHECK-NEXT:  }364  // CHECK-NEXT:  return365  return366}367 368// -----369 370// CHECK-LABEL: func @should_fuse_if_top_level_access() {371func.func @should_fuse_if_top_level_access() {372  %m = memref.alloc() : memref<10xf32>373  %cf7 = arith.constant 7.0 : f32374 375  affine.for %i0 = 0 to 10 {376    affine.store %cf7, %m[%i0] : memref<10xf32>377  }378  affine.for %i1 = 0 to 10 {379    %v0 = affine.load %m[%i1] : memref<10xf32>380  }381 382  %c0 = arith.constant 4 : index383  %v1 = affine.load %m[%c0] : memref<10xf32>384  // Top-level load to '%m' should prevent creating a private memref but385  // loop nests should be fused and '%i0' should be removed.386  // CHECK:      %[[m:.*]] = memref.alloc() : memref<10xf32>387  // CHECK-NOT:  memref.alloc388 389  // CHECK:      affine.for %[[i1:.*]] = 0 to 10 {390  // CHECK-NEXT:   affine.store %{{.*}}, %[[m]][%[[i1]]] : memref<10xf32>391  // CHECK-NEXT:   affine.load %[[m]][%[[i1]]] : memref<10xf32>392  // CHECK-NEXT: }393  // CHECK:      affine.load %[[m]][%{{.*}}] : memref<10xf32>394  return395}396 397// -----398 399// CHECK-LABEL: func @should_fuse_but_not_remove_src() {400func.func @should_fuse_but_not_remove_src() {401  %m = memref.alloc() : memref<100xf32>402  %cf7 = arith.constant 7.0 : f32403 404  affine.for %i0 = 0 to 100 {405    affine.store %cf7, %m[%i0] : memref<100xf32>406  }407  affine.for %i1 = 0 to 17 {408    %v0 = affine.load %m[%i1] : memref<100xf32>409  }410  %v1 = affine.load %m[99] : memref<100xf32>411 412  // Loop '%i0' and '%i1' should be fused but '%i0' shouldn't be removed to413  // preserve the dependence with the top-level access.414  // CHECK:      affine.for %{{.*}} = 0 to 100 {415  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<100xf32>416  // CHECK-NEXT: }417  // CHECK-NEXT: affine.for %{{.*}} = 0 to 17 {418  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>419  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>420  // CHECK-NEXT: }421  // CHECK-NEXT: affine.load %{{.*}}[99] : memref<100xf32>422  // CHECK-NEXT: return423  return424}425 426// -----427 428// CHECK-LABEL: func @should_fuse_no_top_level_access() {429func.func @should_fuse_no_top_level_access() {430  %m = memref.alloc() : memref<10xf32>431  %cf7 = arith.constant 7.0 : f32432 433  affine.for %i0 = 0 to 10 {434    affine.store %cf7, %m[%i0] : memref<10xf32>435  }436  affine.for %i1 = 0 to 10 {437    %v0 = affine.load %m[%i1] : memref<10xf32>438  }439  // CHECK:      affine.for %{{.*}} = 0 to 10 {440  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>441  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>442  // CHECK-NEXT: }443  // CHECK-NEXT: return444  return445}446 447// -----448 449#set0 = affine_set<(d0) : (1 == 0)>450 451// CHECK-LABEL: func @should_fuse_despite_affine_if() {452func.func @should_fuse_despite_affine_if() {453  %m = memref.alloc() : memref<10xf32>454  %cf7 = arith.constant 7.0 : f32455 456  affine.for %i0 = 0 to 10 {457    affine.store %cf7, %m[%i0] : memref<10xf32>458  }459  affine.for %i1 = 0 to 10 {460    %v0 = affine.load %m[%i1] : memref<10xf32>461  }462  %c0 = arith.constant 4 : index463  affine.if #set0(%c0) {464  }465  // An unrelated affine.if op doesn't prevent fusion.466  // CHECK:      affine.for %{{.*}} = 0 to 10 {467  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>468  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>469  // CHECK-NEXT: }470  return471}472 473// -----474 475#set0 = affine_set<(d0) : (1 == 0)>476 477// CHECK-LABEL: func @should_not_fuse_if_op_in_loop_nest() {478func.func @should_not_fuse_if_op_in_loop_nest() {479  %m = memref.alloc() : memref<10xf32>480  %cf7 = arith.constant 7.0 : f32481  %c4 = arith.constant 4 : index482 483  affine.for %i0 = 0 to 10 {484    affine.store %cf7, %m[%i0] : memref<10xf32>485  }486  affine.for %i1 = 0 to 10 {487    affine.if #set0(%c4) {488    }489    %v0 = affine.load %m[%i1] : memref<10xf32>490  }491 492  // IfOp in ForOp should prevent fusion.493  // CHECK:      affine.for %{{.*}} = 0 to 10 {494  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>495  // CHECK-NEXT: }496  // CHECK:      affine.for %{{.*}} = 0 to 10 {497  // CHECK-NEXT:   affine.if #set(%{{.*}}) {498  // CHECK-NEXT:   }499  // CHECK-NEXT:   affine.load %{{.*}}[%{{.*}}] : memref<10xf32>500  // CHECK-NEXT: }501  return502}503 504// -----505 506#set = affine_set<(d0) : (d0 - 1 >= 0)>507 508// CHECK-LABEL: func @should_fuse_if_op_in_loop_nest_not_sandwiched() -> memref<10xf32> {509func.func @should_fuse_if_op_in_loop_nest_not_sandwiched() -> memref<10xf32> {510  %a = memref.alloc() : memref<10xf32>511  %b = memref.alloc() : memref<10xf32>512  %cf7 = arith.constant 7.0 : f32513 514  affine.for %i0 = 0 to 10 {515    affine.store %cf7, %a[%i0] : memref<10xf32>516  }517  affine.for %i1 = 0 to 10 {518    %v0 = affine.load %a[%i1] : memref<10xf32>519    affine.store %v0, %b[%i1] : memref<10xf32>520  }521  affine.for %i2 = 0 to 10 {522    affine.if #set(%i2) {523      %v0 = affine.load %b[%i2] : memref<10xf32>524    }525  }526 527  // IfOp in ForOp should not prevent fusion if it does not in between the528  // source and dest ForOp ops.529 530  // CHECK:      affine.for531  // CHECK-NEXT:   affine.store532  // CHECK-NEXT:   affine.load533  // CHECK-NEXT:   affine.store534  // CHECK:      affine.for535  // CHECK-NEXT:   affine.if536  // CHECK-NEXT:     affine.load537  // CHECK-NOT:  affine.for538  // CHECK:      return539 540  return %a : memref<10xf32>541}542 543// -----544 545#set = affine_set<(d0) : (d0 - 1 >= 0)>546 547// CHECK-LABEL: func @should_not_fuse_if_op_in_loop_nest_between_src_and_dest() -> memref<10xf32> {548func.func @should_not_fuse_if_op_in_loop_nest_between_src_and_dest() -> memref<10xf32> {549  %a = memref.alloc() : memref<10xf32>550  %b = memref.alloc() : memref<10xf32>551  %cf7 = arith.constant 7.0 : f32552 553  affine.for %i0 = 0 to 10 {554    affine.store %cf7, %a[%i0] : memref<10xf32>555  }556  affine.for %i1 = 0 to 10 {557    affine.if #set(%i1) {558      affine.store %cf7, %a[%i1] : memref<10xf32>559    }560  }561  affine.for %i3 = 0 to 10 {562    %v0 = affine.load %a[%i3] : memref<10xf32>563    affine.store %v0, %b[%i3] : memref<10xf32>564  }565  return %b : memref<10xf32>566 567  // IfOp in ForOp which modifies the memref should prevent fusion if it is in568  // between the source and dest ForOp.569 570  // CHECK:      affine.for571  // CHECK-NEXT:   affine.store572  // CHECK:      affine.for573  // CHECK-NEXT:   affine.if574  // CHECK-NEXT:     affine.store575  // CHECK:      affine.for576  // CHECK-NEXT:   affine.load577  // CHECK-NEXT:   affine.store578  // CHECK:      return579}580 581// -----582 583// CHECK-LABEL: func @permute_and_fuse() {584func.func @permute_and_fuse() {585  %m = memref.alloc() : memref<10x20x30xf32>586 587  %cf7 = arith.constant 7.0 : f32588  affine.for %i0 = 0 to 10 {589    affine.for %i1 = 0 to 20 {590      affine.for %i2 = 0 to 30 {591        affine.store %cf7, %m[%i0, %i1, %i2] : memref<10x20x30xf32>592      }593    }594  }595  affine.for %i3 = 0 to 30 {596    affine.for %i4 = 0 to 10 {597      affine.for %i5 = 0 to 20 {598        %v0 = affine.load %m[%i4, %i5, %i3] : memref<10x20x30xf32>599        "foo"(%v0) : (f32) -> ()600      }601    }602  }603// CHECK:       affine.for %{{.*}} = 0 to 30 {604// CHECK-NEXT:    affine.for %{{.*}} = 0 to 10 {605// CHECK-NEXT:      affine.for %{{.*}} = 0 to 20 {606// CHECK-NEXT:        affine.store %{{.*}}, %{{.*}}[0, 0, 0] : memref<1x1x1xf32>607// CHECK-NEXT:        affine.load %{{.*}}[0, 0, 0] : memref<1x1x1xf32>608// CHECK-NEXT:        "foo"(%{{.*}}) : (f32) -> ()609// CHECK-NEXT:      }610// CHECK-NEXT:    }611// CHECK-NEXT:  }612// CHECK-NEXT:  return613 614  return615}616 617// -----618 619// CHECK-DAG: [[$MAP0:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> (d0 * 4 + d1)>620// CHECK-DAG: [[$MAP1:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> (d0 floordiv 4)>621// CHECK-DAG: [[$MAP2:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> (d0 mod 4)>622 623// Reshape from a 64 x f32 to 16 x 4 x f32.624// CHECK-LABEL: func @fuse_reshape_64_16_4625func.func @fuse_reshape_64_16_4(%in : memref<64xf32>) {626  %out = memref.alloc() : memref<16x4xf32>627 628  affine.for %i0 = 0 to 64 {629    %v = affine.load %in[%i0] : memref<64xf32>630    affine.store %v, %out[%i0 floordiv 4, %i0 mod 4] : memref<16x4xf32>631  }632 633  affine.for %i1 = 0 to 16 {634    affine.for %i2 = 0 to 4 {635      %w = affine.load %out[%i1, %i2] : memref<16x4xf32>636      "foo"(%w) : (f32) -> ()637    }638  }639  return640  // CHECK:      affine.for %{{.*}} =641  // CHECK-NEXT:   affine.for %{{.*}} =642  // CHECK-NOT:    for643  // CHECK:        }644  // CHECK-NEXT: }645  // CHECK-NEXT: return646}647 648// -----649// CHECK-DAG: [[$MAP0:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> (d0 floordiv 4)>650// CHECK-DAG: [[$MAP1:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> (d0 mod 4)>651// CHECK-DAG: [[$MAP2:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> (d0 * 4 + d1)>652 653// Reshape a 16x4xf32 to 64xf32.654// CHECK-LABEL: func @fuse_reshape_16_4_64655func.func @fuse_reshape_16_4_64() {656  %in = memref.alloc() : memref<16x4xf32>657  %out = memref.alloc() : memref<64xf32>658 659  affine.for %i0 = 0 to 16 {660    affine.for %i1 = 0 to 4 {661      %v = affine.load %in[%i0, %i1] : memref<16x4xf32>662      affine.store %v, %out[4*%i0 + %i1] : memref<64xf32>663    }664  }665 666  affine.for %i2 = 0 to 64 {667    %w = affine.load %out[%i2] : memref<64xf32>668    "foo"(%w) : (f32) -> ()669  }670// CHECK:       affine.for %{{.*}} = 0 to 64 {671// CHECK-NEXT:    affine.apply [[$MAP0]](%{{.*}})672// CHECK-NEXT:    affine.apply [[$MAP1]](%{{.*}})673// CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<16x4xf32>674// CHECK-NEXT:    affine.apply [[$MAP2]](%{{.*}}, %{{.*}})675// CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>676// CHECK-NEXT:    affine.load %{{.*}}[0] : memref<1xf32>677// CHECK-NEXT:    "foo"(%{{.*}}) : (f32) -> ()678// CHECK-NEXT:  }679// CHECK-NEXT:  return680  return681}682 683 684// -----685 686// All three loop nests below (6-d one, 2-d one, 2-d one is fused into a single687// 2-d loop nest).688func.func @R6_to_R2_reshape_square() -> memref<64x9xi32> {689  %in = memref.alloc() : memref<2x2x3x3x16x1xi32>690  %out = memref.alloc() : memref<64x9xi32>691  %live_out = memref.alloc() : memref<64x9xi32>692 693  // Initialize input.694  affine.for %i0 = 0 to 2 {695    affine.for %i1 = 0 to 2 {696      affine.for %i2 = 0 to 3 {697        affine.for %i3 = 0 to 3 {698          affine.for %i4 = 0 to 16 {699            affine.for %i5 = 0 to 1 {700              %val = "foo"(%i0, %i1, %i2, %i3, %i4, %i5) : (index, index, index, index, index, index) -> i32701              affine.store %val, %in[%i0, %i1, %i2, %i3, %i4, %i5] : memref<2x2x3x3x16x1xi32>702            }703          }704        }705      }706    }707  }708 709  affine.for %ii = 0 to 64 {710    affine.for %jj = 0 to 9 {711      // Convert output coordinates to linear index.712      %a0 = affine.apply affine_map<(d0, d1) -> (d0 * 9 + d1)> (%ii, %jj)713      %0 = affine.apply affine_map<(d0) -> (d0 floordiv (2 * 3 * 3 * 16 * 1))>(%a0)714      %1 = affine.apply affine_map<(d0) -> ((d0 mod 288) floordiv (3 * 3 * 16 * 1))>(%a0)715      %2 = affine.apply affine_map<(d0) -> (((d0 mod 288) mod 144) floordiv (3 * 16 * 1))>(%a0)716      %3 = affine.apply affine_map<(d0) -> ((((d0 mod 288) mod 144) mod 48) floordiv (16 * 1))>(%a0)717      %4 = affine.apply affine_map<(d0) -> ((((d0 mod 288) mod 144) mod 48) mod 16)>(%a0)718      %5 = affine.apply affine_map<(d0) -> (((((d0 mod 144) mod 144) mod 48) mod 16) mod 1)>(%a0)719      %v = affine.load %in[%0, %1, %2, %3, %4, %5] : memref<2x2x3x3x16x1xi32>720      affine.store %v, %out[%ii, %jj] : memref<64x9xi32>721    }722  }723 724  affine.for %i = 0 to 64 {725    affine.for %j = 0 to 9 {726      %a = affine.load %out[%i, %j] : memref<64x9xi32>727      %b = arith.muli %a, %a : i32728      affine.store %b, %live_out[%i, %j] : memref<64x9xi32>729    }730  }731  return %live_out : memref<64x9xi32>732}733// Everything above is fused to a single 2-d loop nest, and the 6-d tensor %in734// is eliminated if -memref-dataflow-opt is also supplied.735//736// CHECK-DAG: [[$MAP0:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> ((d0 * 9 + d1) floordiv 288)>737// CHECK-DAG: [[$MAP1:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> (((d0 * 9 + d1) mod 288) floordiv 144)>738// CHECK-DAG: [[$MAP2:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> (((d0 * 9 + d1) mod 144) floordiv 48)>739// CHECK-DAG: [[$MAP3:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> (((d0 * 9 + d1) mod 48) floordiv 16)>740// CHECK-DAG: [[$MAP4:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> ((d0 * 9 + d1) mod 16)>741// CHECK-DAG: [[$MAP11:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> (d0 * 9 + d1)>742// CHECK-DAG: [[$MAP12:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> (d0 floordiv 288)>743// CHECK-DAG: [[$MAP13:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> ((d0 mod 288) floordiv 144)>744// CHECK-DAG: [[$MAP14:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> ((d0 mod 144) floordiv 48)>745// CHECK-DAG: [[$MAP15:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> ((d0 mod 48) floordiv 16)>746// CHECK-DAG: [[$MAP16:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> (d0 mod 16)>747// CHECK-DAG: [[$MAP17:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> (0)>748 749//750// CHECK-LABEL: func @R6_to_R2_reshape751// CHECK:       memref.alloc() : memref<1x1x1x1x1x1xi32>752// CHECK:       memref.alloc() : memref<1x1xi32>753// CHECK:       memref.alloc() : memref<64x9xi32>754// CHECK-NEXT:  affine.for %{{.*}} = 0 to 64 {755// CHECK-NEXT:    affine.for %{{.*}} = 0 to 9 {756// CHECK-NEXT:      affine.apply [[$MAP0]](%{{.*}}, %{{.*}})757// CHECK-NEXT:      affine.apply [[$MAP1]](%{{.*}}, %{{.*}})758// CHECK-NEXT:      affine.apply [[$MAP2]](%{{.*}}, %{{.*}})759// CHECK-NEXT:      affine.apply [[$MAP3]](%{{.*}}, %{{.*}})760// CHECK-NEXT:      affine.apply [[$MAP4]](%{{.*}}, %{{.*}})761// CHECK-NEXT:      "foo"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (index, index, index, index, index, index) -> i32762// CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[0, 0, 0, 0, 0, 0] : memref<1x1x1x1x1x1xi32>763// CHECK-NEXT:      affine.apply [[$MAP11]](%{{.*}}, %{{.*}})764// CHECK-NEXT:      affine.apply [[$MAP12]](%{{.*}})765// CHECK-NEXT:      affine.apply [[$MAP13]](%{{.*}})766// CHECK-NEXT:      affine.apply [[$MAP14]](%{{.*}})767// CHECK-NEXT:      affine.apply [[$MAP15]](%{{.*}})768// CHECK-NEXT:      affine.apply [[$MAP16]](%{{.*}})769// CHECK-NEXT:      affine.apply [[$MAP17]](%{{.*}})770// CHECK-NEXT:      affine.load %{{.*}}[0, 0, 0, 0, 0, 0] : memref<1x1x1x1x1x1xi32>771// CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[0, 0] : memref<1x1xi32>772// CHECK-NEXT:      affine.load %{{.*}}[0, 0] : memref<1x1xi32>773// CHECK-NEXT:      arith.muli %{{.*}}, %{{.*}} : i32774// CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<64x9xi32>775// CHECK-NEXT:    }776// CHECK-NEXT:  }777// CHECK-NEXT:  return %{{.*}} : memref<64x9xi32>778 779// -----780 781// CHECK-LABEL: func @fuse_symbolic_bounds782func.func @fuse_symbolic_bounds(%M : index, %N : index) {783  %N_plus_5 = affine.apply affine_map<(d0) -> (d0 + 5)>(%N)784  %m = memref.alloc(%M, %N_plus_5) : memref<? x ? x f32>785 786  %c0 = arith.constant 0.0 : f32787  %s = arith.constant 5 : index788 789  affine.for %i0 = 0 to %M {790    affine.for %i1 = 0 to affine_map<(d0) -> (d0 + 5)> (%N) {791      affine.store %c0, %m[%i0, %i1] : memref<? x ? x f32>792    }793  }794 795  affine.for %i2 = 0 to %M {796    affine.for %i3 = 0 to %N {797      %v = affine.load %m[%i2, %i3 + symbol(%s)] : memref<? x ? x f32>798    }799  }800 801  return802}803 804// -----805 806// CHECK-LABEL: func @should_fuse_reduction_at_depth_of_one807func.func @should_fuse_reduction_at_depth_of_one() {808  %a = memref.alloc() : memref<10x100xf32>809  %b = memref.alloc() : memref<10xf32>810 811  affine.for %i0 = 0 to 10 {812    affine.for %i1 = 0 to 100 {813      %v0 = affine.load %b[%i0] : memref<10xf32>814      %v1 = affine.load %a[%i0, %i1] : memref<10x100xf32>815      %v2 = "maxf"(%v0, %v1) : (f32, f32) -> f32816      affine.store %v2, %b[%i0] : memref<10xf32>817    }818  }819  affine.for %i2 = 0 to 10 {820    affine.for %i3 = 0 to 100 {821      %v3 = affine.load %b[%i2] : memref<10xf32>822      %v4 = affine.load %a[%i2, %i3] : memref<10x100xf32>823      %v5 = arith.subf %v4, %v3 : f32824      affine.store %v5, %b[%i2] : memref<10xf32>825    }826  }827  // This test should fuse the src reduction loop at depth 1 in the destination828  // loop nest, which improves locality and enables subsequence passes to829  // decrease the reduction memref size and possibly place it in a faster830  // memory space.831  // CHECK:       affine.for %{{.*}} = 0 to 10 {832  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 100 {833  // CHECK-NEXT:      affine.load %{{.*}}[0] : memref<1xf32>834  // CHECK-NEXT:      affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<10x100xf32>835  // CHECK-NEXT:      "maxf"(%{{.*}}, %{{.*}}) : (f32, f32) -> f32836  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>837  // CHECK-NEXT:    }838  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 100 {839  // CHECK-NEXT:      affine.load %{{.*}}[0] : memref<1xf32>840  // CHECK-NEXT:      affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<10x100xf32>841  // CHECK-NEXT:      arith.subf %{{.*}}, %{{.*}} : f32842  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>843  // CHECK-NEXT:    }844  // CHECK-NEXT:  }845  // CHECK-NEXT:  return846  return847}848 849// -----850 851// CHECK-LABEL: func @should_fuse_at_src_depth1_and_dst_depth1852func.func @should_fuse_at_src_depth1_and_dst_depth1() {853  %a = memref.alloc() : memref<100x16xf32>854  %b = memref.alloc() : memref<100x16xf32>855 856  affine.for %i0 = 0 to 100 {857    affine.for %i1 = 0 to 16 {858      %v0 = affine.load %a[%i0, %i1] : memref<100x16xf32>859      "op0"(%v0) : (f32) -> ()860    }861    affine.for %i2 = 0 to 16 {862      %v1 = "op1"() : () -> (f32)863      affine.store %v1, %b[%i0, %i2] : memref<100x16xf32>864    }865  }866 867  affine.for %i3 = 0 to 100 {868    affine.for %i4 = 0 to 16 {869      %v2 = affine.load %b[%i3, %i4] : memref<100x16xf32>870      "op2"(%v2) : (f32) -> ()871    }872  }873  // We can slice iterations of the '%i0' and '%i1' loops in the source874  // loop nest, but slicing at depth 2 and inserting the slice in the875  // destination loop nest at depth2 causes extra computation. Instead,876  // the fusion algorithm should detect that the source loop should be sliced877  // at depth 1 and the slice should be inserted at depth 1.878  // CHECK:       affine.for %{{.*}} = 0 to 100 {879  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 16 {880  // CHECK-NEXT:      affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<100x16xf32>881  // CHECK-NEXT:      "op0"(%{{.*}}) : (f32) -> ()882  // CHECK-NEXT:    }883  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 16 {884  // CHECK-NEXT:      %{{.*}} = "op1"() : () -> f32885  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[0, %{{.*}}] : memref<1x16xf32>886  // CHECK-NEXT:    }887  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 16 {888  // CHECK-NEXT:      affine.load %{{.*}}[0, %{{.*}}] : memref<1x16xf32>889  // CHECK-NEXT:      "op2"(%{{.*}}) : (f32) -> ()890  // CHECK-NEXT:    }891  // CHECK-NEXT:  }892  // CHECK-NEXT:  return893  return894}895 896// -----897// CHECK: [[$MAP0:#map[0-9]*]] = affine_map<(d0, d1) -> (d0 * 10 + d1)>898 899// CHECK-LABEL: func @should_fuse_src_depth1_at_dst_depth2900func.func @should_fuse_src_depth1_at_dst_depth2() {901  %a = memref.alloc() : memref<100xf32>902  %c0 = arith.constant 0.0 : f32903 904  affine.for %i0 = 0 to 100 {905    affine.store %c0, %a[%i0] : memref<100xf32>906  }907 908  affine.for %i1 = 0 to 10 {909    affine.for %i2 = 0 to 10 {910      %a0 = affine.apply affine_map<(d0, d1) -> (d0 * 10 + d1)> (%i1, %i2)911      %v0 = affine.load %a[%a0] : memref<100xf32>912    }913  }914  // The source loop nest slice loop bound is a function of both destination915  // loop IVs, so we should slice at depth 1 and insert the slice at depth 2.916  // CHECK:       affine.for %{{.*}} = 0 to 10 {917  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 10 {918  // CHECK-NEXT:      affine.apply [[$MAP0]](%{{.*}}, %{{.*}})919  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>920  // CHECK-NEXT:      affine.apply [[$MAP0]](%{{.*}}, %{{.*}})921  // CHECK-NEXT:      affine.load %{{.*}}[0] : memref<1xf32>922  // CHECK-NEXT:    }923  // CHECK-NEXT:  }924  // CHECK-NEXT:  return925  return926}927 928// -----929 930// CHECK-LABEL: func @fusion_at_depth0_not_currently_supported931func.func @fusion_at_depth0_not_currently_supported() {932  %0 = memref.alloc() : memref<10xf32>933  %c0 = arith.constant 0 : index934  %cst = arith.constant 0.000000e+00 : f32935  affine.for %i0 = 0 to 10 {936    affine.store %cst, %0[%i0] : memref<10xf32>937  }938  affine.for %i1 = 0 to 10 {939    %1 = affine.load %0[%c0] : memref<10xf32>940  }941  // NOTE: Should shrink memref size to 1 element access by load in dst loop942  // nest, and make the store in the slice store to the same element.943  // CHECK-DAG:   memref.alloc() : memref<1xf32>944  // CHECK:       affine.for %{{.*}} = 0 to 10 {945  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>946  // CHECK-NEXT:    affine.load %{{.*}}[0] : memref<1xf32>947  // CHECK-NEXT:  }948  // CHECK-NEXT:  return949  return950}951 952// -----953 954// CHECK-LABEL: func @should_fuse_deep_loop_nests955func.func @should_fuse_deep_loop_nests() {956  %0 = memref.alloc() : memref<2x2x3x3x16x10xf32, 2>957  %1 = memref.alloc() : memref<2x2x3x3x16x10xf32, 2>958  %2 = memref.alloc() : memref<3x3x3x3x16x10xf32, 2>959  %c0 = arith.constant 0 : index960  %c1 = arith.constant 1 : index961  %c1_0 = arith.constant 1 : index962  %cst = arith.constant 0.000000e+00 : f32963  affine.for %i0 = 0 to 2 {964    affine.for %i1 = 0 to 2 {965      affine.for %i2 = 0 to 3 {966        affine.for %i3 = 0 to 3 {967          affine.for %i4 = 0 to 16 {968            affine.for %i5 = 0 to 10 {969              %3 = affine.load %0[%i0, %i1, %i2, %i3, %i4, %i5]970                : memref<2x2x3x3x16x10xf32, 2>971            }972          }973          affine.for %i6 = 0 to 16 {974            affine.for %i7 = 0 to 10 {975              affine.store %cst, %1[%i0, %i1, %i2, %i3, %i6, %i7]976                : memref<2x2x3x3x16x10xf32, 2>977            }978          }979        }980      }981    }982  }983  affine.for %i8 = 0 to 3 {984    affine.for %i9 = 0 to 3 {985      affine.for %i10 = 0 to 2 {986        affine.for %i11 = 0 to 2 {987          affine.for %i12 = 0 to 3 {988            affine.for %i13 = 0 to 3 {989              affine.for %i14 = 0 to 2 {990                affine.for %i15 = 0 to 2 {991                  affine.for %i16 = 0 to 16 {992                    affine.for %i17 = 0 to 10 {993                      %5 = affine.load %0[%i14, %i15, %i12, %i13, %i16, %i17]994                        : memref<2x2x3x3x16x10xf32, 2>995                    }996                  }997                  affine.for %i18 = 0 to 16 {998                    affine.for %i19 = 0 to 10 {999                      %6 = affine.load %1[%i10, %i11, %i8, %i9, %i18, %i19]1000                        : memref<2x2x3x3x16x10xf32, 2>1001                    }1002                  }1003                }1004              }1005            }1006          }1007        }1008      }1009    }1010  }1011// The first four loops of the source loop nest can be sliced with iteration1012// bounds which are a function of the first four loops of destination loop nest,1013// where the destination loops nests have been interchanged.1014 1015// CHECK-DAG:   memref.alloc() : memref<1x1x1x1x16x10xf32, 2>1016// CHECK:       affine.for %{{.*}} = 0 to 3 {1017// CHECK-NEXT:    affine.for %{{.*}} = 0 to 3 {1018// CHECK-NEXT:      affine.for %{{.*}} = 0 to 2 {1019// CHECK-NEXT:        affine.for %{{.*}} = 0 to 2 {1020// CHECK-NEXT:          affine.for %{{.*}} = 0 to 3 {1021// CHECK-NEXT:            affine.for %{{.*}} = 0 to 3 {1022// CHECK-NEXT:              affine.for %{{.*}} = 0 to 16 {1023// CHECK-NEXT:                affine.for %{{.*}} = 0 to 10 {1024// CHECK-NEXT:                  affine.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : memref<2x2x3x3x16x10xf32, 2>1025// CHECK-NEXT:                }1026// CHECK-NEXT:              }1027// CHECK-NEXT:              affine.for %{{.*}} = 0 to 16 {1028// CHECK-NEXT:                affine.for %{{.*}} = 0 to 10 {1029// CHECK-NEXT:                  affine.store %{{.*}}, %{{.*}}[0, 0, 0, 0, %{{.*}}, %{{.*}}] : memref<1x1x1x1x16x10xf32, 2>1030// CHECK-NEXT:                }1031// CHECK-NEXT:              }1032// CHECK-NEXT:              affine.for %{{.*}} = 0 to 2 {1033// CHECK-NEXT:                affine.for %{{.*}} = 0 to 2 {1034// CHECK-NEXT:                  affine.for %{{.*}} = 0 to 16 {1035// CHECK-NEXT:                    affine.for %{{.*}} = 0 to 10 {1036// CHECK-NEXT:                      affine.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : memref<2x2x3x3x16x10xf32, 2>1037// CHECK-NEXT:                    }1038// CHECK-NEXT:                  }1039// CHECK-NEXT:                  affine.for %{{.*}} = 0 to 16 {1040// CHECK-NEXT:                    affine.for %{{.*}} = 0 to 10 {1041// CHECK-NEXT:                      affine.load %{{.*}}[0, 0, 0, 0, %{{.*}}, %{{.*}}] : memref<1x1x1x1x16x10xf32, 2>1042// CHECK-NEXT:                    }1043// CHECK-NEXT:                  }1044// CHECK-NEXT:                }1045// CHECK-NEXT:              }1046// CHECK-NEXT:            }1047// CHECK-NEXT:          }1048// CHECK-NEXT:        }1049// CHECK-NEXT:      }1050// CHECK-NEXT:    }1051// CHECK-NEXT:  }1052// CHECK-NEXT:  return1053  return1054}1055 1056// -----1057 1058// CHECK-LABEL: func @should_fuse_at_depth1_and_reduce_slice_trip_count1059func.func @should_fuse_at_depth1_and_reduce_slice_trip_count() {1060  %a = memref.alloc() : memref<4x256xf32>1061  %b = memref.alloc() : memref<4x256xf32>1062 1063  %c0 = arith.constant 0 : index1064  %cf0 = arith.constant 0.0 : f321065 1066  affine.for %i0 = 0 to 4 {1067    affine.for %i1 = 0 to 256 {1068      %v0 = affine.load %b[%i0, %i1] : memref<4x256xf32>1069    }1070    affine.for %i2 = 0 to 256 {1071      affine.store %cf0, %a[%i0, %i2] : memref<4x256xf32>1072    }1073  }1074 1075  affine.for %d0 = 0 to 4 {1076    affine.for %d1 = 0 to 16 {1077      %v1 = affine.load %a[%d0, %d1] : memref<4x256xf32>1078    }1079  }1080  // The cost of fusing at depth 2 is greater than the cost of fusing at depth 11081  // for two reasons:1082  // 1) Inserting the unsliceable src loop %i1 to a higher depth removes1083  //    redundant computation and reduces costs.1084  // 2) Inserting the sliceable src loop %i2 at depth 1, we can still reduce1085  //    its trip count to 16 (from 256) reducing costs.1086  // NOTE: the size of the private memref created for the fused loop nest1087  // is reduced from the original shape from 4x256 to 4x16 because of the1088  // data accessed by the load.1089  // CHECK-DAG:   memref.alloc() : memref<1x16xf32>1090  // CHECK:       affine.for %{{.*}} = 0 to 4 {1091  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 256 {1092  // CHECK-NEXT:      affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<4x256xf32>1093  // CHECK-NEXT:    }1094  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 16 {1095  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[0, %{{.*}}] : memref<1x16xf32>1096  // CHECK-NEXT:    }1097  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 16 {1098  // CHECK-NEXT:      affine.load %{{.*}}[0, %{{.*}}] : memref<1x16xf32>1099  // CHECK-NEXT:    }1100  // CHECK-NEXT:  }1101  // CHECK-NEXT:  return1102  return1103}1104 1105// -----1106 1107// CHECK-LABEL: func @should_fuse_at_depth1_with_trip_count_201108func.func @should_fuse_at_depth1_with_trip_count_20() {1109  %a = memref.alloc() : memref<100xf32>1110  %c0 = arith.constant 0 : index1111  %cf0 = arith.constant 0.0 : f321112 1113  affine.for %i0 = 0 to 100 {1114    affine.store %cf0, %a[%i0]: memref<100xf32>1115  }1116 1117  affine.for %i1 = 0 to 5 {1118    affine.for %i2 = 0 to 10 {1119      %v0 = affine.load %a[%i2]: memref<100xf32>1120    }1121    affine.for %i3 = 0 to 10 {1122      affine.for %i4 = 0 to 20 {1123        %v1 = affine.load %a[%i4]: memref<100xf32>1124      }1125    }1126  }1127  // NOTE: The size of the private memref created for fusion is shrunk to 20xf321128  // CHECK-DAG:   memref.alloc() : memref<20xf32>1129  // CHECK:       affine.for %{{.*}} = 0 to 5 {1130  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 20 {1131  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<20xf32>1132  // CHECK-NEXT:    }1133  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 10 {1134  // CHECK-NEXT:      affine.load %{{.*}}[%{{.*}}] : memref<20xf32>1135  // CHECK-NEXT:    }1136  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 10 {1137  // CHECK-NEXT:      affine.for %{{.*}} = 0 to 20 {1138  // CHECK-NEXT:        affine.load %{{.*}}[%{{.*}}] : memref<20xf32>1139  // CHECK-NEXT:      }1140  // CHECK-NEXT:    }1141  // CHECK-NEXT:  }1142  // CHECK-NEXT:  return1143  return1144}1145 1146// -----1147 1148// CHECK-LABEL: func @should_fuse_at_depth1_with_trip_count_191149func.func @should_fuse_at_depth1_with_trip_count_19() {1150  %a = memref.alloc() : memref<100xf32>1151  %c0 = arith.constant 0 : index1152  %cf0 = arith.constant 0.0 : f321153 1154  affine.for %i0 = 0 to 100 {1155    affine.store %cf0, %a[%i0]: memref<100xf32>1156  }1157 1158  affine.for %i1 = 0 to 5 {1159    affine.for %i2 = 0 to 19 {1160      %v0 = affine.load %a[%i2]: memref<100xf32>1161    }1162    affine.for %i3 = 0 to 10 {1163      affine.for %i4 = 0 to 10 {1164        %v1 = affine.load %a[%i4]: memref<100xf32>1165      }1166    }1167  }1168  // NOTE: The size of the private memref created for fusion is shrunk to 19xf321169  // CHECK-DAG:   memref.alloc() : memref<19xf32>1170  // CHECK:       affine.for %{{.*}} = 0 to 5 {1171  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 19 {1172  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<19xf32>1173  // CHECK-NEXT:    }1174  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 19 {1175  // CHECK-NEXT:      affine.load %{{.*}}[%{{.*}}] : memref<19xf32>1176  // CHECK-NEXT:    }1177  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 10 {1178  // CHECK-NEXT:      affine.for %{{.*}} = 0 to 10 {1179  // CHECK-NEXT:        affine.load %{{.*}}[%{{.*}}] : memref<19xf32>1180  // CHECK-NEXT:      }1181  // CHECK-NEXT:    }1182  // CHECK-NEXT:  }1183  // CHECK-NEXT:  return1184  return1185}1186 1187 1188// -----1189 1190// CHECK-LABEL: func @should_fuse_with_private_memref() {1191func.func @should_fuse_with_private_memref() {1192  %m = memref.alloc() : memref<100xf32>1193  %cf7 = arith.constant 7.0 : f321194 1195  affine.for %i0 = 0 to 100 {1196    affine.store %cf7, %m[%i0] : memref<100xf32>1197  }1198  affine.for %i1 = 0 to 17 {1199    %v0 = affine.load %m[%i1] : memref<100xf32>1200  }1201  affine.for %i2 = 0 to 82 {1202    %v1 = affine.load %m[%i2] : memref<100xf32>1203  }1204  // Should create a new private memref.1205  // CHECK-DAG:  memref.alloc() : memref<1xf32>1206  // CHECK:      affine.for %{{.*}} = 0 to 17 {1207  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>1208  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>1209  // CHECK-NEXT: }1210  // CHECK:      affine.for %{{.*}} = 0 to 82 {1211  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>1212  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>1213  // CHECK-NEXT: }1214  // CHECK-NEXT: return1215  return1216}1217 1218// -----1219 1220// CHECK-LABEL: func @should_fuse_live_out_arg_but_preserve_src_loop(%{{.*}}: memref<10xf32>) {1221func.func @should_fuse_live_out_arg_but_preserve_src_loop(%arg0: memref<10xf32>) {1222  %cf7 = arith.constant 7.0 : f321223 1224  affine.for %i0 = 0 to 10 {1225    affine.store %cf7, %arg0[%i0] : memref<10xf32>1226  }1227  affine.for %i1 = 0 to 9 {1228    %v0 = affine.load %arg0[%i1] : memref<10xf32>1229  }1230  // This tests that the loop nest '%i0' should not be removed after fusion1231  // because it writes to memref argument '%arg0', and its read region1232  // does not cover its write region (so fusion would shrink the write region1233  // in the fused loop nest, so complete live out data region would not1234  // be written).1235  // CHECK:       affine.for %{{.*}} = 0 to 10 {1236  // CHECK-NEXT:    affine.store %{{.*}} : memref<10xf32>1237  // CHECK-NEXT:  }1238  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 9 {1239  // CHECK-NEXT:    affine.store %{{.*}} : memref<1xf32>1240  // CHECK-NEXT:    affine.load %{{.*}} : memref<1xf32>1241  // CHECK-NEXT:  }1242  // CHECK-NEXT:  return1243  return1244}1245 1246// -----1247 1248// CHECK-LABEL: func @should_fuse_live_out_arg(%{{.*}}: memref<10xf32>) {1249func.func @should_fuse_live_out_arg(%arg0: memref<10xf32>) {1250  %cf7 = arith.constant 7.0 : f321251 1252  affine.for %i0 = 0 to 10 {1253    affine.store %cf7, %arg0[%i0] : memref<10xf32>1254  }1255  affine.for %i1 = 0 to 10 {1256    %v0 = affine.load %arg0[%i1] : memref<10xf32>1257  }1258  // The read/write regions for memref '%{{.*}}' are the same for both1259  // loops, so they should fuse.1260 1261  // CHECK:       affine.for %{{.*}} = 0 to 10 {1262  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>1263  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>1264  // CHECK-NEXT:  }1265  // CHECK-NEXT:  return1266  return1267}1268 1269// -----1270 1271// CHECK-LABEL: func @should_fuse_escaping_memref_but_preserve_src_loop() -> memref<10xf32>1272func.func @should_fuse_escaping_memref_but_preserve_src_loop() -> memref<10xf32> {1273  %cf7 = arith.constant 7.0 : f321274  %m = memref.alloc() : memref<10xf32>1275  affine.for %i0 = 0 to 10 {1276    affine.store %cf7, %m[%i0] : memref<10xf32>1277  }1278  affine.for %i1 = 0 to 9 {1279    %v0 = affine.load %m[%i1] : memref<10xf32>1280  }1281  // This tests that the loop nest '%i0' should not be removed after fusion1282  // because it writes to memref '%m', which is returned by the function, and1283  // the '%i1' memory region does not cover '%i0' memory region.1284 1285  // CHECK-DAG:   memref.alloc() : memref<1xf32>1286  // CHECK:       affine.for %{{.*}} = 0 to 10 {1287  // CHECK-NEXT:    affine.store %{{.*}} : memref<10xf32>1288  // CHECK-NEXT:  }1289  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 9 {1290  // CHECK-NEXT:    affine.store %{{.*}} : memref<1xf32>1291  // CHECK-NEXT:    affine.load %{{.*}} : memref<1xf32>1292  // CHECK-NEXT:  }1293  // CHECK-NEXT:  return %{{.*}} : memref<10xf32>1294  return %m : memref<10xf32>1295}1296// -----1297 1298// This should fuse with the %in becoming a 1x1x1.1299func.func @R3_to_R2_reshape() {1300  %in = memref.alloc() : memref<2x3x16xi32>1301 1302  %c0 = arith.constant 0 : index1303 1304  affine.for %i0 = 0 to 2 {1305    affine.for %i1 = 0 to 3 {1306      affine.for %i2 = 0 to 16 {1307        %val = "foo"(%i0, %i1, %i2) : (index, index, index) -> i321308        affine.store %val, %in[%i0, %i1, %i2] : memref<2x3x16xi32>1309      }1310    }1311  }1312 1313  affine.for %ii = 0 to 32 {1314    affine.for %jj = 0 to 3 {1315      %a0 = affine.apply affine_map<(d0, d1) -> (d0 * 3 + d1)> (%ii, %jj)1316      %idx = affine.apply affine_map<(d0) -> (d0 floordiv (3 * 16))> (%a0)1317      %v = affine.load %in[%idx, %jj, %c0]1318        : memref<2x3x16xi32>1319    }1320  }1321  return1322}1323// CHECK-DAG: [[$MAP0:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> ((d0 * 3 + d1) floordiv 48)>1324// CHECK-DAG: [[$MAP1:#map[0-9a-zA-Z_]*]] = affine_map<(d0, d1) -> (d0 * 3 + d1)>1325// CHECK-DAG: [[$MAP2:#map[0-9a-zA-Z_]*]] = affine_map<(d0) -> (d0 floordiv 48)>1326 1327// CHECK-LABEL: func @R3_to_R2_reshape()1328// CHECK-DAG:    memref.alloc() : memref<1x1x1xi32>1329// CHECK:        affine.for %{{.*}} = 0 to 32 {1330// CHECK-NEXT:     affine.for %{{.*}} = 0 to 3 {1331// CHECK-NEXT:      affine.apply [[$MAP0]](%{{.*}}, %{{.*}})1332// CHECK-NEXT:      "foo"(%{{.*}}, %{{.*}}, %{{.*}}) : (index, index, index) -> i321333// CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[0, 0, 0] : memref<1x1x1xi32>1334// CHECK-NEXT:      affine.apply [[$MAP1]](%{{.*}}, %{{.*}})1335// CHECK-NEXT:      affine.apply [[$MAP2]](%{{.*}})1336// CHECK-NEXT:      affine.load %{{.*}}[0, 0, 0] : memref<1x1x1xi32>1337// CHECK-NEXT:    }1338// CHECK-NEXT:  }1339// CHECK-NEXT:  return1340 1341// -----1342 1343func.func @should_fuse_multi_output_producer() {1344  %a = memref.alloc() : memref<10xf32>1345  %b = memref.alloc() : memref<10xf32>1346 1347  %cf7 = arith.constant 7.0 : f321348 1349  affine.for %i0 = 0 to 10 {1350    affine.store %cf7, %a[%i0] : memref<10xf32>1351    affine.store %cf7, %b[%i0] : memref<10xf32>1352  }1353  affine.for %i1 = 0 to 10 {1354    %v0 = affine.load %a[%i1] : memref<10xf32>1355    %v1 = affine.load %b[%i1] : memref<10xf32>1356  }1357 1358  // CHECK:       affine.for %{{.*}} = 0 to 10 {1359  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>1360  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>1361  // CHECK-NEXT:    affine.load %{{.*}}[0] : memref<1xf32>1362  // CHECK-NEXT:    affine.load %{{.*}}[0] : memref<1xf32>1363  // CHECK-NEXT:  }1364  // CHECK-NEXT:  return1365  return1366}1367 1368// -----1369 1370// CHECK-LABEL: func @fusion_preventing_deps_on_middle_loop() {1371func.func @fusion_preventing_deps_on_middle_loop() {1372  %a = memref.alloc() : memref<10xf32>1373  %b = memref.alloc() : memref<10xf32>1374  %c = memref.alloc() : memref<10xf32>1375 1376  %cf7 = arith.constant 7.0 : f321377 1378  affine.for %i0 = 0 to 10 {1379    %v0 = affine.load %a[%i0] : memref<10xf32>1380    affine.store %v0, %b[%i0] : memref<10xf32>1381  }1382  affine.for %i1 = 0 to 10 {1383    affine.store %cf7, %a[%i1] : memref<10xf32>1384    %v1 = affine.load %c[%i1] : memref<10xf32>1385  }1386  affine.for %i2 = 0 to 10 {1387    %v2 = affine.load %b[%i2] : memref<10xf32>1388    affine.store %v2, %c[%i2] : memref<10xf32>1389  }1390  // Loops '%i0' and '%i2' cannot fuse along producer/consumer edge on memref1391  // '%b', because of the WAR dep from '%i0' to '%i1' on memref '%a' and1392  // because of the WAR dep from '%i1' to '%i2' on memref '%c'.1393  // CHECK:       affine.for %{{.*}} = 0 to 10 {1394  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>1395  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>1396  // CHECK-NEXT:  }1397  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 10 {1398  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>1399  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>1400  // CHECK-NEXT:  }1401  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 10 {1402  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>1403  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>1404  // CHECK-NEXT:  }1405  // CHECK-NEXT:  return1406  return1407}1408 1409// -----1410 1411// CHECK-LABEL: func @should_fuse_and_move_to_preserve_war_dep() {1412func.func @should_fuse_and_move_to_preserve_war_dep() {1413  %a = memref.alloc() : memref<10xf32>1414  %b = memref.alloc() : memref<10xf32>1415  %c = memref.alloc() : memref<10xf32>1416 1417  %cf7 = arith.constant 7.0 : f321418 1419  affine.for %i0 = 0 to 10 {1420    %v0 = affine.load %b[%i0] : memref<10xf32>1421    affine.store %v0, %a[%i0] : memref<10xf32>1422  }1423  affine.for %i1 = 0 to 3 {1424    %v2 = affine.load %c[%i1] : memref<10xf32>1425  }1426  affine.for %i2 = 0 to 5 {1427    affine.store %cf7, %b[%i2] : memref<10xf32>1428  }1429  affine.for %i3 = 0 to 10 {1430    %v1 = affine.load %a[%i3] : memref<10xf32>1431    affine.store %cf7, %c[%i3] : memref<10xf32>1432  }1433 1434  // Dependence graph:1435  //1436  //         %i0 ---------1437  //               |     |1438  //     --- %i1   | %b  | %a1439  //     |         |     |1440  //  %c |   %i2 <--     |1441  //     |               |1442  //     --> %i3 <--------1443  //1444  // It is possible to fuse loop '%i0' into '%i3' and preserve dependences1445  // if the fused loop nest is inserted between loops '%i1' and '%i2'.1446 1447  // CHECK-DAG:   memref.alloc() : memref<1xf32>1448  // CHECK:       affine.for %{{.*}} = 0 to 3 {1449  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>1450  // CHECK-NEXT:  }1451  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 10 {1452  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>1453  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>1454  // CHECK-NEXT:    affine.load %{{.*}}[0] : memref<1xf32>1455  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>1456  // CHECK-NEXT:  }1457  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 5 {1458  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>1459  // CHECK-NEXT:  }1460  // CHECK-NEXT:  return1461  return1462}1463 1464// -----1465 1466// CHECK-LABEL: func @fusion_preventing_dep_on_constant() {1467func.func @fusion_preventing_dep_on_constant() {1468  %a = memref.alloc() : memref<10xf32>1469  %b = memref.alloc() : memref<10xf32>1470  %c = memref.alloc() : memref<10xf32>1471 1472  %cf7 = arith.constant 7.0 : f321473 1474  affine.for %i0 = 0 to 10 {1475    %v0 = affine.load %b[%i0] : memref<10xf32>1476    affine.store %cf7, %a[%i0] : memref<10xf32>1477  }1478  affine.for %i1 = 0 to 10 {1479    affine.store %cf7, %b[%i1] : memref<10xf32>1480  }1481  %cf11 = arith.constant 11.0 : f321482  affine.for %i2 = 0 to 10 {1483    %v2 = affine.load %a[%i2] : memref<10xf32>1484    affine.store %cf11, %c[%i2] : memref<10xf32>1485  }1486  // Loops '%i0' and '%i2' cannot fuse along producer/consumer edge on memref1487  // '%a', because of the WAR dep from '%i0' to '%i1' on memref '%b' and1488  // because of the SSA value dep from '%cf11' def to use in '%i2'.1489  // CHECK:       affine.for %{{.*}} = 0 to 10 {1490  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>1491  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>1492  // CHECK-NEXT:  }1493  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 10 {1494  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>1495  // CHECK-NEXT:  }1496  // CHECK-NEXT:  %{{.*}} = arith.constant 1.100000e+01 : f321497  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 10 {1498  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>1499  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>1500  // CHECK-NEXT:  }1501  // CHECK-NEXT:  return1502  return1503}1504 1505// -----1506 1507// CHECK-LABEL: func @should_fuse_and_preserve_dep_on_constant() {1508func.func @should_fuse_and_preserve_dep_on_constant() {1509  %a = memref.alloc() : memref<10xf32>1510  %b = memref.alloc() : memref<10xf32>1511  %c = memref.alloc() : memref<10xf32>1512 1513  %cf7 = arith.constant 7.0 : f321514  %cf11 = arith.constant 11.0 : f321515  affine.for %i0 = 0 to 10 {1516    %v0 = affine.load %b[%i0] : memref<10xf32>1517    affine.store %cf7, %a[%i0] : memref<10xf32>1518  }1519  affine.for %i1 = 0 to 10 {1520    affine.store %cf7, %b[%i1] : memref<10xf32>1521  }1522  affine.for %i2 = 0 to 10 {1523    %v2 = affine.load %a[%i2] : memref<10xf32>1524    affine.store %cf11, %c[%i2] : memref<10xf32>1525  }1526 1527  // Loops '%i0' and '%i2' can fuse along producer/consumer edge on memref1528  // '%a', and preserve the WAR dep from '%i0' to '%i1' on memref '%b', and1529  // the SSA value dep from '%cf11' def to use in '%i2'.1530 1531  // CHECK:       arith.constant 1.100000e+01 : f321532  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 10 {1533  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>1534  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>1535  // CHECK-NEXT:    affine.load %{{.*}}[0] : memref<1xf32>1536  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>1537  // CHECK-NEXT:  }1538  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 10 {1539  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>1540  // CHECK-NEXT:  }1541  // CHECK-NEXT:  return1542  return1543}1544 1545// -----1546 1547// CHECK-LABEL: @producer_consumer_with_outmost_user1548func.func @producer_consumer_with_outmost_user(%arg0 : f16) {1549  %c0 = arith.constant 0 : index1550  %src = memref.alloc() : memref<f16, 1>1551  %dst = memref.alloc() : memref<f16>1552  %tag = memref.alloc() : memref<1xi32>1553  affine.for %arg1 = 4 to 6 {1554    affine.for %arg2 = 0 to 1 {1555      %0 = arith.addf %arg0, %arg0 : f161556      affine.store %0, %src[] : memref<f16, 1>1557    }1558    affine.for %arg3 = 0 to 1 {1559      %0 = affine.load %src[] : memref<f16, 1>1560    }1561  }1562  affine.dma_start %src[], %dst[], %tag[%c0], %c0 : memref<f16, 1>, memref<f16>, memref<1xi32>1563  // CHECK:       %[[CST_INDEX:.*]] = arith.constant 0 : index1564  // CHECK:       %[[DMA_SRC:.*]] = memref.alloc() : memref<f16, 1>1565  // CHECK:       %[[DMA_DST:.*]] = memref.alloc() : memref<f16>1566  // CHECK:       %[[DMA_TAG:.*]] = memref.alloc() : memref<1xi32>1567  // CHECK:       affine.for %arg1 = 4 to 61568  // CHECK-NEXT:  affine.for %arg2 = 0 to 11569  // CHECK-NEXT:  %[[RESULT_ADD:.*]] = arith.addf %arg0, %arg0 : f161570  // CHECK-NEXT:  affine.store %[[RESULT_ADD]], %[[DMA_SRC]][] : memref<f16, 1>1571  // CHECK-NEXT:  affine.load %[[DMA_SRC]][] : memref<f16, 1>1572  // CHECK:       affine.dma_start %[[DMA_SRC]][], %[[DMA_DST]][], %[[DMA_TAG]][%[[CST_INDEX]]], %[[CST_INDEX]] : memref<f16, 1>, memref<f16>, memref<1xi32>1573  // CHECK-NEXT:  return1574  return1575}1576 1577// Add further tests in mlir/test/Transforms/loop-fusion-4.mlir1578 1579