xref: /llvm-project/mlir/test/Dialect/Transform/test-interpreter.mlir (revision 1c352e66e7bac03a654cbd4c13c3bec6ed346048)
1// RUN: mlir-opt %s --transform-interpreter -allow-unregistered-dialect --split-input-file --verify-diagnostics | FileCheck %s
2
3// UNSUPPORTED: target=aarch64-pc-windows-msvc
4
5module attributes {transform.with_named_sequence} {
6  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
7    // expected-remark @below {{applying transformation}}
8    transform.test_transform_op
9    transform.yield
10  }
11}
12
13// -----
14
15module attributes {transform.with_named_sequence} {
16  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
17    %0 = transform.test_produce_self_handle_or_forward_operand { foo = "bar" } : () -> !transform.any_op
18    // expected-remark @below {{succeeded}}
19    transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
20    transform.yield
21  }
22}
23
24// -----
25
26module attributes {transform.with_named_sequence} {
27  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
28    %0 = transform.test_produce_self_handle_or_forward_operand { foo = "bar" } : () -> !transform.any_op
29    // expected-error @below {{expected the operand to be associated a payload op of kind transform.sequence got transform.test_produce_self_handle_or_forward_operand}}
30    transform.test_consume_operand_of_op_kind_or_fail %0, "transform.sequence" : !transform.any_op
31    transform.yield
32  }
33}
34
35// -----
36
37// It is okay to have multiple handles to the same payload op as long
38// as only one of them is consumed. The expensive checks mode is necessary
39// to detect double-consumption.
40module attributes {transform.with_named_sequence} {
41  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
42    %0 = transform.test_produce_self_handle_or_forward_operand { foo = "bar" } : () -> !transform.any_op
43    %1 = transform.test_copy_payload %0 : (!transform.any_op) -> !transform.any_op
44    // expected-remark @below {{succeeded}}
45    transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
46    transform.yield
47  }
48}
49
50// -----
51
52module attributes {transform.with_named_sequence} {
53  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
54    transform.sequence %arg0 : !transform.any_op failures(propagate) {
55    ^bb0(%arg1: !transform.any_op):
56      // expected-remark @below {{applying transformation "a"}}
57      test_transform_op "a"
58      // expected-remark @below {{applying transformation "b"}}
59      test_transform_op "b"
60      // expected-remark @below {{applying transformation "c"}}
61      test_transform_op "c"
62    }
63    // expected-remark @below {{applying transformation "d"}}
64    transform.test_transform_op "d"
65    // expected-remark @below {{applying transformation "e"}}
66    transform.test_transform_op "e"
67    transform.yield
68  }
69}
70
71// -----
72
73module attributes {transform.with_named_sequence} {
74  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
75    %0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
76    transform.sequence %0 : !transform.any_op failures(propagate) {
77    ^bb0(%arg1: !transform.any_op):
78      // expected-remark @below {{succeeded}}
79      test_consume_operand_of_op_kind_or_fail %arg1, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
80    }
81    transform.yield
82  }
83}
84
85// -----
86
87module attributes {transform.with_named_sequence} {
88  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
89    %0 = transform.sequence %arg0 : !transform.any_op -> !transform.any_op failures(propagate) {
90    ^bb0(%arg1: !transform.any_op):
91      %1 = test_produce_self_handle_or_forward_operand : () -> !transform.any_op
92      yield %1 : !transform.any_op
93    }
94    // expected-remark @below {{succeeded}}
95    transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
96    transform.yield
97  }
98}
99
100// -----
101
102// expected-remark @below {{parent function}}
103func.func @foo() {
104  %0 = arith.constant 0 : i32
105  return
106}
107
108// expected-remark @below {{parent function}}
109func.func @bar() {
110  %0 = arith.constant 0 : i32
111  %1 = arith.constant 1 : i32
112  return
113}
114
115module attributes {transform.with_named_sequence} {
116  transform.named_sequence @__transform_main(%root: !transform.any_op) {
117    transform.with_pdl_patterns %root : !transform.any_op {
118    ^bb0(%arg0: !transform.any_op):
119      pdl.pattern @const : benefit(1) {
120        %r = pdl.types
121        %0 = pdl.operation "arith.constant" -> (%r : !pdl.range<type>)
122        pdl.rewrite %0 with "transform.dialect"
123      }
124
125      transform.sequence %arg0 : !transform.any_op failures(propagate) {
126      ^bb1(%arg1: !transform.any_op):
127        %f = pdl_match @const in %arg1 : (!transform.any_op) -> !transform.any_op
128        %m = get_parent_op %f {isolated_from_above} : (!transform.any_op) -> !transform.any_op
129        transform.debug.emit_remark_at %m, "parent function" : !transform.any_op
130      }
131    }
132    transform.yield
133  }
134}
135
136// -----
137
138func.func @test_get_nth_parent() {
139  "test.foo"() ({
140    // expected-remark @below{{2nd parent}}
141    "test.foo"() ({
142      "test.qux"() ({
143        // expected-remark @below{{1st parent}}
144        "test.foo"() ({
145          "test.bar"() : () -> ()
146        }) : () -> ()
147      }) : () -> ()
148    }) : () -> ()
149  }) : () -> ()
150}
151
152module attributes {transform.with_named_sequence} {
153  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
154    %f = transform.structured.match ops{["test.bar"]} in %arg0 : (!transform.any_op) -> !transform.any_op
155    %parent = transform.get_parent_op %f {nth_parent = 1, op_name = "test.foo"} : (!transform.any_op) -> !transform.any_op
156    transform.debug.emit_remark_at %parent, "1st parent" : !transform.any_op
157    %parent2 = transform.get_parent_op %f {nth_parent = 2, op_name = "test.foo"} : (!transform.any_op) -> !transform.any_op
158    transform.debug.emit_remark_at %parent2, "2nd parent" : !transform.any_op
159    transform.yield
160  }
161}
162
163// -----
164
165func.func @foo() {
166  %0 = arith.constant 0 : i32
167  return
168}
169
170module attributes {transform.with_named_sequence} {
171  transform.named_sequence @__transform_main(%root: !transform.any_op) {
172    transform.with_pdl_patterns %root : !transform.any_op {
173    ^bb0(%arg0: !transform.any_op):
174      pdl.pattern @match_func : benefit(1) {
175        %0 = pdl.operands
176        %1 = pdl.types
177        %2 = pdl.operation "func.func"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
178        pdl.rewrite %2 with "transform.dialect"
179      }
180
181      transform.sequence %arg0 : !transform.any_op failures(propagate) {
182      ^bb1(%arg1: !transform.any_op):
183        // This is necessary to run the transformation on something other than the
184        // top-level module, "alternatives" cannot be run on that.
185        %0 = pdl_match @match_func in %arg1 : (!transform.any_op) -> !transform.any_op
186        transform.alternatives %0 : !transform.any_op {
187        ^bb2(%arg2: !transform.any_op):
188          %1 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
189          // This operation fails, which triggers the next alternative without
190          // reporting the error.
191          transform.test_consume_operand_of_op_kind_or_fail %1, "transform.sequence" : !transform.any_op
192        }, {
193        ^bb2(%arg2: !transform.any_op):
194          %1 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
195          // expected-remark @below {{succeeded}}
196          transform.test_consume_operand_of_op_kind_or_fail %1, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
197        }
198      }
199    }
200    transform.yield
201  }
202}
203
204// -----
205
206func.func private @bar()
207
208func.func @foo() {
209  call @bar() : () -> ()
210  return
211}
212
213module attributes {transform.with_named_sequence} {
214  transform.named_sequence @__transform_main(%root: !transform.any_op) {
215    transform.with_pdl_patterns %root : !transform.any_op {
216    ^bb0(%arg0: !transform.any_op):
217      pdl.pattern @match_call : benefit(1) {
218        %0 = pdl.operands
219        %1 = pdl.types
220        %2 = pdl.operation "func.call"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
221        pdl.rewrite %2 with "transform.dialect"
222      }
223
224      transform.sequence %arg0 : !transform.any_op failures(propagate) {
225      ^bb1(%arg1: !transform.any_op):
226        %0 = pdl_match @match_call in %arg1 : (!transform.any_op) -> !transform.any_op
227        %1 = get_parent_op %0 {isolated_from_above} : (!transform.any_op) -> !transform.any_op
228        // expected-error @below {{all alternatives failed}}
229        transform.alternatives %1 : !transform.any_op {
230        ^bb2(%arg2: !transform.any_op):
231          %2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
232          // expected-remark @below {{applying}}
233          transform.test_emit_remark_and_erase_operand %2, "applying" {fail_after_erase} : !transform.any_op
234        }
235      }
236    }
237    transform.yield
238  }
239}
240
241// -----
242
243func.func private @bar()
244
245func.func @foo() {
246  // expected-remark @below {{still here}}
247  call @bar() : () -> ()
248  return
249}
250
251module attributes {transform.with_named_sequence} {
252  transform.named_sequence @__transform_main(%root: !transform.any_op) {
253    transform.with_pdl_patterns %root : !transform.any_op {
254    ^bb0(%arg0: !transform.any_op):
255      pdl.pattern @match_call : benefit(1) {
256        %0 = pdl.operands
257        %1 = pdl.types
258        %2 = pdl.operation "func.call"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
259        pdl.rewrite %2 with "transform.dialect"
260      }
261
262      transform.sequence %arg0 : !transform.any_op failures(propagate) {
263      ^bb1(%arg1: !transform.any_op):
264        %0 = pdl_match @match_call in %arg1 : (!transform.any_op) -> !transform.any_op
265        %1 = get_parent_op %0 {isolated_from_above} : (!transform.any_op) -> !transform.any_op
266        transform.alternatives %1 : !transform.any_op {
267        ^bb2(%arg2: !transform.any_op):
268          %2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
269          // expected-remark @below {{applying}}
270          transform.test_emit_remark_and_erase_operand %2, "applying" {fail_after_erase} : !transform.any_op
271        }, {
272        ^bb2(%arg2: !transform.any_op):
273          %2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
274          transform.debug.emit_remark_at %2, "still here" : !transform.any_op
275          // This alternative succeeds.
276        }, {
277        ^bb2(%arg2: !transform.any_op):
278          // This alternative is never run, so we must not have a remark here.
279          %2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
280          transform.test_emit_remark_and_erase_operand %2, "should not happen" {fail_after_erase} : !transform.any_op
281        }
282      }
283    }
284    transform.yield
285  }
286}
287
288// -----
289
290func.func private @bar()
291
292func.func @erase_call() {
293  call @bar() : () -> ()
294  return
295}
296
297module attributes {transform.with_named_sequence} {
298  transform.named_sequence @__transform_main(%root: !transform.any_op) {
299    transform.with_pdl_patterns %root : !transform.any_op {
300    ^bb0(%arg0: !transform.any_op):
301      pdl.pattern @match_call : benefit(1) {
302        %0 = pdl.operands
303        %1 = pdl.types
304        %2 = pdl.operation "func.call"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
305        pdl.rewrite %2 with "transform.dialect"
306      }
307
308      transform.sequence %arg0 : !transform.any_op failures(propagate) {
309      ^bb1(%arg1: !transform.any_op):
310        %0 = pdl_match @match_call in %arg1 : (!transform.any_op) -> !transform.any_op
311        %1 = get_parent_op %0 {isolated_from_above} : (!transform.any_op) -> !transform.any_op
312        transform.alternatives %1 : !transform.any_op {
313        ^bb2(%arg2: !transform.any_op):
314          %2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
315          // expected-remark @below {{applying}}
316          transform.test_emit_remark_and_erase_operand %2, "applying" {fail_after_erase} : !transform.any_op
317        }, {
318        ^bb2(%arg2: !transform.any_op):
319          %2 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
320          // expected-remark @below {{applying second time}}
321          transform.test_emit_remark_and_erase_operand %2, "applying second time" : !transform.any_op
322        }
323      }
324    }
325    transform.yield
326  }
327}
328
329// -----
330
331func.func private @bar()
332
333func.func @foo() {
334  call @bar() : () -> ()
335  return
336}
337
338module attributes {transform.with_named_sequence} {
339  transform.named_sequence @__transform_main(%root: !transform.any_op) {
340    transform.with_pdl_patterns %root : !transform.any_op {
341    ^bb0(%arg0: !transform.any_op):
342      pdl.pattern @match_call : benefit(1) {
343        %0 = pdl.operands
344        %1 = pdl.types
345        %2 = pdl.operation "func.call"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
346        pdl.rewrite %2 with "transform.dialect"
347      }
348
349      transform.sequence %arg0 : !transform.any_op failures(propagate) {
350      ^bb1(%arg1: !transform.any_op):
351        %0 = pdl_match @match_call in %arg1 : (!transform.any_op) -> !transform.any_op
352        %1 = get_parent_op %0 {isolated_from_above} : (!transform.any_op) -> !transform.any_op
353        %2 = transform.alternatives %1 : !transform.any_op -> !transform.any_op {
354        ^bb2(%arg2: !transform.any_op):
355          %3 = transform.pdl_match @match_call in %arg2 : (!transform.any_op) -> !transform.any_op
356          // expected-remark @below {{applying}}
357          transform.test_emit_remark_and_erase_operand %3, "applying" {fail_after_erase} : !transform.any_op
358          %4 = transform.test_produce_self_handle_or_forward_operand %3 : (!transform.any_op) -> !transform.any_op
359          transform.yield %4 : !transform.any_op
360        }, {
361        ^bb2(%arg2: !transform.any_op):
362          %4 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
363          transform.yield %4 : !transform.any_op
364        }
365        // The first alternative failed, so the returned value is taken from the
366        // second alternative, associated test_produce_self_handle_or_forward_operand rather
367        // than pdl_match.
368        // expected-remark @below {{succeeded}}
369        transform.test_consume_operand_of_op_kind_or_fail %2, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
370      }
371    }
372    transform.yield
373  }
374}
375
376// -----
377
378// expected-note @below {{scope}}
379module attributes {transform.with_named_sequence} {
380  func.func @foo() {
381    %0 = arith.constant 0 : i32
382    return
383  }
384
385  func.func @bar() {
386    %0 = arith.constant 0 : i32
387    %1 = arith.constant 1 : i32
388    return
389  }
390
391  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
392    // expected-error @below {{scope must not contain the transforms being applied}}
393    transform.alternatives %arg1 : !transform.any_op {
394    ^bb2(%arg2: !transform.any_op):
395      %0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
396      transform.test_consume_operand_of_op_kind_or_fail %0, "transform.sequence" : !transform.any_op
397    }, {
398    ^bb2(%arg2: !transform.any_op):
399      %0 = transform.test_produce_self_handle_or_forward_operand : () -> !transform.any_op
400      transform.test_consume_operand_of_op_kind_or_fail %0, "transform.test_produce_self_handle_or_forward_operand" : !transform.any_op
401    }
402    transform.yield
403  }
404}
405
406// -----
407
408func.func @foo(%arg0: index, %arg1: index, %arg2: index) {
409  // expected-note @below {{scope}}
410  scf.for %i = %arg0 to %arg1 step %arg2 {
411    %0 = arith.constant 0 : i32
412  }
413  return
414}
415
416module attributes {transform.with_named_sequence} {
417  transform.named_sequence @__transform_main(%root: !transform.any_op) {
418    transform.with_pdl_patterns %root : !transform.any_op {
419    ^bb0(%arg0: !transform.any_op):
420      pdl.pattern @match_const : benefit(1) {
421        %0 = pdl.operands
422        %1 = pdl.types
423        %2 = pdl.operation "arith.constant"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
424        pdl.rewrite %2 with "transform.dialect"
425      }
426
427
428      sequence %arg0 : !transform.any_op failures(propagate) {
429      ^bb1(%arg1: !transform.any_op):
430        %0 = transform.pdl_match @match_const in %arg1 : (!transform.any_op) -> !transform.any_op
431        %1 = transform.get_parent_op %0 {op_name = "scf.for"} : (!transform.any_op) -> !transform.any_op
432        // expected-error @below {{only isolated-from-above ops can be alternative scopes}}
433        alternatives %1 : !transform.any_op {
434        ^bb2(%arg2: !transform.any_op):
435        }
436      }
437    }
438    transform.yield
439  }
440}
441// -----
442
443func.func @foo() {
444  // expected-note @below {{when applied to this op}}
445  "op" () : () -> ()
446  return
447}
448
449module attributes {transform.with_named_sequence} {
450  transform.named_sequence @__transform_main(%root: !transform.any_op) {
451    transform.with_pdl_patterns %root : !transform.any_op {
452    ^bb0(%arg0: !transform.any_op):
453      pdl.pattern @some : benefit(1) {
454        %0 = pdl.operands
455        %1 = pdl.types
456        %2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
457        pdl.rewrite %2 with "transform.dialect"
458      }
459
460      transform.sequence %arg0 : !transform.any_op failures(propagate) {
461      ^bb0(%arg1: !transform.any_op):
462        %0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
463        // expected-error @below {{application of transform.test_wrong_number_of_results expected to produce 3 results (actually produced 1).}}
464        // expected-note @below {{if you need variadic results, consider a generic `apply` instead of the specialized `applyToOne`.}}
465        transform.test_wrong_number_of_results %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
466      }
467    }
468    transform.yield
469  }
470}
471
472// -----
473
474func.func @foo() {
475  "op" () : () -> ()
476  // expected-note @below {{when applied to this op}}
477  "op" () : () -> ()
478  return
479}
480
481module attributes {transform.with_named_sequence} {
482  transform.named_sequence @__transform_main(%root: !transform.any_op) {
483    transform.with_pdl_patterns %root : !transform.any_op {
484    ^bb0(%arg0: !transform.any_op):
485      pdl.pattern @some : benefit(1) {
486        %0 = pdl.operands
487        %1 = pdl.types
488        %2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
489        pdl.rewrite %2 with "transform.dialect"
490      }
491
492      transform.sequence %arg0 : !transform.any_op failures(propagate) {
493      ^bb0(%arg1: !transform.any_op):
494        %0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
495        // expected-error @below {{application of transform.test_wrong_number_of_multi_results expected to produce 1 results (actually produced 0)}}
496        // expected-note @below {{if you need variadic results, consider a generic `apply` instead of the specialized `applyToOne`.}}
497        transform.test_wrong_number_of_multi_results %0 : (!transform.any_op) -> (!transform.any_op)
498      }
499    }
500    transform.yield
501  }
502}
503
504// -----
505
506func.func @foo() {
507  "op" () : () -> ()
508  "op" () : () -> ()
509  "op" () : () -> ()
510  return
511}
512
513module attributes {transform.with_named_sequence} {
514  transform.named_sequence @__transform_main(%root: !transform.any_op) {
515    transform.with_pdl_patterns %root : !transform.any_op {
516    ^bb0(%arg0: !transform.any_op):
517      pdl.pattern @some : benefit(1) {
518        %0 = pdl.operands
519        %1 = pdl.types
520        %2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
521        pdl.rewrite %2 with "transform.dialect"
522      }
523
524      transform.sequence %arg0 : !transform.any_op failures(propagate) {
525      ^bb0(%arg1: !transform.any_op):
526        %0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
527        // Transform matches 3 ops and produces 2 results.
528        %1:2 = transform.test_correct_number_of_multi_results %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
529      }
530    }
531    transform.yield
532  }
533}
534
535// -----
536
537func.func @foo() {
538  "wrong_op_name" () : () -> ()
539  return
540}
541
542module attributes {transform.with_named_sequence} {
543  transform.named_sequence @__transform_main(%root: !transform.any_op) {
544    transform.with_pdl_patterns %root : !transform.any_op {
545    ^bb0(%arg0: !transform.any_op):
546      pdl.pattern @some : benefit(1) {
547        %0 = pdl.operands
548        %1 = pdl.types
549        %2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
550        pdl.rewrite %2 with "transform.dialect"
551      }
552
553      transform.sequence %arg0 : !transform.any_op failures(propagate) {
554      ^bb0(%arg1: !transform.any_op):
555        %0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
556        // Transform fails to match any but still produces 2 results.
557        %1:2 = transform.test_correct_number_of_multi_results %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
558      }
559    }
560    transform.yield
561  }
562}
563
564// -----
565
566// This should not fail.
567
568func.func @foo() {
569  "op" () : () -> ()
570  return
571}
572
573module attributes {transform.with_named_sequence} {
574  transform.named_sequence @__transform_main(%root: !transform.any_op) {
575    transform.with_pdl_patterns %root : !transform.any_op {
576    ^bb0(%arg0: !transform.any_op):
577      pdl.pattern @some : benefit(1) {
578        %0 = pdl.operands
579        %1 = pdl.types
580        %2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
581        pdl.rewrite %2 with "transform.dialect"
582      }
583
584      transform.sequence %arg0 : !transform.any_op failures(propagate) {
585      ^bb0(%arg1: !transform.any_op):
586        %0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
587        transform.test_mixed_null_and_non_null_results %0 : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
588      }
589    }
590    transform.yield
591  }
592}
593
594// -----
595
596// Expecting to match all operations by merging the handles that matched addi
597// and subi separately.
598func.func @foo(%arg0: index) {
599  // expected-remark @below {{matched}}
600  %0 = arith.addi %arg0, %arg0 : index
601  // expected-remark @below {{matched}}
602  %1 = arith.subi %arg0, %arg0 : index
603  // expected-remark @below {{matched}}
604  %2 = arith.addi %0, %1 : index
605  return
606}
607
608module attributes {transform.with_named_sequence} {
609  transform.named_sequence @__transform_main(%root: !transform.any_op) {
610    transform.with_pdl_patterns %root : !transform.any_op {
611    ^bb0(%arg0: !transform.any_op):
612      pdl.pattern @addi : benefit(1) {
613        %0 = pdl.operands
614        %1 = pdl.types
615        %2 = pdl.operation "arith.addi"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
616        pdl.rewrite %2 with "transform.dialect"
617      }
618      pdl.pattern @subi : benefit(1) {
619        %0 = pdl.operands
620        %1 = pdl.types
621        %2 = pdl.operation "arith.subi"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
622        pdl.rewrite %2 with "transform.dialect"
623      }
624
625      transform.sequence %arg0 : !transform.any_op failures(propagate) {
626      ^bb0(%arg1: !transform.any_op):
627        %0 = pdl_match @addi in %arg1 : (!transform.any_op) -> !transform.any_op
628        %1 = pdl_match @subi in %arg1 : (!transform.any_op) -> !transform.any_op
629        %2 = merge_handles %0, %1 : !transform.any_op
630        transform.debug.emit_remark_at %2, "matched" : !transform.any_op
631      }
632    }
633    transform.yield
634  }
635}
636
637// -----
638
639func.func @foo(%arg0: index) {
640  %0 = arith.addi %arg0, %arg0 : index
641  return
642}
643
644module attributes {transform.with_named_sequence} {
645  transform.named_sequence @__transform_main(%root: !transform.any_op) {
646    transform.with_pdl_patterns %root : !transform.any_op {
647    ^bb0(%arg0: !transform.any_op):
648      pdl.pattern @addi : benefit(1) {
649        %0 = pdl.operands
650        %1 = pdl.types
651        %2 = pdl.operation "arith.addi"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
652        pdl.rewrite %2 with "transform.dialect"
653      }
654
655      transform.sequence %arg0 : !transform.any_op failures(propagate) {
656      ^bb0(%arg1: !transform.any_op):
657        %0 = pdl_match @addi in %arg1 : (!transform.any_op) -> !transform.any_op
658        %1 = pdl_match @addi in %arg1 : (!transform.any_op) -> !transform.any_op
659        %2 = merge_handles deduplicate %0, %1 : !transform.any_op
660        %3 = num_associations %2 : (!transform.any_op) -> !transform.param<i64>
661        // expected-remark @below {{1}}
662        transform.debug.emit_param_as_remark  %3 : !transform.param<i64>
663      }
664    }
665    transform.yield
666  }
667}
668
669// -----
670
671func.func @foo() {
672  "op" () { target_me } : () -> ()
673  // expected-note @below {{when applied to this op}}
674  "op" () : () -> ()
675  return
676}
677
678module attributes {transform.with_named_sequence} {
679  transform.named_sequence @__transform_main(%root: !transform.any_op) {
680    transform.with_pdl_patterns %root : !transform.any_op {
681    ^bb0(%arg0: !transform.any_op):
682      pdl.pattern @some : benefit(1) {
683        %0 = pdl.operands
684        %1 = pdl.types
685        %2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
686        pdl.rewrite %2 with "transform.dialect"
687      }
688
689      transform.sequence %arg0 : !transform.any_op failures(propagate) {
690      ^bb0(%arg1: !transform.any_op):
691        %0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
692        // expected-error @below {{failed to apply}}
693        transform.test_mixed_success_and_silenceable %0 : !transform.any_op
694      }
695    }
696    transform.yield
697  }
698}
699
700// -----
701
702func.func @foo() {
703  "op" () : () -> ()
704  return
705}
706
707module attributes {transform.with_named_sequence} {
708  transform.named_sequence @__transform_main(%root: !transform.any_op) {
709    transform.with_pdl_patterns %root : !transform.any_op {
710    ^bb0(%arg0: !transform.any_op):
711      pdl.pattern @some : benefit(1) {
712        %0 = pdl.operands
713        %1 = pdl.types
714        %2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
715        pdl.rewrite %2 with "transform.dialect"
716      }
717
718      transform.sequence %arg0 : !transform.any_op failures(suppress) {
719      ^bb0(%arg1: !transform.any_op):
720        %0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
721        // Not expecting error here because we are suppressing it.
722        // expected-remark @below {{foo}}
723        test_emit_remark_and_erase_operand %0, "foo" {fail_after_erase} : !transform.any_op
724      }
725    }
726    transform.yield
727  }
728}
729
730// -----
731
732func.func @foo() {
733  "op" () : () -> ()
734  return
735}
736
737module attributes {transform.with_named_sequence} {
738  transform.named_sequence @__transform_main(%root: !transform.any_op) {
739    transform.with_pdl_patterns %root : !transform.any_op {
740    ^bb0(%arg0: !transform.any_op):
741      pdl.pattern @some : benefit(1) {
742        %0 = pdl.operands
743        %1 = pdl.types
744        %2 = pdl.operation "op"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
745        pdl.rewrite %2 with "transform.dialect"
746      }
747
748      transform.sequence %arg0 : !transform.any_op failures(propagate) {
749      ^bb0(%arg1: !transform.any_op):
750        %0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
751        // expected-error @below {{silenceable error}}
752        // expected-remark @below {{foo}}
753        test_emit_remark_and_erase_operand %0, "foo" {fail_after_erase} : !transform.any_op
754      }
755    }
756    transform.yield
757  }
758}
759
760
761// -----
762
763module attributes {transform.with_named_sequence} {
764  func.func private @foo()
765  func.func private @bar()
766
767  transform.named_sequence @__transform_main(%root: !transform.any_op) {
768    transform.with_pdl_patterns %root : !transform.any_op {
769
770    ^bb0(%arg0: !transform.any_op):
771      pdl.pattern @func : benefit(1) {
772        %0 = pdl.operands
773        %1 = pdl.types
774        %2 = pdl.operation "func.func"(%0 : !pdl.range<value>) -> (%1 : !pdl.range<type>)
775        pdl.rewrite %2 with "transform.dialect"
776      }
777
778      transform.sequence %arg0 : !transform.any_op failures(propagate) {
779      ^bb0(%arg1: !transform.any_op):
780        %0 = pdl_match @func in %arg1 : (!transform.any_op) -> !transform.any_op
781        %1 = replicate num(%0) %arg1 : !transform.any_op, !transform.any_op
782        %p = num_associations %1 : (!transform.any_op) -> !transform.param<i64>
783        // expected-remark @below {{2}}
784        transform.debug.emit_param_as_remark  %p : !transform.param<i64>
785        %2 = replicate num(%0) %1 : !transform.any_op, !transform.any_op
786        %p2 = num_associations %2 : (!transform.any_op) -> !transform.param<i64>
787        // expected-remark @below {{4}}
788        transform.debug.emit_param_as_remark  %p2 : !transform.param<i64>
789      }
790    }
791    transform.yield
792  }
793}
794
795// -----
796
797func.func @bar() {
798  // expected-remark @below {{transform applied}}
799  %0 = arith.constant 0 : i32
800  // expected-remark @below {{transform applied}}
801  %1 = arith.constant 1 : i32
802  return
803}
804
805module attributes {transform.with_named_sequence} {
806  transform.named_sequence @__transform_main(%root: !transform.any_op) {
807    transform.with_pdl_patterns %root : !transform.any_op {
808    ^bb0(%arg0: !transform.any_op):
809      pdl.pattern @const : benefit(1) {
810        %r = pdl.types
811        %0 = pdl.operation "arith.constant" -> (%r : !pdl.range<type>)
812        pdl.rewrite %0 with "transform.dialect"
813      }
814
815      transform.sequence %arg0 : !transform.any_op failures(propagate) {
816      ^bb1(%arg1: !transform.any_op):
817        %f = pdl_match @const in %arg1 : (!transform.any_op) -> !transform.any_op
818        transform.foreach %f : !transform.any_op {
819        ^bb2(%arg2: !transform.any_op):
820          %p = transform.num_associations %arg2 : (!transform.any_op) -> !transform.param<i64>
821          // expected-remark @below {{1}}
822          transform.debug.emit_param_as_remark  %p : !transform.param<i64>
823          transform.debug.emit_remark_at %arg2, "transform applied" : !transform.any_op
824        }
825      }
826    }
827    transform.yield
828  }
829}
830
831// -----
832
833module attributes { transform.with_named_sequence } {
834  transform.named_sequence @__transform_main(%arg0: !transform.any_op {transform.readonly}) {
835    %0 = transform.structured.match ops{["linalg.matmul"]} in %arg0 : (!transform.any_op) -> !transform.any_op
836    %results, %types = transform.foreach %0 : !transform.any_op -> !transform.any_value, !transform.any_param {
837    ^bb0(%op0 : !transform.any_op):
838      %result = transform.get_result %op0[0] : (!transform.any_op) -> !transform.any_value
839      %type = transform.get_type elemental %result  : (!transform.any_value) -> !transform.any_param
840      transform.yield %result, %type : !transform.any_value, !transform.any_param
841    }
842    transform.debug.emit_remark_at %results, "result selected" : !transform.any_value
843    transform.debug.emit_param_as_remark %types, "elemental types" at %0 : !transform.any_param, !transform.any_op
844
845    transform.yield
846  }
847}
848
849func.func @payload(%lhs: tensor<10x20xf16>,
850                   %rhs: tensor<20x15xf32>) -> (tensor<10x15xf64>, tensor<10x15xf32>) {
851  %cst64 = arith.constant 0.0 : f64
852  %empty64 = tensor.empty() : tensor<10x15xf64>
853  %fill64 = linalg.fill ins(%cst64 : f64) outs(%empty64 : tensor<10x15xf64>) -> tensor<10x15xf64>
854  // expected-remark @below {{result selected}}
855  // expected-note @below {{value handle points to an op result #0}}
856  // expected-remark @below {{elemental types f64, f32}}
857  %result64 = linalg.matmul ins(%lhs, %rhs: tensor<10x20xf16>, tensor<20x15xf32>)
858                         outs(%fill64: tensor<10x15xf64>) -> tensor<10x15xf64>
859
860  %cst32 = arith.constant 0.0 : f32
861  %empty32 = tensor.empty() : tensor<10x15xf32>
862  %fill32 = linalg.fill ins(%cst32 : f32) outs(%empty32 : tensor<10x15xf32>) -> tensor<10x15xf32>
863  // expected-remark @below {{result selected}}
864  // expected-note @below {{value handle points to an op result #0}}
865  // expected-remark @below {{elemental types f64, f32}}
866  %result32 = linalg.matmul ins(%lhs, %rhs: tensor<10x20xf16>, tensor<20x15xf32>)
867                           outs(%fill32: tensor<10x15xf32>) -> tensor<10x15xf32>
868
869  return %result64, %result32 : tensor<10x15xf64>, tensor<10x15xf32>
870
871}
872
873// -----
874
875func.func @two_const_ops() {
876  %0 = arith.constant 0 : index
877  %1 = arith.constant 1 : index
878  return
879}
880
881module attributes {transform.with_named_sequence} {
882  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
883    %two_ops = transform.structured.match ops{["arith.constant"]} in %arg1 : (!transform.any_op) -> !transform.any_op
884    %one_param = transform.param.constant 1 : i32 -> !transform.test_dialect_param
885    // expected-error @below {{prior targets' payload size (2) differs from payload size (1) of target}}
886    transform.foreach %two_ops, %one_param : !transform.any_op, !transform.test_dialect_param {
887    ^bb2(%op: !transform.any_op, %param: !transform.test_dialect_param):
888    }
889    transform.yield
890  }
891}
892
893// -----
894
895func.func @one_const_op() {
896  %0 = arith.constant 0 : index
897  return
898}
899
900module attributes {transform.with_named_sequence} {
901  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
902    %one_op = transform.structured.match ops{["arith.constant"]} in %arg1 : (!transform.any_op) -> !transform.any_op
903    %one_val = transform.test_produce_value_handle_to_self_operand %one_op : (!transform.any_op) -> !transform.any_value
904    %param_one = transform.param.constant 1 : i32 -> !transform.test_dialect_param
905    %param_two = transform.param.constant 2 : i32 -> !transform.test_dialect_param
906    %two_params = transform.merge_handles %param_one, %param_two : !transform.test_dialect_param
907
908    // expected-error @below {{prior targets' payload size (1) differs from payload size (2) of target}}
909    transform.foreach %one_val, %one_op, %two_params : !transform.any_value, !transform.any_op, !transform.test_dialect_param {
910    ^bb2(%val: !transform.any_value, %op: !transform.any_op, %param: !transform.test_dialect_param):
911    }
912    transform.yield
913  }
914}
915
916// -----
917
918// CHECK-LABEL: func @consume_in_foreach()
919//  CHECK-NEXT:   return
920func.func @consume_in_foreach() {
921  %0 = arith.constant 0 : index
922  %1 = arith.constant 1 : index
923  %2 = arith.constant 2 : index
924  %3 = arith.constant 3 : index
925  return
926}
927
928module attributes {transform.with_named_sequence} {
929  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
930    %f = transform.structured.match ops{["arith.constant"]} in %arg1 : (!transform.any_op) -> !transform.any_op
931    transform.foreach %f : !transform.any_op {
932    ^bb2(%arg2: !transform.any_op):
933      // expected-remark @below {{erasing}}
934      transform.test_emit_remark_and_erase_operand %arg2, "erasing" : !transform.any_op
935    }
936    transform.yield
937  }
938}
939
940// -----
941
942func.func @bar() {
943  scf.execute_region {
944    // expected-remark @below {{transform applied}}
945    %0 = arith.constant 0 : i32
946    scf.yield
947  }
948
949  scf.execute_region {
950    // expected-remark @below {{transform applied}}
951    %1 = arith.constant 1 : i32
952    // expected-remark @below {{transform applied}}
953    %2 = arith.constant 2 : i32
954    scf.yield
955  }
956
957  return
958}
959
960module attributes {transform.with_named_sequence} {
961  transform.named_sequence @__transform_main(%root: !transform.any_op) {
962    transform.with_pdl_patterns %root : !transform.any_op {
963    ^bb0(%arg0: !transform.any_op):
964      pdl.pattern @const : benefit(1) {
965        %r = pdl.types
966        %0 = pdl.operation "arith.constant" -> (%r : !pdl.range<type>)
967        pdl.rewrite %0 with "transform.dialect"
968      }
969
970      pdl.pattern @execute_region : benefit(1) {
971        %r = pdl.types
972        %0 = pdl.operation "scf.execute_region" -> (%r : !pdl.range<type>)
973        pdl.rewrite %0 with "transform.dialect"
974      }
975
976      transform.sequence %arg0 : !transform.any_op failures(propagate) {
977      ^bb1(%arg1: !transform.any_op):
978        %f = pdl_match @execute_region in %arg1 : (!transform.any_op) -> !transform.any_op
979        %results = transform.foreach %f : !transform.any_op -> !transform.any_op {
980        ^bb2(%arg2: !transform.any_op):
981          %g = transform.pdl_match @const in %arg2 : (!transform.any_op) -> !transform.any_op
982          transform.yield %g : !transform.any_op
983        }
984
985        %p = transform.num_associations %results : (!transform.any_op) -> !transform.param<i64>
986        // expected-remark @below {{3}}
987        transform.debug.emit_param_as_remark  %p : !transform.param<i64>
988        transform.debug.emit_remark_at %results, "transform applied" : !transform.any_op
989      }
990    }
991    transform.yield
992  }
993}
994
995// -----
996
997func.func @get_parent_for_op_no_loop(%arg0: index, %arg1: index) {
998  // expected-remark @below {{found muli}}
999  %0 = arith.muli %arg0, %arg1 : index
1000  arith.addi %0, %arg1 : index
1001  return
1002}
1003
1004module attributes {transform.with_named_sequence} {
1005  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1006    %addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1007    %muli = transform.get_producer_of_operand %addi[0] : (!transform.any_op) -> !transform.any_op
1008    transform.debug.emit_remark_at %muli, "found muli" : !transform.any_op
1009    transform.yield
1010  }
1011}
1012
1013// -----
1014
1015func.func @get_parent_for_op_no_loop(%arg0: index, %arg1: index) {
1016  // expected-note @below {{target op}}
1017  %0 = arith.muli %arg0, %arg1 : index
1018  return
1019}
1020
1021module attributes {transform.with_named_sequence} {
1022  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1023    %muli = transform.structured.match ops{["arith.muli"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1024    // expected-error @below {{could not find a producer for operand number: 0 of}}
1025    %bbarg = transform.get_producer_of_operand %muli[0] : (!transform.any_op) -> !transform.any_op
1026    transform.yield
1027  }
1028}
1029
1030// -----
1031
1032func.func @get_consumer(%arg0: index, %arg1: index) {
1033  %0 = arith.muli %arg0, %arg1 : index
1034  // expected-remark @below {{found addi}}
1035  arith.addi %0, %arg1 : index
1036  return
1037}
1038
1039module attributes {transform.with_named_sequence} {
1040  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1041    %muli = transform.structured.match ops{["arith.muli"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1042    %addi = transform.get_consumers_of_result %muli[0] : (!transform.any_op) -> !transform.any_op
1043    transform.debug.emit_remark_at %addi, "found addi" : !transform.any_op
1044    transform.yield
1045  }
1046}
1047
1048// -----
1049
1050func.func @get_consumer_fail_1(%arg0: index, %arg1: index) {
1051  %0 = arith.muli %arg0, %arg1 : index
1052  %1 = arith.muli %arg0, %arg1 : index
1053  return
1054}
1055
1056module attributes {transform.with_named_sequence} {
1057  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1058    %muli = transform.structured.match ops{["arith.muli"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1059    // expected-error @below {{handle must be mapped to exactly one payload op}}
1060    %bbarg = transform.get_consumers_of_result %muli[0] : (!transform.any_op) -> !transform.any_op
1061    transform.yield
1062  }
1063}
1064
1065// -----
1066
1067func.func @get_consumer_fail_2(%arg0: index, %arg1: index) {
1068  %0 = arith.muli %arg0, %arg1 : index
1069  return
1070}
1071
1072module attributes {transform.with_named_sequence} {
1073  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1074    %muli = transform.structured.match ops{["arith.muli"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1075    // expected-error @below {{result number overflow}}
1076    %bbarg = transform.get_consumers_of_result %muli[1] : (!transform.any_op) -> !transform.any_op
1077    transform.yield
1078  }
1079}
1080
1081// -----
1082
1083func.func @split_handle(%a: index, %b: index, %c: index) {
1084  %0 = arith.muli %a, %b : index
1085  %1 = arith.muli %a, %c : index
1086  return
1087}
1088
1089module attributes {transform.with_named_sequence} {
1090  transform.named_sequence @__transform_main(%fun: !transform.any_op) {
1091    %muli = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
1092    %h:2 = transform.split_handle %muli : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
1093    %p = transform.num_associations %h#0 : (!transform.any_op) -> !transform.param<i64>
1094    // expected-remark @below {{1}}
1095    transform.debug.emit_param_as_remark  %p : !transform.param<i64>
1096    %muli_2 = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
1097    // expected-error @below {{expected to contain 3 payloads but it contains 2 payloads}}
1098    %h_2:3 = transform.split_handle %muli_2 : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
1099    transform.yield
1100  }
1101}
1102
1103// -----
1104
1105func.func @split_handle(%a: index, %b: index, %c: index) {
1106  %0 = arith.muli %a, %b : index
1107  %1 = arith.muli %a, %c : index
1108  return
1109}
1110
1111module attributes {transform.with_named_sequence} {
1112  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1113    transform.sequence %root : !transform.any_op failures(suppress) {
1114    ^bb1(%fun: !transform.any_op):
1115      %muli = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
1116      %h:2 = split_handle %muli : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
1117      %p = transform.num_associations %h#0 : (!transform.any_op) -> !transform.param<i64>
1118      // expected-remark @below {{1}}
1119      transform.debug.emit_param_as_remark  %p : !transform.param<i64>
1120      %muli_2 = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
1121      // Silenceable failure and all handles are now empty.
1122      %h_2:3 = split_handle %muli_2 : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
1123      %p2 = transform.num_associations %h_2#0 : (!transform.any_op) -> !transform.param<i64>
1124      // expected-remark @below {{0}}
1125      transform.debug.emit_param_as_remark  %p2 : !transform.param<i64>
1126    }
1127    transform.yield
1128  }
1129}
1130
1131// -----
1132
1133func.func @split_handle(%a: index, %b: index, %c: index) {
1134  %0 = arith.muli %a, %b : index
1135  %1 = arith.muli %a, %c : index
1136  return
1137}
1138
1139module attributes {transform.with_named_sequence} {
1140  transform.named_sequence @__transform_main(%fun: !transform.any_op) {
1141    %muli_2 = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
1142    // No error, last result handle is empty.
1143    %h:3 = transform.split_handle %muli_2 {fail_on_payload_too_small = false} : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
1144    %p = transform.num_associations %h#0 : (!transform.any_op) -> !transform.param<i64>
1145    // expected-remark @below {{1}}
1146    transform.debug.emit_param_as_remark  %p : !transform.param<i64>
1147    %p2 = transform.num_associations %h#1 : (!transform.any_op) -> !transform.param<i64>
1148    // expected-remark @below {{1}}
1149    transform.debug.emit_param_as_remark  %p2 : !transform.param<i64>
1150    %p3 = transform.num_associations %h#2 : (!transform.any_op) -> !transform.param<i64>
1151    // expected-remark @below {{0}}
1152    transform.debug.emit_param_as_remark  %p3 : !transform.param<i64>
1153    transform.yield
1154  }
1155}
1156
1157// -----
1158
1159func.func @split_handle(%a: index, %b: index, %c: index) {
1160  %0 = arith.muli %a, %b : index
1161  %1 = arith.muli %a, %c : index
1162  %2 = arith.muli %a, %c : index
1163  %3 = arith.muli %a, %c : index
1164  return
1165}
1166
1167module attributes {transform.with_named_sequence} {
1168  transform.named_sequence @__transform_main(%fun: !transform.any_op) {
1169    %muli_2 = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
1170    %h:2 = transform.split_handle %muli_2 {overflow_result = 0} : (!transform.any_op) -> (!transform.any_op, !transform.any_op)
1171    %p = transform.num_associations %h#0 : (!transform.any_op) -> !transform.param<i64>
1172    // expected-remark @below {{3}}
1173    transform.debug.emit_param_as_remark  %p : !transform.param<i64>
1174    %p2 = transform.num_associations %h#1 : (!transform.any_op) -> !transform.param<i64>
1175    // expected-remark @below {{1}}
1176    transform.debug.emit_param_as_remark  %p2 : !transform.param<i64>
1177    transform.yield
1178  }
1179}
1180
1181// -----
1182
1183func.func private @opaque() -> (i32, i32)
1184
1185func.func @split_handle() {
1186  func.call @opaque() : () -> (i32, i32)
1187  return
1188}
1189
1190module attributes {transform.with_named_sequence} {
1191  transform.named_sequence @__transform_main(%fun: !transform.any_op) {
1192    %op = transform.structured.match ops{["func.call"]} in %fun : (!transform.any_op) -> !transform.any_op
1193    %val = transform.get_result %op[all] : (!transform.any_op) -> !transform.any_value
1194    %p = transform.num_associations %val : (!transform.any_value) -> !transform.any_param
1195    // expected-remark @below {{total 2}}
1196    transform.debug.emit_param_as_remark %p, "total" : !transform.any_param
1197    %h:2 = transform.split_handle %val : (!transform.any_value) -> (!transform.any_value, !transform.any_value)
1198    %p1 = transform.num_associations %h#0 : (!transform.any_value) -> !transform.any_param
1199    %p2 = transform.num_associations %h#1 : (!transform.any_value) -> !transform.any_param
1200    // expected-remark @below {{first 1}}
1201    transform.debug.emit_param_as_remark %p1, "first" : !transform.any_param
1202    // expected-remark @below {{second 1}}
1203    transform.debug.emit_param_as_remark %p1, "second" : !transform.any_param
1204    transform.yield
1205  }
1206}
1207
1208// -----
1209
1210func.func private @opaque() -> (i32, i32)
1211
1212func.func @split_handle() {
1213  func.call @opaque() : () -> (i32, i32)
1214  return
1215}
1216
1217module attributes {transform.with_named_sequence} {
1218  transform.named_sequence @__transform_main(%fun: !transform.any_op) {
1219    %op = transform.structured.match ops{["func.call"]} in %fun : (!transform.any_op) -> !transform.any_op
1220    %val = transform.get_result %op[all] : (!transform.any_op) -> !transform.any_value
1221    %type = transform.get_type %val : (!transform.any_value) -> !transform.any_param
1222    %p = transform.num_associations %type : (!transform.any_param) -> !transform.any_param
1223    // expected-remark @below {{total 2}}
1224    transform.debug.emit_param_as_remark %p, "total" : !transform.any_param
1225    %h:2 = transform.split_handle %type : (!transform.any_param) -> (!transform.any_param, !transform.any_param)
1226    %p1 = transform.num_associations %h#0 : (!transform.any_param) -> !transform.any_param
1227    %p2 = transform.num_associations %h#1 : (!transform.any_param) -> !transform.any_param
1228    // expected-remark @below {{first 1}}
1229    transform.debug.emit_param_as_remark %p1, "first" : !transform.any_param
1230    // expected-remark @below {{second 1}}
1231    transform.debug.emit_param_as_remark %p1, "second" : !transform.any_param
1232    transform.yield
1233  }
1234}
1235
1236// -----
1237
1238module attributes {transform.with_named_sequence} {
1239  transform.named_sequence @__transform_main(%fun: !transform.any_op) {
1240    // expected-error @below {{op expects result types to implement the same transform interface as the operand type}}
1241    transform.split_handle %fun : (!transform.any_op) -> (!transform.any_op, !transform.any_value)
1242    transform.yield
1243  }
1244}
1245
1246// -----
1247
1248"test.some_op"() : () -> ()
1249"other_dialect.other_op"() : () -> ()
1250
1251module attributes {transform.with_named_sequence} {
1252  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1253    transform.with_pdl_patterns %root : !transform.any_op {
1254    ^bb0(%arg0: !transform.any_op):
1255      pdl.pattern @some : benefit(1) {
1256        %0 = pdl.operation "test.some_op"
1257        pdl.rewrite %0 with "transform.dialect"
1258      }
1259
1260      sequence %arg0 : !transform.any_op failures(propagate) {
1261      ^bb1(%arg1: !transform.any_op):
1262        %0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
1263        %2 = transform.cast %0 : !transform.any_op to !transform.test_dialect_op
1264        transform.cast %2 : !transform.test_dialect_op to !transform.any_op
1265      }
1266    }
1267    transform.yield
1268  }
1269}
1270
1271// -----
1272
1273"test.some_op"() : () -> ()
1274"other_dialect.other_op"() : () -> ()
1275
1276module attributes {transform.with_named_sequence} {
1277  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1278    transform.with_pdl_patterns %root : !transform.any_op {
1279    ^bb0(%arg0: !transform.any_op):
1280      pdl.pattern @other : benefit(1) {
1281        %0 = pdl.operation "other_dialect.other_op"
1282        pdl.rewrite %0 with "transform.dialect"
1283      }
1284
1285      sequence %arg0 : !transform.any_op failures(propagate) {
1286      ^bb1(%arg1: !transform.any_op):
1287        %0 = pdl_match @other in %arg1 : (!transform.any_op) -> !transform.any_op
1288        // expected-error @below {{expected the payload operation to belong to the 'test' dialect}}
1289        %2 = transform.cast %0 : !transform.any_op to !transform.test_dialect_op
1290        transform.cast %2 : !transform.test_dialect_op to !transform.any_op
1291      }
1292    }
1293    transform.yield
1294  }
1295}
1296
1297// -----
1298
1299"test.some_op"() : () -> ()
1300"other_dialect.other_op"() : () -> ()
1301
1302module attributes {transform.with_named_sequence} {
1303  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1304    transform.with_pdl_patterns %root : !transform.any_op {
1305    ^bb0(%arg0: !transform.any_op):
1306      pdl.pattern @some : benefit(1) {
1307        %0 = pdl.operation "test.some_op"
1308        pdl.rewrite %0 with "transform.dialect"
1309      }
1310
1311      sequence %arg0 : !transform.any_op failures(propagate) {
1312      ^bb1(%arg1: !transform.any_op):
1313        %0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
1314        %2 = transform.cast %0 : !transform.any_op to !transform.op<"test.some_op">
1315        transform.cast %2 : !transform.op<"test.some_op"> to !transform.any_op
1316      }
1317    }
1318    transform.yield
1319  }
1320}
1321
1322// -----
1323
1324"test.some_op"() : () -> ()
1325// expected-note @below {{payload operation}}
1326"other_dialect.other_op"() : () -> ()
1327
1328module attributes {transform.with_named_sequence} {
1329  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1330    transform.with_pdl_patterns %root : !transform.any_op {
1331    ^bb0(%arg0: !transform.any_op):
1332      pdl.pattern @other : benefit(1) {
1333        %0 = pdl.operation "other_dialect.other_op"
1334        pdl.rewrite %0 with "transform.dialect"
1335      }
1336
1337      sequence %arg0 : !transform.any_op failures(propagate) {
1338      ^bb1(%arg1: !transform.any_op):
1339        %0 = pdl_match @other in %arg1 : (!transform.any_op) -> !transform.any_op
1340        // expected-error @below {{incompatible payload operation name}}
1341        %2 = transform.cast %0 : !transform.any_op to !transform.op<"test.some_op">
1342        transform.cast %2 : !transform.op<"test.some_op"> to !transform.any_op
1343      }
1344    }
1345    transform.yield
1346  }
1347}
1348
1349// -----
1350
1351module attributes {transform.with_named_sequence} {
1352  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1353    transform.with_pdl_patterns %root : !transform.any_op {
1354    ^bb0(%arg0: !transform.any_op):
1355      transform.sequence %arg0 : !transform.any_op failures(propagate) {
1356      ^bb0(%arg1: !transform.any_op):
1357        %0 = pdl_match @some in %arg1 : (!transform.any_op) -> !transform.any_op
1358        // here, the handles nested under are {%root, %arg0, %arg1, %0}
1359        // expected-remark @below {{4 handles nested under}}
1360        transform.test_report_number_of_tracked_handles_nested_under %arg1 : !transform.any_op
1361        // expected-remark @below {{erased}}
1362        transform.test_emit_remark_and_erase_operand %0, "erased" : !transform.any_op
1363        // here, the handles nested under are only {%root, %arg0, %arg1}
1364        // expected-remark @below {{3 handles nested under}}
1365        transform.test_report_number_of_tracked_handles_nested_under %arg1 : !transform.any_op
1366      }
1367
1368      pdl.pattern @some : benefit(1) {
1369        %0 = pdl.operation "test.some_op"
1370        pdl.rewrite %0 with "transform.dialect"
1371      }
1372    }
1373    transform.yield
1374  }
1375}
1376
1377"test.some_op"() : () -> ()
1378
1379// -----
1380
1381func.func @split_handle(%a: index, %b: index, %c: index) {
1382  %0 = arith.muli %a, %b : index
1383  %1 = arith.muli %a, %c : index
1384  return
1385}
1386
1387module attributes {transform.with_named_sequence} {
1388  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1389    transform.sequence %root : !transform.any_op -> !transform.any_op failures(propagate) {
1390    ^bb1(%fun: !transform.any_op):
1391      %muli = transform.structured.match ops{["arith.muli"]} in %fun : (!transform.any_op) -> !transform.any_op
1392      // expected-error @below {{expected to contain 3 payloads but it contains 2 payloads}}
1393      %h_2:3 = split_handle %muli : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
1394      /// Test that yield does not crash in the presence of silenceable error in
1395      /// propagate mode.
1396      yield %fun : !transform.any_op
1397    }
1398    transform.yield
1399  }
1400}
1401
1402// -----
1403
1404module attributes {transform.with_named_sequence} {
1405  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1406    transform.sequence %root : !transform.any_op -> !transform.any_op failures(suppress) {
1407    ^bb0(%arg0: !transform.any_op):
1408      %muli = transform.structured.match ops{["arith.muli"]} in %arg0 : (!transform.any_op) -> !transform.any_op
1409      // Edge case propagating empty handles in splitting.
1410      %0:3 = split_handle %muli : (!transform.any_op) -> (!transform.any_op, !transform.any_op, !transform.any_op)
1411      // Test does not crash when accessing the empty handle.
1412      yield %0#0 : !transform.any_op
1413    }
1414    transform.yield
1415  }
1416}
1417
1418// -----
1419
1420module attributes {transform.with_named_sequence} {
1421  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1422    %0 = transform.test_produce_param (0 : i32) : !transform.test_dialect_param
1423    // expected-remark @below {{0 : i32}}
1424    transform.debug.emit_param_as_remark  %0 : !transform.test_dialect_param
1425    transform.yield
1426  }
1427}
1428
1429// -----
1430
1431module attributes {transform.with_named_sequence} {
1432  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1433    // expected-error @below {{expected the type of the parameter attribute ('i32') to match the parameter type ('i64')}}
1434    transform.test_produce_param (0 : i32) : !transform.param<i64>
1435    transform.yield
1436  }
1437}
1438
1439// -----
1440
1441
1442module attributes {transform.with_named_sequence} {
1443  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1444    %0 = transform.test_add_to_param 40
1445    %1 = transform.test_add_to_param %0, 2
1446    // expected-remark @below {{42 : i32}}
1447    transform.debug.emit_param_as_remark  %1 : !transform.test_dialect_param
1448    transform.yield
1449  }
1450}
1451
1452// -----
1453
1454module attributes {transform.with_named_sequence} {
1455  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1456    %0 = transform.structured.match ops{["func.func"]} in %arg0 : (!transform.any_op) -> !transform.any_op
1457    %1 = transform.test_produce_param_with_number_of_test_ops %0 : !transform.any_op
1458    // expected-remark @below {{1 : i32, 3 : i32}}
1459    transform.debug.emit_param_as_remark  %1 : !transform.test_dialect_param
1460    %2 = transform.test_add_to_param %1, 100
1461    // expected-remark @below {{101 : i32, 103 : i32}}
1462    transform.debug.emit_param_as_remark  %2 : !transform.test_dialect_param
1463    transform.yield
1464  }
1465}
1466
1467func.func private @one_test_op(%arg0: i32) {
1468  "test.op_a"(%arg0) { attr = 0 : i32} : (i32) -> i32
1469  return
1470}
1471
1472func.func private @three_test_ops(%arg0: i32) {
1473  "test.op_a"(%arg0) { attr = 0 : i32} : (i32) -> i32
1474  "test.op_a"(%arg0) { attr = 0 : i32} : (i32) -> i32
1475  "test.op_a"(%arg0) { attr = 0 : i32} : (i32) -> i32
1476  return
1477}
1478
1479// -----
1480
1481// expected-note @below {{when applied to this op}}
1482module attributes {transform.with_named_sequence} {
1483  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1484    // expected-error @below {{expected to produce an Operation * for result #0}}
1485    transform.test_produce_transform_param_or_forward_operand %arg0
1486      { first_result_is_param }
1487      : (!transform.any_op) -> (!transform.any_op, !transform.param<i64>)
1488    transform.yield
1489  }
1490}
1491
1492// -----
1493
1494// Should not fail.
1495
1496module attributes {transform.with_named_sequence} {
1497  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1498    transform.test_produce_transform_param_or_forward_operand %arg0
1499      { first_result_is_null }
1500      : (!transform.any_op) -> (!transform.any_op, !transform.param<i64>)
1501    transform.yield
1502  }
1503}
1504
1505// -----
1506
1507// expected-note @below {{when applied to this op}}
1508module attributes {transform.with_named_sequence} {
1509  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1510    // expected-error @below {{expected to produce an Attribute for result #1}}
1511    transform.test_produce_transform_param_or_forward_operand %arg0
1512      { second_result_is_handle }
1513      : (!transform.any_op) -> (!transform.any_op, !transform.param<i64>)
1514    transform.yield
1515  }
1516}
1517
1518// -----
1519
1520// expected-note @below {{when applied to this op}}
1521module attributes {transform.with_named_sequence} {
1522  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1523    // expected-error @below {{expected to produce a Value for result #0}}
1524    transform.test_produce_transform_param_or_forward_operand %arg0
1525      { second_result_is_handle }
1526      : (!transform.any_op) -> (!transform.any_value, !transform.param<i64>)
1527    transform.yield
1528  }
1529}
1530
1531// -----
1532
1533module attributes {transform.with_named_sequence} {
1534  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1535    // expected-error @below {{attempting to assign a null payload op to this transform value}}
1536    %0 = transform.test_produce_null_payload : !transform.any_op
1537    transform.yield
1538  }
1539}
1540
1541// -----
1542
1543module attributes {transform.with_named_sequence} {
1544  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1545    // expected-error @below {{attempting to assign a null parameter to this transform value}}
1546    %0 = transform.test_produce_null_param : !transform.param<i64>
1547    transform.yield
1548  }
1549}
1550
1551// -----
1552
1553module attributes {transform.with_named_sequence} {
1554  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1555    // expected-error @below {{attempting to assign a null payload value to this transform handle}}
1556    %0 = transform.test_produce_null_value : !transform.any_value
1557    transform.yield
1558  }
1559}
1560
1561// -----
1562
1563// expected-error @below {{could not find a nested named sequence with name: __transform_main}}
1564module {
1565}
1566
1567// -----
1568
1569module attributes {transform.with_named_sequence} {
1570  // expected-remark @below {{value handle}}
1571  // expected-note @below {{value handle points to a block argument #0 in block #0 in region #0}}
1572  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1573    %0 = transform.test_produce_value_handle_to_self_operand %arg0 : (!transform.any_op) -> !transform.any_value
1574    transform.debug.emit_remark_at %0, "value handle" : !transform.any_value
1575    transform.yield
1576  }
1577}
1578
1579// -----
1580
1581// expected-remark @below {{result handle}}
1582// expected-note @below {{value handle points to an op result #1}}
1583%0:2 = "test.get_two_results"() : () -> (i32, i32)
1584// expected-remark @below {{result handle}}
1585// expected-note @below {{value handle points to an op result #1}}
1586%1:3 = "test.get_three_results"() : () -> (i32, i32, f32)
1587
1588module attributes {transform.with_named_sequence} {
1589  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1590    %2 = transform.structured.match ops{["test.get_two_results", "test.get_three_results"]} in %arg0 : (!transform.any_op) -> !transform.any_op
1591    %3 = transform.test_produce_value_handle_to_result %2, 1 : (!transform.any_op) -> !transform.any_value
1592    transform.debug.emit_remark_at %3, "result handle" : !transform.any_value
1593    transform.yield
1594  }
1595}
1596
1597// -----
1598
1599"test.op_with_regions"() ({
1600^bb0:
1601  "test.regon_terminator"() : () -> ()
1602}, {
1603^bb1:
1604  "test.regon_terminator"() : () -> ()
1605// expected-remark @below {{block argument handle}}
1606// expected-note @below {{value handle points to a block argument #2 in block #1 in region #1}}
1607^bb2(%arg0: i32, %arg1: f64, %arg3: index):
1608  "test.match_anchor"() : () -> ()
1609  "test.regon_terminator"() : () -> ()
1610}) : () -> ()
1611
1612module attributes {transform.with_named_sequence} {
1613  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1614    %2 = transform.structured.match ops{["test.match_anchor"]} in %arg0 : (!transform.any_op) -> !transform.any_op
1615    %3 = transform.test_produce_value_handle_to_argument_of_parent_block %2, 2 : (!transform.any_op) -> !transform.any_value
1616    transform.debug.emit_remark_at %3, "block argument handle" : !transform.any_value
1617    transform.yield
1618  }
1619}
1620
1621// -----
1622
1623module attributes {transform.with_named_sequence} {
1624  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1625    // expected-note @below {{value defined here with type '!transform.test_dialect_param'}}
1626    %0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
1627    // expected-error @below {{unexpectedly consumed a value that is not a handle as operand #0}}
1628    transform.test_consume_operand %0 : !transform.test_dialect_param
1629    transform.yield
1630  }
1631}
1632
1633// -----
1634
1635// expected-remark @below {{addi operand}}
1636// expected-note @below {{value handle points to a block argument #0}}
1637func.func @get_operand_of_op(%arg0: index, %arg1: index) -> index {
1638  %r = arith.addi %arg0, %arg1 : index
1639  return %r : index
1640}
1641
1642module attributes {transform.with_named_sequence} {
1643  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1644    %addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1645    %operand = transform.get_operand %addi[0] : (!transform.any_op) -> !transform.any_value
1646    transform.debug.emit_remark_at %operand, "addi operand" : !transform.any_value
1647    transform.yield
1648  }
1649}
1650
1651// -----
1652
1653func.func @get_out_of_bounds_operand_of_op(%arg0: index, %arg1: index) -> index {
1654  // expected-note @below {{while considering positions of this payload operation}}
1655  %r = arith.addi %arg0, %arg1 : index
1656  return %r : index
1657}
1658
1659module attributes {transform.with_named_sequence} {
1660  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1661    %addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1662    // expected-error @below {{position overflow 2 (updated from 2) for maximum 2}}
1663    %operand = transform.get_operand %addi[2] : (!transform.any_op) -> !transform.any_value
1664    transform.debug.emit_remark_at %operand, "addi operand" : !transform.any_value
1665    transform.yield
1666  }
1667}
1668
1669// -----
1670
1671// expected-remark @below {{addi operand}}
1672// expected-note @below {{value handle points to a block argument #1}}
1673func.func @get_inverted_operand_of_op(%arg0: index, %arg1: index) -> index {
1674  %r = arith.addi %arg0, %arg1 : index
1675  return %r : index
1676}
1677
1678module attributes {transform.with_named_sequence} {
1679  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1680    %addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1681    %operand = transform.get_operand %addi[except(0)] : (!transform.any_op) -> !transform.any_value
1682    transform.debug.emit_remark_at %operand, "addi operand" : !transform.any_value
1683    transform.yield
1684  }
1685}
1686
1687// -----
1688
1689func.func @get_multiple_operands_of_op(%arg0: index, %arg1: index) -> index {
1690  %r = arith.addi %arg0, %arg1 : index
1691  return %r : index
1692}
1693
1694module attributes {transform.with_named_sequence} {
1695  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1696    %addui = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1697    %operands = transform.get_operand %addui[all] : (!transform.any_op) -> !transform.any_value
1698    %p = transform.num_associations %operands : (!transform.any_value) -> !transform.param<i64>
1699    // expected-remark @below {{2}}
1700    transform.debug.emit_param_as_remark %p : !transform.param<i64>
1701    transform.yield
1702  }
1703}
1704
1705// -----
1706
1707func.func @get_result_of_op(%arg0: index, %arg1: index) -> index {
1708  // expected-remark @below {{addi result}}
1709  // expected-note @below {{value handle points to an op result #0}}
1710  %r = arith.addi %arg0, %arg1 : index
1711  return %r : index
1712}
1713
1714module attributes {transform.with_named_sequence} {
1715  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1716    %addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1717    %result = transform.get_result %addi[0] : (!transform.any_op) -> !transform.any_value
1718    transform.debug.emit_remark_at %result, "addi result" : !transform.any_value
1719    transform.yield
1720  }
1721}
1722
1723// -----
1724
1725func.func @get_out_of_bounds_result_of_op(%arg0: index, %arg1: index) -> index {
1726  // expected-note @below {{while considering positions of this payload operation}}
1727  %r = arith.addi %arg0, %arg1 : index
1728  return %r : index
1729}
1730
1731module attributes {transform.with_named_sequence} {
1732  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1733    %addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1734    // expected-error @below {{position overflow 1 (updated from 1) for maximum 1}}
1735    %result = transform.get_result %addi[1] : (!transform.any_op) -> !transform.any_value
1736    transform.debug.emit_remark_at %result, "addi result" : !transform.any_value
1737    transform.yield
1738  }
1739}
1740
1741// -----
1742
1743func.func @get_result_of_op(%arg0: index, %arg1: index) -> index {
1744  // expected-remark @below {{matched}}
1745  %r = arith.addi %arg0, %arg1 : index
1746  return %r : index
1747}
1748
1749module attributes {transform.with_named_sequence} {
1750  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1751    %addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1752    %result = transform.get_result %addi[0] : (!transform.any_op) -> !transform.any_value
1753    %op = transform.get_defining_op %result : (!transform.any_value) -> !transform.any_op
1754    transform.debug.emit_remark_at %op, "matched" : !transform.any_op
1755    transform.yield
1756  }
1757}
1758
1759// -----
1760
1761func.func @get_multiple_result_of_op(%arg0: index, %arg1: index) -> (index, i1) {
1762  %r, %b = arith.addui_extended %arg0, %arg1 : index, i1
1763  return %r, %b : index, i1
1764}
1765
1766module attributes {transform.with_named_sequence} {
1767  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1768    %addui = transform.structured.match ops{["arith.addui_extended"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1769    %results = transform.get_result %addui[all] : (!transform.any_op) -> !transform.any_value
1770    %p = transform.num_associations %results : (!transform.any_value) -> !transform.param<i64>
1771    // expected-remark @below {{2}}
1772    transform.debug.emit_param_as_remark %p : !transform.param<i64>
1773    transform.yield
1774  }
1775}
1776
1777// -----
1778
1779// expected-note @below {{target value}}
1780func.func @get_result_of_op_bbarg(%arg0: index, %arg1: index) -> index {
1781  %r = arith.addi %arg0, %arg1 : index
1782  return %r : index
1783}
1784
1785module attributes {transform.with_named_sequence} {
1786  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
1787    %addi = transform.structured.match ops{["arith.addi"]} in %arg1 : (!transform.any_op) -> !transform.any_op
1788    %bbarg = transform.test_produce_value_handle_to_argument_of_parent_block %addi, 0 : (!transform.any_op) -> !transform.any_value
1789    // expected-error @below {{cannot get defining op of block argument}}
1790    %op = transform.get_defining_op %bbarg : (!transform.any_value) -> !transform.any_op
1791    transform.debug.emit_remark_at %op, "matched" : !transform.any_op
1792    transform.yield
1793  }
1794}
1795
1796// -----
1797
1798module @named_inclusion attributes { transform.with_named_sequence } {
1799
1800  transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly}) -> () {
1801    // expected-remark @below {{applying transformation "a"}}
1802    transform.test_transform_op "a"
1803    transform.yield
1804  }
1805
1806  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1807    transform.include @foo failures(propagate) (%arg0) : (!transform.any_op) -> ()
1808    transform.yield
1809  }
1810}
1811
1812// -----
1813
1814module @named_inclusion_in_named attributes { transform.with_named_sequence } {
1815
1816  transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly}) -> () {
1817    // expected-remark @below {{applying transformation "a"}}
1818    transform.test_transform_op "a"
1819    transform.yield
1820  }
1821
1822  transform.named_sequence @bar(%arg0: !transform.any_op {transform.readonly}) -> () {
1823    // expected-remark @below {{applying transformation "b"}}
1824    transform.test_transform_op "b"
1825    transform.include @foo failures(propagate) (%arg0) : (!transform.any_op) -> ()
1826    transform.yield
1827  }
1828
1829  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1830    transform.include @bar failures(suppress) (%arg0) : (!transform.any_op) -> ()
1831    transform.yield
1832  }
1833}
1834
1835// -----
1836
1837// expected-remark @below {{operation}}
1838module @named_operands attributes { transform.with_named_sequence } {
1839
1840  transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly},
1841                                %arg1: !transform.any_value {transform.readonly}) -> () {
1842    transform.debug.emit_remark_at %arg0, "operation" : !transform.any_op
1843    transform.debug.emit_remark_at %arg1, "value" : !transform.any_value
1844    transform.yield
1845  }
1846
1847  // expected-remark @below {{value}}
1848  // expected-note @below {{value handle points to a block argument #0 in block #0 in region #0}}
1849  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1850    %0 = transform.test_produce_value_handle_to_self_operand %arg0 : (!transform.any_op) -> !transform.any_value
1851    transform.include @foo failures(propagate) (%arg0, %0) : (!transform.any_op, !transform.any_value) -> ()
1852    transform.yield
1853  }
1854}
1855
1856// -----
1857
1858// expected-remark @below {{operation}}
1859module @named_return attributes { transform.with_named_sequence } {
1860
1861  // expected-remark @below {{value}}
1862  // expected-note @below {{value handle points to a block argument #0 in block #0 in region #0}}
1863  transform.named_sequence @foo(%arg0: !transform.any_op {transform.readonly}) -> (!transform.any_op, !transform.any_value) {
1864    %0 = transform.test_produce_value_handle_to_self_operand %arg0 : (!transform.any_op) -> !transform.any_value
1865    transform.yield %arg0, %0 : !transform.any_op, !transform.any_value
1866  }
1867
1868  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1869    %0:2 = transform.include @foo failures(propagate) (%arg0) : (!transform.any_op) -> (!transform.any_op, !transform.any_value)
1870    transform.debug.emit_remark_at %0#0, "operation" : !transform.any_op
1871    transform.debug.emit_remark_at %0#1, "value" : !transform.any_value
1872    transform.yield
1873  }
1874}
1875
1876// -----
1877
1878module attributes { transform.with_named_sequence } {
1879  transform.named_sequence @match1(%current: !transform.any_op {transform.readonly}) -> (!transform.any_op) {
1880    transform.test_succeed_if_operand_of_op_kind %current, "test.some_op" : !transform.any_op
1881    transform.yield %current : !transform.any_op
1882  }
1883
1884  transform.named_sequence @match2(%current: !transform.any_op {transform.readonly}) -> (!transform.any_op) {
1885    transform.test_succeed_if_operand_of_op_kind %current, "func.func" : !transform.any_op
1886    transform.yield %current : !transform.any_op
1887  }
1888
1889  transform.named_sequence @action1(%current: !transform.any_op {transform.readonly}) {
1890    transform.debug.emit_remark_at %current, "matched1" : !transform.any_op
1891    transform.yield
1892  }
1893  transform.named_sequence @action2(%current: !transform.any_op {transform.readonly}) {
1894    transform.debug.emit_remark_at %current, "matched2" : !transform.any_op
1895    transform.yield
1896  }
1897
1898  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1899    transform.foreach_match in %root
1900        @match1 -> @action1,
1901        @match2 -> @action2
1902      : (!transform.any_op) -> (!transform.any_op)
1903    transform.yield
1904  }
1905
1906  // expected-remark @below {{matched2}}
1907  func.func private @foo()
1908  // expected-remark @below {{matched2}}
1909  func.func private @bar()
1910  "test.testtest"() : () -> ()
1911  // expected-remark @below {{matched1}}
1912  "test.some_op"() : () -> ()
1913}
1914
1915// -----
1916
1917module attributes { transform.with_named_sequence } {
1918  transform.named_sequence @match(!transform.any_op {transform.readonly})
1919  transform.named_sequence @action()
1920
1921  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1922    // expected-error @below {{unresolved external symbol @match}}
1923    transform.foreach_match in %root
1924      @match -> @action : (!transform.any_op) -> !transform.any_op
1925    transform.yield
1926  }
1927}
1928
1929// -----
1930
1931module attributes { transform.with_named_sequence } {
1932  transform.named_sequence @match(%arg: !transform.any_op {transform.readonly}) {
1933    transform.yield
1934  }
1935  transform.named_sequence @action()
1936
1937  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1938    // expected-error @below {{unresolved external symbol @action}}
1939    transform.foreach_match in %root
1940      @match -> @action : (!transform.any_op) -> !transform.any_op
1941    transform.yield
1942  }
1943}
1944
1945// -----
1946
1947module attributes { transform.with_named_sequence } {
1948  transform.named_sequence @match(%arg: !transform.any_op {transform.readonly}) {
1949    // expected-error @below {{expected operations in the match part to implement MatchOpInterface}}
1950    "test.unknown_op"() : () -> ()
1951    transform.yield
1952  }
1953  transform.named_sequence @action() {
1954    transform.yield
1955  }
1956
1957  transform.named_sequence @__transform_main(%root: !transform.any_op) {
1958    transform.foreach_match in %root
1959      @match -> @action : (!transform.any_op) -> !transform.any_op
1960    transform.yield
1961  }
1962}
1963
1964// -----
1965
1966module attributes { transform.with_named_sequence } {
1967  transform.named_sequence @match_func(%arg0: !transform.any_op {transform.readonly})
1968    -> !transform.any_op {
1969    transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
1970    transform.yield %arg0 : !transform.any_op
1971  }
1972
1973  transform.named_sequence @print_func(%arg0: !transform.any_op {transform.readonly}) {
1974    transform.debug.emit_remark_at %arg0, "matched func" : !transform.any_op
1975    transform.yield
1976  }
1977
1978  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
1979    transform.foreach_match in %arg0 @match_func -> @print_func : (!transform.any_op) -> !transform.any_op
1980    transform.yield
1981  }
1982
1983  // expected-remark @below {{matched func}}
1984  func.func @payload() {
1985    return
1986  }
1987
1988  // expected-remark @below {{matched func}}
1989  func.func private @declaration()
1990
1991  "test.something_else"() : () -> ()
1992}
1993
1994// -----
1995
1996module attributes { transform.with_named_sequence } {
1997  transform.named_sequence @eq_1(%arg0: !transform.any_op {transform.readonly})
1998    -> !transform.any_op {
1999    transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
2000    %0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
2001    %1 = transform.param.constant 1 : i32 -> !transform.test_dialect_param
2002    transform.match.param.cmpi eq %0, %1 : !transform.test_dialect_param
2003    transform.debug.emit_remark_at %arg0, "matched == 1" : !transform.any_op
2004    transform.yield %arg0 : !transform.any_op
2005  }
2006
2007  transform.named_sequence @ne_0(%arg0: !transform.any_op {transform.readonly})
2008    -> !transform.any_op {
2009    transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
2010    %0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
2011    %1 = transform.param.constant 0 : i32 -> !transform.test_dialect_param
2012    transform.match.param.cmpi ne %0, %1 : !transform.test_dialect_param
2013    transform.debug.emit_remark_at %arg0, "matched != 0" : !transform.any_op
2014    transform.yield %arg0 : !transform.any_op
2015  }
2016
2017  transform.named_sequence @gt_m1(%arg0: !transform.any_op {transform.readonly})
2018    -> !transform.any_op {
2019    transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
2020    %0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
2021    %1 = transform.param.constant -1 : i32 -> !transform.test_dialect_param
2022    transform.match.param.cmpi gt %0, %1 : !transform.test_dialect_param
2023    transform.debug.emit_remark_at %arg0, "matched > -1" : !transform.any_op
2024    transform.yield %arg0 : !transform.any_op
2025  }
2026
2027  transform.named_sequence @ge_1(%arg0: !transform.any_op {transform.readonly})
2028    -> !transform.any_op {
2029    transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
2030    %0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
2031    %1 = transform.param.constant 1 : i32 -> !transform.test_dialect_param
2032    transform.match.param.cmpi ge %0, %1 : !transform.test_dialect_param
2033    transform.debug.emit_remark_at %arg0, "matched >= 1" : !transform.any_op
2034    transform.yield %arg0 : !transform.any_op
2035  }
2036
2037  transform.named_sequence @lt_1(%arg0: !transform.any_op {transform.readonly})
2038    -> !transform.any_op {
2039    transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
2040    %0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
2041    %1 = transform.param.constant 1 : i32 -> !transform.test_dialect_param
2042    transform.match.param.cmpi lt %0, %1 : !transform.test_dialect_param
2043    transform.debug.emit_remark_at %arg0, "matched < 1" : !transform.any_op
2044    transform.yield %arg0 : !transform.any_op
2045  }
2046
2047  transform.named_sequence @le_1(%arg0: !transform.any_op {transform.readonly})
2048    -> !transform.any_op {
2049    transform.match.operation_name %arg0 ["func.func"] : !transform.any_op
2050    %0 = transform.test_produce_param_with_number_of_test_ops %arg0 : !transform.any_op
2051    %1 = transform.param.constant 1 : i32 -> !transform.test_dialect_param
2052    transform.match.param.cmpi le %0, %1 : !transform.test_dialect_param
2053    transform.debug.emit_remark_at %arg0, "matched <= 1" : !transform.any_op
2054    transform.yield %arg0 : !transform.any_op
2055  }
2056
2057  transform.named_sequence @do_nothing(%arg0: !transform.any_op {transform.readonly}) {
2058    transform.yield
2059  }
2060
2061  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2062    %0 = transform.foreach_match in %arg0 @eq_1 -> @do_nothing : (!transform.any_op) -> !transform.any_op
2063    %1 = transform.foreach_match in %0 @ne_0 -> @do_nothing : (!transform.any_op) -> !transform.any_op
2064    %2 = transform.foreach_match in %1 @gt_m1 -> @do_nothing : (!transform.any_op) -> !transform.any_op
2065    %3 = transform.foreach_match in %2 @ge_1 -> @do_nothing : (!transform.any_op) -> !transform.any_op
2066    %4 = transform.foreach_match in %3 @lt_1 -> @do_nothing : (!transform.any_op) -> !transform.any_op
2067    %5 = transform.foreach_match in %4 @le_1 -> @do_nothing : (!transform.any_op) -> !transform.any_op
2068    transform.yield
2069  }
2070
2071  // expected-remark @below {{matched > -1}}
2072  // expected-remark @below {{matched < 1}}
2073  // expected-remark @below {{matched <= 1}}
2074  func.func private @declaration()
2075
2076  // expected-remark @below {{matched == 1}}
2077  // expected-remark @below {{matched != 0}}
2078  // expected-remark @below {{matched > -1}}
2079  // expected-remark @below {{matched >= 1}}
2080  // expected-remark @below {{matched <= 1}}
2081  func.func @definition() {
2082    "test.something"() : () -> ()
2083    return
2084  }
2085}
2086
2087// -----
2088
2089// CHECK-LABEL: func @test_tracked_rewrite() {
2090//  CHECK-NEXT:   transform.test_dummy_payload_op  {new_op} : () -> i1
2091//  CHECK-NEXT:   transform.test_dummy_payload_op  {new_op} : () -> i1
2092//  CHECK-NEXT:   return
2093//  CHECK-NEXT: }
2094func.func @test_tracked_rewrite() {
2095  %0 = transform.test_dummy_payload_op {replace_me} : () -> (i1)
2096  %1 = transform.test_dummy_payload_op {erase_me} : () -> (i1)
2097  %2 = transform.test_dummy_payload_op {replace_me} : () -> (i1)
2098  func.return
2099}
2100
2101module attributes {transform.with_named_sequence} {
2102  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
2103    %0 = transform.structured.match ops{["transform.test_dummy_payload_op"]} in %arg1 : (!transform.any_op) -> !transform.any_op
2104    // expected-remark @below {{2 iterations}}
2105    transform.test_tracked_rewrite %0 : (!transform.any_op) -> ()
2106    // One replacement op (test.drop_mapping) is dropped from the mapping.
2107    %p = transform.num_associations %0 : (!transform.any_op) -> !transform.param<i64>
2108    // expected-remark @below {{2}}
2109    transform.debug.emit_param_as_remark  %p : !transform.param<i64>
2110    transform.yield
2111  }
2112}
2113
2114// -----
2115
2116// Parameter deduplication happens by value
2117
2118module attributes {transform.with_named_sequence} {
2119
2120  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2121    %1 = transform.param.constant 1 -> !transform.param<i64>
2122    %2 = transform.param.constant 1 -> !transform.param<i64>
2123    %3 = transform.param.constant 2 -> !transform.param<i64>
2124    %4 = transform.merge_handles %1, %2 { deduplicate } : !transform.param<i64>
2125    %p = transform.num_associations %4 : (!transform.param<i64>) -> !transform.param<i64>
2126    // expected-remark @below {{1}}
2127    transform.debug.emit_param_as_remark %p : !transform.param<i64>
2128
2129    %5 = transform.merge_handles %1, %1 { deduplicate } : !transform.param<i64>
2130    %p2 = transform.num_associations %5 : (!transform.param<i64>) -> !transform.param<i64>
2131    // expected-remark @below {{1}}
2132    transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
2133
2134    %6 = transform.merge_handles %1, %3 { deduplicate } : !transform.param<i64>
2135    %p3 = transform.num_associations %6 : (!transform.param<i64>) -> !transform.param<i64>
2136    // expected-remark @below {{2}}
2137    transform.debug.emit_param_as_remark %p3 : !transform.param<i64>
2138
2139    %7 = transform.merge_handles %1, %1, %2, %3 : !transform.param<i64>
2140    %p4 = transform.num_associations %7 : (!transform.param<i64>) -> !transform.param<i64>
2141    // expected-remark @below {{4}}
2142    transform.debug.emit_param_as_remark %p4 : !transform.param<i64>
2143    transform.yield
2144  }
2145}
2146
2147// -----
2148
2149%0:3 = "test.get_two_results"() : () -> (i32, i32, f32)
2150
2151module attributes {transform.with_named_sequence} {
2152  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2153    %1 = transform.structured.match ops{["test.get_two_results"]} in %arg0 : (!transform.any_op) -> !transform.any_op
2154    %2 = transform.test_produce_value_handle_to_result %1, 0 : (!transform.any_op) -> !transform.any_value
2155    %3 = transform.test_produce_value_handle_to_result %1, 1 : (!transform.any_op) -> !transform.any_value
2156
2157    %4 = transform.merge_handles %2, %2 { deduplicate } : !transform.any_value
2158    %p = transform.num_associations %4 : (!transform.any_value) -> !transform.param<i64>
2159    // expected-remark @below {{1}}
2160    transform.debug.emit_param_as_remark %p : !transform.param<i64>
2161
2162    %5 = transform.merge_handles %2, %3 { deduplicate } : !transform.any_value
2163    %p2 = transform.num_associations %5 : (!transform.any_value) -> !transform.param<i64>
2164    // expected-remark @below {{2}}
2165    transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
2166
2167    %6 = transform.test_produce_value_handle_to_result %1, 0 : (!transform.any_op) -> !transform.any_value
2168    %7 = transform.merge_handles %2, %6 { deduplicate } : !transform.any_value
2169    %p3 = transform.num_associations %6 : (!transform.any_value) -> !transform.param<i64>
2170    // expected-remark @below {{1}}
2171    transform.debug.emit_param_as_remark %p3 : !transform.param<i64>
2172
2173    %8 = transform.merge_handles %2, %2, %3, %4 : !transform.any_value
2174    %p4 = transform.num_associations %8 : (!transform.any_value) -> !transform.param<i64>
2175    // expected-remark @below {{4}}
2176    transform.debug.emit_param_as_remark %p4 : !transform.param<i64>
2177    transform.yield
2178  }
2179}
2180// -----
2181
2182// CHECK-LABEL: func @test_annotation()
2183//  CHECK-NEXT:   "test.annotate_me"()
2184//  CHECK-SAME:                        any_attr = "example"
2185//  CHECK-SAME:                        broadcast_attr = 2 : i64
2186//  CHECK-SAME:                        new_attr = 1 : i32
2187//  CHECK-SAME:                        unit_attr
2188//  CHECK-NEXT:   "test.annotate_me"()
2189//  CHECK-SAME:                        any_attr = "example"
2190//  CHECK-SAME:                        broadcast_attr = 2 : i64
2191//  CHECK-SAME:                        existing_attr = "test"
2192//  CHECK-SAME:                        new_attr = 1 : i32
2193//  CHECK-SAME:                        unit_attr
2194//  CHECK-NEXT:   "test.annotate_me"()
2195//  CHECK-SAME:                        any_attr = "example"
2196//  CHECK-SAME:                        broadcast_attr = 2 : i64
2197//  CHECK-SAME:                        new_attr = 1 : i32
2198//  CHECK-SAME:                        unit_attr
2199func.func @test_annotation() {
2200  %0 = "test.annotate_me"() : () -> (i1)
2201  %1 = "test.annotate_me"() {existing_attr = "test"} : () -> (i1)
2202  %2 = "test.annotate_me"() {new_attr = 0} : () -> (i1)
2203}
2204
2205module attributes {transform.with_named_sequence} {
2206  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2207    %0 = transform.structured.match ops{["test.annotate_me"]} in %arg0 : (!transform.any_op) -> !transform.any_op
2208    %1 = transform.test_produce_param_with_number_of_test_ops %0 : !transform.any_op
2209    transform.annotate %0 "new_attr" = %1 : !transform.any_op, !transform.test_dialect_param
2210
2211    %2 = transform.param.constant 2 -> !transform.param<i64>
2212    transform.annotate %0 "broadcast_attr" = %2 : !transform.any_op, !transform.param<i64>
2213    transform.annotate %0 "unit_attr" : !transform.any_op
2214
2215    %3 = transform.param.constant "example" -> !transform.any_param
2216    transform.annotate %0 "any_attr" = %3 : !transform.any_op, !transform.any_param
2217    transform.yield
2218  }
2219}
2220
2221// -----
2222
2223func.func @notify_payload_op_replaced(%arg0: index, %arg1: index) {
2224  %0 = arith.muli %arg0, %arg1 {original} : index
2225  // expected-remark @below{{updated handle}}
2226  %1 = arith.muli %arg0, %arg1 {replacement} : index
2227  return
2228}
2229
2230module attributes {transform.with_named_sequence} {
2231  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
2232    %0 = transform.structured.match attributes{original} in %arg1 : (!transform.any_op) -> !transform.any_op
2233    %1 = transform.structured.match attributes{replacement} in %arg1 : (!transform.any_op) -> !transform.any_op
2234    transform.test_notify_payload_op_replaced %0, %1 : (!transform.any_op, !transform.any_op) -> ()
2235    transform.debug.emit_remark_at %0, "updated handle" : !transform.any_op
2236    transform.yield
2237  }
2238}
2239
2240// -----
2241
2242// CHECK-LABEL: func @test_apply_cse()
2243//       CHECK:   %[[const:.*]] = arith.constant 0 : index
2244//       CHECK:   %[[ex1:.*]] = scf.execute_region -> index {
2245//       CHECK:     scf.yield %[[const]]
2246//       CHECK:   }
2247//       CHECK:   %[[ex2:.*]] = scf.execute_region -> index {
2248//       CHECK:     scf.yield %[[const]]
2249//       CHECK:   }
2250//       CHECK:   return %[[const]], %[[ex1]], %[[ex2]]
2251func.func @test_apply_cse() -> (index, index, index) {
2252  // expected-remark @below{{eliminated 1}}
2253  // expected-remark @below{{eliminated 2}}
2254  %0 = arith.constant 0 : index
2255  %1 = scf.execute_region -> index {
2256    %2 = arith.constant 0 : index
2257    scf.yield %2 : index
2258  } {first}
2259  %3 = scf.execute_region -> index {
2260    %4 = arith.constant 0 : index
2261    scf.yield %4 : index
2262  } {second}
2263  return %0, %1, %3 : index, index, index
2264}
2265
2266module attributes {transform.with_named_sequence} {
2267  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
2268    %0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
2269    %first = transform.structured.match attributes{first} in %0 : (!transform.any_op) -> !transform.any_op
2270    %elim_first = transform.structured.match ops{["arith.constant"]} in %first : (!transform.any_op) -> !transform.any_op
2271    %second = transform.structured.match attributes{first} in %0 : (!transform.any_op) -> !transform.any_op
2272    %elim_second = transform.structured.match ops{["arith.constant"]} in %first : (!transform.any_op) -> !transform.any_op
2273
2274    // There are 3 arith.constant ops.
2275    %all = transform.structured.match ops{["arith.constant"]} in %0 : (!transform.any_op) -> !transform.any_op
2276    %p = transform.num_associations %all : (!transform.any_op) -> !transform.param<i64>
2277    // expected-remark @below{{3}}
2278    transform.debug.emit_param_as_remark %p : !transform.param<i64>
2279    // "deduplicate" has no effect because these are 3 different ops.
2280    %merged_before = transform.merge_handles deduplicate %all : !transform.any_op
2281    %p2 = transform.num_associations %merged_before : (!transform.any_op) -> !transform.param<i64>
2282    // expected-remark @below{{3}}
2283    transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
2284
2285    // Apply CSE.
2286    transform.apply_cse to %0 : !transform.any_op
2287
2288    // The handle is still mapped to 3 arith.constant ops.
2289    %p3 = transform.num_associations %all : (!transform.any_op) -> !transform.param<i64>
2290    // expected-remark @below{{3}}
2291    transform.debug.emit_param_as_remark %p3 : !transform.param<i64>
2292    // But they are all the same op.
2293    %merged_after = transform.merge_handles deduplicate %all : !transform.any_op
2294    %p4 = transform.num_associations %merged_after : (!transform.any_op) -> !transform.param<i64>
2295    // expected-remark @below{{1}}
2296    transform.debug.emit_param_as_remark %p4 : !transform.param<i64>
2297
2298    // The other handles were also updated.
2299    transform.debug.emit_remark_at %elim_first, "eliminated 1" : !transform.any_op
2300    %p5 = transform.num_associations %elim_first : (!transform.any_op) -> !transform.param<i64>
2301    // expected-remark @below{{1}}
2302    transform.debug.emit_param_as_remark %p5 : !transform.param<i64>
2303    transform.debug.emit_remark_at %elim_second, "eliminated 2" : !transform.any_op
2304    %p6 = transform.num_associations %elim_second : (!transform.any_op) -> !transform.param<i64>
2305    // expected-remark @below{{1}}
2306    transform.debug.emit_param_as_remark %p6 : !transform.param<i64>
2307    transform.yield
2308  }
2309}
2310
2311// -----
2312
2313// CHECK-LABEL: func @test_licm(
2314//       CHECK:   arith.muli
2315//       CHECK:   scf.for {{.*}} {
2316//       CHECK:     vector.print
2317//       CHECK:   }
2318func.func @test_licm(%arg0: index, %arg1: index, %arg2: index) {
2319  scf.for %iv = %arg0 to %arg1 step %arg2 {
2320    %0 = arith.muli %arg0, %arg1 : index
2321    vector.print %0 : index
2322  }
2323  return
2324}
2325
2326module attributes {transform.with_named_sequence} {
2327  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
2328    %0 = transform.structured.match ops{["scf.for"]} in %arg1 : (!transform.any_op) -> !transform.any_op
2329    transform.apply_licm to %0 : !transform.any_op
2330    transform.yield
2331  }
2332}
2333
2334// -----
2335
2336// expected-note @below{{when applied to this op}}
2337module attributes {transform.with_named_sequence} {
2338  func.func @test_licm_invalid() {
2339    return
2340  }
2341
2342  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
2343    // expected-error @below{{transform applied to the wrong op kind}}
2344    transform.apply_licm to %arg1 : !transform.any_op
2345    transform.yield
2346  }
2347}
2348
2349// -----
2350
2351func.func @get_parent_op() {
2352  // expected-remark @below{{found test.foo parent}}
2353  "test.foo"() ({
2354    // expected-remark @below{{direct parent}}
2355    "test.bar"() ({
2356      "test.qux"() : () -> ()
2357      "test.qux"() : () -> ()
2358    }) : () -> ()
2359  }) : () -> ()
2360}
2361
2362module attributes {transform.with_named_sequence} {
2363  transform.named_sequence @__transform_main(%arg1: !transform.any_op) {
2364    %0 = transform.structured.match ops{["test.qux"]} in %arg1 : (!transform.any_op) -> !transform.any_op
2365
2366    // Get parent by name.
2367    %1 = transform.get_parent_op %0 {op_name = "test.foo"} : (!transform.any_op) -> !transform.any_op
2368    transform.debug.emit_remark_at %1, "found test.foo parent" : !transform.any_op
2369
2370    // Get immediate parent.
2371    %2 = transform.get_parent_op %0 : (!transform.any_op) -> !transform.any_op
2372    transform.debug.emit_remark_at %2, "direct parent" : !transform.any_op
2373    %p = transform.num_associations %2 : (!transform.any_op) -> !transform.param<i64>
2374    // expected-remark @below{{2}}
2375    transform.debug.emit_param_as_remark %p : !transform.param<i64>
2376
2377    // Deduplicate results.
2378    %3 = transform.structured.match ops{["test.qux"]} in %arg1 : (!transform.any_op) -> !transform.any_op
2379    %4 = transform.get_parent_op %3 {deduplicate} : (!transform.any_op) -> !transform.any_op
2380    %p2 = transform.num_associations %4 : (!transform.any_op) -> !transform.param<i64>
2381    // expected-remark @below{{1}}
2382    transform.debug.emit_param_as_remark %p2 : !transform.param<i64>
2383    transform.yield
2384  }
2385}
2386
2387
2388// -----
2389
2390// expected-note @below {{target op}}
2391module attributes {transform.with_named_sequence} {
2392  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2393    // expected-error @below{{could not find a parent op that matches all requirements}}
2394    %3 = transform.get_parent_op %arg0 {op_name = "builtin.module"} : (!transform.any_op) -> !transform.any_op
2395    transform.yield
2396  }
2397}
2398
2399// -----
2400
2401func.func @cast(%arg0: f32) -> f64 {
2402  // expected-remark @below{{f64}}
2403  %0 = arith.extf %arg0 : f32 to f64
2404  return %0 : f64
2405}
2406
2407module attributes {transform.with_named_sequence} {
2408  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2409    %0 = transform.structured.match ops{["arith.extf"]} in %arg0 : (!transform.any_op) -> !transform.op<"arith.extf">
2410    %1 = transform.get_result %0[0] : (!transform.op<"arith.extf">) -> !transform.any_value
2411    %2 = transform.get_type %1 : (!transform.any_value) -> !transform.type
2412    transform.debug.emit_param_as_remark %2 at %0 : !transform.type, !transform.op<"arith.extf">
2413    transform.yield
2414  }
2415}
2416
2417// -----
2418
2419module attributes {transform.with_named_sequence} {
2420  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2421    // expected-error @below {{expected type attribute, got 0 : i32}}
2422    transform.test_produce_param (0 : i32) : !transform.type
2423    transform.yield
2424  }
2425}
2426
2427// -----
2428
2429module attributes {transform.with_named_sequence} {
2430  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2431    // expected-error @below {{expected affine map attribute, got 0 : i32}}
2432    transform.test_produce_param (0 : i32) : !transform.affine_map
2433    transform.yield
2434  }
2435}
2436
2437// -----
2438
2439// CHECK-LABEL: @type_param_anchor
2440func.func private @type_param_anchor()
2441
2442module attributes {transform.with_named_sequence} {
2443  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2444    // CHECK: test_produce_param(f32) : !transform.type
2445    transform.test_produce_param(f32) : !transform.type
2446    transform.yield
2447  }
2448}
2449
2450// -----
2451
2452// CHECK-LABEL: @affine_map_param_anchor
2453func.func private @affine_map_param_anchor()
2454
2455module attributes {transform.with_named_sequence} {
2456  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2457    // CHECK: test_produce_param(#{{.*}}) : !transform.affine_map
2458    transform.test_produce_param(affine_map<(d0) -> ()>) : !transform.affine_map
2459    transform.yield
2460  }
2461}
2462
2463// -----
2464
2465func.func @verify_success(%arg0: f64) -> f64 {
2466  return %arg0 : f64
2467}
2468
2469module attributes {transform.with_named_sequence} {
2470  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2471    %0 = transform.structured.match ops{["func.func"]} in %arg0 : (!transform.any_op) -> !transform.any_op
2472    transform.verify %0 : !transform.any_op
2473    transform.yield
2474  }
2475}
2476
2477// -----
2478
2479// expected-error @below{{fail_to_verify is set}}
2480// expected-note @below{{payload op}}
2481func.func @verify_failure(%arg0: f64) -> f64 {
2482  return %arg0 : f64
2483}
2484
2485module attributes {transform.with_named_sequence} {
2486  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2487    %0 = transform.structured.match ops{["func.func"]} in %arg0 : (!transform.any_op) -> !transform.any_op
2488    transform.test_produce_invalid_ir %0 : !transform.any_op
2489    // expected-error @below{{failed to verify payload op}}
2490    transform.verify %0 : !transform.any_op
2491    transform.yield
2492  }
2493}
2494
2495// -----
2496
2497func.func @select() {
2498  // expected-remark @below{{found foo}}
2499  "test.foo"() : () -> ()
2500  // expected-remark @below{{found bar}}
2501  "test.bar"() : () -> ()
2502  // expected-remark @below{{found foo}}
2503  "test.foo"() : () -> ()
2504  func.return
2505}
2506
2507module attributes {transform.with_named_sequence} {
2508  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2509    // Match all ops inside the function (including the function itself).
2510    %func_op = transform.structured.match ops{["func.func"]} in %arg0 : (!transform.any_op) -> !transform.any_op
2511    %0 = transform.structured.match in %func_op : (!transform.any_op) -> !transform.any_op
2512    %p = transform.num_associations %0 : (!transform.any_op) -> !transform.param<i64>
2513    // expected-remark @below{{5}}
2514    transform.debug.emit_param_as_remark %p : !transform.param<i64>
2515
2516    // Select "test.foo".
2517    %foo = transform.select "test.foo" in %0 : (!transform.any_op) -> !transform.any_op
2518    transform.debug.emit_remark_at %foo, "found foo" : !transform.any_op
2519
2520    // Select "test.bar".
2521    %bar = transform.select "test.bar" in %0 : (!transform.any_op) -> !transform.any_op
2522    transform.debug.emit_remark_at %bar, "found bar" : !transform.any_op
2523    transform.yield
2524  }
2525}
2526
2527// -----
2528
2529// CHECK-LABEL: func @apply_dce(
2530//  CHECK-NEXT:   memref.store
2531//  CHECK-NEXT:   return
2532func.func @apply_dce(%f: f32, %m: memref<5xf32>, %idx: index) {
2533  // Two dead ops, interleaved with a non-dead op.
2534  %0 = tensor.empty() : tensor<5xf32>
2535  memref.store %f, %m[%idx] : memref<5xf32>
2536  %1 = tensor.insert %f into %0[%idx] : tensor<5xf32>
2537  return
2538}
2539
2540module attributes {transform.with_named_sequence} {
2541  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2542    %func_op = transform.structured.match ops{["func.func"]} in %arg0 : (!transform.any_op) -> !transform.any_op
2543    %empty_op = transform.structured.match ops{["tensor.empty"]} in %func_op : (!transform.any_op) -> !transform.any_op
2544    transform.apply_dce to %func_op : !transform.any_op
2545
2546    %p = transform.num_associations %empty_op : (!transform.any_op) -> !transform.param<i64>
2547    // expected-remark @below{{0}}
2548    transform.debug.emit_param_as_remark %p : !transform.param<i64>
2549    transform.yield
2550  }
2551}
2552
2553
2554// -----
2555
2556func.func @no_constant_under_loop(%lb: index, %ub: index, %step: index) {
2557  scf.for %i= %lb to %ub step %step {
2558    arith.constant 0 : index
2559  }
2560  return
2561}
2562
2563module @named_inclusion attributes { transform.with_named_sequence } {
2564// Match `arith.constant`s that are not nested under a `scf.for` and ensure
2565// there are none in the program
2566
2567  transform.named_sequence @print(%root: !transform.any_op {transform.readonly}) {
2568    transform.debug.emit_remark_at %root, "matched func" : !transform.any_op
2569    transform.yield
2570  }
2571
2572  transform.named_sequence @match_constant_not_under_scf_for(%root: !transform.any_op {transform.readonly})
2573    -> !transform.any_op {
2574    transform.match.operation_name %root ["arith.constant"] : !transform.any_op
2575    %for = transform.get_parent_op %root { op_name = "scf.for", allow_empty_results }
2576      : (!transform.any_op) -> (!transform.any_op)
2577    transform.match.operation_empty %for : !transform.any_op
2578    transform.yield %root : !transform.any_op
2579  }
2580
2581  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2582    transform.foreach_match in %arg0
2583        @match_constant_not_under_scf_for -> @print
2584      : (!transform.any_op) -> (!transform.any_op)
2585    transform.yield
2586  }
2587}
2588
2589// -----
2590
2591func.func @no_constant_under_loop(%lb: index, %ub: index, %step: index) {
2592  // expected-remark @below {{no parent scf.for}}
2593  arith.constant 0 : index
2594  return
2595}
2596
2597module @named_inclusion attributes { transform.with_named_sequence } {
2598  // Match `arith.constant`s that are not nested under a `scf.for` and ensure
2599  // there are none in the program
2600
2601  transform.named_sequence @print(%root: !transform.any_op {transform.readonly}) {
2602    transform.debug.emit_remark_at %root, "no parent scf.for" : !transform.any_op
2603    transform.yield
2604  }
2605
2606  transform.named_sequence @match_constant_not_under_scf_for(%root: !transform.any_op {transform.readonly})
2607    -> !transform.any_op {
2608    transform.match.operation_name %root ["arith.constant"] : !transform.any_op
2609    %for = transform.get_parent_op %root { op_name = "scf.for", allow_empty_results }
2610      : (!transform.any_op) -> (!transform.any_op)
2611    transform.match.operation_empty %for : !transform.any_op
2612    transform.yield %root : !transform.any_op
2613  }
2614
2615  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2616    transform.foreach_match in %arg0
2617        @match_constant_not_under_scf_for -> @print
2618      : (!transform.any_op) -> (!transform.any_op)
2619    transform.yield
2620  }
2621}
2622
2623// -----
2624
2625module attributes { transform.with_named_sequence } {
2626  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2627    // expected-error @below {{result #0, associated with 2 payload objects, expected 1}}
2628    transform.collect_matching @matcher in %arg0 : (!transform.any_op) -> !transform.any_op
2629    transform.yield
2630  }
2631
2632  transform.named_sequence @matcher(%arg0: !transform.any_op {transform.readonly}) -> !transform.any_op {
2633    %0 = transform.merge_handles %arg0, %arg0 : !transform.any_op
2634    transform.yield %0 : !transform.any_op
2635  }
2636}
2637
2638// -----
2639
2640module attributes { transform.with_named_sequence } {
2641  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2642    // expected-error @below {{unresolved external symbol @matcher}}
2643    transform.collect_matching @matcher in %arg0 : (!transform.any_op) -> !transform.any_op
2644    transform.yield
2645  }
2646
2647  transform.named_sequence @matcher(%arg0: !transform.any_op {transform.readonly}) -> !transform.any_op
2648}
2649
2650// -----
2651
2652module attributes { transform.with_named_sequence } {
2653  transform.named_sequence @__transform_main(%arg0: !transform.any_op) {
2654    // expected-remark @below {{matched}}
2655    %0 = transform.collect_matching @matcher in %arg0 : (!transform.any_op) -> !transform.any_op
2656    // expected-remark @below {{matched}}
2657    transform.debug.emit_remark_at %0, "matched" : !transform.any_op
2658    transform.yield
2659  }
2660
2661  transform.named_sequence @matcher(%arg0: !transform.any_op {transform.readonly}) -> !transform.any_op {
2662    transform.match.operation_name %arg0 ["transform.debug.emit_remark_at", "transform.collect_matching"] : !transform.any_op
2663    transform.yield %arg0 : !transform.any_op
2664  }
2665}
2666