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