469 lines · plain
1// RUN: mlir-opt --transform-interpreter --split-input-file --verify-diagnostics %s2 3// expected-note @below {{ancestor payload op}}4func.func @func() {5 // expected-note @below {{nested payload op}}6 return7}8 9module attributes {transform.with_named_sequence} {10 transform.named_sequence @__transform_main(%root: !transform.any_op) {11 transform.with_pdl_patterns %root : !transform.any_op {12 ^bb0(%arg0: !transform.any_op):13 pdl.pattern @return : benefit(1) {14 %0 = operands15 %1 = types16 %2 = operation "func.return"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)17 rewrite %2 with "transform.dialect"18 }19 20 sequence %arg0 : !transform.any_op failures(propagate) {21 ^bb1(%arg1: !transform.any_op):22 // expected-note @below {{handle to invalidated ops}}23 %0 = pdl_match @return in %arg1 : (!transform.any_op) -> !transform.any_op24 %1 = get_parent_op %0 {isolated_from_above} : (!transform.any_op) -> !transform.any_op25 // expected-note @below {{invalidated by this transform op that consumes its operand #0}}26 test_consume_operand %1 : !transform.any_op27 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}28 transform.debug.emit_remark_at %0, "remark" : !transform.any_op29 }30 }31 transform.yield32 }33}34 35// -----36 37func.func @func1() {38 // expected-note @below {{repeated target op}}39 return40}41func.func private @func2()42 43module attributes {transform.with_named_sequence} {44 transform.named_sequence @__transform_main(%root: !transform.any_op) {45 transform.with_pdl_patterns %root : !transform.any_op {46 ^bb0(%arg0: !transform.any_op):47 pdl.pattern @func : benefit(1) {48 %0 = operands49 %1 = types50 %2 = operation "func.func"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)51 rewrite %2 with "transform.dialect"52 }53 pdl.pattern @return : benefit(1) {54 %0 = operands55 %1 = types56 %2 = operation "func.return"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)57 rewrite %2 with "transform.dialect"58 }59 60 sequence %arg0 : !transform.any_op failures(propagate) {61 ^bb1(%arg1: !transform.any_op):62 %0 = pdl_match @func in %arg1 : (!transform.any_op) -> !transform.any_op63 %1 = pdl_match @return in %arg1 : (!transform.any_op) -> !transform.any_op64 %2 = replicate num(%0) %1 : !transform.any_op, !transform.any_op65 // expected-error @below {{a handle passed as operand #0 and consumed by this operation points to a payload entity more than once}}66 test_consume_operand %2 : !transform.any_op67 transform.debug.emit_remark_at %0, "remark" : !transform.any_op68 }69 }70 transform.yield71 }72}73 74 75// -----76 77// expected-note @below {{ancestor payload op}}78// expected-note @below {{nested payload op}}79module attributes {transform.with_named_sequence} {80 81 transform.named_sequence @__transform_main(%0: !transform.any_op) {82 %1 = transform.test_copy_payload %0 : (!transform.any_op) -> !transform.any_op83 // expected-note @below {{handle to invalidated ops}}84 %2 = transform.test_copy_payload %0 : (!transform.any_op) ->!transform.any_op85 // expected-note @below {{invalidated by this transform op that consumes its operand #0}}86 transform.test_consume_operand %1 : !transform.any_op87 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}88 transform.test_consume_operand %2 : !transform.any_op89 transform.yield90 }91}92 93// -----94 95// expected-note @below {{ancestor payload op}}96// expected-note @below {{nested payload op}}97module attributes {transform.with_named_sequence} {98 99 transform.named_sequence @__transform_main(%0: !transform.any_op) {100 %1 = transform.test_copy_payload %0 : (!transform.any_op) -> !transform.any_op101 // expected-note @below {{handle to invalidated ops}}102 %2 = transform.test_copy_payload %0 : (!transform.any_op) -> !transform.any_op103 // Consuming two handles in the same operation is invalid if they point104 // to overlapping sets of payload IR ops.105 //106 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}107 // expected-note @below {{invalidated by this transform op that consumes its operand #0 and invalidates all handles to payload IR entities}}108 transform.test_consume_operand %1, %2 : !transform.any_op, !transform.any_op109 transform.yield110 }111}112 113// -----114 115// Deduplication attribute allows "merge_handles" to take repeated operands.116 117module attributes {transform.with_named_sequence} {118 119 transform.named_sequence @__transform_main(%0: !transform.any_op) {120 %1 = transform.test_copy_payload %0 : (!transform.any_op) -> !transform.any_op121 %2 = transform.test_copy_payload %0 : (!transform.any_op) -> !transform.any_op122 transform.merge_handles %1, %2 { deduplicate } : !transform.any_op123 transform.yield124 }125}126// -----127 128// expected-note @below {{payload value}}129%0 = "test.match_anchor"() : () -> (i32)130 131module attributes {transform.with_named_sequence} {132 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {133 %2 = transform.structured.match ops{["test.match_anchor"]} in %arg0 : (!transform.any_op) -> !transform.any_op134 %3 = transform.test_produce_value_handle_to_result %2, 0 : (!transform.any_op) -> !transform.any_value135 // expected-note @below {{invalidated handle}}136 %4 = transform.test_produce_value_handle_to_result %2, 0 : (!transform.any_op) -> !transform.any_value137 // expected-note @below {{invalidated by this transform op that consumes its operand #0 and invalidates handles to the same values as associated with it}}138 transform.test_consume_operand %3 : !transform.any_value139 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}140 transform.test_consume_operand %4 : !transform.any_value141 transform.yield142 }143}144 145// -----146 147// expected-note @below {{ancestor op associated with the consumed handle}}148// expected-note @below {{payload value}}149// expected-note @below {{op defining the value as result #0}}150%0 = "test.match_anchor"() : () -> (i32)151 152module attributes {transform.with_named_sequence} {153 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {154 %2 = transform.structured.match ops{["test.match_anchor"]} in %arg0 : (!transform.any_op) -> !transform.any_op155 // expected-note @below {{invalidated handle}}156 %3 = transform.test_produce_value_handle_to_result %2, 0 : (!transform.any_op) -> !transform.any_value157 // expected-note @below {{invalidated by this transform op that consumes its operand #0 and invalidates all handles to payload IR entities associated with this operand and entities nested in them}}158 transform.test_consume_operand %2 : !transform.any_op159 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}160 transform.test_consume_operand %3 : !transform.any_value161 transform.yield162 }163}164 165// -----166 167// expected-note @below {{ancestor op associated with the consumed handle}}168"test.match_anchor_1"() ({169^bb0:170 // expected-note @below {{op defining the value as result #0}}171 // expected-note @below {{payload value}}172 %0 = "test.match_anchor_2"() : () -> (i32)173 "test.region_terminator"() : () -> ()174}) : () -> ()175 176module attributes {transform.with_named_sequence} {177 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {178 %1 = transform.structured.match ops{["test.match_anchor_1"]} in %arg0 : (!transform.any_op) -> !transform.any_op179 %2 = transform.structured.match ops{["test.match_anchor_2"]} in %arg0 : (!transform.any_op) -> !transform.any_op180 // expected-note @below {{invalidated handle}}181 %3 = transform.test_produce_value_handle_to_result %2, 0 : (!transform.any_op) -> !transform.any_value182 // expected-note @below {{invalidated by this transform op that consumes its operand #0 and invalidates all handles to payload IR entities associated with this operand and entities nested in them}}183 transform.test_consume_operand %1 : !transform.any_op184 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}185 transform.test_consume_operand %3 : !transform.any_value186 transform.yield187 }188}189 190// -----191 192// expected-note @below {{ancestor op associated with the consumed handle}}193// expected-note @below {{op defining the value as block argument #0 of block #0 in region #0}}194"test.match_anchor_1"() ({195// expected-note @below {{payload value}}196^bb0(%arg0: i32):197 %0 = "test.match_anchor_2"() : () -> (i32)198 "test.region_terminator"() : () -> ()199}) : () -> ()200 201module attributes {transform.with_named_sequence} {202 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {203 %1 = transform.structured.match ops{["test.match_anchor_1"]} in %arg0 : (!transform.any_op) -> !transform.any_op204 %2 = transform.structured.match ops{["test.match_anchor_2"]} in %arg0 : (!transform.any_op) -> !transform.any_op205 // expected-note @below {{invalidated handle}}206 %3 = transform.test_produce_value_handle_to_argument_of_parent_block %2, 0 : (!transform.any_op) -> !transform.any_value207 // expected-note @below {{invalidated by this transform op that consumes its operand #0 and invalidates all handles to payload IR entities associated with this operand and entities nested in them}}208 transform.test_consume_operand %1 : !transform.any_op209 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}210 transform.test_consume_operand %3 : !transform.any_value211 transform.yield212 }213}214 215// -----216 217// expected-note @below {{ancestor op associated with the consumed handle}}218"test.match_anchor_1"() ({219^bb:220 // expected-note @below {{op defining the value as block argument #0 of block #0 in region #0}}221 "test.op_with_regions"() ({222 // expected-note @below {{payload value}}223 ^bb0(%arg0: i32):224 %0 = "test.match_anchor_2"() : () -> (i32)225 "test.region_terminator"() : () -> ()226 }): () -> ()227}) : () -> ()228 229module attributes {transform.with_named_sequence} {230 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {231 %1 = transform.structured.match ops{["test.match_anchor_1"]} in %arg0 : (!transform.any_op) -> !transform.any_op232 %2 = transform.structured.match ops{["test.match_anchor_2"]} in %arg0 : (!transform.any_op) -> !transform.any_op233 // expected-note @below {{invalidated handle}}234 %3 = transform.test_produce_value_handle_to_argument_of_parent_block %2, 0 : (!transform.any_op) -> !transform.any_value235 // expected-note @below {{invalidated by this transform op that consumes its operand #0 and invalidates all handles to payload IR entities associated with this operand and entities nested in them}}236 transform.test_consume_operand %1 : !transform.any_op237 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}238 transform.test_consume_operand %3 : !transform.any_value239 transform.yield240 }241}242 243// -----244 245// expected-note @below {{ancestor payload op}}246// expected-note @below {{nested payload op}}247// expected-note @below {{consumed handle points to this payload value}}248%0 = "test.match_anchor"() : () -> (i32)249 250module attributes {transform.with_named_sequence} {251 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {252 // expected-note @below {{handle to invalidated ops}}253 %2 = transform.structured.match ops{["test.match_anchor"]} in %arg0 : (!transform.any_op) -> !transform.any_op254 %3 = transform.test_produce_value_handle_to_result %2, 0 : (!transform.any_op) -> !transform.any_value255 // expected-note @below {{invalidated by this transform op that consumes its operand #0 and invalidates all handles to payload IR entities associated with this operand and entities nested in them}}256 transform.test_consume_operand %3 : !transform.any_value257 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}258 transform.test_consume_operand %2 : !transform.any_op 259 transform.yield260 }261}262 263// -----264 265// expected-note @below {{ancestor payload op}}266// expected-note @below {{consumed handle points to this payload value}}267%0 = "test.match_anchor_1"() ({268^bb0:269 // expected-note @below {{nested payload op}}270 "test.match_anchor_2"() : () -> ()271 "test.region_terminator"() : () -> ()272}) : () -> (i32)273 274module attributes {transform.with_named_sequence} {275 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {276 %1 = transform.structured.match ops{["test.match_anchor_1"]} in %arg0 : (!transform.any_op) -> !transform.any_op277 // expected-note @below {{handle to invalidated ops}}278 %2 = transform.structured.match ops{["test.match_anchor_2"]} in %arg0 : (!transform.any_op) -> !transform.any_op279 %3 = transform.test_produce_value_handle_to_result %1, 0 : (!transform.any_op) -> !transform.any_value280 // expected-note @below {{invalidated by this transform op that consumes its operand #0 and invalidates all handles to payload IR entities associated with this operand and entities nested in them}}281 transform.test_consume_operand %3 : !transform.any_value282 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}283 transform.test_consume_operand %2 : !transform.any_op284 transform.yield285 }286}287 288 289// -----290 291"test.match_anchor_1"() ({292// expected-note @below {{consumed handle points to this payload value}}293^bb0(%arg0: f32):294 // expected-note @below {{ancestor payload op}}295 // expected-note @below {{nested payload op}}296 "test.match_anchor_2"() : () -> ()297 "test.region_terminator"() : () -> ()298}) : () -> ()299 300module attributes {transform.with_named_sequence} {301 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {302 // expected-note @below {{handle to invalidated ops}}303 %2 = transform.structured.match ops{["test.match_anchor_2"]} in %arg0 : (!transform.any_op) -> !transform.any_op304 %3 = transform.test_produce_value_handle_to_argument_of_parent_block %2, 0 : (!transform.any_op) -> !transform.any_value305 // expected-note @below {{invalidated by this transform op that consumes its operand #0 and invalidates all handles to payload IR entities associated with this operand and entities nested in them}}306 transform.test_consume_operand %3 : !transform.any_value307 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}308 transform.test_consume_operand %2 : !transform.any_op309 transform.yield310 }311}312 313// -----314 315"test.op_with_regions"() ({316// expected-note @below {{consumed handle points to this payload value}}317^bb(%arg0: i32):318 // expected-note @below {{ancestor payload op}}319 "test.op_with_regions"() ({320 ^bb0:321 // expected-note @below {{nested payload op}}322 "test.match_anchor_2"() : () -> ()323 "test.region_terminator"() : () -> ()324 }): () -> ()325 "test.match_anchor_1"() : () -> ()326}) : () -> ()327 328module attributes {transform.with_named_sequence} {329 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {330 %1 = transform.structured.match ops{["test.match_anchor_1"]} in %arg0 : (!transform.any_op) -> !transform.any_op331 // expected-note @below {{handle to invalidated ops}}332 %2 = transform.structured.match ops{["test.match_anchor_2"]} in %arg0 : (!transform.any_op) -> !transform.any_op333 %3 = transform.test_produce_value_handle_to_argument_of_parent_block %1, 0 : (!transform.any_op) -> !transform.any_value334 // expected-note @below {{invalidated by this transform op that consumes its operand #0 and invalidates all handles to payload IR entities associated with this operand and entities nested in them}}335 transform.test_consume_operand %3 : !transform.any_value336 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}337 transform.test_consume_operand %2 : !transform.any_op338 transform.yield339 }340}341 342// -----343 344// Removing a block argument does not invalidate handles to operations in another block.345// Not expecting an error here.346 347"test.op_with_regions"() ({348^bb1(%arg0: i32):349 "test.match_anchor_1"() : () -> ()350^bb2:351 "test.match_anchor_2"() : () -> ()352}) : () -> ()353 354module attributes {transform.with_named_sequence} {355 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {356 %1 = transform.structured.match ops{["test.match_anchor_1"]} in %arg0 : (!transform.any_op) -> !transform.any_op357 %2 = transform.structured.match ops{["test.match_anchor_2"]} in %arg0 : (!transform.any_op) -> !transform.any_op358 %3 = transform.test_produce_value_handle_to_argument_of_parent_block %1, 0 : (!transform.any_op) -> !transform.any_value359 transform.test_consume_operand %3 : !transform.any_value360 transform.test_consume_operand %2 : !transform.any_op361 transform.yield362 }363}364 365// -----366 367module attributes {transform.with_named_sequence} {368 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {369 %0 = transform.test_produce_empty_payload : !transform.any_op370 // expected-note @below {{invalidated by this transform op that consumes its operand #0}}371 transform.test_consume_operand %0 : !transform.any_op372 // expected-error @below {{uses a handle associated with empty payload and invalidated by a previously executed transform op}}373 transform.debug.emit_remark_at %0, "remark" : !transform.any_op374 transform.yield375 }376}377 378// -----379 380// Make sure we properly report a use-after-consume error when repeated handles381// are allowed in the consuming op. We still want to report handles consumed by382// _previous_ operations, just not by this one. To bypass the quick static check383// of repeated consumption, create a handle to the transform operation and384// invalidate the handle to the root module thus invalidating all other handles.385 386// expected-note @below {{ancestor payload op}}387module attributes {transform.with_named_sequence} {388 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {389 // expected-note @below {{handle to invalidated ops}}390 // expected-note @below {{nested payload op}}391 %0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op392 // expected-note @below {{invalidated by this transform op that consumes its operand #0 and invalidates all handles to payload IR entities associated with this operand and entities nested in them}}393 transform.test_consume_operand %arg0 : !transform.any_op394 // expected-error @below {{uses a handle invalidated by a previously executed transform op}}395 transform.test_consume_operand %0 { allow_repeated_handles } : !transform.any_op396 transform.yield397 }398}399 400// -----401 402// Re-entering the region should not trigger the consumption error from previous403// execution of the region.404 405module attributes {transform.with_named_sequence} {406 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {407 transform.test_re_enter_region {408 %0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op409 transform.test_consume_operand %0 : !transform.any_op410 transform.yield411 }412 transform.yield413 }414}415 416// -----417 418// Re-entering the region should not trigger the consumption error from previous419// execution of the region.420 421module attributes {transform.with_named_sequence} {422 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {423 %0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op424 transform.test_re_enter_region %0 : !transform.any_op {425 ^bb0(%arg1: !transform.any_op):426 transform.test_consume_operand %arg1 : !transform.any_op427 transform.yield428 }429 transform.yield430 }431}432 433// -----434 435// Consuming the same handle repeatedly in the region should trigger an error.436module attributes {transform.with_named_sequence} {437 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {438 // expected-note @below {{payload op}}439 // expected-note @below {{handle to invalidated ops}}440 %0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op441 transform.test_re_enter_region {442 // expected-error @below {{op uses a handle invalidated by a previously executed transform op}}443 // expected-note @below {{invalidated by this transform op}}444 transform.test_consume_operand %0 : !transform.any_op445 transform.yield446 }447 transform.yield448 }449}450 451// -----452 453module @named_inclusion_and_consumption attributes { transform.with_named_sequence } {454 455 transform.named_sequence @foo(%arg0: !transform.any_op {transform.consumed}) -> () {456 // Consuming this handle removes the mapping from the current stack frame457 // mapping and from the caller's stack frame mapping. (If this were not458 // be the case, the "expensive checks" caching mechanism for op names459 // would throw an error saying that an op is mapped but not in the cache.)460 transform.test_consume_operand %arg0 : !transform.any_op461 transform.yield462 }463 464 transform.named_sequence @__transform_main(%arg0: !transform.any_op) {465 transform.include @foo failures(propagate) (%arg0) : (!transform.any_op) -> ()466 transform.yield467 }468}469