584 lines · plain
1// RUN: mlir-opt %s -transform-interpreter -split-input-file -verify-diagnostics | FileCheck %s2 3// Outlined functions:4//5// CHECK: func @foo(%{{.+}}, %{{.+}}, %{{.+}}, %{{.+}})6// CHECK: scf.for7// CHECK: arith.addi8//9// CHECK: func @foo[[$SUFFIX:.+]](%{{.+}}, %{{.+}}, %{{.+}})10// CHECK: scf.for11// CHECK: arith.addi12//13// CHECK-LABEL: @loop_outline_op14func.func @loop_outline_op(%arg0: index, %arg1: index, %arg2: index) {15 // CHECK: scf.for16 // CHECK-NOT: scf.for17 // CHECK: scf.execute_region18 // CHECK: func.call @foo19 scf.for %i = %arg0 to %arg1 step %arg2 {20 scf.for %j = %arg0 to %arg1 step %arg2 {21 arith.addi %i, %j : index22 }23 }24 // CHECK: scf.execute_region25 // CHECK-NOT: scf.for26 // CHECK: func.call @foo[[$SUFFIX]]27 scf.for %j = %arg0 to %arg1 step %arg2 {28 arith.addi %j, %j : index29 }30 return31}32 33module attributes {transform.with_named_sequence} {34 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {35 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op36 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for">37 // CHECK: = transform.loop.outline %{{.*}}38 transform.loop.outline %1 {func_name = "foo"} : (!transform.op<"scf.for">) -> (!transform.any_op, !transform.any_op)39 transform.yield40 }41}42 43// -----44 45// CHECK-LABEL: @loop_peel_op46func.func @loop_peel_op() {47 // CHECK: %[[C0:.+]] = arith.constant 048 // CHECK: %[[C41:.+]] = arith.constant 4149 // CHECK: %[[C5:.+]] = arith.constant 550 // CHECK: %[[C40:.+]] = arith.constant 4051 // CHECK: scf.for %{{.+}} = %[[C0]] to %[[C40]] step %[[C5]]52 // CHECK: arith.addi53 // CHECK: scf.for %{{.+}} = %[[C40]] to %[[C41]] step %[[C5]]54 // CHECK: arith.addi55 %0 = arith.constant 0 : index56 %1 = arith.constant 41 : index57 %2 = arith.constant 5 : index58 // expected-remark @below {{main loop}}59 // expected-remark @below {{remainder loop}}60 scf.for %i = %0 to %1 step %2 {61 arith.addi %i, %i : index62 }63 return64}65 66module attributes {transform.with_named_sequence} {67 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {68 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op69 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for">70 %main_loop, %remainder = transform.loop.peel %1 : (!transform.op<"scf.for">) -> (!transform.op<"scf.for">, !transform.op<"scf.for">)71 // Make sure 72 transform.debug.emit_remark_at %main_loop, "main loop" : !transform.op<"scf.for">73 transform.debug.emit_remark_at %remainder, "remainder loop" : !transform.op<"scf.for">74 transform.yield75 }76}77 78// -----79 80// CHECK-LABEL: @loop_peel_first_iter_op81func.func @loop_peel_first_iter_op() {82 // CHECK: %[[C0:.+]] = arith.constant 083 // CHECK: %[[C41:.+]] = arith.constant 4184 // CHECK: %[[C5:.+]] = arith.constant 585 // CHECK: %[[C5_0:.+]] = arith.constant 586 // CHECK: scf.for %{{.+}} = %[[C0]] to %[[C5_0]] step %[[C5]]87 // CHECK: arith.addi88 // CHECK: scf.for %{{.+}} = %[[C5_0]] to %[[C41]] step %[[C5]]89 // CHECK: arith.addi90 %0 = arith.constant 0 : index91 %1 = arith.constant 41 : index92 %2 = arith.constant 5 : index93 scf.for %i = %0 to %1 step %2 {94 arith.addi %i, %i : index95 }96 return97}98 99module attributes {transform.with_named_sequence} {100 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {101 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op102 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for">103 %main_loop, %remainder = transform.loop.peel %1 {peel_front = true} : (!transform.op<"scf.for">) -> (!transform.op<"scf.for">, !transform.op<"scf.for">)104 transform.yield105 }106}107 108// -----109 110func.func @loop_pipeline_op(%A: memref<?xf32>, %result: memref<?xf32>) {111 %c0 = arith.constant 0 : index112 %c1 = arith.constant 1 : index113 %c4 = arith.constant 4 : index114 %cf = arith.constant 1.0 : f32115 // CHECK: memref.load %[[MEMREF:.+]][%{{.+}}]116 // CHECK: memref.load %[[MEMREF]]117 // CHECK: arith.addf118 // CHECK: scf.for119 // CHECK: memref.load120 // CHECK: arith.addf121 // CHECK: memref.store122 // CHECK: arith.addf123 // CHECK: memref.store124 // CHECK: memref.store125 // expected-remark @below {{transformed}}126 scf.for %i0 = %c0 to %c4 step %c1 {127 %A_elem = memref.load %A[%i0] : memref<?xf32>128 %A1_elem = arith.addf %A_elem, %cf : f32129 memref.store %A1_elem, %result[%i0] : memref<?xf32>130 }131 return132}133 134module attributes {transform.with_named_sequence} {135 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {136 %0 = transform.structured.match ops{["arith.addf"]} in %arg1 : (!transform.any_op) -> !transform.any_op137 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for">138 %2 = transform.loop.pipeline %1 : (!transform.op<"scf.for">) -> !transform.any_op139 // Verify that the returned handle is usable.140 transform.debug.emit_remark_at %2, "transformed" : !transform.any_op141 transform.yield142 }143}144 145// -----146 147// CHECK-LABEL: @loop_unroll_op148func.func @loop_unroll_op() {149 %c0 = arith.constant 0 : index150 %c42 = arith.constant 42 : index151 %c5 = arith.constant 5 : index152 // CHECK: scf.for %[[I:.+]] =153 scf.for %i = %c0 to %c42 step %c5 {154 // CHECK-COUNT-4: arith.addi %[[I]]155 arith.addi %i, %i : index156 }157 return158}159 160module attributes {transform.with_named_sequence} {161 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {162 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op163 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for">164 transform.loop.unroll %1 { factor = 4 } : !transform.op<"scf.for">165 transform.yield166 }167}168 169// -----170 171// CHECK-LABEL: @loop_unroll_and_jam_op172func.func @loop_unroll_and_jam_op() {173 // CHECK: %[[VAL_0:.*]] = arith.constant 0 : index174 // CHECK: %[[VAL_1:.*]] = arith.constant 40 : index175 // CHECK: %[[VAL_2:.*]] = arith.constant 2 : index176 // CHECK: %[[FACTOR:.*]] = arith.constant 4 : index177 // CHECK: %[[STEP:.*]] = arith.constant 8 : index178 %c0 = arith.constant 0 : index179 %c40 = arith.constant 40 : index180 %c2 = arith.constant 2 : index181 // CHECK: scf.for %[[VAL_5:.*]] = %[[VAL_0]] to %[[VAL_1]] step %[[STEP]] {182 scf.for %i = %c0 to %c40 step %c2 {183 // CHECK: %[[VAL_6:.*]] = arith.addi %[[VAL_5]], %[[VAL_5]] : index184 // CHECK: %[[VAL_7:.*]] = arith.constant 2 : index185 // CHECK: %[[VAL_8:.*]] = arith.addi %[[VAL_5]], %[[VAL_7]] : index186 // CHECK: %[[VAL_9:.*]] = arith.addi %[[VAL_8]], %[[VAL_8]] : index187 // CHECK: %[[VAL_10:.*]] = arith.constant 4 : index188 // CHECK: %[[VAL_11:.*]] = arith.addi %[[VAL_5]], %[[VAL_10]] : index189 // CHECK: %[[VAL_12:.*]] = arith.addi %[[VAL_11]], %[[VAL_11]] : index190 // CHECK: %[[VAL_13:.*]] = arith.constant 6 : index191 // CHECK: %[[VAL_14:.*]] = arith.addi %[[VAL_5]], %[[VAL_13]] : index192 // CHECK: %[[VAL_15:.*]] = arith.addi %[[VAL_14]], %[[VAL_14]] : index193 arith.addi %i, %i : index194 }195 return196}197 198module attributes {transform.with_named_sequence} {199 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {200 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op201 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for">202 transform.loop.unroll_and_jam %1 { factor = 4 } : !transform.op<"scf.for">203 transform.yield204 }205}206 207// -----208 209// CHECK-LABEL: @loop_unroll_and_jam_op210// CHECK: %[[VAL_0:.*]]: memref<96x128xi8, 3>, %[[VAL_1:.*]]: memref<128xi8, 3>) {211func.func private @loop_unroll_and_jam_op(%arg0: memref<96x128xi8, 3>, %arg1: memref<128xi8, 3>) {212 // CHECK: %[[UB_INNER:.*]] = arith.constant 96213 // CHECK: %[[STEP_INNER:.*]] = arith.constant 1214 // CHECK: %[[UB_OUTER:.*]] = arith.constant 128215 // CHECK: %[[LB:.*]] = arith.constant 0216 // CHECK: %[[UNUSED:.*]] = arith.constant 4217 // CHECK: %[[UNROLL_FACTOR:.*]] = arith.constant 4218 %c96 = arith.constant 96 : index219 %c1 = arith.constant 1 : index220 %c128 = arith.constant 128 : index221 %c0 = arith.constant 0 : index222 // CHECK: scf.for %[[OUTER_I:.*]] = %[[LB]] to %[[UB_OUTER]] step %[[UNROLL_FACTOR]] {223 scf.for %arg2 = %c0 to %c128 step %c1 {224 // CHECK: %[[LOAD0:.*]] = memref.load %[[VAL_1]]{{\[}}%[[OUTER_I]]]225 // CHECK: %[[ONE_0:.*]] = arith.constant 1226 // CHECK: %[[INC_LOAD1:.*]] = arith.addi %[[OUTER_I]], %[[ONE_0]]227 // CHECK: %[[LOAD1:.*]] = memref.load %[[VAL_1]]{{\[}}%[[INC_LOAD1]]]228 // CHECK: %[[TWO_0:.*]] = arith.constant 2229 // CHECK: %[[INC_LOAD2:.*]] = arith.addi %[[OUTER_I]], %[[TWO_0]]230 // CHECK: %[[LOAD2:.*]] = memref.load %[[VAL_1]]{{\[}}%[[INC_LOAD2]]]231 // CHECK: %[[THREE_0:.*]] = arith.constant 3232 // CHECK: %[[INC_LOAD3:.*]] = arith.addi %[[OUTER_I]], %[[THREE_0]]233 // CHECK: %[[LOAD3:.*]] = memref.load %[[VAL_1]]{{\[}}%[[INC_LOAD3]]]234 %3 = memref.load %arg1[%arg2] : memref<128xi8, 3>235 // CHECK: %[[VAL_19:.*]]:4 = scf.for %[[VAL_20:.*]] = %[[LB]] to %[[UB_INNER]] step %[[STEP_INNER]] iter_args(%[[VAL_21:.*]] = %[[LOAD0]], %[[VAL_22:.*]] = %[[LOAD1]], %[[VAL_23:.*]] = %[[LOAD2]], %[[VAL_24:.*]] = %[[LOAD3]])236 %sum = scf.for %arg3 = %c0 to %c96 step %c1 iter_args(%does_not_alias_aggregated = %3) -> (i8) {237 // CHECK: %[[LOAD0_INNER:.*]] = memref.load %[[VAL_0]]{{\[}}%[[VAL_20]], %[[OUTER_I]]]238 // CHECK: %[[SUM_0:.*]] = arith.addi %[[LOAD0_INNER]], %[[LOAD0]]239 // CHECK: %[[ONE_1:.*]] = arith.constant 1240 // CHECK: %[[INC1_INNER:.*]] = arith.addi %[[OUTER_I]], %[[ONE_1]]241 // CHECK: %[[LOAD1_INNER:.*]] = memref.load %[[VAL_0]]{{\[}}%[[VAL_20]], %[[INC1_INNER]]]242 // CHECK: %[[SUM_1:.*]] = arith.addi %[[LOAD1_INNER]], %[[LOAD1]]243 // CHECK: %[[TWO_1:.*]] = arith.constant 2244 // CHECK: %[[INC2_INNER:.*]] = arith.addi %[[OUTER_I]], %[[TWO_1]]245 // CHECK: %[[LOAD2_INNER:.*]] = memref.load %[[VAL_0]]{{\[}}%[[VAL_20]], %[[INC2_INNER]]]246 // CHECK: %[[SUM_2:.*]] = arith.addi %[[LOAD2_INNER]], %[[LOAD2]]247 // CHECK: %[[THREE_1:.*]] = arith.constant 3248 // CHECK: %[[INC3_INNER:.*]] = arith.addi %[[OUTER_I]], %[[THREE_1]]249 // CHECK: %[[LOAD3_INNER:.*]] = memref.load %[[VAL_0]]{{\[}}%[[VAL_20]], %[[INC3_INNER]]]250 // CHECK: %[[SUM_3:.*]] = arith.addi %[[LOAD3_INNER]], %[[LOAD3]]251 %2 = memref.load %arg0[%arg3, %arg2] : memref<96x128xi8, 3>252 %4 = arith.addi %2, %3 : i8253 // CHECK: scf.yield %[[SUM_0]], %[[SUM_1]], %[[SUM_2]], %[[SUM_3]]254 scf.yield %4 : i8255 }256 memref.store %sum, %arg1[%arg2] : memref<128xi8, 3>257 // CHECK: memref.store %[[VAL_39:.*]]#0, %[[VAL_1]]{{\[}}%[[OUTER_I]]]258 // CHECK: %[[ONE_2:.*]] = arith.constant 1259 // CHECK: %[[INC_STORE1:.*]] = arith.addi %[[OUTER_I]], %[[ONE_2]]260 // CHECK: memref.store %[[VAL_39]]#1, %[[VAL_1]]{{\[}}%[[INC_STORE1]]]261 // CHECK: %[[TWO_2:.*]] = arith.constant 2262 // CHECK: %[[INC_STORE2:.*]] = arith.addi %[[OUTER_I]], %[[TWO_2]]263 // CHECK: memref.store %[[VAL_39]]#2, %[[VAL_1]]{{\[}}%[[INC_STORE2]]]264 // CHECK: %[[THREE_2:.*]] = arith.constant 3265 // CHECK: %[[INC_STORE3:.*]] = arith.addi %[[OUTER_I]], %[[THREE_2]]266 // CHECK: memref.store %[[VAL_39]]#3, %[[VAL_1]]{{\[}}%[[INC_STORE3]]]267 }268 return269}270 271module attributes {transform.with_named_sequence} {272 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {273 %0 = transform.structured.match ops{["memref.store"]} in %arg1 : (!transform.any_op) -> !transform.any_op274 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for">275 transform.loop.unroll_and_jam %1 { factor = 4 } : !transform.op<"scf.for">276 transform.yield277 }278}279 280// -----281 282// CHECK-LABEL: @loop_unroll_and_jam_op283func.func @loop_unroll_and_jam_op() {284 // CHECK: %[[ZERO:.*]] = arith.constant 0285 // CHECK: %[[UNUSED_FACTOR:.*]] = arith.constant 4286 // CHECK: %[[UNUSED_STEP:.*]] = arith.constant 2287 // CHECK: %[[UNUSED_STEP2:.*]] = arith.constant 2288 // CHECK: %[[UNUSED_UB:.*]] = arith.constant 4289 // CHECK: %[[ITER_0_RES:.*]] = arith.addi %[[ZERO]], %[[ZERO]]290 // CHECK: %[[TWO:.*]] = arith.constant 2291 // CHECK: %[[STEP_1_I:.*]] = arith.addi %[[ZERO]], %[[TWO]]292 // CHECK: %[[ITER_1_RES:.*]] = arith.addi %[[STEP_1_I]], %[[STEP_1_I]]293 %c0 = arith.constant 0 : index294 %c4 = arith.constant 4 : index295 %c2 = arith.constant 2 : index296 scf.for %i = %c0 to %c4 step %c2 {297 arith.addi %i, %i : index298 }299 return300}301 302module attributes {transform.with_named_sequence} {303 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {304 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op305 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for">306 transform.loop.unroll_and_jam %1 { factor = 4 } : !transform.op<"scf.for">307 transform.yield308 }309}310 311// -----312 313// CHECK-LABEL: @loop_unroll_and_jam_op314func.func @loop_unroll_and_jam_op() {315 // CHECK: %[[LB:.*]] = arith.constant 0316 // CHECK: %[[UB:.*]] = arith.constant 4317 // CHECK: %[[STEP:.*]] = arith.constant 2318 %c0 = arith.constant 0 : index319 %c4 = arith.constant 4 : index320 %c2 = arith.constant 2 : index321 // CHECK: scf.for %[[I:.*]] = %[[LB]] to %[[UB]] step %[[STEP]] {322 scf.for %i = %c0 to %c4 step %c2 {323 scf.yield324 }325 return326}327 328module attributes {transform.with_named_sequence} {329 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {330 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op331 %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.op<"scf.for">332 transform.loop.unroll_and_jam %1 { factor = 2 } : !transform.op<"scf.for">333 transform.yield334 }335}336 337// -----338 339// CHECK-LABEL: @loop_unroll_and_jam_op340// CHECK: %[[VAL_0:.*]]: memref<21x30xf32, 1>, %[[INIT0:.*]]: f32, %[[INIT1:.*]]: f32) {341func.func @loop_unroll_and_jam_op(%arg0: memref<21x30xf32, 1>, %init : f32, %init1 : f32) {342 // CHECK: %[[LAST_OUT_ITER:.*]] = arith.constant 20343 // CHECK: %[[VAL_4:.*]]:2 = affine.for %[[OUTER_I:.*]] = 0 to 20 step 2 iter_args(%[[VAL_6:.*]] = %[[INIT0]], %[[VAL_7:.*]] = %[[INIT0]])344 %0 = affine.for %arg3 = 0 to 21 iter_args(%arg4 = %init) -> (f32) {345 // CHECK: %[[VAL_8:.*]]:2 = affine.for %[[INNER_I:.*]] = 0 to 30 iter_args(%[[SUM0:.*]] = %[[INIT1]], %[[SUM1:.*]] = %[[INIT1]])346 %1 = affine.for %arg5 = 0 to 30 iter_args(%arg6 = %init1) -> (f32) {347 // CHECK: %[[LOAD0:.*]] = affine.load %[[VAL_0]]{{\[}}%[[OUTER_I]], %[[INNER_I]]]348 // CHECK: %[[ITER_SUM0:.*]] = arith.addf %[[SUM0]], %[[LOAD0]]349 // CHECK: %[[APPLY_OUTER_I:.*]] = affine.apply #map(%[[OUTER_I]])350 // CHECK: %[[LOAD1:.*]] = affine.load %[[VAL_0]]{{\[}}%[[APPLY_OUTER_I]], %[[INNER_I]]]351 // CHECK: %[[ITER_SUM1:.*]] = arith.addf %[[SUM1]], %[[LOAD1]]352 // CHECK: affine.yield %[[ITER_SUM0]], %[[ITER_SUM1]]353 %3 = affine.load %arg0[%arg3, %arg5] : memref<21x30xf32, 1>354 %4 = arith.addf %arg6, %3 : f32355 affine.yield %4 : f32356 }357 // CHECK: %[[MUL0:.*]] = arith.mulf %[[VAL_6]], %[[VAL_18:.*]]#0358 // CHECK: %[[VAL_19:.*]] = affine.apply #map(%[[OUTER_I]])359 // CHECK: %[[MUL1:.*]] = arith.mulf %[[VAL_7]], %[[VAL_18]]#1360 // CHECK: affine.yield %[[MUL0]], %[[MUL1]]361 // CHECK: }362 // CHECK: %[[VAL_21:.*]] = arith.mulf %[[VAL_22:.*]]#0, %[[VAL_22]]#1363 // CHECK: %[[VAL_23:.*]] = affine.for %[[SUFFIX_I:.*]] = 0 to 30 iter_args(%[[ITER_I:.*]] = %[[INIT1]])364 // CHECK: %[[LOAD_SUFFIX:.*]] = affine.load %[[VAL_0]]{{\[}}%[[LAST_OUT_ITER]], %[[SUFFIX_I]]]365 // CHECK: %[[RES:.*]] = arith.addf %[[ITER_I]], %[[LOAD_SUFFIX]]366 // CHECK: affine.yield %[[RES]]367 %2 = arith.mulf %arg4, %1 : f32368 affine.yield %2 : f32369 }370 // CHECK: %[[VAL_28:.*]] = arith.mulf %[[VAL_21]], %[[VAL_29:.*]]371 return372}373 374module attributes {transform.with_named_sequence} {375 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {376 %0 = transform.structured.match ops{["arith.addf"]} in %arg1 : (!transform.any_op) -> !transform.any_op377 %1 = transform.get_parent_op %0 {op_name = "affine.for"} : (!transform.any_op) -> !transform.op<"affine.for">378 %2 = transform.get_parent_op %1 {op_name = "affine.for"} : (!transform.op<"affine.for">) -> !transform.op<"affine.for">379 transform.loop.unroll_and_jam %2 { factor = 2 } : !transform.op<"affine.for">380 transform.yield381 }382}383 384// -----385 386func.func @loop_unroll_op() {387 %c0 = arith.constant 0 : index388 %c42 = arith.constant 42 : index389 %c5 = arith.constant 5 : index390 // CHECK: affine.for %[[I:.+]] =391 // expected-remark @below {{affine for loop}}392 affine.for %i = %c0 to %c42 {393 // CHECK-COUNT-4: arith.addi394 arith.addi %i, %i : index395 }396 return397}398 399module attributes {transform.with_named_sequence} {400 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {401 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op402 %1 = transform.get_parent_op %0 {op_name = "affine.for"} : (!transform.any_op) -> !transform.op<"affine.for">403 transform.debug.emit_remark_at %1, "affine for loop" : !transform.op<"affine.for">404 transform.loop.unroll %1 { factor = 4, affine = true } : !transform.op<"affine.for">405 transform.yield406 }407}408 409// -----410 411func.func @test_mixed_loops() {412 %c0 = arith.constant 0 : index413 %c42 = arith.constant 42 : index414 %c5 = arith.constant 5 : index415 scf.for %j = %c0 to %c42 step %c5 {416 // CHECK: affine.for %[[I:.+]] =417 // expected-remark @below {{affine for loop}}418 affine.for %i = %c0 to %c42 {419 // CHECK-COUNT-4: arith.addi420 arith.addi %i, %i : index421 }422 }423 return424}425 426module attributes {transform.with_named_sequence} {427 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {428 %0 = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op429 %1 = transform.get_parent_op %0 {op_name = "affine.for"} : (!transform.any_op) -> !transform.op<"affine.for">430 transform.debug.emit_remark_at %1, "affine for loop" : !transform.op<"affine.for">431 transform.loop.unroll %1 { factor = 4 } : !transform.op<"affine.for">432 transform.yield433 }434}435 436// -----437 438// CHECK-LABEL: func @test_promote_if_one_iteration(439// CHECK-NOT: scf.for440// CHECK: %[[r:.*]] = "test.foo"441// CHECK: return %[[r]]442func.func @test_promote_if_one_iteration(%a: index) -> index {443 %c0 = arith.constant 0 : index444 %c1 = arith.constant 1 : index445 %0 = scf.for %j = %c0 to %c1 step %c1 iter_args(%arg0 = %a) -> index {446 %1 = "test.foo"(%a) : (index) -> (index)447 scf.yield %1 : index448 }449 return %0 : index450}451 452module attributes {transform.with_named_sequence} {453 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {454 %0 = transform.structured.match ops{["scf.for"]} in %arg1 : (!transform.any_op) -> !transform.any_op455 transform.loop.promote_if_one_iteration %0 : !transform.any_op456 transform.yield457 }458}459 460 461// -----462 463// CHECK-LABEL: func @test_structural_conversion_patterns(464// CHECK: scf.for {{.*}} -> (memref<f32>) {465 466func.func @test_structural_conversion_patterns(%a: tensor<f32>) -> tensor<f32> {467 %c0 = arith.constant 0 : index468 %c1 = arith.constant 1 : index469 %c10 = arith.constant 10 : index470 %0 = scf.for %j = %c0 to %c10 step %c1 iter_args(%arg0 = %a) -> tensor<f32> {471 %1 = "test.foo"(%arg0) : (tensor<f32>) -> (tensor<f32>)472 scf.yield %1 : tensor<f32>473 }474 return %0 : tensor<f32>475}476 477module attributes {transform.with_named_sequence} {478 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {479 %0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op480 transform.apply_conversion_patterns to %0 {481 transform.apply_conversion_patterns.scf.structural_conversions482 } with type_converter {483 transform.apply_conversion_patterns.transform.test_type_converter484 } { partial_conversion } : !transform.any_op485 transform.yield486 }487}488 489// -----490 491// CHECK-LABEL: func @coalesce_i32_loops(492 493// This test checks for loop coalescing success for non-index loop boundaries and step type494func.func @coalesce_i32_loops() {495 // CHECK: %[[VAL_0:.*]] = arith.constant 0 : i32496 // CHECK: %[[VAL_1:.*]] = arith.constant 128 : i32497 // CHECK: %[[VAL_2:.*]] = arith.constant 2 : i32498 // CHECK: %[[VAL_3:.*]] = arith.constant 64 : i32499 %0 = arith.constant 0 : i32500 %1 = arith.constant 128 : i32501 %2 = arith.constant 2 : i32502 %3 = arith.constant 64 : i32503 // CHECK: %[[VAL_4:.*]] = arith.constant 64 : i32504 // CHECK: %[[ZERO:.*]] = arith.constant 0 : i32505 // CHECK: %[[ONE:.*]] = arith.constant 1 : i32506 // CHECK: %[[VAL_7:.*]] = arith.constant 32 : i32507 // CHECK: %[[VAL_8:.*]] = arith.constant 0 : i32508 // CHECK: %[[VAL_9:.*]] = arith.constant 1 : i32509 // CHECK: %[[UB:.*]] = arith.muli %[[VAL_4]], %[[VAL_7]] : i32510 // CHECK: scf.for %[[VAL_11:.*]] = %[[ZERO]] to %[[UB]] step %[[ONE]] : i32 {511 scf.for %i = %0 to %1 step %2 : i32 {512 scf.for %j = %0 to %3 step %2 : i32 {513 arith.addi %i, %j : i32514 }515 } {coalesce}516 return517}518 519module attributes {transform.with_named_sequence} {520 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {521 %0 = transform.structured.match ops{["scf.for"]} attributes {coalesce} in %arg1 : (!transform.any_op) -> !transform.any_op522 %1 = transform.cast %0 : !transform.any_op to !transform.op<"scf.for">523 %2 = transform.loop.coalesce %1: (!transform.op<"scf.for">) -> (!transform.op<"scf.for">)524 transform.yield525 }526}527 528 529// -----530 531// CHECK-LABEL: func.func @loop_pipeline532func.func @loop_pipeline(%arg0: memref<4x16xf32>, %arg1: vector<16xf32>) -> vector<16xf32> {533 %c0 = arith.constant 0 : index534 %c1 = arith.constant 1 : index535 %cst = arith.constant 0.000000e+00 : f32536 %c3 = arith.constant 3 : index537 // CHECK: vector.transfer_read538 // CHECK: vector.transfer_read539 // CHECK: vector.transfer_read540 // CHECK: arith.addf541 // CHECK: arith.addf542 // CHECK: arith.addf543 %0 = scf.for %arg2 = %c0 to %c3 step %c1 iter_args(%arg3 = %arg1) -> (vector<16xf32>) {544 %1 = vector.transfer_read %arg0[%arg2, %c0], %cst {in_bounds = [true]} : memref<4x16xf32>, vector<16xf32>545 %2 = arith.addf %1, %arg3 : vector<16xf32>546 scf.yield %2 : vector<16xf32>547 }548 return %0 : vector<16xf32>549}550module attributes {transform.with_named_sequence} {551 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {552 %0 = transform.structured.match ops{["scf.for"]} in %arg1 : (!transform.any_op) -> !transform.op<"scf.for">553 %1 = transform.loop.pipeline %0 {iteration_interval = 1 : i64, read_latency = 5 : i64, scheduling_type = "full-loops"} : (!transform.op<"scf.for">) -> !transform.any_op554 transform.yield555 }556}557 558 559// -----560 561// CHECK-LABEL: func.func @loop_pipeline_lb_gt_0562func.func @loop_pipeline_lb_gt_0(%arg0: memref<4x16xf32>, %arg1: vector<16xf32>) -> vector<16xf32> {563 %c1 = arith.constant 1 : index564 %cst = arith.constant 0.000000e+00 : f32565 %c3 = arith.constant 3 : index566 // CHECK: vector.transfer_read567 // CHECK: vector.transfer_read568 // CHECK: arith.addf569 // CHECK: arith.addf570 %0 = scf.for %arg2 = %c1 to %c3 step %c1 iter_args(%arg3 = %arg1) -> (vector<16xf32>) {571 %1 = vector.transfer_read %arg0[%arg2, %c1], %cst {in_bounds = [true]} : memref<4x16xf32>, vector<16xf32>572 %2 = arith.addf %1, %arg3 : vector<16xf32>573 scf.yield %2 : vector<16xf32>574 }575 return %0 : vector<16xf32>576}577module attributes {transform.with_named_sequence} {578 transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {579 %0 = transform.structured.match ops{["scf.for"]} in %arg1 : (!transform.any_op) -> !transform.op<"scf.for">580 %1 = transform.loop.pipeline %0 {iteration_interval = 1 : i64, read_latency = 5 : i64, scheduling_type = "full-loops"} : (!transform.op<"scf.for">) -> !transform.any_op581 transform.yield582 }583}584