780 lines · plain
1// RUN: mlir-opt -test-greedy-patterns -mlir-print-debuginfo -mlir-print-local-scope %s | FileCheck %s2 3// CHECK-LABEL: verifyFusedLocs4func.func @verifyFusedLocs(%arg0 : i32) -> i32 {5 %0 = "test.op_a"(%arg0) {attr = 10 : i32} : (i32) -> i32 loc("a")6 %result = "test.op_a"(%0) {attr = 20 : i32} : (i32) -> i32 loc("b")7 8 // CHECK: "test.op_b"(%arg0) <{attr = 10 : i32}> : (i32) -> i32 loc("a")9 // CHECK: "test.op_b"(%arg0) <{attr = 20 : i32}> : (i32) -> i32 loc(fused["b", "a"])10 return %result : i3211}12 13// CHECK-LABEL: verifyDesignatedLoc14func.func @verifyDesignatedLoc(%arg0 : i32) -> i32 {15 %0 = "test.loc_src"(%arg0) : (i32) -> i32 loc("loc3")16 %1 = "test.loc_src"(%0) : (i32) -> i32 loc("loc2")17 %2 = "test.loc_src"(%1) : (i32) -> i32 loc("loc1")18 "test.loc_src_no_res"(%2) : (i32) -> () loc("loc4")19 20 // CHECK: "test.loc_dst"({{.*}}) : (i32) -> i32 loc("loc1")21 // CHECK: "test.loc_dst"({{.*}}) : (i32) -> i32 loc("named")22 // CHECK: "test.loc_dst"({{.*}}) : (i32) -> i32 loc(fused<"fused">["loc2", "loc3"])23 // CHECK: "test.loc_dst_no_res"({{.*}}) : (i32) -> () loc("loc4")24 return %1 : i3225}26 27// CHECK-LABEL: verifyZeroResult28func.func @verifyZeroResult(%arg0 : i32) {29 // CHECK: "test.op_i"(%arg0) : (i32) -> ()30 "test.op_h"(%arg0) : (i32) -> ()31 return32}33 34// CHECK-LABEL: verifyZeroArg35func.func @verifyZeroArg() -> i32 {36 // CHECK: "test.op_k"() : () -> i3237 %0 = "test.op_j"() : () -> i3238 return %0 : i3239}40 41// CHECK-LABEL: testIgnoreArgMatch42// CHECK-SAME: (%{{[a-z0-9]*}}: i32 loc({{[^)]*}}), %[[ARG1:[a-z0-9]*]]: i32 loc({{[^)]*}}),43func.func @testIgnoreArgMatch(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: f32) {44 // CHECK: "test.ignore_arg_match_dst"(%[[ARG1]]) <{f = 15 : i64}>45 "test.ignore_arg_match_src"(%arg0, %arg1, %arg2) {d = 42, e = 24, f = 15} : (i32, i32, i32) -> ()46 47 // CHECK: test.ignore_arg_match_src48 // Not match because wrong type for $c.49 "test.ignore_arg_match_src"(%arg0, %arg1, %arg3) {d = 42, e = 24, f = 15} : (i32, i32, f32) -> ()50 51 // CHECK: test.ignore_arg_match_src52 // Not match because wrong type for $f.53 "test.ignore_arg_match_src"(%arg0, %arg1, %arg2) {d = 42 : i32, e = 24, f = 15} : (i32, i32, i32) -> ()54 return55}56 57// CHECK-LABEL: verifyInterleavedOperandAttribute58// CHECK-SAME: %[[ARG0:.*]]: i32 loc({{[^)]*}}), %[[ARG1:.*]]: i32 loc({{[^)]*}})59func.func @verifyInterleavedOperandAttribute(%arg0: i32, %arg1: i32) {60 // CHECK: "test.interleaved_operand_attr2"(%[[ARG0]], %[[ARG1]]) <{attr1 = 15 : i64, attr2 = 42 : i64}>61 "test.interleaved_operand_attr1"(%arg0, %arg1) {attr1 = 15, attr2 = 42} : (i32, i32) -> ()62 return63}64 65// CHECK-LABEL: verifyBenefit66func.func @verifyBenefit(%arg0 : i32) -> i32 {67 %0 = "test.op_d"(%arg0) : (i32) -> i3268 %1 = "test.op_g"(%arg0) : (i32) -> i3269 %2 = "test.op_g"(%1) : (i32) -> i3270 71 // CHECK: "test.op_f"(%arg0)72 // CHECK: "test.op_b"(%arg0) <{attr = 34 : i32}>73 return %0 : i3274}75 76// CHECK-LABEL: verifyNativeCodeCall77func.func @verifyNativeCodeCall(%arg0: i32, %arg1: i32) -> (i32, i32) {78 // CHECK: %0 = "test.native_code_call2"(%arg0) <{attr = [42, 24]}> : (i32) -> i3279 // CHECK: return %0, %arg180 %0 = "test.native_code_call1"(%arg0, %arg1) {choice = true, attr1 = 42, attr2 = 24} : (i32, i32) -> (i32)81 %1 = "test.native_code_call1"(%arg0, %arg1) {choice = false, attr1 = 42, attr2 = 24} : (i32, i32) -> (i32)82 return %0, %1: i32, i3283}84 85// CHECK-LABEL: verifyAuxiliaryNativeCodeCall86func.func @verifyAuxiliaryNativeCodeCall(%arg0: i32) -> (i32) {87 // CHECK: test.op_i88 // CHECK: test.op_k89 %0 = "test.native_code_call3"(%arg0) : (i32) -> (i32)90 return %0 : i3291}92 93// CHECK-LABEL: verifyNativeCodeCallBinding94func.func @verifyNativeCodeCallBinding(%arg0 : i32) -> (i32) {95 %0 = "test.op_k"() : () -> (i32)96 // CHECK: %[[A:.*]], %[[B:.*]] = "test.native_code_call5"(%1, %1) : (i32, i32) -> (i32, i32)97 %1, %2 = "test.native_code_call4"(%0) : (i32) -> (i32, i32)98 %3 = "test.constant"() {value = 1 : i8} : () -> i899 // %3 is i8 so it'll fail at GetFirstI32Result match. The operation should100 // keep the same form.101 // CHECK: %{{.*}}, %{{.*}} = "test.native_code_call4"({{%.*}}) : (i8) -> (i32, i32)102 %4, %5 = "test.native_code_call4"(%3) : (i8) -> (i32, i32)103 // CHECK: return %[[A]]104 return %1 : i32105}106 107// CHECK-LABEL: verifyMultipleNativeCodeCallBinding108func.func @verifyMultipleNativeCodeCallBinding(%arg0 : i32) -> (i32) {109 %0 = "test.op_k"() : () -> (i32)110 %1 = "test.op_k"() : () -> (i32)111 // CHECK: %[[A:.*]] = "test.native_code_call7"(%1) : (i32) -> i32112 // CHECK: %[[A:.*]] = "test.native_code_call7"(%0) : (i32) -> i32113 %2, %3 = "test.native_code_call6"(%0, %1) : (i32, i32) -> (i32, i32)114 return %2 : i32115}116 117// CHECK-LABEL: verifyAllAttrConstraintOf118func.func @verifyAllAttrConstraintOf() -> (i32, i32, i32) {119 // CHECK: "test.all_attr_constraint_of2"120 %0 = "test.all_attr_constraint_of1"() {attr = [0, 1]} : () -> (i32)121 // CHECK: "test.all_attr_constraint_of1"122 %1 = "test.all_attr_constraint_of1"() {attr = [0, 2]} : () -> (i32)123 // CHECK: "test.all_attr_constraint_of1"124 %2 = "test.all_attr_constraint_of1"() {attr = [-1, 1]} : () -> (i32)125 return %0, %1, %2: i32, i32, i32126}127 128// CHECK-LABEL: verifyManyArgs129// CHECK-SAME: (%[[ARG:.*]]: i32 loc({{[^)]*}}))130func.func @verifyManyArgs(%arg: i32) {131 // CHECK: "test.many_arguments"(%[[ARG]], %[[ARG]], %[[ARG]], %[[ARG]], %[[ARG]], %[[ARG]], %[[ARG]], %[[ARG]], %[[ARG]])132 // CHECK-SAME: {attr1 = 24 : i64, attr2 = 42 : i64, attr3 = 42 : i64, attr4 = 42 : i64, attr5 = 42 : i64, attr6 = 42 : i64, attr7 = 42 : i64, attr8 = 42 : i64, attr9 = 42 : i64}133 "test.many_arguments"(%arg, %arg, %arg, %arg, %arg, %arg, %arg, %arg, %arg) {134 attr1 = 42, attr2 = 42, attr3 = 42, attr4 = 42, attr5 = 42,135 attr6 = 42, attr7 = 42, attr8 = 42, attr9 = 42136 } : (i32, i32, i32, i32, i32, i32, i32, i32, i32) -> ()137 return138}139 140// CHECK-LABEL: verifyEqualArgs141func.func @verifyEqualArgs(%arg0: i32, %arg1: i32) {142 // def TestEqualArgsPattern : Pat<(OpN $a, $a), (OpO $a)>;143 144 // CHECK: "test.op_o"(%arg0) : (i32) -> i32145 "test.op_n"(%arg0, %arg0) : (i32, i32) -> (i32)146 147 // CHECK: "test.op_n"(%arg0, %arg1) : (i32, i32) -> i32148 "test.op_n"(%arg0, %arg1) : (i32, i32) -> (i32)149 150 return151}152 153// CHECK-LABEL: verifyNestedOpEqualArgs154func.func @verifyNestedOpEqualArgs(155 %arg0: i32, %arg1: i32, %arg2 : i32, %arg3 : i32, %arg4 : i32, %arg5 : i32) {156 // def TestNestedOpEqualArgsPattern :157 // Pat<(OpN $b, (OpP $a, $b, $c, $d, $e, $f)), (replaceWithValue $b)>;158 159 // CHECK: "test.op_o"(%arg1)160 %0 = "test.op_p"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5)161 : (i32, i32, i32, i32, i32, i32) -> (i32)162 %1 = "test.op_n"(%arg1, %0) : (i32, i32) -> (i32)163 %2 = "test.op_o"(%1) : (i32) -> (i32)164 165 // CHECK-NEXT: %[[P:.*]] = "test.op_p"166 // CHECK-NEXT: %[[N:.*]] = "test.op_n"(%arg0, %[[P]])167 // CHECK-NEXT: "test.op_o"(%[[N]])168 %3 = "test.op_p"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5)169 : (i32, i32, i32, i32, i32, i32) -> (i32)170 %4 = "test.op_n"(%arg0, %3) : (i32, i32) -> (i32)171 %5 = "test.op_o"(%4) : (i32) -> (i32)172 173 return174}175 176// CHECK-LABEL: verifyNestedSameOpAndSameArgEquality177func.func @verifyNestedSameOpAndSameArgEquality(%arg0: i32, %arg1: i32) -> i32 {178 // def TestNestedSameOpAndSameArgEqualityPattern:179 // Pat<(OpN (OpN $_, $x), $x), (replaceWithValue $x)>;180 181 %0 = "test.op_n"(%arg1, %arg0) : (i32, i32) -> (i32)182 %1 = "test.op_n"(%0, %arg0) : (i32, i32) -> (i32)183 // CHECK: return %arg0 : i32184 return %1 : i32185}186 187// CHECK-LABEL: verifyMultipleEqualArgs188func.func @verifyMultipleEqualArgs(189 %arg0: i32, %arg1 : i32, %arg2 : i32, %arg3 : i32, %arg4 : i32) {190 // def TestMultipleEqualArgsPattern :191 // Pat<(OpP $a, $b, $a, $a, $b, $c), (OpN $c, $b)>;192 193 // CHECK: "test.op_n"(%arg2, %arg1) : (i32, i32) -> i32194 "test.op_p"(%arg0, %arg1, %arg0, %arg0, %arg1, %arg2) :195 (i32, i32, i32, i32 , i32, i32) -> i32196 197 // CHECK: test.op_p198 "test.op_p"(%arg0, %arg1, %arg0, %arg0, %arg0, %arg2) :199 (i32, i32, i32, i32 , i32, i32) -> i32200 201 // CHECK: test.op_p202 "test.op_p"(%arg0, %arg1, %arg1, %arg0, %arg1, %arg2) :203 (i32, i32, i32, i32 , i32, i32) -> i32204 205 // CHECK: test.op_p206 "test.op_p"(%arg0, %arg1, %arg2, %arg2, %arg3, %arg4) :207 (i32, i32, i32, i32 , i32, i32) -> i32208 209 return210}211 212func.func @verifyEqualArgsCheckBeforeUserConstraints(%arg0: i32, %arg1: f32) {213 // def TestEqualArgsCheckBeforeUserConstraintsPattern :214 // Pat<(OpQ:$op $x, $x),215 // (replaceWithValue $x),216 // [(AssertBinOpEqualArgsAndReturnTrue $op)]>;217 218 // CHECK: "test.op_q"(%arg0, %arg1)219 %0 = "test.op_q"(%arg0, %arg1) : (i32, f32) -> (i32)220 221 // CHECK: "test.op_q"(%arg1, %arg0)222 %1 = "test.op_q"(%arg1, %arg0) : (f32, i32) -> (i32)223 224 return225}226 227//===----------------------------------------------------------------------===//228// Test Symbol Binding229//===----------------------------------------------------------------------===//230 231// CHECK-LABEL: symbolBinding232func.func @symbolBinding(%arg0: i32) -> i32 {233 // An op with one use is matched.234 // CHECK: %0 = "test.symbol_binding_b"(%arg0)235 // CHECK: %1 = "test.symbol_binding_c"(%0)236 // CHECK: %2 = "test.symbol_binding_d"(%0, %1) <{attr = 42 : i64}>237 %0 = "test.symbol_binding_a"(%arg0) {attr = 42} : (i32) -> (i32)238 239 // An op without any use is not matched.240 // CHECK: "test.symbol_binding_a"(%arg0)241 %1 = "test.symbol_binding_a"(%arg0) {attr = 42} : (i32) -> (i32)242 243 // CHECK: return %2244 return %0: i32245}246 247// CHECK-LABEL: symbolBindingNoResult248func.func @symbolBindingNoResult(%arg0: i32) {249 // CHECK: test.symbol_binding_b250 "test.symbol_binding_no_result"(%arg0) : (i32) -> ()251 return252}253 254//===----------------------------------------------------------------------===//255// Test Attributes256//===----------------------------------------------------------------------===//257 258// CHECK-LABEL: succeedMatchOpAttr259func.func @succeedMatchOpAttr() -> i32 {260 // CHECK: "test.match_op_attribute2"() <{default_valued_attr = 3 : i32, more_attr = 4 : i32, optional_attr = 2 : i32, required_attr = 1 : i32}>261 %0 = "test.match_op_attribute1"() {required_attr = 1: i32, optional_attr = 2: i32, default_valued_attr = 3: i32, more_attr = 4: i32} : () -> (i32)262 return %0: i32263}264 265// CHECK-LABEL: succeedMatchMissingOptionalAttr266func.func @succeedMatchMissingOptionalAttr() -> i32 {267 // CHECK: "test.match_op_attribute2"() <{default_valued_attr = 3 : i32, more_attr = 4 : i32, required_attr = 1 : i32}>268 %0 = "test.match_op_attribute1"() {required_attr = 1: i32, default_valued_attr = 3: i32, more_attr = 4: i32} : () -> (i32)269 return %0: i32270}271 272// CHECK-LABEL: succeedMatchMissingDefaultValuedAttr273func.func @succeedMatchMissingDefaultValuedAttr() -> i32 {274 // CHECK: "test.match_op_attribute2"() <{default_valued_attr = 42 : i32, more_attr = 4 : i32, optional_attr = 2 : i32, required_attr = 1 : i32}>275 %0 = "test.match_op_attribute1"() {required_attr = 1: i32, optional_attr = 2: i32, more_attr = 4: i32} : () -> (i32)276 return %0: i32277}278 279// CHECK-LABEL: failedMatchAdditionalConstraintNotSatisfied280func.func @failedMatchAdditionalConstraintNotSatisfied() -> i32 {281 // CHECK: "test.match_op_attribute1"()282 %0 = "test.match_op_attribute1"() {required_attr = 1: i32, optional_attr = 2: i32, more_attr = 5: i32} : () -> (i32)283 return %0: i32284}285 286// CHECK-LABEL: verifyConstantAttr287func.func @verifyConstantAttr(%arg0 : i32) -> i32 {288 // CHECK: "test.op_b"(%arg0) <{attr = 17 : i32}> : (i32) -> i32 loc("a")289 %0 = "test.op_c"(%arg0) : (i32) -> i32 loc("a")290 return %0 : i32291}292 293// CHECK-LABEL: verifyUnitAttr294func.func @verifyUnitAttr() -> (i32, i32) {295 // Unit attribute present in the matched op is propagated as attr2.296 // CHECK: "test.match_op_attribute4"() <{attr1, attr2}> : () -> i32297 %0 = "test.match_op_attribute3"() {attr} : () -> i32298 299 // Since the original op doesn't have the unit attribute, the new op300 // only has the constant-constructed unit attribute attr1.301 // CHECK: "test.match_op_attribute4"() <{attr1}> : () -> i32302 %1 = "test.match_op_attribute3"() : () -> i32303 return %0, %1 : i32, i32304}305 306//===----------------------------------------------------------------------===//307// Test Constant Matching308//===----------------------------------------------------------------------===//309 310// CHECK-LABEL: testConstOp311func.func @testConstOp() -> (i32) {312 // CHECK-NEXT: [[C0:%.+]] = "test.constant"() <{value = 1313 %0 = "test.constant"() {value = 1 : i32} : () -> i32314 315 // CHECK-NEXT: return [[C0]]316 return %0 : i32317}318 319// CHECK-LABEL: testConstOpUsed320func.func @testConstOpUsed() -> (i32) {321 // CHECK-NEXT: [[C0:%.+]] = "test.constant"() <{value = 1322 %0 = "test.constant"() {value = 1 : i32} : () -> i32323 324 // CHECK-NEXT: [[V0:%.+]] = "test.op_s"([[C0]])325 %1 = "test.op_s"(%0) {value = 1 : i32} : (i32) -> i32326 327 // CHECK-NEXT: return [[V0]]328 return %1 : i32329}330 331// CHECK-LABEL: testConstOpReplaced332func.func @testConstOpReplaced() -> (i32) {333 // CHECK-NEXT: [[C0:%.+]] = "test.constant"() <{value = 1334 %0 = "test.constant"() {value = 1 : i32} : () -> i32335 %1 = "test.constant"() {value = 2 : i32} : () -> i32336 337 // CHECK: [[V0:%.+]] = "test.op_s"([[C0]]) <{value = 2 : i32}338 %2 = "test.op_r"(%0, %1) : (i32, i32) -> i32339 340 // CHECK: [[V0]]341 return %2 : i32342}343 344// CHECK-LABEL: testConstOpMatchFailure345func.func @testConstOpMatchFailure() -> (i64) {346 // CHECK-DAG: [[C0:%.+]] = "test.constant"() <{value = 1347 %0 = "test.constant"() {value = 1 : i64} : () -> i64348 349 // CHECK-DAG: [[C1:%.+]] = "test.constant"() <{value = 2350 %1 = "test.constant"() {value = 2 : i64} : () -> i64351 352 // CHECK: [[V0:%.+]] = "test.op_r"([[C0]], [[C1]])353 %2 = "test.op_r"(%0, %1) : (i64, i64) -> i64354 355 // CHECK: [[V0]]356 return %2 : i64357}358 359// CHECK-LABEL: testConstOpMatchNonConst360func.func @testConstOpMatchNonConst(%arg0 : i32) -> (i32) {361 // CHECK-DAG: [[C0:%.+]] = "test.constant"() <{value = 1362 %0 = "test.constant"() {value = 1 : i32} : () -> i32363 364 // CHECK: [[V0:%.+]] = "test.op_r"([[C0]], %arg0)365 %1 = "test.op_r"(%0, %arg0) : (i32, i32) -> i32366 367 // CHECK: [[V0]]368 return %1 : i32369}370 371 372 373//===----------------------------------------------------------------------===//374// Test Enum Attributes375//===----------------------------------------------------------------------===//376 377// CHECK-LABEL: verifyI32EnumAttr378func.func @verifyI32EnumAttr() -> i32 {379 // CHECK: "test.i32_enum_attr"() <{attr = 10 : i32}380 %0 = "test.i32_enum_attr"() {attr = 5: i32} : () -> i32381 return %0 : i32382}383 384// CHECK-LABEL: verifyI64EnumAttr385func.func @verifyI64EnumAttr() -> i32 {386 // CHECK: "test.i64_enum_attr"() <{attr = 10 : i64}387 %0 = "test.i64_enum_attr"() {attr = 5: i64} : () -> i32388 return %0 : i32389}390 391//===----------------------------------------------------------------------===//392// Test ElementsAttr393//===----------------------------------------------------------------------===//394 395// CHECK-LABEL: rewrite_i32elementsattr396func.func @rewrite_i32elementsattr() -> () {397 // CHECK: attr = dense<0> : tensor<i32>398 "test.i32ElementsAttr"() {attr = dense<[3, 5]>:tensor<2xi32>} : () -> ()399 return400}401 402// CHECK-LABEL: rewrite_f64elementsattr403func.func @rewrite_f64elementsattr() -> () {404 "test.float_elements_attr"() {405 // Should match406 // CHECK: scalar_f32_attr = dense<[5.000000e+00, 6.000000e+00]> : tensor<2xf32>407 scalar_f32_attr = dense<[3.0, 4.0]> : tensor<2xf32>,408 tensor_f64_attr = dense<6.0> : tensor<4x8xf64>409 } : () -> ()410 411 "test.float_elements_attr"() {412 // Should not match413 // CHECK: scalar_f32_attr = dense<7.000000e+00> : tensor<2xf32>414 scalar_f32_attr = dense<7.0> : tensor<2xf32>,415 tensor_f64_attr = dense<3.0> : tensor<4x8xf64>416 } : () -> ()417 return418}419 420//===----------------------------------------------------------------------===//421// Test Multi-result Ops422//===----------------------------------------------------------------------===//423 424// CHECK-LABEL: @useMultiResultOpToReplaceWhole425func.func @useMultiResultOpToReplaceWhole() -> (i32, f32, f32) {426 // CHECK: %[[A:.*]], %[[B:.*]], %[[C:.*]] = "test.another_three_result"()427 // CHECK: return %[[A]], %[[B]], %[[C]]428 %0:3 = "test.three_result"() {kind = 1} : () -> (i32, f32, f32)429 return %0#0, %0#1, %0#2 : i32, f32, f32430}431 432// CHECK-LABEL: @useMultiResultOpToReplacePartial1433func.func @useMultiResultOpToReplacePartial1() -> (i32, f32, f32) {434 // CHECK: %[[A:.*]], %[[B:.*]] = "test.two_result"()435 // CHECK: %[[C:.*]] = "test.one_result1"()436 // CHECK: return %[[A]], %[[B]], %[[C]]437 %0:3 = "test.three_result"() {kind = 2} : () -> (i32, f32, f32)438 return %0#0, %0#1, %0#2 : i32, f32, f32439}440 441// CHECK-LABEL: @useMultiResultOpToReplacePartial2442func.func @useMultiResultOpToReplacePartial2() -> (i32, f32, f32) {443 // CHECK: %[[A:.*]] = "test.one_result2"()444 // CHECK: %[[B:.*]], %[[C:.*]] = "test.another_two_result"()445 // CHECK: return %[[A]], %[[B]], %[[C]]446 %0:3 = "test.three_result"() {kind = 3} : () -> (i32, f32, f32)447 return %0#0, %0#1, %0#2 : i32, f32, f32448}449 450// CHECK-LABEL: @useMultiResultOpResultsSeparately451func.func @useMultiResultOpResultsSeparately() -> (i32, f32, f32) {452 // CHECK: %[[A:.*]], %[[B:.*]] = "test.two_result"()453 // CHECK: %[[C:.*]] = "test.one_result1"()454 // CHECK: %[[D:.*]], %[[E:.*]] = "test.two_result"()455 // CHECK: return %[[A]], %[[C]], %[[E]]456 %0:3 = "test.three_result"() {kind = 4} : () -> (i32, f32, f32)457 return %0#0, %0#1, %0#2 : i32, f32, f32458}459 460// CHECK-LABEL: @constraintOnSourceOpResult461func.func @constraintOnSourceOpResult() -> (i32, f32, i32) {462 // CHECK: %[[A:.*]], %[[B:.*]] = "test.two_result"()463 // CHECK: %[[C:.*]] = "test.one_result2"()464 // CHECK: %[[D:.*]] = "test.one_result1"()465 // CHECK: return %[[A]], %[[B]], %[[C]]466 %0:2 = "test.two_result"() {kind = 5} : () -> (i32, f32)467 %1:2 = "test.two_result"() {kind = 5} : () -> (i32, f32)468 return %0#0, %0#1, %1#0 : i32, f32, i32469}470 471// CHECK-LABEL: @useAuxiliaryOpToReplaceMultiResultOp472func.func @useAuxiliaryOpToReplaceMultiResultOp() -> (i32, f32, f32) {473 // An auxiliary op is generated to help building the op for replacing the474 // matched op.475 // CHECK: %[[A:.*]], %[[B:.*]] = "test.two_result"()476 477 // CHECK: %[[C:.*]] = "test.one_result3"(%[[B]])478 // CHECK: %[[D:.*]], %[[E:.*]] = "test.another_two_result"()479 // CHECK: return %[[C]], %[[D]], %[[E]]480 %0:3 = "test.three_result"() {kind = 6} : () -> (i32, f32, f32)481 return %0#0, %0#1, %0#2 : i32, f32, f32482}483 484//===----------------------------------------------------------------------===//485// Test Multi-result Ops486//===----------------------------------------------------------------------===//487 488// CHECK-LABEL: @replaceOneVariadicOutOneVariadicInOp489func.func @replaceOneVariadicOutOneVariadicInOp(%arg0: i32, %arg1: i32, %arg2: i32) -> (i32, i32, i32, i32, i32, i32) {490 // CHECK: %[[cnt1:.*]] = "test.one_variadic_out_one_variadic_in2"(%arg0)491 // CHECK: %[[cnt2:.*]]:2 = "test.one_variadic_out_one_variadic_in2"(%arg0, %arg1)492 // CHECK: %[[cnt3:.*]]:3 = "test.one_variadic_out_one_variadic_in2"(%arg0, %arg1, %arg2)493 // CHECK: return %[[cnt1]], %[[cnt2]]#0, %[[cnt2]]#1, %[[cnt3]]#0, %[[cnt3]]#1, %[[cnt3]]#2494 495 %0 = "test.one_variadic_out_one_variadic_in1"(%arg0) : (i32) -> (i32)496 %1:2 = "test.one_variadic_out_one_variadic_in1"(%arg0, %arg1) : (i32, i32) -> (i32, i32)497 %2:3 = "test.one_variadic_out_one_variadic_in1"(%arg0, %arg1, %arg2) : (i32, i32, i32) -> (i32, i32, i32)498 return %0, %1#0, %1#1, %2#0, %2#1, %2#2 : i32, i32, i32, i32, i32, i32499}500 501// CHECK-LABEL: @replaceMixedVariadicInputOp502func.func @replaceMixedVariadicInputOp(%arg0: i32, %arg1: f32, %arg2: i32) -> () {503 // CHECK: "test.mixed_variadic_in2"(%arg1)504 // CHECK: "test.mixed_variadic_in2"(%arg0, %arg1, %arg2)505 // CHECK: "test.mixed_variadic_in2"(%arg0, %arg0, %arg1, %arg2, %arg2)506 507 "test.mixed_variadic_in1"(%arg1) : (f32) -> ()508 "test.mixed_variadic_in1"(%arg0, %arg1, %arg2) : (i32, f32, i32) -> ()509 "test.mixed_variadic_in1"(%arg0, %arg0, %arg1, %arg2, %arg2) : (i32, i32, f32, i32, i32) -> ()510 return511}512 513// CHECK-LABEL: @replaceMixedVariadicOutputOp514func.func @replaceMixedVariadicOutputOp() -> (f32, i32, f32, i32, i32, i32, f32, i32, i32) {515 // CHECK: %[[cnt1:.*]] = "test.mixed_variadic_out2"()516 // CHECK: %[[cnt3_a:.*]], %[[cnt3_b:.*]], %[[cnt3_c:.*]] = "test.mixed_variadic_out2"()517 // CHECK: %[[cnt5_a:.*]]:2, %[[cnt5_b:.*]], %[[cnt5_c:.*]]:2 = "test.mixed_variadic_out2"()518 // CHECK: return %[[cnt1]], %[[cnt3_a]], %[[cnt3_b]], %[[cnt3_c]], %[[cnt5_a]]#0, %[[cnt5_a]]#1, %[[cnt5_b]], %[[cnt5_c]]#0, %[[cnt5_c]]#1519 520 %0 = "test.mixed_variadic_out1"() : () -> (f32)521 %1:3 = "test.mixed_variadic_out1"() : () -> (i32, f32, i32)522 %2:5 = "test.mixed_variadic_out1"() : () -> (i32, i32, f32, i32, i32)523 return %0, %1#0, %1#1, %1#2, %2#0, %2#1, %2#2, %2#3, %2#4 : f32, i32, f32, i32, i32, i32, f32, i32, i32524}525 526// CHECK-LABEL: @generateVariadicOutputOpInNestedPattern527func.func @generateVariadicOutputOpInNestedPattern() -> (i32) {528 // CHECK: %[[cnt5_a:.*]], %[[cnt5_b:.*]]:2, %[[cnt5_c:.*]]:2 = "test.mixed_variadic_out3"()529 // CHECK: %[[res:.*]] = "test.mixed_variadic_in3"(%[[cnt5_a]], %[[cnt5_b]]#0, %[[cnt5_b]]#1, %[[cnt5_c]]#0, %[[cnt5_c]]#1)530 // CHECK: return %[[res]]531 532 %0 = "test.one_i32_out"() : () -> (i32)533 return %0 : i32534}535 536// CHECK-LABEL: @testMatchVariadic537func.func @testMatchVariadic(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> () {538 // CHECK: "test.mixed_variadic_in5"(%arg0, %arg1, %arg2) <{attr1 = 0 : i32, pattern_name = "MatchVariadic"}> : (i32, i32, i32) -> ()539 "test.mixed_variadic_in4"(%arg0, %arg1, %arg2) {attr1 = 0 : i32} : (i32, i32, i32) -> ()540 541 // Note: Not rewritten because variadic operand size mismatches.542 // CHECK: "test.mixed_variadic_in4"(%arg0, %arg1, %arg2, %arg3) <{attr1 = 0 : i32}> : (i32, i32, i32, i32) -> ()543 "test.mixed_variadic_in4"(%arg0, %arg1, %arg2, %arg3) {attr1 = 0 : i32} : (i32, i32, i32, i32) -> ()544 545 return546}547 548// CHECK-LABEL: @testReplaceVariadic549func.func @testReplaceVariadic(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> () {550 // CHECK: "test.mixed_variadic_in3"(%arg2, %arg1, %arg0) <{count = 1 : i32}>551 "test.mixed_variadic_in5"(%arg0, %arg1, %arg2) <{attr1 = 0 : i32, pattern_name = "MatchInverseVariadic"}> : (i32, i32, i32) -> ()552 553 return554}555 556// CHECK-LABEL: @testMatchVariadicSubDag557func.func @testMatchVariadicSubDag(%arg0: i32, %arg1: i32, %arg2: i32) -> () {558 // CHECK: %[[IN0:.*]] = "test.mixed_variadic_in_out_i32"(%arg0) : (i32) -> i32559 %0 = "test.mixed_variadic_in_out_i32"(%arg0) : (i32) -> i32560 // CHECK: %[[IN1:.*]] = "test.mixed_variadic_in_out_i32"(%arg1) : (i32) -> i32561 %1 = "test.mixed_variadic_in_out_i32"(%arg1) : (i32) -> i32562 563 // CHECK: "test.mixed_variadic_in5"(%arg0, %arg1, %arg2) <{attr1 = 1 : i32, pattern_name = "MatchVariadicSubDag"}> : (i32, i32, i32) -> ()564 "test.mixed_variadic_in4"(%0, %1, %arg2) {attr1 = 1 : i32} : (i32, i32, i32) -> ()565 566 // Note: MatchVariadicSubDag doesn't apply567 // CHECK: "test.mixed_variadic_in4"(%arg0, %arg1, %arg2) <{attr1 = 1 : i32}> : (i32, i32, i32) -> ()568 "test.mixed_variadic_in4"(%arg0, %arg1, %arg2) {attr1 = 1 : i32} : (i32, i32, i32) -> ()569 570 return571}572 573// CHECK-LABEL: @testMatchVariadicSameSymbol574func.func @testMatchVariadicSameSymbol(%arg0: i32, %arg1: i32, %arg2: i32) -> () {575 // CHECK: "test.mixed_variadic_in5"(%arg0, %arg0, %arg2) <{attr1 = 2 : i32, pattern_name = "MatchVariadicSameSymbol"}> : (i32, i32, i32) -> ()576 "test.mixed_variadic_in4"(%arg0, %arg0, %arg2) {attr1 = 2 : i32} : (i32, i32, i32) -> ()577 578 // Note: MatchVariadicSameSymbol doesn't apply.579 // CHECK: "test.mixed_variadic_in4"(%arg0, %arg1, %arg2) <{attr1 = 2 : i32}> : (i32, i32, i32) -> ()580 "test.mixed_variadic_in4"(%arg0, %arg1, %arg2) {attr1 = 2 : i32} : (i32, i32, i32) -> ()581 582 return583}584 585// CHECK-LABEL: @testMatchAndRewriteVariadicFullRange586func.func @testMatchAndRewriteVariadicFullRange(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> () {587 // CHECK: "test.mixed_variadic_in6"(%arg2, %arg3, %arg0, %arg1) <{attr1 = -1 : i32}> : (i32, i32, i32, i32) -> ()588 "test.mixed_variadic_in6"(%arg0, %arg1, %arg2, %arg3) {attr1 = 1 : i32} : (i32, i32, i32, i32) -> ()589 590 // Note: MatchAndRewriteVariadicFullRange doesn't apply because the length of each variadic operand is not equal to 2.591 // CHECK: "test.mixed_variadic_in6"(%arg0, %arg1) <{attr1 = 1 : i32}> : (i32, i32) -> ()592 "test.mixed_variadic_in6"(%arg0, %arg1) {attr1 = 1 : i32} : (i32, i32) -> ()593 594 return595}596 597// CHECK-LABEL: @testMatchMultiVariadicSubSymbol598func.func @testMatchMultiVariadicSubSymbol(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> () {599 // CHECK: "test.mixed_variadic_in5"(%arg2, %arg3, %arg1) <{attr1 = 2 : i32, pattern_name = "MatchMultiVariadicSubSymbol"}> : (i32, i32, i32) -> ()600 "test.mixed_variadic_in6"(%arg0, %arg1, %arg2, %arg3) {attr1 = 2 : i32} : (i32, i32, i32, i32) -> ()601 602 return603}604 605// CHECK-LABEL: @testMatchMixedVaradicOptional606func.func @testMatchMixedVaradicOptional(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> () {607 // CHECK: "test.mixed_variadic_in6"(%arg0, %arg1, %arg2) <{attr1 = 2 : i32}> : (i32, i32, i32) -> ()608 "test.mixed_variadic_optional_in7"(%arg0, %arg1, %arg2) {attr1 = 2 : i32, operandSegmentSizes = array<i32: 2, 1>} : (i32, i32, i32) -> ()609 // CHECK: test.mixed_variadic_optional_in7610 "test.mixed_variadic_optional_in7"(%arg0, %arg1) {attr1 = 2 : i32, operandSegmentSizes = array<i32: 2, 0>} : (i32, i32) -> ()611 612 return613}614 615//===----------------------------------------------------------------------===//616// Test patterns that operate on properties617//===----------------------------------------------------------------------===//618 619// CHECK-LABEL: @testSimplePropertyRewrite620func.func @testSimplePropertyRewrite() {621 // CHECK-NEXT: test.prop_pattern_op_1 "o1" 2 true622 test.prop_pattern_op_1 "o1" 1 false623 // Pattern not applied when predicate not met624 // CHECK-NEXT: test.prop_pattern_op_1 "o2" -1 false625 test.prop_pattern_op_1 "o2" -1 false626 // Pattern not applied when constant doesn't match627 // CHCEK-NEXT: test.prop_pattern_op_1 "o3" 1 true628 test.prop_pattern_op_1 "o3" 1 true629 return630}631 632// CHECK-LABEL: @testNestedPropertyRewrite633func.func @testNestedPropertyRewrite() {634 // CHECK: %[[v:.*]] = test.prop_pattern_op_1 "s1" -2 false635 // CHECK: test.prop_pattern_op_2 %[[v]] "s1.t1"636 %v = test.prop_pattern_op_1 "s1" 1 false637 test.prop_pattern_op_2 %v "t1"638 return639}640 641//===----------------------------------------------------------------------===//642// Test that natives calls are only called once during rewrites.643//===----------------------------------------------------------------------===//644 645// CHECK-LABEL: redundantTest646func.func @redundantTest(%arg0: i32) -> i32 {647 %0 = "test.op_m"(%arg0) : (i32) -> i32648 // CHECK: "test.op_m"(%arg0) <{optional_attr = 314159265 : i32}> : (i32) -> i32649 return %0 : i32650}651 652//===----------------------------------------------------------------------===//653// Test either directive654//===----------------------------------------------------------------------===//655 656// CHECK-LABEL: @eitherDagLeafOnly657func.func @eitherDagLeafOnly(%arg0 : i32, %arg1 : i16, %arg2 : i8) -> () {658 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32659 %0 = "test.either_op_a"(%arg0, %arg1, %arg2) : (i32, i16, i8) -> i32660 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32661 %1 = "test.either_op_a"(%arg1, %arg0, %arg2) : (i16, i32, i8) -> i32662 return663}664 665// CHECK-LABEL: @eitherDagLeafDagNode666func.func @eitherDagLeafDagNode(%arg0 : i32, %arg1 : i16, %arg2 : i8) -> () {667 %0 = "test.either_op_b"(%arg0, %arg0) : (i32, i32) -> i32668 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32669 %1 = "test.either_op_a"(%0, %arg1, %arg2) : (i32, i16, i8) -> i32670 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32671 %2 = "test.either_op_a"(%arg1, %0, %arg2) : (i16, i32, i8) -> i32672 return673}674 675// CHECK-LABEL: @eitherDagNodeDagNode676func.func @eitherDagNodeDagNode(%arg0 : i32, %arg1 : i16, %arg2 : i8) -> () {677 %0 = "test.either_op_b"(%arg0, %arg0) : (i32, i32) -> i32678 %1 = "test.either_op_b"(%arg1, %arg1) : (i16, i16) -> i32679 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32680 %2 = "test.either_op_a"(%0, %1, %arg2) : (i32, i32, i8) -> i32681 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32682 %3 = "test.either_op_a"(%1, %0, %arg2) : (i32, i32, i8) -> i32683 return684}685 686// CHECK-LABEL: @testEitherOpWithAttr687func.func @testEitherOpWithAttr(%arg0 : i32, %arg1 : i16) -> () {688 // CHECK: "test.either_op_b"(%arg1, %arg0) : (i16, i32) -> i32689 %0 = "test.either_op_c"(%arg0, %arg1) {attr = 0 : i32} : (i32, i16) -> i32690 // CHECK: "test.either_op_b"(%arg1, %arg0) : (i16, i32) -> i32691 %1 = "test.either_op_c"(%arg1, %arg0) {attr = 0 : i32} : (i16, i32) -> i32692 // CHECK: "test.either_op_c"(%arg0, %arg1) <{attr = 1 : i32}> : (i32, i16) -> i32693 %2 = "test.either_op_c"(%arg0, %arg1) {attr = 1 : i32} : (i32, i16) -> i32694 return695}696 697//===----------------------------------------------------------------------===//698// Test that ops without type deduction can be created with type builders.699//===----------------------------------------------------------------------===//700 701// CHECK-LABEL: @explicitReturnTypeTest702func.func @explicitReturnTypeTest(%arg0 : i64) -> i8 {703 %0 = "test.source_op"(%arg0) {tag = 11 : i32} : (i64) -> i8704 // CHECK: "test.op_x"(%arg0) : (i64) -> i32705 // CHECK: "test.op_x"(%0) : (i32) -> i8706 return %0 : i8707}708 709// CHECK-LABEL: @returnTypeBuilderTest710func.func @returnTypeBuilderTest(%arg0 : i1) -> i8 {711 %0 = "test.source_op"(%arg0) {tag = 22 : i32} : (i1) -> i8712 // CHECK: "test.op_x"(%arg0) : (i1) -> i1713 // CHECK: "test.op_x"(%0) : (i1) -> i8714 return %0 : i8715}716 717// CHECK-LABEL: @multipleReturnTypeBuildTest718func.func @multipleReturnTypeBuildTest(%arg0 : i1) -> i1 {719 %0 = "test.source_op"(%arg0) {tag = 33 : i32} : (i1) -> i1720 // CHECK: "test.one_to_two"(%arg0) : (i1) -> (i64, i32)721 // CHECK: "test.op_x"(%0#0) : (i64) -> i32722 // CHECK: "test.op_x"(%0#1) : (i32) -> i64723 // CHECK: "test.two_to_one"(%1, %2) : (i32, i64) -> i1724 return %0 : i1725}726 727// CHECK-LABEL: @copyValueType728func.func @copyValueType(%arg0 : i8) -> i32 {729 %0 = "test.source_op"(%arg0) {tag = 44 : i32} : (i8) -> i32730 // CHECK: "test.op_x"(%arg0) : (i8) -> i8731 // CHECK: "test.op_x"(%0) : (i8) -> i32732 return %0 : i32733}734 735// CHECK-LABEL: @multipleReturnTypeDifferent736func.func @multipleReturnTypeDifferent(%arg0 : i1) -> i64 {737 %0 = "test.source_op"(%arg0) {tag = 55 : i32} : (i1) -> i64738 // CHECK: "test.one_to_two"(%arg0) : (i1) -> (i1, i64)739 // CHECK: "test.two_to_one"(%0#0, %0#1) : (i1, i64) -> i64740 return %0 : i64741}742 743//===----------------------------------------------------------------------===//744// Test that multiple trailing directives can be mixed in patterns.745//===----------------------------------------------------------------------===//746 747// CHECK-LABEL: @returnTypeAndLocation748func.func @returnTypeAndLocation(%arg0 : i32) -> i1 {749 %0 = "test.source_op"(%arg0) {tag = 66 : i32} : (i32) -> i1750 // CHECK: "test.op_x"(%arg0) : (i32) -> i32 loc("loc1")751 // CHECK: "test.op_x"(%arg0) : (i32) -> i32 loc("loc2")752 // CHECK: "test.two_to_one"(%0, %1) : (i32, i32) -> i1753 return %0 : i1754}755 756//===----------------------------------------------------------------------===//757// Test that patterns can create ConstantStrAttr758//===----------------------------------------------------------------------===//759 760// CHECK-LABEL: @testConstantStrAttr761func.func @testConstantStrAttr() -> () {762 // CHECK: test.has_str_value {value = "foo"}763 test.no_str_value {value = "bar"}764 return765}766 767//===----------------------------------------------------------------------===//768// Test that patterns with variadics propagate sizes769//===----------------------------------------------------------------------===//770 771// CHECK-LABEL: @testVariadic772func.func @testVariadic(%arg_0: i32, %arg_1: i32, %brg: i64,773 %crg_0: f32, %crg_1: f32, %crg_2: f32, %crg_3: f32) -> () {774 // CHECK: "test.variadic_rewrite_dst_op"(%arg2, %arg3, %arg4, %arg5, %arg6, %arg0, %arg1) <{operandSegmentSizes = array<i32: 1, 4, 2>}> : (i64, f32, f32, f32, f32, i32, i32) -> ()775 "test.variadic_rewrite_src_op"(%arg_0, %arg_1, %brg,776 %crg_0, %crg_1, %crg_2, %crg_3) {operandSegmentSizes = array<i32: 2, 1, 4>} :777 (i32, i32, i64, f32, f32, f32, f32) -> ()778 return779}780