1// RUN: mlir-opt %s -transform-interpreter --split-input-file --verify-diagnostics 2 3#map0 = affine_map<(d0) -> (d0 * 110)> 4#map1 = affine_map<(d0) -> (696, d0 * 110 + 110)> 5func.func @test_loops_do_not_get_coalesced() { 6 affine.for %i = 0 to 7 { 7 affine.for %j = #map0(%i) to min #map1(%i) { 8 } 9 } {coalesce} 10 return 11} 12 13module attributes {transform.with_named_sequence} { 14 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { 15 %0 = transform.structured.match ops{["affine.for"]} attributes {coalesce} in %arg1 : (!transform.any_op) -> !transform.any_op 16 %1 = transform.cast %0 : !transform.any_op to !transform.op<"affine.for"> 17 // expected-error @below {{failed to coalesce}} 18 %2 = transform.loop.coalesce %1: (!transform.op<"affine.for">) -> (!transform.op<"affine.for">) 19 transform.yield 20 } 21} 22 23// ----- 24 25func.func @test_loops_do_not_get_unrolled() { 26 affine.for %i = 0 to 7 { 27 arith.addi %i, %i : index 28 } 29 return 30} 31 32module attributes {transform.with_named_sequence} { 33 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { 34 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op 35 %1 = transform.get_parent_op %0 {op_name = "affine.for"} : (!transform.any_op) -> !transform.op<"affine.for"> 36 // expected-error @below {{failed to unroll}} 37 transform.loop.unroll %1 { factor = 8 } : !transform.op<"affine.for"> 38 transform.yield 39 } 40} 41 42// ----- 43 44func.func @loop_unroll_and_jam_unsupported_trip_count_not_multiple_of_factor() { 45 %c0 = arith.constant 0 : index 46 %c40 = arith.constant 40 : index 47 %c2 = arith.constant 2 : index 48 scf.for %i = %c0 to %c40 step %c2 { 49 arith.addi %i, %i : index 50 } 51 return 52} 53 54module attributes {transform.with_named_sequence} { 55 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { 56 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op 57 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for"> 58 // expected-error @below {{failed to unroll and jam}} 59 transform.loop.unroll_and_jam %1 { factor = 3 } : !transform.op<"scf.for"> 60 transform.yield 61 } 62} 63 64// ----- 65 66func.func @loop_unroll_and_jam_unsupported_loop_with_results() -> index { 67 %c0 = arith.constant 0 : index 68 %c40 = arith.constant 40 : index 69 %c2 = arith.constant 2 : index 70 %sum = scf.for %i = %c0 to %c40 step %c2 iter_args(%does_not_alias_aggregated = %c0) -> (index) { 71 %sum = arith.addi %i, %i : index 72 scf.yield %sum : index 73 } 74 return %sum : index 75} 76 77module attributes {transform.with_named_sequence} { 78 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { 79 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op 80 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for"> 81 // expected-error @below {{failed to unroll and jam}} 82 transform.loop.unroll_and_jam %1 { factor = 4 } : !transform.op<"scf.for"> 83 transform.yield 84 } 85} 86 87// ----- 88 89func.func private @loop_unroll_and_jam_unsupported_dynamic_trip_count(%arg0: memref<96x128xi8, 3>, %arg1: memref<128xi8, 3>) { 90 %c96 = arith.constant 96 : index 91 %c1 = arith.constant 1 : index 92 %c128 = arith.constant 128 : index 93 %c0 = arith.constant 0 : index 94 %c4 = arith.constant 4 : index 95 scf.for %arg4 = %c0 to %c4 step %c1 { 96 scf.for %arg2 = %c0 to %c128 step %arg4 { 97 %3 = memref.load %arg1[%arg2] : memref<128xi8, 3> 98 %sum = scf.for %arg3 = %c0 to %c96 step %c1 iter_args(%does_not_alias_aggregated = %3) -> (i8) { 99 %2 = memref.load %arg0[%arg3, %arg2] : memref<96x128xi8, 3> 100 %4 = arith.addi %2, %3 : i8 101 scf.yield %4 : i8 102 } 103 memref.store %sum, %arg1[%arg2] : memref<128xi8, 3> 104 } 105 scf.yield 106 } 107 return 108} 109 110module attributes {transform.with_named_sequence} { 111 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { 112 %0 = transform.structured.match ops{["memref.store"]} in %arg1 : (!transform.any_op) -> !transform.any_op 113 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for"> 114 // expected-error @below {{failed to unroll and jam}} 115 transform.loop.unroll_and_jam %1 { factor = 4 } : !transform.op<"scf.for"> 116 transform.yield 117 } 118} 119 120// ----- 121 122func.func @loop_unroll_and_jam_unsupported_dynamic_trip_count(%upper_bound: index) { 123 %c0 = arith.constant 0 : index 124 %c2 = arith.constant 2 : index 125 scf.for %i = %c0 to %upper_bound step %c2 { 126 arith.addi %i, %i : index 127 } 128 return 129} 130 131module attributes {transform.with_named_sequence} { 132 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { 133 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op 134 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for"> 135 // expected-error @below {{failed to unroll and jam}} 136 transform.loop.unroll_and_jam %1 { factor = 2 } : !transform.op<"scf.for"> 137 transform.yield 138 } 139} 140 141// ----- 142 143func.func private @cond() -> i1 144func.func private @body() 145 146func.func @loop_outline_op_multi_region() { 147 // expected-note @below {{target op}} 148 scf.while : () -> () { 149 %0 = func.call @cond() : () -> i1 150 scf.condition(%0) 151 } do { 152 ^bb0: 153 func.call @body() : () -> () 154 scf.yield 155 } 156 return 157} 158 159module attributes {transform.with_named_sequence} { 160 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { 161 %0 = transform.structured.match ops{["scf.while"]} in %arg1 : (!transform.any_op) -> !transform.any_op 162 // expected-error @below {{failed to outline}} 163 transform.loop.outline %0 {func_name = "foo"} : (!transform.any_op) -> (!transform.any_op, !transform.any_op) 164 transform.yield 165 } 166} 167 168// ----- 169 170func.func @test_loop_peeling_not_beneficial() { 171 // Loop peeling is not beneficial because the step size already divides 172 // ub - lb evenly. lb, ub and step are constant in this test case and the 173 // "fast path" is exercised. 174 %lb = arith.constant 0 : index 175 %ub = arith.constant 40 : index 176 %step = arith.constant 5 : index 177 scf.for %i = %lb to %ub step %step { 178 arith.addi %i, %i : index 179 } 180 return 181} 182 183module attributes {transform.with_named_sequence} { 184 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { 185 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op 186 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for"> 187 // expected-error @below {{failed to peel}} 188 transform.loop.peel %1 : (!transform.op<"scf.for">) -> (!transform.any_op, !transform.any_op) 189 transform.yield 190 } 191} 192 193// ----- 194 195func.func @test_loop_peeling_not_beneficial_already_peeled(%lb: index, %ub: index, %step: index) { 196 // Loop peeling is not beneficial because the step size already divides 197 // ub - lb evenly. This test case exercises the "slow path". 198 %new_ub = affine.apply affine_map<()[s0, s1, s2] -> (s1 - (s1 - s0) mod s2)>()[%lb, %ub, %step] 199 scf.for %i = %lb to %new_ub step %step { 200 arith.addi %i, %i : index 201 } 202 return 203} 204 205module attributes {transform.with_named_sequence} { 206 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { 207 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op 208 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for"> 209 // expected-error @below {{failed to peel}} 210 transform.loop.peel %1 : (!transform.op<"scf.for">) -> (!transform.any_op, !transform.any_op) 211 transform.yield 212 } 213} 214 215// ----- 216 217func.func @test_loop_peeling_not_beneficial_already_peeled_lb_zero(%ub: index, %step: index) { 218 // Loop peeling is not beneficial because the step size already divides 219 // ub - lb evenly. This test case exercises the "slow path". 220 %lb = arith.constant 0 : index 221 %new_ub = affine.apply affine_map<()[s1, s2] -> (s1 - s1 mod s2)>()[%ub, %step] 222 scf.for %i = %lb to %new_ub step %step { 223 arith.addi %i, %i : index 224 } 225 return 226} 227 228module attributes {transform.with_named_sequence} { 229 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) { 230 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op 231 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for"> 232 // expected-error @below {{failed to peel}} 233 transform.loop.peel %1 : (!transform.op<"scf.for">) -> (!transform.any_op, !transform.any_op) 234 transform.yield 235 } 236} 237