759 lines · plain
1// RUN: mlir-opt -split-input-file -convert-pdl-to-pdl-interp %s | FileCheck %s2 3// CHECK-LABEL: module @empty_module4module @empty_module {5// CHECK: func @matcher(%{{.*}}: !pdl.operation)6// CHECK-NEXT: pdl_interp.finalize7}8 9// -----10 11// CHECK-LABEL: module @simple12module @simple {13 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)14 // CHECK: pdl_interp.check_operation_name of %[[ROOT]] is "foo.op" -> ^bb2, ^bb115 // CHECK: ^bb1:16 // CHECK: pdl_interp.finalize17 // CHECK: ^bb2:18 // CHECK: pdl_interp.check_operand_count of %[[ROOT]] is 0 -> ^bb3, ^bb119 // CHECK: ^bb3:20 // CHECK: pdl_interp.check_result_count of %[[ROOT]] is 0 -> ^bb4, ^bb121 // CHECK: ^bb4:22 // CHECK: pdl_interp.record_match @rewriters::@pdl_generated_rewriter23 // CHECK-SAME: benefit(1), loc([%[[ROOT]]]), root("foo.op") -> ^bb124 25 // CHECK: module @rewriters26 // CHECK: func @pdl_generated_rewriter(%[[REWRITE_ROOT:.*]]: !pdl.operation)27 // CHECK: pdl_interp.apply_rewrite "rewriter"(%[[REWRITE_ROOT]]28 // CHECK: pdl_interp.finalize29 pdl.pattern : benefit(1) {30 %root = operation "foo.op"31 rewrite %root with "rewriter"32 }33}34 35// -----36 37// CHECK-LABEL: module @attributes38module @attributes {39 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)40 // Check the value of "attr".41 // CHECK-DAG: %[[ATTR:.*]] = pdl_interp.get_attribute "attr" of %[[ROOT]]42 // CHECK-DAG: pdl_interp.is_not_null %[[ATTR]] : !pdl.attribute43 // CHECK-DAG: pdl_interp.check_attribute %[[ATTR]] is 10 : i6444 45 // Check the type of "attr1".46 // CHECK-DAG: %[[ATTR1:.*]] = pdl_interp.get_attribute "attr1" of %[[ROOT]]47 // CHECK-DAG: pdl_interp.is_not_null %[[ATTR1]] : !pdl.attribute48 // CHECK-DAG: %[[ATTR1_TYPE:.*]] = pdl_interp.get_attribute_type of %[[ATTR1]]49 // CHECK-DAG: pdl_interp.check_type %[[ATTR1_TYPE]] is i6450 pdl.pattern : benefit(1) {51 %type = type : i6452 %attr = attribute = 10 : i6453 %attr1 = attribute : %type54 %root = operation {"attr" = %attr, "attr1" = %attr1}55 rewrite %root with "rewriter"56 }57}58 59// -----60 61// CHECK-LABEL: module @constraints62module @constraints {63 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)64 // CHECK-DAG: %[[INPUT:.*]] = pdl_interp.get_operand 0 of %[[ROOT]]65 // CHECK-DAG: %[[INPUT1:.*]] = pdl_interp.get_operand 1 of %[[ROOT]]66 // CHECK-DAG: %[[RESULT:.*]] = pdl_interp.get_result 0 of %[[ROOT]]67 // CHECK: pdl_interp.apply_constraint "multi_constraint"(%[[INPUT]], %[[INPUT1]], %[[RESULT]]68 69 pdl.pattern : benefit(1) {70 %input0 = operand71 %input1 = operand72 %root = operation(%input0, %input1 : !pdl.value, !pdl.value)73 %result0 = result 0 of %root74 75 pdl.apply_native_constraint "multi_constraint"(%input0, %input1, %result0 : !pdl.value, !pdl.value, !pdl.value)76 rewrite %root with "rewriter"77 }78}79 80// -----81 82// CHECK-LABEL: module @constraint_with_result83module @constraint_with_result {84 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)85 // CHECK: %[[ATTR:.*]] = pdl_interp.apply_constraint "check_op_and_get_attr_constr"(%[[ROOT]]86 // CHECK: pdl_interp.record_match @rewriters::@pdl_generated_rewriter(%[[ROOT]], %[[ATTR]] : !pdl.operation, !pdl.attribute)87 pdl.pattern : benefit(1) {88 %root = operation89 %attr = pdl.apply_native_constraint "check_op_and_get_attr_constr"(%root : !pdl.operation) : !pdl.attribute90 rewrite %root with "rewriter"(%attr : !pdl.attribute)91 }92}93 94// -----95 96// CHECK-LABEL: module @constraint_with_unused_result97module @constraint_with_unused_result {98 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)99 // CHECK: %[[ATTR:.*]] = pdl_interp.apply_constraint "check_op_and_get_attr_constr"(%[[ROOT]]100 // CHECK: pdl_interp.record_match @rewriters::@pdl_generated_rewriter(%[[ROOT]] : !pdl.operation)101 pdl.pattern : benefit(1) {102 %root = operation103 %attr = pdl.apply_native_constraint "check_op_and_get_attr_constr"(%root : !pdl.operation) : !pdl.attribute104 rewrite %root with "rewriter"105 }106}107 108// -----109 110// CHECK-LABEL: module @constraint_with_result_multiple111module @constraint_with_result_multiple {112 // check that native constraints work as expected even when multiple identical constraints are fused113 114 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)115 // CHECK: %[[ATTR:.*]] = pdl_interp.apply_constraint "check_op_and_get_attr_constr"(%[[ROOT]]116 // CHECK-NOT: pdl_interp.apply_constraint "check_op_and_get_attr_constr"117 // CHECK: pdl_interp.record_match @rewriters::@pdl_generated_rewriter_0(%[[ROOT]], %[[ATTR]] : !pdl.operation, !pdl.attribute)118 // CHECK: pdl_interp.record_match @rewriters::@pdl_generated_rewriter(%[[ROOT]], %[[ATTR]] : !pdl.operation, !pdl.attribute)119 pdl.pattern : benefit(1) {120 %root = operation121 %attr = pdl.apply_native_constraint "check_op_and_get_attr_constr"(%root : !pdl.operation) : !pdl.attribute122 rewrite %root with "rewriter"(%attr : !pdl.attribute)123 }124 pdl.pattern : benefit(1) {125 %root = operation126 %attr = pdl.apply_native_constraint "check_op_and_get_attr_constr"(%root : !pdl.operation) : !pdl.attribute127 rewrite %root with "rewriter"(%attr : !pdl.attribute)128 }129}130 131// -----132 133// CHECK-LABEL: module @negated_constraint134module @negated_constraint {135 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)136 // CHECK: pdl_interp.apply_constraint "constraint"(%[[ROOT]] : !pdl.operation) {isNegated = true}137 // CHECK: pdl_interp.record_match @rewriters::@pdl_generated_rewriter(%[[ROOT]] : !pdl.operation)138 pdl.pattern : benefit(1) {139 %root = operation140 pdl.apply_native_constraint "constraint"(%root : !pdl.operation) {isNegated = true}141 rewrite %root with "rewriter"142 }143}144 145// -----146 147// CHECK-LABEL: module @inputs148module @inputs {149 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)150 // CHECK-DAG: pdl_interp.check_operand_count of %[[ROOT]] is 2151 152 // Get the input and check the type.153 // CHECK-DAG: %[[INPUT:.*]] = pdl_interp.get_operand 0 of %[[ROOT]]154 // CHECK-DAG: pdl_interp.is_not_null %[[INPUT]] : !pdl.value155 // CHECK-DAG: %[[INPUT_TYPE:.*]] = pdl_interp.get_value_type of %[[INPUT]]156 // CHECK-DAG: pdl_interp.check_type %[[INPUT_TYPE]] is i64157 158 // Get the second operand and check that it is equal to the first.159 // CHECK-DAG: %[[INPUT1:.*]] = pdl_interp.get_operand 1 of %[[ROOT]]160 // CHECK-DAG: pdl_interp.are_equal %[[INPUT]], %[[INPUT1]] : !pdl.value161 pdl.pattern : benefit(1) {162 %type = type : i64163 %input = operand : %type164 %root = operation(%input, %input : !pdl.value, !pdl.value)165 rewrite %root with "rewriter"166 }167}168 169// -----170 171// CHECK-LABEL: module @variadic_inputs172module @variadic_inputs {173 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)174 // CHECK-DAG: pdl_interp.check_operand_count of %[[ROOT]] is at_least 2175 176 // The first operand has a known index.177 // CHECK-DAG: %[[INPUT:.*]] = pdl_interp.get_operand 0 of %[[ROOT]]178 // CHECK-DAG: pdl_interp.is_not_null %[[INPUT]] : !pdl.value179 180 // The second operand is a group of unknown size, with a type constraint.181 // CHECK-DAG: %[[VAR_INPUTS:.*]] = pdl_interp.get_operands 1 of %[[ROOT]] : !pdl.range<value>182 // CHECK-DAG: pdl_interp.is_not_null %[[VAR_INPUTS]] : !pdl.range<value>183 184 // CHECK-DAG: %[[INPUT_TYPE:.*]] = pdl_interp.get_value_type of %[[VAR_INPUTS]] : !pdl.range<type>185 // CHECK-DAG: pdl_interp.check_types %[[INPUT_TYPE]] are [i64]186 187 // The third operand is at an unknown offset due to operand 2, but is expected188 // to be of size 1.189 // CHECK-DAG: %[[INPUT2:.*]] = pdl_interp.get_operands 2 of %[[ROOT]] : !pdl.value190 // CHECK-DAG: pdl_interp.are_equal %[[INPUT]], %[[INPUT2]] : !pdl.value191 pdl.pattern : benefit(1) {192 %types = types : [i64]193 %inputs = operands : %types194 %input = operand195 %root = operation(%input, %inputs, %input : !pdl.value, !pdl.range<value>, !pdl.value)196 rewrite %root with "rewriter"197 }198}199 200// -----201 202// CHECK-LABEL: module @single_operand_range203module @single_operand_range {204 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)205 206 // Check that the operand range is treated as all of the operands of the207 // operation.208 // CHECK-DAG: %[[RESULTS:.*]] = pdl_interp.get_operands of %[[ROOT]]209 // CHECK-DAG: %[[RESULT_TYPES:.*]] = pdl_interp.get_value_type of %[[RESULTS]] : !pdl.range<type>210 // CHECK-DAG: pdl_interp.check_types %[[RESULT_TYPES]] are [i64]211 212 // The operand count is unknown, so there is no need to check for it.213 // CHECK-NOT: pdl_interp.check_operand_count214 pdl.pattern : benefit(1) {215 %types = types : [i64]216 %operands = operands : %types217 %root = operation(%operands : !pdl.range<value>)218 rewrite %root with "rewriter"219 }220}221 222// -----223 224// CHECK-LABEL: module @results225module @results {226 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)227 // CHECK: pdl_interp.check_result_count of %[[ROOT]] is 2228 229 // Get the result and check the type.230 // CHECK-DAG: %[[RESULT:.*]] = pdl_interp.get_result 0 of %[[ROOT]]231 // CHECK-DAG: pdl_interp.is_not_null %[[RESULT]] : !pdl.value232 // CHECK-DAG: %[[RESULT_TYPE:.*]] = pdl_interp.get_value_type of %[[RESULT]]233 // CHECK-DAG: pdl_interp.check_type %[[RESULT_TYPE]] is i32234 235 // The second result doesn't have any constraints, so we don't generate an236 // access for it.237 // CHECK-NOT: pdl_interp.get_result 1 of %[[ROOT]]238 pdl.pattern : benefit(1) {239 %type1 = type : i32240 %type2 = type241 %root = operation -> (%type1, %type2 : !pdl.type, !pdl.type)242 rewrite %root with "rewriter"243 }244}245 246// -----247 248// CHECK-LABEL: module @variadic_results249module @variadic_results {250 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)251 // CHECK-DAG: pdl_interp.check_result_count of %[[ROOT]] is at_least 2252 253 // The first result has a known index.254 // CHECK-DAG: %[[RESULT:.*]] = pdl_interp.get_result 0 of %[[ROOT]]255 // CHECK-DAG: pdl_interp.is_not_null %[[RESULT]] : !pdl.value256 257 // The second result is a group of unknown size, with a type constraint.258 // CHECK-DAG: %[[VAR_RESULTS:.*]] = pdl_interp.get_results 1 of %[[ROOT]] : !pdl.range<value>259 // CHECK-DAG: pdl_interp.is_not_null %[[VAR_RESULTS]] : !pdl.range<value>260 261 // CHECK-DAG: %[[RESULT_TYPE:.*]] = pdl_interp.get_value_type of %[[VAR_RESULTS]] : !pdl.range<type>262 // CHECK-DAG: pdl_interp.check_types %[[RESULT_TYPE]] are [i64]263 264 // The third result is at an unknown offset due to result 1, but is expected265 // to be of size 1.266 // CHECK-DAG: %[[RESULT2:.*]] = pdl_interp.get_results 2 of %[[ROOT]] : !pdl.value267 // CHECK-DAG: pdl_interp.is_not_null %[[RESULT2]] : !pdl.value268 pdl.pattern : benefit(1) {269 %types = types : [i64]270 %type = type271 %root = operation -> (%type, %types, %type : !pdl.type, !pdl.range<type>, !pdl.type)272 rewrite %root with "rewriter"273 }274}275 276// -----277 278// CHECK-LABEL: module @single_result_range279module @single_result_range {280 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)281 282 // Check that the result range is treated as all of the results of the283 // operation.284 // CHECK-DAG: %[[RESULTS:.*]] = pdl_interp.get_results of %[[ROOT]]285 // CHECK-DAG: %[[RESULT_TYPES:.*]] = pdl_interp.get_value_type of %[[RESULTS]] : !pdl.range<type>286 // CHECK-DAG: pdl_interp.check_types %[[RESULT_TYPES]] are [i64]287 288 // The result count is unknown, so there is no need to check for it.289 // CHECK-NOT: pdl_interp.check_result_count290 pdl.pattern : benefit(1) {291 %types = types : [i64]292 %root = operation -> (%types : !pdl.range<type>)293 rewrite %root with "rewriter"294 }295}296 297// -----298 299// CHECK-LABEL: module @results_as_operands300module @results_as_operands {301 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)302 303 // Get the first result and check it matches the first operand.304 // CHECK-DAG: %[[OPERAND_0:.*]] = pdl_interp.get_operand 0 of %[[ROOT]]305 // CHECK-DAG: %[[DEF_OP_0:.*]] = pdl_interp.get_defining_op of %[[OPERAND_0]]306 // CHECK-DAG: %[[RESULT_0:.*]] = pdl_interp.get_result 0 of %[[DEF_OP_0]]307 // CHECK-DAG: pdl_interp.are_equal %[[RESULT_0]], %[[OPERAND_0]]308 309 // Get the second result and check it matches the second operand.310 // CHECK-DAG: %[[OPERAND_1:.*]] = pdl_interp.get_operand 1 of %[[ROOT]]311 // CHECK-DAG: %[[DEF_OP_1:.*]] = pdl_interp.get_defining_op of %[[OPERAND_1]]312 // CHECK-DAG: %[[RESULT_1:.*]] = pdl_interp.get_result 1 of %[[DEF_OP_1]]313 // CHECK-DAG: pdl_interp.are_equal %[[RESULT_1]], %[[OPERAND_1]]314 315 // Check that the parent operation of both results is the same.316 // CHECK-DAG: pdl_interp.are_equal %[[DEF_OP_0]], %[[DEF_OP_1]]317 318 pdl.pattern : benefit(1) {319 %type1 = type : i32320 %type2 = type321 %inputOp = operation -> (%type1, %type2 : !pdl.type, !pdl.type)322 %result1 = result 0 of %inputOp323 %result2 = result 1 of %inputOp324 325 %root = operation(%result1, %result2 : !pdl.value, !pdl.value)326 rewrite %root with "rewriter"327 }328}329 330// -----331 332// CHECK-LABEL: module @single_result_range_as_operands333module @single_result_range_as_operands {334 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)335 // CHECK-DAG: %[[OPERANDS:.*]] = pdl_interp.get_operands of %[[ROOT]] : !pdl.range<value>336 // CHECK-DAG: %[[OP:.*]] = pdl_interp.get_defining_op of %[[OPERANDS]] : !pdl.range<value>337 // CHECK-DAG: pdl_interp.is_not_null %[[OP]]338 // CHECK-DAG: %[[RESULTS:.*]] = pdl_interp.get_results of %[[OP]] : !pdl.range<value>339 // CHECK-DAG: pdl_interp.are_equal %[[RESULTS]], %[[OPERANDS]] : !pdl.range<value>340 341 pdl.pattern : benefit(1) {342 %types = types343 %inputOp = operation -> (%types : !pdl.range<type>)344 %results = results of %inputOp345 346 %root = operation(%results : !pdl.range<value>)347 rewrite %root with "rewriter"348 }349}350 351// -----352 353// CHECK-LABEL: module @switch_single_result_type354module @switch_single_result_type {355 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)356 // CHECK: %[[RESULT:.*]] = pdl_interp.get_result 0 of %[[ROOT]]357 // CHECK: %[[RESULT_TYPE:.*]] = pdl_interp.get_value_type of %[[RESULT]]358 // CHECK: pdl_interp.switch_type %[[RESULT_TYPE]] to [i32, i64]359 pdl.pattern : benefit(1) {360 %type = type : i32361 %root = operation -> (%type : !pdl.type)362 rewrite %root with "rewriter"363 }364 pdl.pattern : benefit(1) {365 %type = type : i64366 %root = operation -> (%type : !pdl.type)367 rewrite %root with "rewriter"368 }369}370 371// -----372 373// CHECK-LABEL: module @switch_result_types374module @switch_result_types {375 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)376 // CHECK: %[[RESULTS:.*]] = pdl_interp.get_results of %[[ROOT]]377 // CHECK: %[[RESULT_TYPES:.*]] = pdl_interp.get_value_type of %[[RESULTS]]378 // CHECK: pdl_interp.switch_types %[[RESULT_TYPES]] to {{\[\[}}i32], [i64, i32]]379 pdl.pattern : benefit(1) {380 %types = types : [i32]381 %root = operation -> (%types : !pdl.range<type>)382 rewrite %root with "rewriter"383 }384 pdl.pattern : benefit(1) {385 %types = types : [i64, i32]386 %root = operation -> (%types : !pdl.range<type>)387 rewrite %root with "rewriter"388 }389}390 391// -----392 393// CHECK-LABEL: module @switch_operand_count_at_least394module @switch_operand_count_at_least {395 // Check that when there are multiple "at_least" checks, the failure branch396 // goes to the next one in increasing order.397 398 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)399 // CHECK: pdl_interp.check_operand_count of %[[ROOT]] is at_least 1 -> ^[[PATTERN_1_NEXT_BLOCK:.*]],400 // CHECK: ^bb2:401 // CHECK-NEXT: pdl_interp.check_operand_count of %[[ROOT]] is at_least 2402 // CHECK: ^[[PATTERN_1_NEXT_BLOCK]]:403 // CHECK-NEXT: {{.*}} -> ^{{.*}}, ^bb2404 pdl.pattern : benefit(1) {405 %operand = operand406 %operands = operands407 %root = operation(%operand, %operands : !pdl.value, !pdl.range<value>)408 rewrite %root with "rewriter"409 }410 pdl.pattern : benefit(1) {411 %operand = operand412 %operand2 = operand413 %operands = operands414 %root = operation(%operand, %operand2, %operands : !pdl.value, !pdl.value, !pdl.range<value>)415 rewrite %root with "rewriter"416 }417}418 419// -----420 421// CHECK-LABEL: module @switch_result_count_at_least422module @switch_result_count_at_least {423 // Check that when there are multiple "at_least" checks, the failure branch424 // goes to the next one in increasing order.425 426 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)427 // CHECK: pdl_interp.check_result_count of %[[ROOT]] is at_least 1 -> ^[[PATTERN_1_NEXT_BLOCK:.*]],428 // CHECK: ^[[PATTERN_2_BLOCK:[a-zA-Z_0-9]*]]:429 // CHECK: pdl_interp.check_result_count of %[[ROOT]] is at_least 2430 // CHECK: ^[[PATTERN_1_NEXT_BLOCK]]:431 // CHECK-NEXT: pdl_interp.get_result432 // CHECK-NEXT: pdl_interp.is_not_null {{.*}} -> ^{{.*}}, ^[[PATTERN_2_BLOCK]]433 pdl.pattern : benefit(1) {434 %type = type435 %types = types436 %root = operation -> (%type, %types : !pdl.type, !pdl.range<type>)437 rewrite %root with "rewriter"438 }439 pdl.pattern : benefit(1) {440 %type = type441 %type2 = type442 %types = types443 %root = operation -> (%type, %type2, %types : !pdl.type, !pdl.type, !pdl.range<type>)444 rewrite %root with "rewriter"445 }446}447 448 449// -----450 451// CHECK-LABEL: module @predicate_ordering452module @predicate_ordering {453 // Check that the result is checked for null first, before applying the454 // constraint. The null check is prevalent in both patterns, so should be455 // prioritized first.456 457 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)458 // CHECK: %[[RESULT:.*]] = pdl_interp.get_result 0 of %[[ROOT]]459 // CHECK-NEXT: pdl_interp.is_not_null %[[RESULT]]460 // CHECK: %[[RESULT_TYPE:.*]] = pdl_interp.get_value_type of %[[RESULT]]461 // CHECK: pdl_interp.apply_constraint "typeConstraint"(%[[RESULT_TYPE]]462 463 pdl.pattern : benefit(1) {464 %resultType = type465 pdl.apply_native_constraint "typeConstraint"(%resultType : !pdl.type)466 %root = operation -> (%resultType : !pdl.type)467 rewrite %root with "rewriter"468 }469 470 pdl.pattern : benefit(1) {471 %resultType = type472 %apply = operation -> (%resultType : !pdl.type)473 rewrite %apply with "rewriter"474 }475}476 477 478// -----479 480// CHECK-LABEL: module @multi_root481module @multi_root {482 // Check the lowering of a simple two-root pattern.483 // This checks that we correctly generate the pdl_interp.choose_op operation484 // and tie the break between %root1 and %root2 in favor of %root1.485 486 // CHECK: func @matcher(%[[ROOT1:.*]]: !pdl.operation)487 // CHECK-DAG: %[[VAL1:.*]] = pdl_interp.get_operand 0 of %[[ROOT1]]488 // CHECK-DAG: %[[OP1:.*]] = pdl_interp.get_defining_op of %[[VAL1]]489 // CHECK-DAG: %[[OPS:.*]] = pdl_interp.get_users of %[[VAL1]] : !pdl.value490 // CHECK-DAG: pdl_interp.foreach %[[ROOT2:.*]] : !pdl.operation in %[[OPS]]491 // CHECK-DAG: %[[OPERANDS:.*]] = pdl_interp.get_operand 0 of %[[ROOT2]]492 // CHECK-DAG: pdl_interp.are_equal %[[OPERANDS]], %[[VAL1]] : !pdl.value -> ^{{.*}}, ^[[CONTINUE:.*]]493 // CHECK-DAG: pdl_interp.continue494 // CHECK-DAG: %[[VAL2:.*]] = pdl_interp.get_operand 1 of %[[ROOT2]]495 // CHECK-DAG: %[[OP2:.*]] = pdl_interp.get_defining_op of %[[VAL2]]496 // CHECK-DAG: pdl_interp.is_not_null %[[OP1]] : !pdl.operation -> ^{{.*}}, ^[[CONTINUE]]497 // CHECK-DAG: pdl_interp.is_not_null %[[OP2]] : !pdl.operation498 // CHECK-DAG: pdl_interp.is_not_null %[[VAL1]] : !pdl.value499 // CHECK-DAG: pdl_interp.is_not_null %[[VAL2]] : !pdl.value500 // CHECK-DAG: pdl_interp.is_not_null %[[ROOT2]] : !pdl.operation501 502 pdl.pattern @rewrite_multi_root : benefit(1) {503 %input1 = operand504 %input2 = operand505 %type = type506 %op1 = operation(%input1 : !pdl.value) -> (%type : !pdl.type)507 %val1 = result 0 of %op1508 %root1 = operation(%val1 : !pdl.value)509 %op2 = operation(%input2 : !pdl.value) -> (%type : !pdl.type)510 %val2 = result 0 of %op2511 %root2 = operation(%val1, %val2 : !pdl.value, !pdl.value)512 rewrite %root1 with "rewriter"(%root2 : !pdl.operation)513 }514}515 516 517// -----518 519// CHECK-LABEL: module @overlapping_roots520module @overlapping_roots {521 // Check the lowering of a degenerate two-root pattern, where one root522 // is in the subtree rooted at another.523 524 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)525 // CHECK-DAG: %[[VAL:.*]] = pdl_interp.get_operand 0 of %[[ROOT]]526 // CHECK-DAG: %[[OP:.*]] = pdl_interp.get_defining_op of %[[VAL]]527 // CHECK-DAG: %[[INPUT1:.*]] = pdl_interp.get_operand 0 of %[[OP]]528 // CHECK-DAG: %[[INPUT2:.*]] = pdl_interp.get_operand 1 of %[[OP]]529 // CHECK-DAG: pdl_interp.is_not_null %[[VAL]] : !pdl.value530 // CHECK-DAG: pdl_interp.is_not_null %[[OP]] : !pdl.operation531 // CHECK-DAG: pdl_interp.is_not_null %[[INPUT1]] : !pdl.value532 // CHECK-DAG: pdl_interp.is_not_null %[[INPUT2]] : !pdl.value533 534 pdl.pattern @rewrite_overlapping_roots : benefit(1) {535 %input1 = operand536 %input2 = operand537 %type = type538 %op = operation(%input1, %input2 : !pdl.value, !pdl.value) -> (%type : !pdl.type)539 %val = result 0 of %op540 %root = operation(%val : !pdl.value)541 rewrite with "rewriter"(%root : !pdl.operation)542 }543}544 545// -----546 547// CHECK-LABEL: module @force_overlapped_root548module @force_overlapped_root {549 // Check the lowering of a degenerate two-root pattern, where one root550 // is in the subtree rooted at another, and we are forced to use this551 // root as the root of the search tree.552 553 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)554 // CHECK-DAG: %[[VAL:.*]] = pdl_interp.get_result 0 of %[[ROOT]]555 // CHECK-DAG: pdl_interp.check_operand_count of %[[ROOT]] is 2556 // CHECK-DAG: pdl_interp.check_result_count of %[[ROOT]] is 1557 // CHECK-DAG: %[[INPUT2:.*]] = pdl_interp.get_operand 1 of %[[ROOT]]558 // CHECK-DAG: pdl_interp.is_not_null %[[INPUT2]] : !pdl.value559 // CHECK-DAG: %[[INPUT1:.*]] = pdl_interp.get_operand 0 of %[[ROOT]]560 // CHECK-DAG: pdl_interp.is_not_null %[[INPUT1]] : !pdl.value561 // CHECK-DAG: %[[OPS:.*]] = pdl_interp.get_users of %[[VAL]] : !pdl.value562 // CHECK-DAG: pdl_interp.foreach %[[OP:.*]] : !pdl.operation in %[[OPS]]563 // CHECK-DAG: pdl_interp.is_not_null %[[OP]] : !pdl.operation564 // CHECK-DAG: pdl_interp.check_operand_count of %[[OP]] is 1565 566 pdl.pattern @rewrite_forced_overlapped_root : benefit(1) {567 %input1 = operand568 %input2 = operand569 %type = type570 %root = operation(%input1, %input2 : !pdl.value, !pdl.value) -> (%type : !pdl.type)571 %val = result 0 of %root572 %op = operation(%val : !pdl.value)573 rewrite %root with "rewriter"(%op : !pdl.operation)574 }575}576 577// -----578 579// CHECK-LABEL: module @variadic_results_all580module @variadic_results_all {581 // Check the correct lowering when using all results of an operation582 // and passing it them as operands to another operation.583 584 // CHECK: func @matcher(%[[ROOT:.*]]: !pdl.operation)585 // CHECK-DAG: pdl_interp.check_operand_count of %[[ROOT]] is 0586 // CHECK-DAG: %[[VALS:.*]] = pdl_interp.get_results of %[[ROOT]] : !pdl.range<value>587 // CHECK-DAG: %[[VAL0:.*]] = pdl_interp.extract 0 of %[[VALS]]588 // CHECK-DAG: %[[OPS:.*]] = pdl_interp.get_users of %[[VAL0]] : !pdl.value589 // CHECK-DAG: pdl_interp.foreach %[[OP:.*]] : !pdl.operation in %[[OPS]]590 // CHECK-DAG: %[[OPERANDS:.*]] = pdl_interp.get_operands of %[[OP]]591 // CHECK-DAG: pdl_interp.are_equal %[[OPERANDS]], %[[VALS]] : !pdl.range<value> -> ^{{.*}}, ^[[CONTINUE:.*]]592 // CHECK-DAG: pdl_interp.is_not_null %[[OP]]593 // CHECK-DAG: pdl_interp.check_result_count of %[[OP]] is 0594 pdl.pattern @variadic_results_all : benefit(1) {595 %types = types596 %root = operation -> (%types : !pdl.range<type>)597 %vals = results of %root598 %op = operation(%vals : !pdl.range<value>)599 rewrite %root with "rewriter"(%op : !pdl.operation)600 }601}602 603// -----604 605// CHECK-LABEL: module @variadic_results_at606module @variadic_results_at {607 // Check the correct lowering when using selected results of an operation608 // and passing it them as an operand to another operation.609 610 // CHECK: func @matcher(%[[ROOT1:.*]]: !pdl.operation)611 // CHECK-DAG: %[[VALS:.*]] = pdl_interp.get_operands 0 of %[[ROOT1]] : !pdl.range<value>612 // CHECK-DAG: %[[OP:.*]] = pdl_interp.get_defining_op of %[[VALS]] : !pdl.range<value>613 // CHECK-DAG: pdl_interp.is_not_null %[[OP]] : !pdl.operation614 // CHECK-DAG: pdl_interp.check_operand_count of %[[ROOT1]] is at_least 1615 // CHECK-DAG: pdl_interp.check_result_count of %[[ROOT1]] is 0616 // CHECK-DAG: %[[VAL:.*]] = pdl_interp.get_operands 1 of %[[ROOT1]] : !pdl.value617 // CHECK-DAG: pdl_interp.is_not_null %[[VAL]]618 // CHECK-DAG: pdl_interp.is_not_null %[[VALS]]619 // CHECK-DAG: %[[VAL0:.*]] = pdl_interp.extract 0 of %[[VALS]]620 // CHECK-DAG: %[[ROOTS2:.*]] = pdl_interp.get_users of %[[VAL0]] : !pdl.value621 // CHECK-DAG: pdl_interp.foreach %[[ROOT2:.*]] : !pdl.operation in %[[ROOTS2]] {622 // CHECK-DAG: %[[OPERANDS:.*]] = pdl_interp.get_operands 1 of %[[ROOT2]]623 // CHECK-DAG: pdl_interp.are_equal %[[OPERANDS]], %[[VALS]] : !pdl.range<value> -> ^{{.*}}, ^[[CONTINUE:.*]]624 // CHECK-DAG: pdl_interp.is_not_null %[[ROOT2]]625 // CHECK-DAG: pdl_interp.check_operand_count of %[[ROOT2]] is at_least 1626 // CHECK-DAG: pdl_interp.check_result_count of %[[ROOT2]] is 0627 // CHECK-DAG: pdl_interp.check_operand_count of %[[OP]] is 0628 // CHECK-DAG: pdl_interp.check_result_count of %[[OP]] is at_least 1629 pdl.pattern @variadic_results_at : benefit(1) {630 %type = type631 %types = types632 %val = operand633 %op = operation -> (%types, %type : !pdl.range<type>, !pdl.type)634 %vals = results 0 of %op -> !pdl.range<value>635 %root1 = operation(%vals, %val : !pdl.range<value>, !pdl.value)636 %root2 = operation(%val, %vals : !pdl.value, !pdl.range<value>)637 rewrite with "rewriter"(%root1, %root2 : !pdl.operation, !pdl.operation)638 }639}640 641// -----642 643// CHECK-LABEL: module @attribute_literal644module @attribute_literal {645 // CHECK: func @matcher(%{{.*}}: !pdl.operation)646 // CHECK: %[[ATTR:.*]] = pdl_interp.create_attribute 10 : i64647 // CHECK: pdl_interp.apply_constraint "constraint"(%[[ATTR]] : !pdl.attribute)648 649 // Check the correct lowering of an attribute that hasn't been bound.650 pdl.pattern : benefit(1) {651 %attr = attribute = 10652 pdl.apply_native_constraint "constraint"(%attr: !pdl.attribute)653 654 %root = operation655 rewrite %root with "rewriter"656 }657}658 659// -----660 661// CHECK-LABEL: module @type_literal662module @type_literal {663 // CHECK: func @matcher(%{{.*}}: !pdl.operation)664 // CHECK: %[[TYPE:.*]] = pdl_interp.create_type i32665 // CHECK: %[[TYPES:.*]] = pdl_interp.create_types [i32, i64]666 // CHECK: pdl_interp.apply_constraint "constraint"(%[[TYPE]], %[[TYPES]] : !pdl.type, !pdl.range<type>)667 668 // Check the correct lowering of a type that hasn't been bound.669 pdl.pattern : benefit(1) {670 %type = type : i32671 %types = types : [i32, i64]672 pdl.apply_native_constraint "constraint"(%type, %types: !pdl.type, !pdl.range<type>)673 674 %root = operation675 rewrite %root with "rewriter"676 }677}678 679// -----680 681// CHECK-LABEL: module @common_connector682module @common_connector {683 // Check the correct lowering when multiple roots are using the same684 // connector.685 686 // CHECK: func @matcher(%[[ROOTC:.*]]: !pdl.operation)687 // CHECK-DAG: %[[VAL2:.*]] = pdl_interp.get_operand 0 of %[[ROOTC]]688 // CHECK-DAG: %[[INTER:.*]] = pdl_interp.get_defining_op of %[[VAL2]] : !pdl.value689 // CHECK-DAG: pdl_interp.is_not_null %[[INTER]] : !pdl.operation -> ^bb2, ^bb1690 // CHECK-DAG: %[[VAL1:.*]] = pdl_interp.get_operand 0 of %[[INTER]]691 // CHECK-DAG: %[[OP:.*]] = pdl_interp.get_defining_op of %[[VAL1]] : !pdl.value692 // CHECK-DAG: pdl_interp.is_not_null %[[OP]]693 // CHECK-DAG: %[[VAL0:.*]] = pdl_interp.get_result 0 of %[[OP]]694 // CHECK-DAG: %[[ROOTS:.*]] = pdl_interp.get_users of %[[VAL0]] : !pdl.value695 // CHECK-DAG: pdl_interp.foreach %[[ROOTA:.*]] : !pdl.operation in %[[ROOTS]] {696 // CHECK-DAG: pdl_interp.is_not_null %[[ROOTA]] : !pdl.operation -> ^{{.*}}, ^[[CONTA:.*]]697 // CHECK-DAG: pdl_interp.continue698 // CHECK-DAG: pdl_interp.foreach %[[ROOTB:.*]] : !pdl.operation in %[[ROOTS]] {699 // CHECK-DAG: pdl_interp.is_not_null %[[ROOTB]] : !pdl.operation -> ^{{.*}}, ^[[CONTB:.*]]700 // CHECK-DAG: %[[ROOTA_OP:.*]] = pdl_interp.get_operand 0 of %[[ROOTA]]701 // CHECK-DAG: pdl_interp.are_equal %[[ROOTA_OP]], %[[VAL0]] : !pdl.value702 // CHECK-DAG: %[[ROOTB_OP:.*]] = pdl_interp.get_operand 0 of %[[ROOTB]]703 // CHECK-DAG: pdl_interp.are_equal %[[ROOTB_OP]], %[[VAL0]] : !pdl.value704 // CHECK-DAG: } -> ^[[CONTA:.*]]705 pdl.pattern @common_connector : benefit(1) {706 %type = type707 %op = operation -> (%type, %type : !pdl.type, !pdl.type)708 %val0 = result 0 of %op709 %val1 = result 1 of %op710 %rootA = operation (%val0 : !pdl.value)711 %rootB = operation (%val0 : !pdl.value)712 %inter = operation (%val1 : !pdl.value) -> (%type : !pdl.type)713 %val2 = result 0 of %inter714 %rootC = operation (%val2 : !pdl.value)715 rewrite with "rewriter"(%rootA, %rootB, %rootC : !pdl.operation, !pdl.operation, !pdl.operation)716 }717}718 719// -----720 721// CHECK-LABEL: module @common_connector_range722module @common_connector_range {723 // Check the correct lowering when multiple roots are using the same724 // connector range.725 726 // CHECK: func @matcher(%[[ROOTC:.*]]: !pdl.operation)727 // CHECK-DAG: %[[VALS2:.*]] = pdl_interp.get_operands of %[[ROOTC]] : !pdl.range<value>728 // CHECK-DAG: %[[INTER:.*]] = pdl_interp.get_defining_op of %[[VALS2]] : !pdl.range<value>729 // CHECK-DAG: pdl_interp.is_not_null %[[INTER]] : !pdl.operation -> ^bb2, ^bb1730 // CHECK-DAG: %[[VALS1:.*]] = pdl_interp.get_operands of %[[INTER]] : !pdl.range<value>731 // CHECK-DAG: %[[OP:.*]] = pdl_interp.get_defining_op of %[[VALS1]] : !pdl.range<value>732 // CHECK-DAG: pdl_interp.is_not_null %[[OP]]733 // CHECK-DAG: %[[VALS0:.*]] = pdl_interp.get_results 0 of %[[OP]]734 // CHECK-DAG: %[[VAL0:.*]] = pdl_interp.extract 0 of %[[VALS0]] : !pdl.value735 // CHECK-DAG: %[[ROOTS:.*]] = pdl_interp.get_users of %[[VAL0]] : !pdl.value736 // CHECK-DAG: pdl_interp.foreach %[[ROOTA:.*]] : !pdl.operation in %[[ROOTS]] {737 // CHECK-DAG: pdl_interp.is_not_null %[[ROOTA]] : !pdl.operation -> ^{{.*}}, ^[[CONTA:.*]]738 // CHECK-DAG: pdl_interp.continue739 // CHECK-DAG: pdl_interp.foreach %[[ROOTB:.*]] : !pdl.operation in %[[ROOTS]] {740 // CHECK-DAG: pdl_interp.is_not_null %[[ROOTB]] : !pdl.operation -> ^{{.*}}, ^[[CONTB:.*]]741 // CHECK-DAG: %[[ROOTA_OPS:.*]] = pdl_interp.get_operands of %[[ROOTA]]742 // CHECK-DAG: pdl_interp.are_equal %[[ROOTA_OPS]], %[[VALS0]] : !pdl.range<value>743 // CHECK-DAG: %[[ROOTB_OPS:.*]] = pdl_interp.get_operands of %[[ROOTB]]744 // CHECK-DAG: pdl_interp.are_equal %[[ROOTB_OPS]], %[[VALS0]] : !pdl.range<value>745 // CHECK-DAG: } -> ^[[CONTA:.*]]746 pdl.pattern @common_connector_range : benefit(1) {747 %types = types748 %op = operation -> (%types, %types : !pdl.range<type>, !pdl.range<type>)749 %vals0 = results 0 of %op -> !pdl.range<value>750 %vals1 = results 1 of %op -> !pdl.range<value>751 %rootA = operation (%vals0 : !pdl.range<value>)752 %rootB = operation (%vals0 : !pdl.range<value>)753 %inter = operation (%vals1 : !pdl.range<value>) -> (%types : !pdl.range<type>)754 %vals2 = results of %inter755 %rootC = operation (%vals2 : !pdl.range<value>)756 rewrite with "rewriter"(%rootA, %rootB, %rootC : !pdl.operation, !pdl.operation, !pdl.operation)757 }758}759