brintos

brintos / llvm-project-archived public Read only

0
0
Text · 35.5 KiB · b26a539 Raw
901 lines · plain
1// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline='builtin.module(func.func(affine-loop-fusion))' -split-input-file | FileCheck %s2// RUN: mlir-opt -allow-unregistered-dialect %s -pass-pipeline='builtin.module(func.func(affine-loop-fusion{maximal}))' -split-input-file | FileCheck %s --check-prefix=MAXIMAL3 4// Part I of fusion tests in  mlir/test/Transforms/loop-fusion.mlir.5// Part III of fusion tests in mlir/test/Transforms/loop-fusion-3.mlir6// Part IV of fusion tests in mlir/test/Transforms/loop-fusion-4.mlir7 8// -----9 10// CHECK-LABEL: func @should_fuse_at_depth_above_loop_carried_dependence(%{{.*}}: memref<64x4xf32>, %{{.*}}: memref<64x4xf32>) {11func.func @should_fuse_at_depth_above_loop_carried_dependence(%arg0: memref<64x4xf32>, %arg1: memref<64x4xf32>) {12  %out = memref.alloc() : memref<64x4xf32>13  %0 = arith.constant 0.0 : f3214  affine.for %i0 = 0 to 64 {15    affine.for %i1 = 0 to 4 {16      affine.store %0, %out[%i0, %i1] : memref<64x4xf32>17    }18  }19  affine.for %i2 = 0 to 4 {20    affine.for %i3 = 0 to 4 {21      affine.for %i4 = 0 to 16 {22        %v = affine.load %arg1[16 * %i3 - %i4 + 15, %i2] : memref<64x4xf32>23        "op0"(%v) : (f32) -> ()24      }25      affine.for %i5 = 0 to 4 {26        affine.for %i6 = 0 to 16 {27          %v = affine.load %arg0[16 * %i5 - %i6 + 15, %i3] : memref<64x4xf32>28          "op1"(%v) : (f32) -> ()29        }30        affine.for %i7 = 0 to 16 {31          %r = "op2"() : () -> (f32)32          %v = affine.load %out[16 * %i5 + %i7, %i2] : memref<64x4xf32>33          %s = arith.addf %v, %r : f3234          affine.store %s, %out[16 * %i5 + %i7, %i2] : memref<64x4xf32>35        }36      }37    }38  }39 40  // We can fuse source loop nest '%i0' into dst loop nest '%i2', but the41  // depth at which we can insert the src loop nest slice into the dst loop42  // nest must be decreased because of a loop carried dependence on loop '%i3'.43  // As a result, the source loop nest is inserted at dst loop nest depth 1,44  // just above the loop with the carried dependence. In addition, the source45  // loop nest iteration bounds on its loop '%i1' are reduced to 1, so the46  // memref size can be reduced to 64x1xf32.47 48  // In this case, since we have multiple producer stores (for %out) with49  // different access functions and we don't yet support private memref50  // computation in such cases, a 64x1 private memref isn't created.51 52  // CHECK:       memref.alloc() : memref<64x4xf32>53  // CHECK:       affine.for %{{.*}} = 0 to 4 {54  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 64 {55  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<64x4xf32>56  // CHECK-NEXT:    }57  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 4 {58  // CHECK-NEXT:      affine.for %{{.*}} = 0 to 16 {59  // CHECK-NEXT:        affine.load %{{.*}}[%{{.*}} * 16 - %{{.*}} + 15, %{{.*}}] : memref<64x4xf32>60  // CHECK-NEXT:        "op0"(%{{.*}}) : (f32) -> ()61  // CHECK-NEXT:      }62  // CHECK-NEXT:      affine.for %{{.*}} = 0 to 4 {63  // CHECK-NEXT:        affine.for %{{.*}} = 0 to 16 {64  // CHECK-NEXT:          affine.load %{{.*}}[%{{.*}} * 16 - %{{.*}} + 15, %{{.*}}] : memref<64x4xf32>65  // CHECK-NEXT:          "op1"(%{{.*}}) : (f32) -> ()66  // CHECK-NEXT:        }67  // CHECK-NEXT:        affine.for %{{.*}} = 0 to 16 {68  // CHECK-NEXT:          %{{.*}} = "op2"() : () -> f3269  // CHECK:               affine.load %{{.*}}[%{{.*}} * 16 + %{{.*}}, %{{.*}}] : memref<64x4xf32>70  // CHECK-NEXT:          arith.addf %{{.*}}, %{{.*}} : f3271  // CHECK:               affine.store %{{.*}}, %{{.*}}[%{{.*}} * 16 + %{{.*}}, %{{.*}}] : memref<64x4xf32>72  // CHECK-NEXT:        }73  // CHECK-NEXT:      }74  // CHECK-NEXT:    }75  // CHECK-NEXT:  }76  // CHECK-NEXT:  return77  return78}79 80// -----81 82// CHECK-LABEL: func @should_fuse_only_two_loops_and_remove_producer() {83func.func @should_fuse_only_two_loops_and_remove_producer() {84  %a = memref.alloc() : memref<10xf32>85  %b = memref.alloc() : memref<10xf32>86 87  %cf7 = arith.constant 7.0 : f3288 89  affine.for %i0 = 0 to 10 {90    affine.store %cf7, %a[%i0] : memref<10xf32>91  }92  affine.for %i1 = 0 to 10 {93    %v0 = affine.load %a[%i1] : memref<10xf32>94    affine.store %v0, %b[%i1] : memref<10xf32>95  }96  affine.for %i2 = 0 to 10 {97    %v1 = affine.load %a[%i2] : memref<10xf32>98    affine.store %v1, %b[%i2] : memref<10xf32>99  }100 101  // On the first visit to '%i2', the fusion algorithm can not fuse loop nest102  // '%i0' into '%i2' because of the dependences '%i0' and '%i2' each have on103  // '%i1'. Then, '%i0' is fused into '%i1' and no private memref is created for104  // memref '%a' to be able to remove '%i0' and still preserve the depencence on105  // '%a' with '%i2'.106  // TODO: Alternatively, we could fuse '%i0' into '%i1' with a private memref,107  // the dependence between '%i0' and '%i1' on memref '%a' would no longer exist,108  // and '%i0' could be fused into '%i2' as well. Note that this approach would109  // duplicate the computation in loop nest '%i0' to loop nests '%i1' and '%i2',110  // which would limit its profitability.111  // CHECK:       affine.for %{{.*}} = 0 to 10 {112  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>113  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>114  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>115  // CHECK-NEXT:  }116  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 10 {117  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>118  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>119  // CHECK-NEXT:  }120  // CHECK-NEXT:   return121  return122}123 124// -----125 126// CHECK-LABEL: func @should_fuse_after_one_loop_interchange() {127func.func @should_fuse_after_one_loop_interchange() {128  %a = memref.alloc() : memref<10xf32>129 130  %cf0 = arith.constant 0.0 : f32131  affine.for %i0 = 0 to 10 {132    affine.store %cf0, %a[%i0] : memref<10xf32>133  }134 135  affine.for %i1 = 0 to 5 {136    affine.for %i2 = 0 to 10 {137      %v0 = affine.load %a[%i2] : memref<10xf32>138      affine.store %v0, %a[%i2] : memref<10xf32>139    }140  }141 142  // The dependence between the load and affine.store is carried on loop '%i1', and143  // cannot be fused with loop '%i0' without violating this dependence.144  // Once loops '%i1' and %i2' are interchanged, loop '%i0' can be fused145  // at loop depth 1, because the loop carrying the dependence has been146  // interchanged and is now at depth 2.147 148  // CHECK:       affine.for %{{.*}} = 0 to 10 {149  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>150  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 5 {151  // CHECK-NEXT:      affine.load %{{.*}}[0] : memref<1xf32>152  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>153  // CHECK-NEXT:    }154  // CHECK-NEXT:  }155  // CHECK-NEXT:  return156  return157}158 159// -----160// CHECK-LABEL: func @should_fuse_after_two_loop_interchanges() {161func.func @should_fuse_after_two_loop_interchanges() {162  %a = memref.alloc() : memref<6x8xf32>163 164  %cf0 = arith.constant 0.0 : f32165  affine.for %i0 = 0 to 6 {166    affine.for %i1 = 0 to 8 {167      affine.store %cf0, %a[%i0, %i1] : memref<6x8xf32>168    }169  }170 171  affine.for %i2 = 0 to 4 {172    affine.for %i3 = 0 to 6 {173      affine.for %i4 = 0 to 2 {174        affine.for %i5 = 0 to 8 {175          %v0 = affine.load %a[%i3, %i5] : memref<6x8xf32>176          %v1 = arith.addf %v0, %v0 : f32177          affine.store %v1, %a[%i3, %i5] : memref<6x8xf32>178        }179      }180    }181  }182 183  // The dependence between the load and affine.store is carried on loops '%i2' and184  // '%i4', and cannot be fused with loop '%i0' without violating this185  // dependence.186  // Once loop '%i2' is interchanged with loop '%i3', and again with loop187  // '%i5', then loop '%i0' can be fused at loop depth 2, because the loop188  // carrying the dependences have been interchanged with loops at depth > 2.189 190  // CHECK:       affine.for %{{.*}} = 0 to 6 {191  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 8 {192  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[0, 0] : memref<1x1xf32>193  // CHECK-NEXT:      affine.for %{{.*}} = 0 to 4 {194  // CHECK-NEXT:        affine.for %{{.*}} = 0 to 2 {195  // CHECK-NEXT:          affine.load %{{.*}}[0, 0] : memref<1x1xf32>196  // CHECK-NEXT:          arith.addf %{{.*}}, %{{.*}} : f32197  // CHECK-NEXT:          affine.store %{{.*}}, %{{.*}}[0, 0] : memref<1x1xf32>198  // CHECK-NEXT:        }199  // CHECK-NEXT:      }200  // CHECK-NEXT:    }201  // CHECK-NEXT:  }202  // CHECK-NEXT:  return203  return204}205 206// -----207 208func.func @should_fuse_live_out_writer(%arg0 : memref<10xf32>) -> memref<10xf32> {209  %cst = arith.constant 0.000000e+00 : f32210  affine.for %i0 = 0 to 10 {211    affine.store %cst, %arg0[%i0] : memref<10xf32>212  }213  affine.for %i1 = 0 to 10 {214    %1 = affine.load %arg0[%i1] : memref<10xf32>215    affine.store %1, %arg0[%i1] : memref<10xf32>216  }217  return %arg0 : memref<10xf32>218 219  // CHECK:       %{{.*}} = arith.constant 0.000000e+00 : f32220  // CHECK-NEXT:  affine.for %{{.*}} = 0 to 10 {221  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>222  // CHECK-NEXT:    affine.load %{{.*}}[%{{.*}}] : memref<10xf32>223  // CHECK-NEXT:    affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>224  // CHECK-NEXT:  }225  // CHECK-NEXT:  return %{{.*}} : memref<10xf32>226}227 228// -----229 230// The fused slice has 16 iterations from along %i0.231 232// CHECK-DAG: [[$MAP_LB:#map[0-9]*]] = affine_map<(d0) -> (d0 * 16)>233// CHECK-DAG: [[$MAP_UB:#map[0-9]*]] = affine_map<(d0) -> (d0 * 16 + 16)>234 235// CHECK-LABEL: slice_tile236func.func @slice_tile(%arg0: memref<128x8xf32>, %arg1: memref<32x8xf32>, %0 : f32) -> memref<32x8xf32> {237  affine.for %i0 = 0 to 32 {238    affine.for %i1 = 0 to 8 {239      affine.store %0, %arg1[%i0, %i1] : memref<32x8xf32>240    }241  }242  affine.for %i = 0 to 2 {243    affine.for %j = 0 to 8 {244      affine.for %k = 0 to 8 {245        affine.for %kk = 0 to 16 {246          %v = affine.load %arg0[16 * %k + %kk, %j] : memref<128x8xf32>247          %r = "foo"(%v) : (f32) -> f32248        }249        affine.for %ii = 0 to 16 {250          %v = affine.load %arg1[16 * %i + %ii, %j] : memref<32x8xf32>251          %s = arith.addf %v, %v : f32252          affine.store %s, %arg1[16 * %i + %ii, %j] : memref<32x8xf32>253        }254      }255    }256  }257  return %arg1 : memref<32x8xf32>258}259// CHECK:       affine.for %{{.*}} = 0 to 2 {260// CHECK-NEXT:    affine.for %{{.*}} = 0 to 8 {261// CHECK-NEXT:      affine.for %{{.*}} = [[$MAP_LB]](%{{.*}}) to [[$MAP_UB]](%{{.*}}) {262// CHECK-NEXT:        affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<32x8xf32>263// CHECK-NEXT:      }264// CHECK-NEXT:      affine.for %{{.*}} = 0 to 8 {265// CHECK-NEXT:        affine.for %{{.*}} = 0 to 16 {266// CHECK-NEXT:          affine.load %{{.*}}[%{{.*}} * 16 + %{{.*}}, %{{.*}}] : memref<128x8xf32>267// CHECK-NEXT:          "foo"(%{{.*}}) : (f32) -> f32268// CHECK-NEXT:        }269// CHECK-NEXT:        affine.for %{{.*}} = 0 to 16 {270// CHECK-NEXT:          affine.load %{{.*}}[%{{.*}} * 16 + %{{.*}}, %{{.*}}] : memref<32x8xf32>271// CHECK-NEXT:          arith.addf %{{.*}}, %{{.*}} : f32272// CHECK-NEXT:          affine.store %{{.*}}, %{{.*}}[%{{.*}} * 16 + %{{.*}}, %{{.*}}] : memref<32x8xf32>273// CHECK-NEXT:        }274// CHECK-NEXT:      }275// CHECK-NEXT:    }276// CHECK-NEXT:  }277// CHECK-NEXT:  return %{{.*}} : memref<32x8xf32>278// CHECK-NEXT:}279 280// -----281 282// Test case which illustrates fix for b/126454413283func.func @test_add_slice_bounds() {284  %a = memref.alloc() : memref<10xf32>285  %b = memref.alloc() : memref<10xf32>286  %cf7 = arith.constant 7.0 : f32287  %c0 = arith.constant 0 : index288 289  affine.for %i0 = 0 to 10 {290    affine.for %i1 = 0 to 10 {291      affine.for %i2 = 0 to 10 {292        %a0 = affine.apply affine_map<(d0) -> (d0)> (%i0)293        %a1 = affine.apply affine_map<(d0) -> (d0)> (%i0)294        %a2 = affine.apply affine_map<(d0, d1) -> (d0 - d1)> (%a0, %a1)295        affine.store %cf7, %a[%a2] : memref<10xf32>296      }297    }298  }299  affine.for %i3 = 0 to 10 {300    affine.for %i4 = 0 to 10 {301      affine.for %i5 = 0 to 10 {302        %v0 = affine.load %a[%c0] : memref<10xf32>303      }304    }305  }306 307// CHECK:        affine.for %{{.*}} = 0 to 10 {308// CHECK-NEXT:     affine.for %{{.*}} = 0 to 10 {309// CHECK-NEXT:       affine.for %{{.*}} = 0 to 10 {310// CHECK-NEXT:         affine.apply #map(%{{.*}})311// CHECK-NEXT:         affine.apply #map(%{{.*}})312// CHECK-NEXT:         affine.apply #map1(%{{.*}}, %{{.*}})313// CHECK-NEXT:         affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>314// CHECK-NEXT:       }315// CHECK-NEXT:     }316// CHECK-NEXT:   }317// CHECK-NEXT:   affine.for %{{.*}} = 0 to 10 {318// CHECK-NEXT:     affine.for %{{.*}} = 0 to 10 {319// CHECK-NEXT:       affine.for %{{.*}} = 0 to 10 {320// CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}] : memref<10xf32>321// CHECK-NEXT:       }322// CHECK-NEXT:     }323// CHECK-NEXT:   }324  return325}326 327// -----328 329func.func @should_fuse_init_loops_siblings_then_shared_producer(%arg0: memref<10x10xf32>, %arg1: memref<10x10xf32>) {330  %0 = memref.alloc() : memref<10x10xf32>331  %cst = arith.constant 0.000000e+00 : f32332  %cst_0 = arith.constant 1.000000e+00 : f32333  %cst_1 = arith.constant 7.000000e+00 : f32334  affine.for %i0 = 0 to 10 {335    affine.for %i1 = 0 to 10 {336      affine.store %cst_1, %0[%i0, %i1] : memref<10x10xf32>337    }338  }339  affine.for %i2 = 0 to 3 {340    affine.for %i3 = 0 to 3 {341      affine.store %cst, %arg0[%i2, %i3] : memref<10x10xf32>342    }343  }344  affine.for %i4 = 0 to 3 {345    affine.for %i5 = 0 to 3 {346      %1 = affine.load %0[%i4, %i5] : memref<10x10xf32>347      %2 = affine.load %arg0[%i4, %i5] : memref<10x10xf32>348      %3 = arith.mulf %1, %2 : f32349      affine.store %3, %arg0[%i4, %i5] : memref<10x10xf32>350    }351  }352  affine.for %i6 = 0 to 3 {353    affine.for %i7 = 0 to 3 {354      affine.store %cst_0, %arg1[%i6, %i7] : memref<10x10xf32>355    }356  }357  affine.for %i8 = 0 to 3 {358    affine.for %i9 = 0 to 3 {359      %4 = affine.load %0[%i8, %i9] : memref<10x10xf32>360      %5 = affine.load %arg1[%i8, %i9] : memref<10x10xf32>361      %6 = arith.addf %4, %5 : f32362      affine.store %6, %arg1[%i8, %i9] : memref<10x10xf32>363    }364  }365 366  // Pass 1: should fuse single-use producer loop nests into their unique user,367  //         so '%i2' will fuse into '%i4' and '%i6' will fuse into '%i8'.368  // Pass 2: should fuse sibling loop nests which share no dependence edges,369  //         so should fuse '%i4' into '%i8'.370  // Pass 3: should fuse single-use producer loop nest '%i0' into '%i8'. Note371  //         that loop nest '%i0' now has a single user after Pass 2 fused its372  //         two users together).373 374// CHECK:        affine.for %{{.*}} = 0 to 3 {375// CHECK-NEXT:     affine.for %{{.*}} = 0 to 3 {376// CHECK-NEXT:       affine.store %{{.*}}, %{{.*}}[0, 0] : memref<1x1xf32>377// CHECK-NEXT:       affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<10x10xf32>378// CHECK-NEXT:       affine.load %{{.*}}[0, 0] : memref<1x1xf32>379// CHECK-NEXT:       affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<10x10xf32>380// CHECK-NEXT:       arith.mulf %{{.*}}, %{{.*}} : f32381// CHECK-NEXT:       affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<10x10xf32>382// CHECK-NEXT:       affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<10x10xf32>383// CHECK-NEXT:       affine.load %{{.*}}[0, 0] : memref<1x1xf32>384// CHECK-NEXT:       affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<10x10xf32>385// CHECK-NEXT:       arith.addf %{{.*}}, %{{.*}} : f32386// CHECK-NEXT:       affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<10x10xf32>387// CHECK-NEXT:     }388// CHECK-NEXT:   }389// CHECK-NEXT:   return390 391  return392}393 394// -----395 396// Test sibling fusion of two matrix-vector products sharing the input matrix.397 398func.func @two_matrix_vector_products() {399  %in_matrix = memref.alloc() : memref<10x10xf32>400  %in_vec0 = memref.alloc() : memref<10xf32>401  %in_vec1 = memref.alloc() : memref<10xf32>402  %out_vec0 = memref.alloc() : memref<10xf32>403  %out_vec1 = memref.alloc() : memref<10xf32>404  %cf7 = arith.constant 7.0 : f32405 406  // Populate input matrix.407  affine.for %i0 = 0 to 10 {408    affine.for %i1 = 0 to 10 {409      affine.store %cf7, %in_matrix[%i0, %i1] : memref<10x10xf32>410    }411  }412  // out_vec0 = in_matrix x in_vec0413  affine.for %i2 = 0 to 10 {414    affine.for %i3 = 0 to 10 {415      %v0 = affine.load %in_matrix[%i2, %i3] : memref<10x10xf32>416      %v1 = affine.load %in_vec0[%i3] : memref<10xf32>417      %v2 = arith.mulf %v0, %v1 : f32418      %v3 = affine.load %out_vec0[%i3] : memref<10xf32>419      %v4 = arith.addf %v2, %v3 : f32420      affine.store %v4, %out_vec0[%i3] : memref<10xf32>421    }422  }423  // out_vec1 = in_matrix x in_vec1424  affine.for %i4 = 0 to 10 {425    affine.for %i5 = 0 to 10 {426      %v5 = affine.load %in_matrix[%i4, %i5] : memref<10x10xf32>427      %v6 = affine.load %in_vec1[%i5] : memref<10xf32>428      %v7 = arith.mulf %v5, %v6 : f32429      %v8 = affine.load %out_vec1[%i5] : memref<10xf32>430      %v9 = arith.addf %v7, %v8 : f32431      affine.store %v9, %out_vec1[%i5] : memref<10xf32>432    }433  }434 435// CHECK:        affine.for %{{.*}} = 0 to 10 {436// CHECK-NEXT:     affine.for %{{.*}} = 0 to 10 {437// CHECK-NEXT:       affine.store %{{.*}}, %{{.*}}[%{{.*}}, 0] : memref<10x1xf32>438// CHECK-NEXT:     }439// CHECK-NEXT:     affine.for %{{.*}} = 0 to 10 {440// CHECK-NEXT:       affine.load %{{.*}}[%{{.*}}, 0] : memref<10x1xf32>441// CHECK-NEXT:       affine.load %{{.*}}[%{{.*}}] : memref<10xf32>442// CHECK-NEXT:       arith.mulf %{{.*}}, %{{.*}} : f32443// CHECK-NEXT:       affine.load %{{.*}}[%{{.*}}] : memref<10xf32>444// CHECK-NEXT:       arith.addf %{{.*}}, %{{.*}} : f32445// CHECK-NEXT:       affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>446// CHECK-NEXT:     }447// CHECK-NEXT:     affine.for %{{.*}} = 0 to 10 {448// CHECK-NEXT:       affine.load %{{.*}}[%{{.*}}, 0] : memref<10x1xf32>449// CHECK-NEXT:       affine.load %{{.*}}[%{{.*}}] : memref<10xf32>450// CHECK-NEXT:       arith.mulf %{{.*}}, %{{.*}} : f32451// CHECK-NEXT:       affine.load %{{.*}}[%{{.*}}] : memref<10xf32>452// CHECK-NEXT:       arith.addf %{{.*}}, %{{.*}} : f32453// CHECK-NEXT:       affine.store %{{.*}}, %{{.*}}[%{{.*}}] : memref<10xf32>454// CHECK-NEXT:     }455// CHECK-NEXT:   }456// CHECK-NEXT:   return457  return458}459 460// -----461 462func.func @should_not_slice_past_slice_barrier() {463  %0 = memref.alloc() : memref<100x16xf32>464  affine.for %i0 = 0 to 100 {465    affine.for %i1 = 0 to 16 {466      %1 = "op1"() : () -> f32467      affine.store %1, %0[%i0, %i1] : memref<100x16xf32>468    } {slice_fusion_barrier = true}469  }470  affine.for %i2 = 0 to 100 {471    affine.for %i3 = 0 to 16 {472      %2 = affine.load %0[%i2, %i3] : memref<100x16xf32>473      "op2"(%2) : (f32) -> ()474    }475  }476  // The 'slice_fusion_barrier' attribute on '%i1' prevents slicing the477  // iteration space of '%i1' and any enclosing loop nests.478// CHECK:        affine.for %{{.*}} = 0 to 100 {479// CHECK-NEXT:     affine.for %{{.*}} = 0 to 16 {480// CHECK-NEXT:       %{{.*}} = "op1"() : () -> f32481// CHECK-NEXT:       affine.store %{{.*}}, %{{.*}}[0, %{{.*}}] : memref<1x16xf32>482// CHECK-NEXT:     } {slice_fusion_barrier = true}483// CHECK-NEXT:     affine.for %{{.*}} = 0 to 16 {484// CHECK-NEXT:       affine.load %{{.*}}[0, %{{.*}}] : memref<1x16xf32>485// CHECK-NEXT:       "op2"(%{{.*}}) : (f32) -> ()486// CHECK-NEXT:     }487// CHECK-NEXT:   }488  return489}490 491// -----492 493#map = affine_map<(d0, d1) -> (d0 * 16 + d1)>494func.func @fuse_across_dim_mismatch(%arg0: memref<4x4x16x1xf32>, %arg1: memref<144x9xf32>, %arg2: memref<9xf32>) {495  %1 = memref.alloc() : memref<144x4xf32>496  %2 = arith.constant 0.0 : f32497  affine.for %i2 = 0 to 9 {498    affine.for %i3 = 0 to 4 {499      affine.for %i5 = 0 to 16 {500        %7 = affine.apply #map(%i2, %i5)501        affine.store %2, %1[%7, %i3] : memref<144x4xf32>502      }503    }504  }505  affine.for %i6 = 0 to 9 {506    affine.for %i7 = 0 to 9 {507      affine.for %i8 = 0 to 4 {508        affine.for %i10 = 0 to 16 {509          %10 = affine.apply #map(%i6, %i10)510          %11 = affine.load %1[%10, %i8] : memref<144x4xf32>511        }512      }513    }514  }515  return516}517// MAXIMAL:      #[[$MAP:.*]] = affine_map<(d0, d1) -> (d0 * 16 + d1)>518// MAXIMAL-LABEL: func @fuse_across_dim_mismatch519// MAXIMAL:        memref.alloc() : memref<1x1xf32>520// MAXIMAL:        affine.for %{{.*}} = 0 to 9 {521// MAXIMAL-NEXT:    affine.for %{{.*}} = 0 to 9 {522// MAXIMAL-NEXT:      affine.for %{{.*}} = 0 to 4 {523// MAXIMAL-NEXT:        affine.for %{{.*}} = 0 to 16 {524// MAXIMAL-NEXT:          affine.apply #[[$MAP]](%{{.*}}, %{{.*}})525// MAXIMAL-NEXT:          affine.store %{{.*}}, %{{.*}}[0, 0] : memref<1x1xf32>526// MAXIMAL-NEXT:          affine.apply #[[$MAP]](%{{.*}}, %{{.*}})527// MAXIMAL-NEXT:          affine.load %{{.*}}[0, 0] : memref<1x1xf32>528// MAXIMAL-NEXT:        }529// MAXIMAL-NEXT:      }530// MAXIMAL-NEXT:    }531// MAXIMAL-NEXT:  }532 533// -----534 535#map3 = affine_map<(d0, d1) -> ((d0 * 72 + d1) floordiv 2304)>536#map4 = affine_map<(d0, d1) -> (((d0 * 72 + d1) mod 2304) floordiv 1152)>537#map5 = affine_map<(d0, d1) -> (((((d0 * 72 + d1) mod 2304) mod 1152) floordiv 9) floordiv 8)>538#map6 = affine_map<(d0, d1) -> (((((d0 * 72 + d1) mod 2304) mod 1152) mod 9) floordiv 3)>539#map7 = affine_map<(d0, d1) -> (((((d0 * 72 + d1) mod 2304) mod 1152) mod 9) mod 3)>540#map10 = affine_map<(d0, d1) -> (d0 * 16 + d1)>541#map11 = affine_map<(d0, d1) -> (d0 * 16 + d1)>542#map12 = affine_map<(d0, d1) -> (d0 * 16 - d1 + 15)>543func.func @fuse_across_varying_dims_complex(%arg0: f32) {544  %c0 = arith.constant 0 : index545  %0 = memref.alloc() : memref<2x2x3x3x16x1xf32>546  %1 = memref.alloc() : memref<64x9xf32>547  %2 = memref.alloc() : memref<144x4xf32>548  affine.for %i0 = 0 to 64 {549    affine.for %i1 = 0 to 9 {550      %4 = affine.apply #map3(%i0, %i1)551      %5 = affine.apply #map4(%i0, %i1)552      %6 = affine.apply #map5(%i0, %i1)553      %7 = affine.apply #map6(%i0, %i1)554      %8 = affine.apply #map7(%i0, %i1)555      %9 = affine.load %0[%4, %5, %7, %8, %6, %c0] : memref<2x2x3x3x16x1xf32>556      affine.store %9, %1[%i0, %i1] : memref<64x9xf32>557    }558  }559  affine.for %i2 = 0 to 9 {560    affine.for %i3 = 0 to 4 {561      affine.for %i4 = 0 to 16 {562        %10 = affine.apply #map10(%i3, %i4)563        %11 = affine.load %1[%10, %i2] : memref<64x9xf32>564      }565      affine.for %i5 = 0 to 16 {566        %14 = affine.apply #map11(%i2, %i5)567        affine.store %arg0, %2[%14, %i3] : memref<144x4xf32>568      }569    }570  }571  affine.for %i6 = 0 to 9 {572    affine.for %i7 = 0 to 9 {573      affine.for %i8 = 0 to 4 {574        affine.for %i9 = 0 to 16 {575          %15 = affine.apply #map12(%i8, %i9)576          %16 = affine.load %1[%15, %i7] : memref<64x9xf32>577        }578      }579    }580  }581  return582}583// MAXIMAL-DAG: [[$MAP0:#map[0-9]*]] = affine_map<(d0, d1) -> ((d0 * 72 + d1) floordiv 2304)>584// MAXIMAL-DAG: [[$MAP1:#map[0-9]*]] = affine_map<(d0, d1) -> (((d0 * 72 + d1) mod 2304) floordiv 1152)>585// MAXIMAL-DAG: [[$MAP2:#map[0-9]*]] = affine_map<(d0, d1) -> ((((d0 * 72 + d1) mod 1152) floordiv 9) floordiv 8)>586// MAXIMAL-DAG: [[$MAP3:#map[0-9]*]] = affine_map<(d0, d1) -> ((d1 mod 9) floordiv 3)>587// MAXIMAL-DAG: [[$MAP4:#map[0-9]*]] = affine_map<(d0, d1) -> (d1 mod 3)>588// MAXIMAL-DAG: [[$MAP7:#map[0-9]*]] = affine_map<(d0, d1) -> (d0 * 16 + d1)>589// MAXIMAL-DAG: [[$MAP8:#map[0-9]*]] = affine_map<(d0, d1) -> (d0 * 16 - d1 + 15)>590// MAXIMAL-LABEL: func @fuse_across_varying_dims_complex591// MAXIMAL-NEXT:  memref.alloc() : memref<64x1xf32>592// MAXIMAL-NEXT:  arith.constant 0 : index593// MAXIMAL-NEXT:  memref.alloc() : memref<2x2x3x3x16x1xf32>594// MAXIMAL-NEXT:  memref.alloc() : memref<144x4xf32>595// MAXIMAL-NEXT:  affine.for %{{.*}} = 0 to 9 {596// MAXIMAL-NEXT:    affine.for %{{.*}} = 0 to 4 {597// MAXIMAL-NEXT:      affine.for %{{.*}} = 0 to 16 {598// MAXIMAL-NEXT:        affine.for %{{.*}} = 0 to 64 {599// MAXIMAL-NEXT:          affine.apply [[$MAP0]](%{{.*}}, %{{.*}})600// MAXIMAL-NEXT:          affine.apply [[$MAP1]](%{{.*}}, %{{.*}})601// MAXIMAL-NEXT:          affine.apply [[$MAP2]](%{{.*}}, %{{.*}})602// MAXIMAL-NEXT:          affine.apply [[$MAP3]](%{{.*}}, %{{.*}})603// MAXIMAL-NEXT:          affine.apply [[$MAP4]](%{{.*}}, %{{.*}})604// MAXIMAL-NEXT:          affine.load %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}] : memref<2x2x3x3x16x1xf32>605// MAXIMAL-NEXT:          affine.store %{{.*}}, %{{.*}}[%{{.*}}, 0] : memref<64x1xf32>606// MAXIMAL-NEXT:        }607// MAXIMAL-NEXT:        affine.apply [[$MAP7]](%{{.*}}, %{{.*}})608// MAXIMAL-NEXT:        affine.load %{{.*}}[%{{.*}} * 16 + %{{.*}}, 0] : memref<64x1xf32>609// MAXIMAL-NEXT:        affine.for %{{.*}} = 0 to 9 {610// MAXIMAL-NEXT:          affine.for %{{.*}} = 0 to 4 {611// MAXIMAL-NEXT:            affine.for %{{.*}} = 0 to 16 {612// MAXIMAL-NEXT:              affine.apply [[$MAP8]](%{{.*}}, %{{.*}})613// MAXIMAL-NEXT:              affine.load %{{.*}}[%{{.*}} * 16 - %{{.*}} + 15, 0] : memref<64x1xf32>614// MAXIMAL-NEXT:            }615// MAXIMAL-NEXT:          }616// MAXIMAL-NEXT:        }617// MAXIMAL-NEXT:      }618// MAXIMAL-NEXT:      affine.for %{{.*}} = 0 to 16 {619// MAXIMAL-NEXT:        affine.apply [[$MAP7]](%{{.*}}, %{{.*}})620// MAXIMAL-NEXT:        affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<144x4xf32>621// MAXIMAL-NEXT:      }622// MAXIMAL-NEXT:    }623// MAXIMAL-NEXT:  }624 625// -----626 627func.func @should_fuse_with_slice_union() {628  %a = memref.alloc() : memref<100xf32>629  %c0 = arith.constant 0 : index630  %cf0 = arith.constant 0.0 : f32631 632  affine.for %i0 = 0 to 100 {633    affine.store %cf0, %a[%i0]: memref<100xf32>634  }635 636  affine.for %i1 = 10 to 20 {637    %v0 = affine.load %a[%i1]: memref<100xf32>638    affine.for %i2 = 15 to 25 {639      %v1 = affine.load %a[%i2]: memref<100xf32>640    }641  }642  // The union of two slice bounds (calculated between the store and each of643  // the loads) is computed and used in the fusion cost calculation, index644  // remapping, and private memref size. The result is that the temporary645  // memref is reduced from 100xf32 to 15xf32 and properly indexed by646  // the fused loops based on the union calculation.647// CHECK:      affine.for %{{.*}} = 10 to 20 {648// CHECK-NEXT:   affine.for %{{.*}} = 10 to 25 {649// CHECK-NEXT:     affine.store %{{.*}}, %{{.*}}[%{{.*}} - 10] : memref<15xf32>650// CHECK-NEXT:   }651// CHECK-NEXT:   affine.load %{{.*}}[%{{.*}} - 10] : memref<15xf32>652// CHECK-NEXT:   affine.for %{{.*}} = 15 to 25 {653// CHECK-NEXT:     affine.load %{{.*}}[%{{.*}} - 10] : memref<15xf32>654// CHECK-NEXT:   }655// CHECK-NEXT: }656// CHECK-NEXT: return657  return658}659 660// -----661 662func.func @affine_add_mm_fused(%arg0: memref<1024x1024xf32>, %arg1: memref<1024x1024xf32>, %arg2: memref<1024x1024xf32>, %arg3: memref<1024x1024xf32>) {663  affine.for %i2 = 0 to 1024 {664    affine.for %i3 = 0 to 1024 {665      %0 = affine.load %arg3[%i2, %i3] : memref<1024x1024xf32>666      %1 = affine.load %arg2[%i2, %i3] : memref<1024x1024xf32>667      %2 = arith.addf %1, %0 : f32668      affine.store %2, %arg2[%i2, %i3] : memref<1024x1024xf32>669    }670  }671  affine.for %i4 = 0 to 1024 {672    affine.for %i5 = 0 to 1024 {673      affine.for %i6 = 0 to 1024 {674        %3 = affine.load %arg1[%i6, %i5] : memref<1024x1024xf32>675        %4 = affine.load %arg0[%i4, %i6] : memref<1024x1024xf32>676        %5 = arith.mulf %4, %3 : f32677        %6 = affine.load %arg2[%i4, %i5] : memref<1024x1024xf32>678        %7 = arith.addf %6, %5 : f32679        affine.store %7, %arg2[%i4, %i5] : memref<1024x1024xf32>680      }681    }682  }683  // Should fuse elementwise add loop at loop depth 2, above loop-carried684  // dependence between load/store on '%arg2', carried on reduction loop %i6.685  // CHECK:       affine.for %{{.*}} = 0 to 1024 {686  // CHECK-NEXT:    affine.for %{{.*}} = 0 to 1024 {687  // CHECK-NEXT:      affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>688  // CHECK-NEXT:      affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>689  // CHECK-NEXT:      arith.addf %{{.*}}, %{{.*}} : f32690  // CHECK-NEXT:      affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>691  // CHECK-NEXT:      affine.for %{{.*}} = 0 to 1024 {692  // CHECK-NEXT:        affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>693  // CHECK-NEXT:        affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>694  // CHECK-NEXT:        arith.mulf %{{.*}}, %{{.*}} : f32695  // CHECK-NEXT:        affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>696  // CHECK-NEXT:        arith.addf %{{.*}}, %{{.*}} : f32697  // CHECK-NEXT:        affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>698  // CHECK-NEXT:      }699  // CHECK-NEXT:    }700  // CHECK-NEXT:  }701  return702}703 704// -----705 706func.func @affine_2mm_fused(%arg0: memref<1024x1024xf32>, %arg1: memref<1024x1024xf32>, %arg2: memref<1024x1024xf32>, %arg3: memref<1024x1024xf32>, %arg4: memref<1024x1024xf32>) {707  %cst = arith.constant 0.000000e+00 : f32708  affine.for %i0 = 0 to 1024 {709    affine.for %i1 = 0 to 1024 {710      affine.store %cst, %arg2[%i0, %i1] : memref<1024x1024xf32>711    }712  }713  affine.for %i2 = 0 to 1024 {714    affine.for %i3 = 0 to 1024 {715      affine.store %cst, %arg4[%i2, %i3] : memref<1024x1024xf32>716    }717  }718  affine.for %i4 = 0 to 1024 {719    affine.for %i5 = 0 to 1024 {720      affine.for %i6 = 0 to 1024 {721        %0 = affine.load %arg1[%i6, %i5] : memref<1024x1024xf32>722        %1 = affine.load %arg0[%i4, %i6] : memref<1024x1024xf32>723        %2 = arith.mulf %1, %0 : f32724        %3 = affine.load %arg2[%i4, %i5] : memref<1024x1024xf32>725        %4 = arith.addf %3, %2 : f32726        affine.store %4, %arg2[%i4, %i5] : memref<1024x1024xf32>727      }728    }729  }730  affine.for %i7 = 0 to 1024 {731    affine.for %i8 = 0 to 1024 {732      affine.for %i9 = 0 to 1024 {733        %5 = affine.load %arg1[%i9, %i8] : memref<1024x1024xf32>734        %6 = affine.load %arg0[%i7, %i9] : memref<1024x1024xf32>735        %7 = arith.mulf %6, %5 : f32736        %8 = affine.load %arg4[%i7, %i8] : memref<1024x1024xf32>737        %9 = arith.addf %8, %7 : f32738        affine.store %9, %arg4[%i7, %i8] : memref<1024x1024xf32>739      }740    }741  }742 743  // Should fuse MM initialization loops into their consumers, then fuse the744  // two matmul loops together for input reuse on '%arg0/%arg1'.745 746  // CHECK:        affine.for %{{.*}} = 0 to 1024 {747  // CHECK-NEXT:     affine.for %{{.*}} = 0 to 1024 {748  // CHECK-NEXT:       affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>749  // CHECK-NEXT:       affine.for %{{.*}} = 0 to 1024 {750  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>751  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>752  // CHECK-NEXT:         arith.mulf %{{.*}}, %{{.*}} : f32753  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>754  // CHECK-NEXT:         arith.addf %{{.*}}, %{{.*}} : f32755  // CHECK-NEXT:         affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>756  // CHECK-NEXT:       }757  // CHECK-NEXT:     }758  // CHECK-NEXT:     affine.for %{{.*}} = 0 to 1024 {759  // CHECK-NEXT:       affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>760  // CHECK-NEXT:       affine.for %{{.*}} = 0 to 1024 {761  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>762  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>763  // CHECK-NEXT:         arith.mulf %{{.*}}, %{{.*}} : f32764  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>765  // CHECK-NEXT:         arith.addf %{{.*}}, %{{.*}} : f32766  // CHECK-NEXT:         affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>767  // CHECK-NEXT:       }768  // CHECK-NEXT:     }769  // CHECK-NEXT:   }770 771  return772}773 774// -----775 776func.func @affine_2_dependent_mm_fused(%arg0: memref<1024x1024xf32>, %arg1: memref<1024x1024xf32>, %arg2: memref<1024x1024xf32>, %arg3: memref<1024x1024xf32>, %arg4: memref<1024x1024xf32>) {777  affine.for %i0 = 0 to 1024 {778    affine.for %i1 = 0 to 1024 {779      affine.for %i2 = 0 to 1024 {780        %0 = affine.load %arg1[%i2, %i1] : memref<1024x1024xf32>781        %1 = affine.load %arg0[%i0, %i2] : memref<1024x1024xf32>782        %2 = arith.mulf %1, %0 : f32783        %3 = affine.load %arg2[%i0, %i1] : memref<1024x1024xf32>784        %4 = arith.addf %3, %2 : f32785        affine.store %4, %arg2[%i0, %i1] : memref<1024x1024xf32>786      }787    }788  }789  affine.for %i3 = 0 to 1024 {790    affine.for %i4 = 0 to 1024 {791      affine.for %i5 = 0 to 1024 {792        %5 = affine.load %arg3[%i5, %i4] : memref<1024x1024xf32>793        %6 = affine.load %arg2[%i3, %i5] : memref<1024x1024xf32>794        %7 = arith.mulf %6, %5 : f32795        %8 = affine.load %arg4[%i3, %i4] : memref<1024x1024xf32>796        %9 = arith.addf %8, %7 : f32797        affine.store %9, %arg4[%i3, %i4] : memref<1024x1024xf32>798      }799    }800  }801 802  // CHECK:        affine.for %{{.*}} = 0 to 1024 {803  // CHECK-NEXT:     affine.for %{{.*}} = 0 to 1024 {804  // CHECK-NEXT:       affine.for %{{.*}} = 0 to 1024 {805  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>806  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>807  // CHECK-NEXT:         arith.mulf %{{.*}}, %{{.*}} : f32808  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>809  // CHECK-NEXT:         arith.addf %{{.*}}, %{{.*}} : f32810  // CHECK-NEXT:         affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>811  // CHECK-NEXT:       }812  // CHECK-NEXT:     }813  // CHECK-NEXT:     affine.for %{{.*}} = 0 to 1024 {814  // CHECK-NEXT:       affine.for %{{.*}} = 0 to 1024 {815  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>816  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>817  // CHECK-NEXT:         arith.mulf %{{.*}}, %{{.*}} : f32818  // CHECK-NEXT:         affine.load %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>819  // CHECK-NEXT:         arith.addf %{{.*}}, %{{.*}} : f32820  // CHECK-NEXT:         affine.store %{{.*}}, %{{.*}}[%{{.*}}, %{{.*}}] : memref<1024x1024xf32>821  // CHECK-NEXT:       }822  // CHECK-NEXT:     }823  // CHECK-NEXT:   }824  return825}826 827// -----828 829// CHECK-LABEL: func @should_fuse_self_dependence_multi_store_producer() {830func.func @should_fuse_self_dependence_multi_store_producer() {831  %m = memref.alloc() : memref<10xf32>832  %local_m = memref.alloc() : memref<10xf32>833  %cf7 = arith.constant 7.0 : f32834 835  affine.for %i0 = 0 to 10 {836    affine.store %cf7, %local_m[%i0] : memref<10xf32>837    %v0 = affine.load %local_m[%i0] : memref<10xf32>838    affine.store %v0, %m[%i0] : memref<10xf32>839  }840  affine.for %i1 = 0 to 10 {841    %v1 = affine.load %m[%i1] : memref<10xf32>842  }843  // CHECK:      affine.for %[[i0:.*]] = 0 to 10 {844  // CHECK-NEXT:   affine.store %{{.*}}, [[LOCAL_M:%.*]][%[[i0]]] : memref<10xf32>845  // CHECK-NEXT:   [[v0:%.*]] = affine.load [[LOCAL_M]][%[[i0]]] : memref<10xf32>846  // CHECK-NEXT:   affine.store [[v0]], %{{.*}}[0] : memref<1xf32>847  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>848  // CHECK-NEXT: }849  // CHECK-NEXT: return850  return851}852 853// -----854 855// CHECK-LABEL: func @should_fuse_dead_multi_store_producer() {856func.func @should_fuse_dead_multi_store_producer() {857  %m = memref.alloc() : memref<10xf32>858  %dead_m = memref.alloc() : memref<10xf32>859  %cf7 = arith.constant 7.0 : f32860 861  affine.for %i0 = 0 to 10 {862    affine.store %cf7, %dead_m[%i0] : memref<10xf32>863    affine.store %cf7, %m[%i0] : memref<10xf32>864  }865  affine.for %i1 = 0 to 10 {866    %v0 = affine.load %m[%i1] : memref<10xf32>867  }868  // CHECK:      affine.for %[[i0:.*]] = 0 to 10 {869  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[%[[i0]]] : memref<10xf32>870  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>871  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>872  // CHECK-NEXT: }873  // CHECK-NEXT: return874  return875}876 877// -----878 879// CHECK-LABEL: func @should_fuse_function_live_out_multi_store_producer880func.func @should_fuse_function_live_out_multi_store_producer(%live_in_out_m : memref<10xf32>) {881  %m = memref.alloc() : memref<10xf32>882  %cf7 = arith.constant 7.0 : f32883 884  affine.for %i0 = 0 to 10 {885    affine.store %cf7, %live_in_out_m[%i0] : memref<10xf32>886    affine.store %cf7, %m[%i0] : memref<10xf32>887  }888  affine.for %i1 = 0 to 10 {889    %v0 = affine.load %m[%i1] : memref<10xf32>890  }891  // CHECK:      affine.for %[[i0:.*]] = 0 to 10 {892  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[%[[i0]]] : memref<10xf32>893  // CHECK-NEXT:   affine.store %{{.*}}, %{{.*}}[0] : memref<1xf32>894  // CHECK-NEXT:   affine.load %{{.*}}[0] : memref<1xf32>895  // CHECK-NEXT: }896  // CHECK-NEXT: return897  return898}899 900// Add further tests in mlir/test/Transforms/loop-fusion-4.mlir901