1// RUN: mlir-opt %s -test-loop-fusion=test-loop-fusion-slice-computation -split-input-file -verify-diagnostics | FileCheck %s 2 3// ----- 4 5// CHECK-LABEL: func @slice_depth1_loop_nest() { 6func.func @slice_depth1_loop_nest() { 7 %0 = memref.alloc() : memref<100xf32> 8 %cst = arith.constant 7.000000e+00 : f32 9 affine.for %i0 = 0 to 16 { 10 // expected-remark@-1 {{Incorrect slice ( src loop: 1, dst loop: 0, depth: 1 : insert point: (1, 1) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] )}} 11 affine.store %cst, %0[%i0] : memref<100xf32> 12 } 13 affine.for %i1 = 0 to 5 { 14 // expected-remark@-1 {{slice ( src loop: 0, dst loop: 1, depth: 1 : insert point: (1, 0) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] )}} 15 %1 = affine.load %0[%i1] : memref<100xf32> 16 } 17 return 18} 19 20// ----- 21 22// CHECK-LABEL: func @forward_slice_slice_depth1_loop_nest() { 23func.func @forward_slice_slice_depth1_loop_nest() { 24 %0 = memref.alloc() : memref<100xf32> 25 %cst = arith.constant 7.000000e+00 : f32 26 affine.for %i0 = 0 to 5 { 27 // expected-remark@-1 {{slice ( src loop: 1, dst loop: 0, depth: 1 : insert point: (1, 1) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] )}} 28 affine.store %cst, %0[%i0] : memref<100xf32> 29 } 30 affine.for %i1 = 0 to 16 { 31 // expected-remark@-1 {{Incorrect slice ( src loop: 0, dst loop: 1, depth: 1 : insert point: (1, 0) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] )}} 32 %1 = affine.load %0[%i1] : memref<100xf32> 33 } 34 return 35} 36 37// ----- 38 39// Loop %i0 writes to locations [2, 17] and loop %i0 reads from locations [3, 6] 40// Slice loop bounds should be adjusted such that the load/store are for the 41// same location. 42// CHECK-LABEL: func @slice_depth1_loop_nest_with_offsets() { 43func.func @slice_depth1_loop_nest_with_offsets() { 44 %0 = memref.alloc() : memref<100xf32> 45 %cst = arith.constant 7.000000e+00 : f32 46 affine.for %i0 = 0 to 16 { 47 // expected-remark@-1 {{Incorrect slice ( src loop: 1, dst loop: 0, depth: 1 : insert point: (1, 2) loop bounds: [(d0) -> (d0 + 3), (d0) -> (d0 + 4)] )}} 48 %a0 = affine.apply affine_map<(d0) -> (d0 + 2)>(%i0) 49 affine.store %cst, %0[%a0] : memref<100xf32> 50 } 51 affine.for %i1 = 4 to 8 { 52 // expected-remark@-1 {{slice ( src loop: 0, dst loop: 1, depth: 1 : insert point: (1, 0) loop bounds: [(d0) -> (d0 - 3), (d0) -> (d0 - 2)] )}} 53 %a1 = affine.apply affine_map<(d0) -> (d0 - 1)>(%i1) 54 %1 = affine.load %0[%a1] : memref<100xf32> 55 } 56 return 57} 58 59// ----- 60 61// Slices at loop depth 1 should only slice the loop bounds of the first scf. 62// Slices at loop depth 2 should slice loop bounds of both loops. 63// CHECK-LABEL: func @slice_depth2_loop_nest() { 64func.func @slice_depth2_loop_nest() { 65 %0 = memref.alloc() : memref<100x100xf32> 66 %cst = arith.constant 7.000000e+00 : f32 67 affine.for %i0 = 0 to 16 { 68 // expected-remark@-1 {{Incorrect slice ( src loop: 1, dst loop: 0, depth: 1 : insert point: (1, 1) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] [(d0) -> (0), (d0) -> (8)] )}} 69 // expected-remark@-2 {{Incorrect slice ( src loop: 1, dst loop: 0, depth: 2 : insert point: (2, 1) loop bounds: [(d0, d1) -> (d0), (d0, d1) -> (d0 + 1)] [(d0, d1) -> (d1), (d0, d1) -> (d1 + 1)] )}} 70 affine.for %i1 = 0 to 16 { 71 affine.store %cst, %0[%i0, %i1] : memref<100x100xf32> 72 } 73 } 74 affine.for %i2 = 0 to 10 { 75 // expected-remark@-1 {{slice ( src loop: 0, dst loop: 1, depth: 1 : insert point: (1, 0) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] [(d0) -> (0), (d0) -> (8)] )}} 76 // expected-remark@-2 {{slice ( src loop: 0, dst loop: 1, depth: 2 : insert point: (2, 0) loop bounds: [(d0, d1) -> (d0), (d0, d1) -> (d0 + 1)] [(d0, d1) -> (d1), (d0, d1) -> (d1 + 1)] )}} 77 affine.for %i3 = 0 to 8 { 78 %1 = affine.load %0[%i2, %i3] : memref<100x100xf32> 79 } 80 } 81 return 82} 83 84// ----- 85 86// The load at depth 1 in loop nest %i2 prevents slicing loop nest %i0 at depths 87// greater than 1. However, loop nest %i2 can be sliced into loop nest %i0 at 88// depths 1 and 2 because the dependent store in loop nest %i0 is at depth 2. 89// CHECK-LABEL: func @slice_depth2_loop_nest_two_loads() { 90func.func @slice_depth2_loop_nest_two_loads() { 91 %0 = memref.alloc() : memref<100x100xf32> 92 %c0 = arith.constant 0 : index 93 %cst = arith.constant 7.000000e+00 : f32 94 affine.for %i0 = 0 to 16 { 95 // expected-remark@-1 {{Incorrect slice ( src loop: 1, dst loop: 0, depth: 1 : insert point: (1, 1) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] [(d0) -> (0), (d0) -> (8)] )}} 96 // expected-remark@-2 {{Incorrect slice ( src loop: 1, dst loop: 0, depth: 2 : insert point: (2, 1) loop bounds: [(d0, d1) -> (d0), (d0, d1) -> (d0 + 1)] [(d0, d1) -> (0), (d0, d1) -> (16)] )}} 97 affine.for %i1 = 0 to 16 { 98 affine.store %cst, %0[%i0, %i1] : memref<100x100xf32> 99 } 100 } 101 affine.for %i2 = 0 to 10 { 102 // expected-remark@-1 {{slice ( src loop: 0, dst loop: 1, depth: 1 : insert point: (1, 0) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] [(d0) -> (0), (d0) -> (8)] )}} 103 affine.for %i3 = 0 to 8 { 104 %1 = affine.load %0[%i2, %i3] : memref<100x100xf32> 105 } 106 %2 = affine.load %0[%i2, %c0] : memref<100x100xf32> 107 } 108 return 109} 110 111// ----- 112 113// The store at depth 1 in loop nest %i0 prevents slicing loop nest %i2 at 114// depths greater than 1 into loop nest %i0. However, loop nest %i0 can be 115// sliced into loop nest %i2 at depths 1 and 2 because the dependent load in 116// loop nest %i2 is at depth 2. 117// CHECK-LABEL: func @slice_depth2_loop_nest_two_stores() { 118func.func @slice_depth2_loop_nest_two_stores() { 119 %0 = memref.alloc() : memref<100x100xf32> 120 %c0 = arith.constant 0 : index 121 %cst = arith.constant 7.000000e+00 : f32 122 affine.for %i0 = 0 to 16 { 123 // expected-remark@-1 {{Incorrect slice ( src loop: 1, dst loop: 0, depth: 1 : insert point: (1, 2) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] [(d0) -> (0), (d0) -> (8)] )}} 124 affine.for %i1 = 0 to 16 { 125 affine.store %cst, %0[%i0, %i1] : memref<100x100xf32> 126 } 127 affine.store %cst, %0[%i0, %c0] : memref<100x100xf32> 128 } 129 affine.for %i2 = 0 to 10 { 130 // expected-remark@-1 {{slice ( src loop: 0, dst loop: 1, depth: 1 : insert point: (1, 0) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] [(d0) -> (0), (d0) -> (16)] )}} 131 // expected-remark@-2 {{slice ( src loop: 0, dst loop: 1, depth: 2 : insert point: (2, 0) loop bounds: [(d0, d1) -> (d0), (d0, d1) -> (d0 + 1)] [(d0, d1) -> (0), (d0, d1) -> (16)] )}} 132 affine.for %i3 = 0 to 8 { 133 %1 = affine.load %0[%i2, %i3] : memref<100x100xf32> 134 } 135 } 136 return 137} 138 139// ----- 140 141// Test loop nest which has a smaller outer trip count than its inner scf. 142// CHECK-LABEL: func @slice_loop_nest_with_smaller_outer_trip_count() { 143func.func @slice_loop_nest_with_smaller_outer_trip_count() { 144 %0 = memref.alloc() : memref<100x100xf32> 145 %c0 = arith.constant 0 : index 146 %cst = arith.constant 7.000000e+00 : f32 147 affine.for %i0 = 0 to 16 { 148 // expected-remark@-1 {{Incorrect slice ( src loop: 1, dst loop: 0, depth: 1 : insert point: (1, 1) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] [(d0) -> (0), (d0) -> (10)] )}} 149 // expected-remark@-2 {{Incorrect slice ( src loop: 1, dst loop: 0, depth: 2 : insert point: (2, 1) loop bounds: [(d0, d1) -> (d0), (d0, d1) -> (d0 + 1)] [(d0, d1) -> (d1), (d0, d1) -> (d1 + 1)] )}} 150 affine.for %i1 = 0 to 16 { 151 affine.store %cst, %0[%i0, %i1] : memref<100x100xf32> 152 } 153 } 154 affine.for %i2 = 0 to 8 { 155 // expected-remark@-1 {{slice ( src loop: 0, dst loop: 1, depth: 1 : insert point: (1, 0) loop bounds: [(d0) -> (d0), (d0) -> (d0 + 1)] [(d0) -> (0), (d0) -> (10)] )}} 156 // expected-remark@-2 {{slice ( src loop: 0, dst loop: 1, depth: 2 : insert point: (2, 0) loop bounds: [(d0, d1) -> (d0), (d0, d1) -> (d0 + 1)] [(d0, d1) -> (d1), (d0, d1) -> (d1 + 1)] )}} 157 affine.for %i3 = 0 to 10 { 158 %1 = affine.load %0[%i2, %i3] : memref<100x100xf32> 159 } 160 } 161 return 162} 163