xref: /llvm-project/mlir/test/Dialect/SCF/transform-ops-invalid.mlir (revision cb8bd6f77235ee15bbe549c8f3486392b8966447)
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