1// RUN: mlir-opt -test-greedy-patterns -mlir-print-debuginfo -mlir-print-local-scope %s | FileCheck %s 2 3// CHECK-LABEL: verifyFusedLocs 4func.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 : i32 11} 12 13// CHECK-LABEL: verifyDesignatedLoc 14func.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 : i32 25} 26 27// CHECK-LABEL: verifyZeroResult 28func.func @verifyZeroResult(%arg0 : i32) { 29 // CHECK: "test.op_i"(%arg0) : (i32) -> () 30 "test.op_h"(%arg0) : (i32) -> () 31 return 32} 33 34// CHECK-LABEL: verifyZeroArg 35func.func @verifyZeroArg() -> i32 { 36 // CHECK: "test.op_k"() : () -> i32 37 %0 = "test.op_j"() : () -> i32 38 return %0 : i32 39} 40 41// CHECK-LABEL: testIgnoreArgMatch 42// 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_src 48 // 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_src 52 // 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 return 55} 56 57// CHECK-LABEL: verifyInterleavedOperandAttribute 58// 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 return 63} 64 65// CHECK-LABEL: verifyBenefit 66func.func @verifyBenefit(%arg0 : i32) -> i32 { 67 %0 = "test.op_d"(%arg0) : (i32) -> i32 68 %1 = "test.op_g"(%arg0) : (i32) -> i32 69 %2 = "test.op_g"(%1) : (i32) -> i32 70 71 // CHECK: "test.op_f"(%arg0) 72 // CHECK: "test.op_b"(%arg0) <{attr = 34 : i32}> 73 return %0 : i32 74} 75 76// CHECK-LABEL: verifyNativeCodeCall 77func.func @verifyNativeCodeCall(%arg0: i32, %arg1: i32) -> (i32, i32) { 78 // CHECK: %0 = "test.native_code_call2"(%arg0) <{attr = [42, 24]}> : (i32) -> i32 79 // CHECK: return %0, %arg1 80 %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, i32 83} 84 85// CHECK-LABEL: verifyAuxiliaryNativeCodeCall 86func.func @verifyAuxiliaryNativeCodeCall(%arg0: i32) -> (i32) { 87 // CHECK: test.op_i 88 // CHECK: test.op_k 89 %0 = "test.native_code_call3"(%arg0) : (i32) -> (i32) 90 return %0 : i32 91} 92 93// CHECK-LABEL: verifyNativeCodeCallBinding 94func.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} : () -> i8 99 // %3 is i8 so it'll fail at GetFirstI32Result match. The operation should 100 // 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 : i32 105} 106 107// CHECK-LABEL: verifyMultipleNativeCodeCallBinding 108func.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) -> i32 112 // CHECK: %[[A:.*]] = "test.native_code_call7"(%0) : (i32) -> i32 113 %2, %3 = "test.native_code_call6"(%0, %1) : (i32, i32) -> (i32, i32) 114 return %2 : i32 115} 116 117// CHECK-LABEL: verifyAllAttrConstraintOf 118func.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, i32 126} 127 128// CHECK-LABEL: verifyManyArgs 129// 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 = 42 136 } : (i32, i32, i32, i32, i32, i32, i32, i32, i32) -> () 137 return 138} 139 140// CHECK-LABEL: verifyEqualArgs 141func.func @verifyEqualArgs(%arg0: i32, %arg1: i32) { 142 // def TestEqualArgsPattern : Pat<(OpN $a, $a), (OpO $a)>; 143 144 // CHECK: "test.op_o"(%arg0) : (i32) -> i32 145 "test.op_n"(%arg0, %arg0) : (i32, i32) -> (i32) 146 147 // CHECK: "test.op_n"(%arg0, %arg1) : (i32, i32) -> i32 148 "test.op_n"(%arg0, %arg1) : (i32, i32) -> (i32) 149 150 return 151} 152 153// CHECK-LABEL: verifyNestedOpEqualArgs 154func.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: %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 164 // CHECK: test.op_p 165 // CHECK: test.op_n 166 %2 = "test.op_p"(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5) 167 : (i32, i32, i32, i32, i32, i32) -> (i32) 168 %3 = "test.op_n"(%arg0, %2) : (i32, i32) -> (i32) 169 170 return 171} 172 173// CHECK-LABEL: verifyNestedSameOpAndSameArgEquality 174func.func @verifyNestedSameOpAndSameArgEquality(%arg0: i32, %arg1: i32) -> i32 { 175 // def TestNestedSameOpAndSameArgEqualityPattern: 176 // Pat<(OpN (OpN $_, $x), $x), (replaceWithValue $x)>; 177 178 %0 = "test.op_n"(%arg1, %arg0) : (i32, i32) -> (i32) 179 %1 = "test.op_n"(%0, %arg0) : (i32, i32) -> (i32) 180 // CHECK: return %arg0 : i32 181 return %1 : i32 182} 183 184// CHECK-LABEL: verifyMultipleEqualArgs 185func.func @verifyMultipleEqualArgs( 186 %arg0: i32, %arg1 : i32, %arg2 : i32, %arg3 : i32, %arg4 : i32) { 187 // def TestMultipleEqualArgsPattern : 188 // Pat<(OpP $a, $b, $a, $a, $b, $c), (OpN $c, $b)>; 189 190 // CHECK: "test.op_n"(%arg2, %arg1) : (i32, i32) -> i32 191 "test.op_p"(%arg0, %arg1, %arg0, %arg0, %arg1, %arg2) : 192 (i32, i32, i32, i32 , i32, i32) -> i32 193 194 // CHECK: test.op_p 195 "test.op_p"(%arg0, %arg1, %arg0, %arg0, %arg0, %arg2) : 196 (i32, i32, i32, i32 , i32, i32) -> i32 197 198 // CHECK: test.op_p 199 "test.op_p"(%arg0, %arg1, %arg1, %arg0, %arg1, %arg2) : 200 (i32, i32, i32, i32 , i32, i32) -> i32 201 202 // CHECK: test.op_p 203 "test.op_p"(%arg0, %arg1, %arg2, %arg2, %arg3, %arg4) : 204 (i32, i32, i32, i32 , i32, i32) -> i32 205 206 return 207} 208 209//===----------------------------------------------------------------------===// 210// Test Symbol Binding 211//===----------------------------------------------------------------------===// 212 213// CHECK-LABEL: symbolBinding 214func.func @symbolBinding(%arg0: i32) -> i32 { 215 // An op with one use is matched. 216 // CHECK: %0 = "test.symbol_binding_b"(%arg0) 217 // CHECK: %1 = "test.symbol_binding_c"(%0) 218 // CHECK: %2 = "test.symbol_binding_d"(%0, %1) <{attr = 42 : i64}> 219 %0 = "test.symbol_binding_a"(%arg0) {attr = 42} : (i32) -> (i32) 220 221 // An op without any use is not matched. 222 // CHECK: "test.symbol_binding_a"(%arg0) 223 %1 = "test.symbol_binding_a"(%arg0) {attr = 42} : (i32) -> (i32) 224 225 // CHECK: return %2 226 return %0: i32 227} 228 229// CHECK-LABEL: symbolBindingNoResult 230func.func @symbolBindingNoResult(%arg0: i32) { 231 // CHECK: test.symbol_binding_b 232 "test.symbol_binding_no_result"(%arg0) : (i32) -> () 233 return 234} 235 236//===----------------------------------------------------------------------===// 237// Test Attributes 238//===----------------------------------------------------------------------===// 239 240// CHECK-LABEL: succeedMatchOpAttr 241func.func @succeedMatchOpAttr() -> i32 { 242 // CHECK: "test.match_op_attribute2"() <{default_valued_attr = 3 : i32, more_attr = 4 : i32, optional_attr = 2 : i32, required_attr = 1 : i32}> 243 %0 = "test.match_op_attribute1"() {required_attr = 1: i32, optional_attr = 2: i32, default_valued_attr = 3: i32, more_attr = 4: i32} : () -> (i32) 244 return %0: i32 245} 246 247// CHECK-LABEL: succeedMatchMissingOptionalAttr 248func.func @succeedMatchMissingOptionalAttr() -> i32 { 249 // CHECK: "test.match_op_attribute2"() <{default_valued_attr = 3 : i32, more_attr = 4 : i32, required_attr = 1 : i32}> 250 %0 = "test.match_op_attribute1"() {required_attr = 1: i32, default_valued_attr = 3: i32, more_attr = 4: i32} : () -> (i32) 251 return %0: i32 252} 253 254// CHECK-LABEL: succeedMatchMissingDefaultValuedAttr 255func.func @succeedMatchMissingDefaultValuedAttr() -> i32 { 256 // CHECK: "test.match_op_attribute2"() <{default_valued_attr = 42 : i32, more_attr = 4 : i32, optional_attr = 2 : i32, required_attr = 1 : i32}> 257 %0 = "test.match_op_attribute1"() {required_attr = 1: i32, optional_attr = 2: i32, more_attr = 4: i32} : () -> (i32) 258 return %0: i32 259} 260 261// CHECK-LABEL: failedMatchAdditionalConstraintNotSatisfied 262func.func @failedMatchAdditionalConstraintNotSatisfied() -> i32 { 263 // CHECK: "test.match_op_attribute1"() 264 %0 = "test.match_op_attribute1"() {required_attr = 1: i32, optional_attr = 2: i32, more_attr = 5: i32} : () -> (i32) 265 return %0: i32 266} 267 268// CHECK-LABEL: verifyConstantAttr 269func.func @verifyConstantAttr(%arg0 : i32) -> i32 { 270 // CHECK: "test.op_b"(%arg0) <{attr = 17 : i32}> : (i32) -> i32 loc("a") 271 %0 = "test.op_c"(%arg0) : (i32) -> i32 loc("a") 272 return %0 : i32 273} 274 275// CHECK-LABEL: verifyUnitAttr 276func.func @verifyUnitAttr() -> (i32, i32) { 277 // Unit attribute present in the matched op is propagated as attr2. 278 // CHECK: "test.match_op_attribute4"() <{attr1, attr2}> : () -> i32 279 %0 = "test.match_op_attribute3"() {attr} : () -> i32 280 281 // Since the original op doesn't have the unit attribute, the new op 282 // only has the constant-constructed unit attribute attr1. 283 // CHECK: "test.match_op_attribute4"() <{attr1}> : () -> i32 284 %1 = "test.match_op_attribute3"() : () -> i32 285 return %0, %1 : i32, i32 286} 287 288//===----------------------------------------------------------------------===// 289// Test Constant Matching 290//===----------------------------------------------------------------------===// 291 292// CHECK-LABEL: testConstOp 293func.func @testConstOp() -> (i32) { 294 // CHECK-NEXT: [[C0:%.+]] = "test.constant"() <{value = 1 295 %0 = "test.constant"() {value = 1 : i32} : () -> i32 296 297 // CHECK-NEXT: return [[C0]] 298 return %0 : i32 299} 300 301// CHECK-LABEL: testConstOpUsed 302func.func @testConstOpUsed() -> (i32) { 303 // CHECK-NEXT: [[C0:%.+]] = "test.constant"() <{value = 1 304 %0 = "test.constant"() {value = 1 : i32} : () -> i32 305 306 // CHECK-NEXT: [[V0:%.+]] = "test.op_s"([[C0]]) 307 %1 = "test.op_s"(%0) {value = 1 : i32} : (i32) -> i32 308 309 // CHECK-NEXT: return [[V0]] 310 return %1 : i32 311} 312 313// CHECK-LABEL: testConstOpReplaced 314func.func @testConstOpReplaced() -> (i32) { 315 // CHECK-NEXT: [[C0:%.+]] = "test.constant"() <{value = 1 316 %0 = "test.constant"() {value = 1 : i32} : () -> i32 317 %1 = "test.constant"() {value = 2 : i32} : () -> i32 318 319 // CHECK: [[V0:%.+]] = "test.op_s"([[C0]]) <{value = 2 : i32} 320 %2 = "test.op_r"(%0, %1) : (i32, i32) -> i32 321 322 // CHECK: [[V0]] 323 return %2 : i32 324} 325 326// CHECK-LABEL: testConstOpMatchFailure 327func.func @testConstOpMatchFailure() -> (i64) { 328 // CHECK-DAG: [[C0:%.+]] = "test.constant"() <{value = 1 329 %0 = "test.constant"() {value = 1 : i64} : () -> i64 330 331 // CHECK-DAG: [[C1:%.+]] = "test.constant"() <{value = 2 332 %1 = "test.constant"() {value = 2 : i64} : () -> i64 333 334 // CHECK: [[V0:%.+]] = "test.op_r"([[C0]], [[C1]]) 335 %2 = "test.op_r"(%0, %1) : (i64, i64) -> i64 336 337 // CHECK: [[V0]] 338 return %2 : i64 339} 340 341// CHECK-LABEL: testConstOpMatchNonConst 342func.func @testConstOpMatchNonConst(%arg0 : i32) -> (i32) { 343 // CHECK-DAG: [[C0:%.+]] = "test.constant"() <{value = 1 344 %0 = "test.constant"() {value = 1 : i32} : () -> i32 345 346 // CHECK: [[V0:%.+]] = "test.op_r"([[C0]], %arg0) 347 %1 = "test.op_r"(%0, %arg0) : (i32, i32) -> i32 348 349 // CHECK: [[V0]] 350 return %1 : i32 351} 352 353 354 355//===----------------------------------------------------------------------===// 356// Test Enum Attributes 357//===----------------------------------------------------------------------===// 358 359// CHECK-LABEL: verifyI32EnumAttr 360func.func @verifyI32EnumAttr() -> i32 { 361 // CHECK: "test.i32_enum_attr"() <{attr = 10 : i32} 362 %0 = "test.i32_enum_attr"() {attr = 5: i32} : () -> i32 363 return %0 : i32 364} 365 366// CHECK-LABEL: verifyI64EnumAttr 367func.func @verifyI64EnumAttr() -> i32 { 368 // CHECK: "test.i64_enum_attr"() <{attr = 10 : i64} 369 %0 = "test.i64_enum_attr"() {attr = 5: i64} : () -> i32 370 return %0 : i32 371} 372 373//===----------------------------------------------------------------------===// 374// Test ElementsAttr 375//===----------------------------------------------------------------------===// 376 377// CHECK-LABEL: rewrite_i32elementsattr 378func.func @rewrite_i32elementsattr() -> () { 379 // CHECK: attr = dense<0> : tensor<i32> 380 "test.i32ElementsAttr"() {attr = dense<[3, 5]>:tensor<2xi32>} : () -> () 381 return 382} 383 384// CHECK-LABEL: rewrite_f64elementsattr 385func.func @rewrite_f64elementsattr() -> () { 386 "test.float_elements_attr"() { 387 // Should match 388 // CHECK: scalar_f32_attr = dense<[5.000000e+00, 6.000000e+00]> : tensor<2xf32> 389 scalar_f32_attr = dense<[3.0, 4.0]> : tensor<2xf32>, 390 tensor_f64_attr = dense<6.0> : tensor<4x8xf64> 391 } : () -> () 392 393 "test.float_elements_attr"() { 394 // Should not match 395 // CHECK: scalar_f32_attr = dense<7.000000e+00> : tensor<2xf32> 396 scalar_f32_attr = dense<7.0> : tensor<2xf32>, 397 tensor_f64_attr = dense<3.0> : tensor<4x8xf64> 398 } : () -> () 399 return 400} 401 402//===----------------------------------------------------------------------===// 403// Test Multi-result Ops 404//===----------------------------------------------------------------------===// 405 406// CHECK-LABEL: @useMultiResultOpToReplaceWhole 407func.func @useMultiResultOpToReplaceWhole() -> (i32, f32, f32) { 408 // CHECK: %[[A:.*]], %[[B:.*]], %[[C:.*]] = "test.another_three_result"() 409 // CHECK: return %[[A]], %[[B]], %[[C]] 410 %0:3 = "test.three_result"() {kind = 1} : () -> (i32, f32, f32) 411 return %0#0, %0#1, %0#2 : i32, f32, f32 412} 413 414// CHECK-LABEL: @useMultiResultOpToReplacePartial1 415func.func @useMultiResultOpToReplacePartial1() -> (i32, f32, f32) { 416 // CHECK: %[[A:.*]], %[[B:.*]] = "test.two_result"() 417 // CHECK: %[[C:.*]] = "test.one_result1"() 418 // CHECK: return %[[A]], %[[B]], %[[C]] 419 %0:3 = "test.three_result"() {kind = 2} : () -> (i32, f32, f32) 420 return %0#0, %0#1, %0#2 : i32, f32, f32 421} 422 423// CHECK-LABEL: @useMultiResultOpToReplacePartial2 424func.func @useMultiResultOpToReplacePartial2() -> (i32, f32, f32) { 425 // CHECK: %[[A:.*]] = "test.one_result2"() 426 // CHECK: %[[B:.*]], %[[C:.*]] = "test.another_two_result"() 427 // CHECK: return %[[A]], %[[B]], %[[C]] 428 %0:3 = "test.three_result"() {kind = 3} : () -> (i32, f32, f32) 429 return %0#0, %0#1, %0#2 : i32, f32, f32 430} 431 432// CHECK-LABEL: @useMultiResultOpResultsSeparately 433func.func @useMultiResultOpResultsSeparately() -> (i32, f32, f32) { 434 // CHECK: %[[A:.*]], %[[B:.*]] = "test.two_result"() 435 // CHECK: %[[C:.*]] = "test.one_result1"() 436 // CHECK: %[[D:.*]], %[[E:.*]] = "test.two_result"() 437 // CHECK: return %[[A]], %[[C]], %[[E]] 438 %0:3 = "test.three_result"() {kind = 4} : () -> (i32, f32, f32) 439 return %0#0, %0#1, %0#2 : i32, f32, f32 440} 441 442// CHECK-LABEL: @constraintOnSourceOpResult 443func.func @constraintOnSourceOpResult() -> (i32, f32, i32) { 444 // CHECK: %[[A:.*]], %[[B:.*]] = "test.two_result"() 445 // CHECK: %[[C:.*]] = "test.one_result2"() 446 // CHECK: %[[D:.*]] = "test.one_result1"() 447 // CHECK: return %[[A]], %[[B]], %[[C]] 448 %0:2 = "test.two_result"() {kind = 5} : () -> (i32, f32) 449 %1:2 = "test.two_result"() {kind = 5} : () -> (i32, f32) 450 return %0#0, %0#1, %1#0 : i32, f32, i32 451} 452 453// CHECK-LABEL: @useAuxiliaryOpToReplaceMultiResultOp 454func.func @useAuxiliaryOpToReplaceMultiResultOp() -> (i32, f32, f32) { 455 // An auxiliary op is generated to help building the op for replacing the 456 // matched op. 457 // CHECK: %[[A:.*]], %[[B:.*]] = "test.two_result"() 458 459 // CHECK: %[[C:.*]] = "test.one_result3"(%[[B]]) 460 // CHECK: %[[D:.*]], %[[E:.*]] = "test.another_two_result"() 461 // CHECK: return %[[C]], %[[D]], %[[E]] 462 %0:3 = "test.three_result"() {kind = 6} : () -> (i32, f32, f32) 463 return %0#0, %0#1, %0#2 : i32, f32, f32 464} 465 466//===----------------------------------------------------------------------===// 467// Test Multi-result Ops 468//===----------------------------------------------------------------------===// 469 470// CHECK-LABEL: @replaceOneVariadicOutOneVariadicInOp 471func.func @replaceOneVariadicOutOneVariadicInOp(%arg0: i32, %arg1: i32, %arg2: i32) -> (i32, i32, i32, i32, i32, i32) { 472 // CHECK: %[[cnt1:.*]] = "test.one_variadic_out_one_variadic_in2"(%arg0) 473 // CHECK: %[[cnt2:.*]]:2 = "test.one_variadic_out_one_variadic_in2"(%arg0, %arg1) 474 // CHECK: %[[cnt3:.*]]:3 = "test.one_variadic_out_one_variadic_in2"(%arg0, %arg1, %arg2) 475 // CHECK: return %[[cnt1]], %[[cnt2]]#0, %[[cnt2]]#1, %[[cnt3]]#0, %[[cnt3]]#1, %[[cnt3]]#2 476 477 %0 = "test.one_variadic_out_one_variadic_in1"(%arg0) : (i32) -> (i32) 478 %1:2 = "test.one_variadic_out_one_variadic_in1"(%arg0, %arg1) : (i32, i32) -> (i32, i32) 479 %2:3 = "test.one_variadic_out_one_variadic_in1"(%arg0, %arg1, %arg2) : (i32, i32, i32) -> (i32, i32, i32) 480 return %0, %1#0, %1#1, %2#0, %2#1, %2#2 : i32, i32, i32, i32, i32, i32 481} 482 483// CHECK-LABEL: @replaceMixedVariadicInputOp 484func.func @replaceMixedVariadicInputOp(%arg0: i32, %arg1: f32, %arg2: i32) -> () { 485 // CHECK: "test.mixed_variadic_in2"(%arg1) 486 // CHECK: "test.mixed_variadic_in2"(%arg0, %arg1, %arg2) 487 // CHECK: "test.mixed_variadic_in2"(%arg0, %arg0, %arg1, %arg2, %arg2) 488 489 "test.mixed_variadic_in1"(%arg1) : (f32) -> () 490 "test.mixed_variadic_in1"(%arg0, %arg1, %arg2) : (i32, f32, i32) -> () 491 "test.mixed_variadic_in1"(%arg0, %arg0, %arg1, %arg2, %arg2) : (i32, i32, f32, i32, i32) -> () 492 return 493} 494 495// CHECK-LABEL: @replaceMixedVariadicOutputOp 496func.func @replaceMixedVariadicOutputOp() -> (f32, i32, f32, i32, i32, i32, f32, i32, i32) { 497 // CHECK: %[[cnt1:.*]] = "test.mixed_variadic_out2"() 498 // CHECK: %[[cnt3_a:.*]], %[[cnt3_b:.*]], %[[cnt3_c:.*]] = "test.mixed_variadic_out2"() 499 // CHECK: %[[cnt5_a:.*]]:2, %[[cnt5_b:.*]], %[[cnt5_c:.*]]:2 = "test.mixed_variadic_out2"() 500 // CHECK: return %[[cnt1]], %[[cnt3_a]], %[[cnt3_b]], %[[cnt3_c]], %[[cnt5_a]]#0, %[[cnt5_a]]#1, %[[cnt5_b]], %[[cnt5_c]]#0, %[[cnt5_c]]#1 501 502 %0 = "test.mixed_variadic_out1"() : () -> (f32) 503 %1:3 = "test.mixed_variadic_out1"() : () -> (i32, f32, i32) 504 %2:5 = "test.mixed_variadic_out1"() : () -> (i32, i32, f32, i32, i32) 505 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, i32 506} 507 508// CHECK-LABEL: @generateVariadicOutputOpInNestedPattern 509func.func @generateVariadicOutputOpInNestedPattern() -> (i32) { 510 // CHECK: %[[cnt5_a:.*]], %[[cnt5_b:.*]]:2, %[[cnt5_c:.*]]:2 = "test.mixed_variadic_out3"() 511 // CHECK: %[[res:.*]] = "test.mixed_variadic_in3"(%[[cnt5_a]], %[[cnt5_b]]#0, %[[cnt5_b]]#1, %[[cnt5_c]]#0, %[[cnt5_c]]#1) 512 // CHECK: return %[[res]] 513 514 %0 = "test.one_i32_out"() : () -> (i32) 515 return %0 : i32 516} 517 518// CHECK-LABEL: @testMatchVariadic 519func.func @testMatchVariadic(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> () { 520 // CHECK: "test.mixed_variadic_in5"(%arg0, %arg1, %arg2) <{attr1 = 0 : i32, pattern_name = "MatchVariadic"}> : (i32, i32, i32) -> () 521 "test.mixed_variadic_in4"(%arg0, %arg1, %arg2) {attr1 = 0 : i32} : (i32, i32, i32) -> () 522 523 // Note: Not rewritten because variadic operand size mismatches. 524 // CHECK: "test.mixed_variadic_in4"(%arg0, %arg1, %arg2, %arg3) <{attr1 = 0 : i32}> : (i32, i32, i32, i32) -> () 525 "test.mixed_variadic_in4"(%arg0, %arg1, %arg2, %arg3) {attr1 = 0 : i32} : (i32, i32, i32, i32) -> () 526 527 return 528} 529 530// CHECK-LABEL: @testReplaceVariadic 531func.func @testReplaceVariadic(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> () { 532 // CHECK: "test.mixed_variadic_in3"(%arg2, %arg1, %arg0) <{count = 1 : i32}> 533 "test.mixed_variadic_in5"(%arg0, %arg1, %arg2) <{attr1 = 0 : i32, pattern_name = "MatchInverseVariadic"}> : (i32, i32, i32) -> () 534 535 return 536} 537 538// CHECK-LABEL: @testMatchVariadicSubDag 539func.func @testMatchVariadicSubDag(%arg0: i32, %arg1: i32, %arg2: i32) -> () { 540 // CHECK: %[[IN0:.*]] = "test.mixed_variadic_in_out_i32"(%arg0) : (i32) -> i32 541 %0 = "test.mixed_variadic_in_out_i32"(%arg0) : (i32) -> i32 542 // CHECK: %[[IN1:.*]] = "test.mixed_variadic_in_out_i32"(%arg1) : (i32) -> i32 543 %1 = "test.mixed_variadic_in_out_i32"(%arg1) : (i32) -> i32 544 545 // CHECK: "test.mixed_variadic_in5"(%arg0, %arg1, %arg2) <{attr1 = 1 : i32, pattern_name = "MatchVariadicSubDag"}> : (i32, i32, i32) -> () 546 "test.mixed_variadic_in4"(%0, %1, %arg2) {attr1 = 1 : i32} : (i32, i32, i32) -> () 547 548 // Note: MatchVariadicSubDag doesn't apply 549 // CHECK: "test.mixed_variadic_in4"(%arg0, %arg1, %arg2) <{attr1 = 1 : i32}> : (i32, i32, i32) -> () 550 "test.mixed_variadic_in4"(%arg0, %arg1, %arg2) {attr1 = 1 : i32} : (i32, i32, i32) -> () 551 552 return 553} 554 555// CHECK-LABEL: @testMatchVariadicSameSymbol 556func.func @testMatchVariadicSameSymbol(%arg0: i32, %arg1: i32, %arg2: i32) -> () { 557 // CHECK: "test.mixed_variadic_in5"(%arg0, %arg0, %arg2) <{attr1 = 2 : i32, pattern_name = "MatchVariadicSameSymbol"}> : (i32, i32, i32) -> () 558 "test.mixed_variadic_in4"(%arg0, %arg0, %arg2) {attr1 = 2 : i32} : (i32, i32, i32) -> () 559 560 // Note: MatchVariadicSameSymbol doesn't apply. 561 // CHECK: "test.mixed_variadic_in4"(%arg0, %arg1, %arg2) <{attr1 = 2 : i32}> : (i32, i32, i32) -> () 562 "test.mixed_variadic_in4"(%arg0, %arg1, %arg2) {attr1 = 2 : i32} : (i32, i32, i32) -> () 563 564 return 565} 566 567// CHECK-LABEL: @testMatchAndRewriteVariadicFullRange 568func.func @testMatchAndRewriteVariadicFullRange(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> () { 569 // CHECK: "test.mixed_variadic_in6"(%arg2, %arg3, %arg0, %arg1) <{attr1 = -1 : i32}> : (i32, i32, i32, i32) -> () 570 "test.mixed_variadic_in6"(%arg0, %arg1, %arg2, %arg3) {attr1 = 1 : i32} : (i32, i32, i32, i32) -> () 571 572 // Note: MatchAndRewriteVariadicFullRange doesn't apply because the length of each variadic operand is not equal to 2. 573 // CHECK: "test.mixed_variadic_in6"(%arg0, %arg1) <{attr1 = 1 : i32}> : (i32, i32) -> () 574 "test.mixed_variadic_in6"(%arg0, %arg1) {attr1 = 1 : i32} : (i32, i32) -> () 575 576 return 577} 578 579// CHECK-LABEL: @testMatchMultiVariadicSubSymbol 580func.func @testMatchMultiVariadicSubSymbol(%arg0: i32, %arg1: i32, %arg2: i32, %arg3: i32) -> () { 581 // CHECK: "test.mixed_variadic_in5"(%arg2, %arg3, %arg1) <{attr1 = 2 : i32, pattern_name = "MatchMultiVariadicSubSymbol"}> : (i32, i32, i32) -> () 582 "test.mixed_variadic_in6"(%arg0, %arg1, %arg2, %arg3) {attr1 = 2 : i32} : (i32, i32, i32, i32) -> () 583 584 return 585} 586 587//===----------------------------------------------------------------------===// 588// Test that natives calls are only called once during rewrites. 589//===----------------------------------------------------------------------===// 590 591// CHECK-LABEL: redundantTest 592func.func @redundantTest(%arg0: i32) -> i32 { 593 %0 = "test.op_m"(%arg0) : (i32) -> i32 594 // CHECK: "test.op_m"(%arg0) <{optional_attr = 314159265 : i32}> : (i32) -> i32 595 return %0 : i32 596} 597 598//===----------------------------------------------------------------------===// 599// Test either directive 600//===----------------------------------------------------------------------===// 601 602// CHECK: @either_dag_leaf_only 603func.func @either_dag_leaf_only_1(%arg0 : i32, %arg1 : i16, %arg2 : i8) -> () { 604 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32 605 %0 = "test.either_op_a"(%arg0, %arg1, %arg2) : (i32, i16, i8) -> i32 606 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32 607 %1 = "test.either_op_a"(%arg1, %arg0, %arg2) : (i16, i32, i8) -> i32 608 return 609} 610 611// CHECK: @either_dag_leaf_dag_node 612func.func @either_dag_leaf_dag_node(%arg0 : i32, %arg1 : i16, %arg2 : i8) -> () { 613 %0 = "test.either_op_b"(%arg0, %arg0) : (i32, i32) -> i32 614 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32 615 %1 = "test.either_op_a"(%0, %arg1, %arg2) : (i32, i16, i8) -> i32 616 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32 617 %2 = "test.either_op_a"(%arg1, %0, %arg2) : (i16, i32, i8) -> i32 618 return 619} 620 621// CHECK: @either_dag_node_dag_node 622func.func @either_dag_node_dag_node(%arg0 : i32, %arg1 : i16, %arg2 : i8) -> () { 623 %0 = "test.either_op_b"(%arg0, %arg0) : (i32, i32) -> i32 624 %1 = "test.either_op_b"(%arg1, %arg1) : (i16, i16) -> i32 625 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32 626 %2 = "test.either_op_a"(%0, %1, %arg2) : (i32, i32, i8) -> i32 627 // CHECK: "test.either_op_b"(%arg1, %arg2) : (i16, i8) -> i32 628 %3 = "test.either_op_a"(%1, %0, %arg2) : (i32, i32, i8) -> i32 629 return 630} 631 632//===----------------------------------------------------------------------===// 633// Test that ops without type deduction can be created with type builders. 634//===----------------------------------------------------------------------===// 635 636func.func @explicitReturnTypeTest(%arg0 : i64) -> i8 { 637 %0 = "test.source_op"(%arg0) {tag = 11 : i32} : (i64) -> i8 638 // CHECK: "test.op_x"(%arg0) : (i64) -> i32 639 // CHECK: "test.op_x"(%0) : (i32) -> i8 640 return %0 : i8 641} 642 643func.func @returnTypeBuilderTest(%arg0 : i1) -> i8 { 644 %0 = "test.source_op"(%arg0) {tag = 22 : i32} : (i1) -> i8 645 // CHECK: "test.op_x"(%arg0) : (i1) -> i1 646 // CHECK: "test.op_x"(%0) : (i1) -> i8 647 return %0 : i8 648} 649 650func.func @multipleReturnTypeBuildTest(%arg0 : i1) -> i1 { 651 %0 = "test.source_op"(%arg0) {tag = 33 : i32} : (i1) -> i1 652 // CHECK: "test.one_to_two"(%arg0) : (i1) -> (i64, i32) 653 // CHECK: "test.op_x"(%0#0) : (i64) -> i32 654 // CHECK: "test.op_x"(%0#1) : (i32) -> i64 655 // CHECK: "test.two_to_one"(%1, %2) : (i32, i64) -> i1 656 return %0 : i1 657} 658 659func.func @copyValueType(%arg0 : i8) -> i32 { 660 %0 = "test.source_op"(%arg0) {tag = 44 : i32} : (i8) -> i32 661 // CHECK: "test.op_x"(%arg0) : (i8) -> i8 662 // CHECK: "test.op_x"(%0) : (i8) -> i32 663 return %0 : i32 664} 665 666func.func @multipleReturnTypeDifferent(%arg0 : i1) -> i64 { 667 %0 = "test.source_op"(%arg0) {tag = 55 : i32} : (i1) -> i64 668 // CHECK: "test.one_to_two"(%arg0) : (i1) -> (i1, i64) 669 // CHECK: "test.two_to_one"(%0#0, %0#1) : (i1, i64) -> i64 670 return %0 : i64 671} 672 673//===----------------------------------------------------------------------===// 674// Test that multiple trailing directives can be mixed in patterns. 675//===----------------------------------------------------------------------===// 676 677func.func @returnTypeAndLocation(%arg0 : i32) -> i1 { 678 %0 = "test.source_op"(%arg0) {tag = 66 : i32} : (i32) -> i1 679 // CHECK: "test.op_x"(%arg0) : (i32) -> i32 loc("loc1") 680 // CHECK: "test.op_x"(%arg0) : (i32) -> i32 loc("loc2") 681 // CHECK: "test.two_to_one"(%0, %1) : (i32, i32) -> i1 682 return %0 : i1 683} 684 685//===----------------------------------------------------------------------===// 686// Test that patterns can create ConstantStrAttr 687//===----------------------------------------------------------------------===// 688 689func.func @testConstantStrAttr() -> () { 690 // CHECK: test.has_str_value {value = "foo"} 691 test.no_str_value {value = "bar"} 692 return 693} 694 695//===----------------------------------------------------------------------===// 696// Test that patterns with variadics propagate sizes 697//===----------------------------------------------------------------------===// 698 699func.func @testVariadic(%arg_0: i32, %arg_1: i32, %brg: i64, 700 %crg_0: f32, %crg_1: f32, %crg_2: f32, %crg_3: f32) -> () { 701 // 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) -> () 702 "test.variadic_rewrite_src_op"(%arg_0, %arg_1, %brg, 703 %crg_0, %crg_1, %crg_2, %crg_3) {operandSegmentSizes = array<i32: 2, 1, 4>} : 704 (i32, i32, i64, f32, f32, f32, f32) -> () 705 return 706} 707