659 lines · plain
1// RUN: mlir-opt %s -allow-unregistered-dialect -pass-pipeline='builtin.module(func.func(canonicalize{test-convergence}))' -split-input-file | FileCheck --dump-input-context 20 %s2 3/// Test the folding of BranchOp.4 5// CHECK-LABEL: func @br_folding(6func.func @br_folding() -> i32 {7 // CHECK-NEXT: %[[CST:.*]] = arith.constant 0 : i328 // CHECK-NEXT: return %[[CST]] : i329 %c0_i32 = arith.constant 0 : i3210 cf.br ^bb1(%c0_i32 : i32)11^bb1(%x : i32):12 return %x : i3213}14 15/// Test that pass-through successors of BranchOp get folded.16 17// CHECK-LABEL: func @br_passthrough(18// CHECK-SAME: %[[ARG0:.*]]: i32, %[[ARG1:.*]]: i3219func.func @br_passthrough(%arg0 : i32, %arg1 : i32) -> (i32, i32) {20 "foo.switch"() [^bb1, ^bb2, ^bb3] : () -> ()21 22^bb1:23 // CHECK: ^bb1:24 // CHECK-NEXT: cf.br ^bb3(%[[ARG0]], %[[ARG1]] : i32, i32)25 26 cf.br ^bb2(%arg0 : i32)27 28^bb2(%arg2 : i32):29 cf.br ^bb3(%arg2, %arg1 : i32, i32)30 31^bb3(%arg4 : i32, %arg5 : i32):32 return %arg4, %arg5 : i32, i3233}34 35/// Test the folding of CondBranchOp with a constant condition.36 37// CHECK-LABEL: func @cond_br_folding(38func.func @cond_br_folding(%cond : i1, %a : i32) {39 // CHECK-NEXT: return40 41 %false_cond = arith.constant false42 %true_cond = arith.constant true43 cf.cond_br %cond, ^bb1, ^bb2(%a : i32)44 45^bb1:46 cf.cond_br %true_cond, ^bb3, ^bb2(%a : i32)47 48^bb2(%x : i32):49 cf.cond_br %false_cond, ^bb2(%x : i32), ^bb350 51^bb3:52 return53}54 55/// Test the folding of CondBranchOp when the successors are identical.56 57// CHECK-LABEL: func @cond_br_same_successor(58func.func @cond_br_same_successor(%cond : i1, %a : i32) {59 // CHECK-NEXT: return60 61 cf.cond_br %cond, ^bb1(%a : i32), ^bb1(%a : i32)62 63^bb1(%result : i32):64 return65}66 67/// Test the folding of CondBranchOp when the successors are identical, but the68/// arguments are different.69 70// CHECK-LABEL: func @cond_br_same_successor_insert_select(71// CHECK-SAME: %[[COND:.*]]: i1, %[[ARG0:.*]]: i32, %[[ARG1:.*]]: i3272// CHECK-SAME: %[[ARG2:.*]]: tensor<2xi32>, %[[ARG3:.*]]: tensor<2xi32>73func.func @cond_br_same_successor_insert_select(74 %cond : i1, %a : i32, %b : i32, %c : tensor<2xi32>, %d : tensor<2xi32>75 ) -> (i32, tensor<2xi32>) {76 // CHECK: %[[RES:.*]] = arith.select %[[COND]], %[[ARG0]], %[[ARG1]]77 // CHECK: %[[RES2:.*]] = arith.select %[[COND]], %[[ARG2]], %[[ARG3]]78 // CHECK: return %[[RES]], %[[RES2]]79 80 cf.cond_br %cond, ^bb1(%a, %c : i32, tensor<2xi32>), ^bb1(%b, %d : i32, tensor<2xi32>)81 82^bb1(%result : i32, %result2 : tensor<2xi32>):83 return %result, %result2 : i32, tensor<2xi32>84}85 86/// Test the compound folding of BranchOp and CondBranchOp.87 88// CHECK-LABEL: func @cond_br_and_br_folding(89func.func @cond_br_and_br_folding(%a : i32) {90 // CHECK-NEXT: return91 92 %false_cond = arith.constant false93 %true_cond = arith.constant true94 cf.cond_br %true_cond, ^bb2, ^bb1(%a : i32)95 96^bb1(%x : i32):97 cf.cond_br %false_cond, ^bb1(%x : i32), ^bb298 99^bb2:100 return101}102 103/// Test that pass-through successors of CondBranchOp get folded.104 105// Test that the weights are preserved:106// CHECK-LABEL: func.func @cond_br_passthrough_weights(107// CHECK-SAME: %[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32, %[[ARG2:.*]]: i1) -> i32 {108func.func @cond_br_passthrough_weights(%arg0 : i32, %arg1 : i32, %cond : i1) -> i32 {109// CHECK: cf.cond_br %[[ARG2]] weights([30, 70]), ^bb1, ^bb2110// CHECK: ^bb1:111// CHECK: return %[[ARG0]] : i32112// CHECK: ^bb2:113// CHECK: return %[[ARG1]] : i32114// CHECK: }115 cf.cond_br %cond weights([30,70]), ^bb1, ^bb3116 117^bb1:118 cf.br ^bb2119 120^bb3:121 cf.br ^bb4122 123^bb2:124 return %arg0 : i32125 126^bb4:127 return %arg1 : i32128}129 130// CHECK-LABEL: func @cond_br_passthrough(131// CHECK-SAME: %[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32, %[[ARG2:.*]]: i32, %[[COND:.*]]: i1132func.func @cond_br_passthrough(%arg0 : i32, %arg1 : i32, %arg2 : i32, %cond : i1) -> (i32, i32) {133 // CHECK: %[[RES:.*]] = arith.select %[[COND]], %[[ARG0]], %[[ARG2]]134 // CHECK: %[[RES2:.*]] = arith.select %[[COND]], %[[ARG1]], %[[ARG2]]135 // CHECK: return %[[RES]], %[[RES2]]136 137 cf.cond_br %cond, ^bb1(%arg0 : i32), ^bb2(%arg2, %arg2 : i32, i32)138 139^bb1(%arg3: i32):140 cf.br ^bb2(%arg3, %arg1 : i32, i32)141 142^bb2(%arg4: i32, %arg5: i32):143 return %arg4, %arg5 : i32, i32144}145 146/// Test the failure modes of collapsing CondBranchOp pass-throughs successors.147 148// CHECK-LABEL: func @cond_br_pass_through_fail(149func.func @cond_br_pass_through_fail(%cond : i1) {150 // CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2151 152 cf.cond_br %cond, ^bb1, ^bb2153 154^bb1:155 // CHECK: ^bb1:156 // CHECK: "foo.op"157 // CHECK: cf.br ^bb2158 159 // Successors can't be collapsed if they contain other operations.160 "foo.op"() : () -> ()161 cf.br ^bb2162 163^bb2:164 return165}166 167 168/// Test the folding of SwitchOp169 170// CHECK-LABEL: func @switch_only_default(171// CHECK-SAME: %[[FLAG:[a-zA-Z0-9_]+]]172// CHECK-SAME: %[[CASE_OPERAND_0:[a-zA-Z0-9_]+]]173func.func @switch_only_default(%flag : i32, %caseOperand0 : f32) {174 // add predecessors for all blocks to avoid other canonicalizations.175 "foo.pred"() [^bb1, ^bb2] : () -> ()176 ^bb1:177 // CHECK-NOT: cf.switch178 // CHECK: cf.br ^[[BB2:[a-zA-Z0-9_]+]](%[[CASE_OPERAND_0]]179 cf.switch %flag : i32, [180 default: ^bb2(%caseOperand0 : f32)181 ]182 // CHECK: ^[[BB2]]({{.*}}):183 ^bb2(%bb2Arg : f32):184 // CHECK-NEXT: "foo.bb2Terminator"185 "foo.bb2Terminator"(%bb2Arg) : (f32) -> ()186}187 188 189// CHECK-LABEL: func @switch_case_matching_default(190// CHECK-SAME: %[[FLAG:[a-zA-Z0-9_]+]]191// CHECK-SAME: %[[CASE_OPERAND_0:[a-zA-Z0-9_]+]]192// CHECK-SAME: %[[CASE_OPERAND_1:[a-zA-Z0-9_]+]]193func.func @switch_case_matching_default(%flag : i32, %caseOperand0 : f32, %caseOperand1 : f32) {194 // add predecessors for all blocks to avoid other canonicalizations.195 "foo.pred"() [^bb1, ^bb2, ^bb3] : () -> ()196 ^bb1:197 // CHECK: cf.switch %[[FLAG]]198 // CHECK-NEXT: default: ^[[BB1:.+]](%[[CASE_OPERAND_0]] : f32)199 // CHECK-NEXT: 10: ^[[BB2:.+]](%[[CASE_OPERAND_1]] : f32)200 // CHECK-NEXT: ]201 cf.switch %flag : i32, [202 default: ^bb2(%caseOperand0 : f32),203 42: ^bb2(%caseOperand0 : f32),204 10: ^bb3(%caseOperand1 : f32),205 17: ^bb2(%caseOperand0 : f32)206 ]207 ^bb2(%bb2Arg : f32):208 "foo.bb2Terminator"(%bb2Arg) : (f32) -> ()209 ^bb3(%bb3Arg : f32):210 "foo.bb3Terminator"(%bb3Arg) : (f32) -> ()211}212 213 214// CHECK-LABEL: func @switch_on_const_no_match(215// CHECK-SAME: %[[CASE_OPERAND_0:[a-zA-Z0-9_]+]]216// CHECK-SAME: %[[CASE_OPERAND_1:[a-zA-Z0-9_]+]]217// CHECK-SAME: %[[CASE_OPERAND_2:[a-zA-Z0-9_]+]]218func.func @switch_on_const_no_match(%caseOperand0 : f32, %caseOperand1 : f32, %caseOperand2 : f32) {219 // add predecessors for all blocks to avoid other canonicalizations.220 "foo.pred"() [^bb1, ^bb2, ^bb3, ^bb4] : () -> ()221 ^bb1:222 // CHECK-NOT: cf.switch223 // CHECK: cf.br ^[[BB2:[a-zA-Z0-9_]+]](%[[CASE_OPERAND_0]]224 %c0_i32 = arith.constant 0 : i32225 cf.switch %c0_i32 : i32, [226 default: ^bb2(%caseOperand0 : f32),227 -1: ^bb3(%caseOperand1 : f32),228 1: ^bb4(%caseOperand2 : f32)229 ]230 // CHECK: ^[[BB2]]({{.*}}):231 // CHECK-NEXT: "foo.bb2Terminator"232 ^bb2(%bb2Arg : f32):233 "foo.bb2Terminator"(%bb2Arg) : (f32) -> ()234 ^bb3(%bb3Arg : f32):235 "foo.bb3Terminator"(%bb3Arg) : (f32) -> ()236 ^bb4(%bb4Arg : f32):237 "foo.bb4Terminator"(%bb4Arg) : (f32) -> ()238}239 240// CHECK-LABEL: func @switch_on_const_with_match(241// CHECK-SAME: %[[CASE_OPERAND_0:[a-zA-Z0-9_]+]]242// CHECK-SAME: %[[CASE_OPERAND_1:[a-zA-Z0-9_]+]]243// CHECK-SAME: %[[CASE_OPERAND_2:[a-zA-Z0-9_]+]]244func.func @switch_on_const_with_match(%caseOperand0 : f32, %caseOperand1 : f32, %caseOperand2 : f32) {245 // add predecessors for all blocks to avoid other canonicalizations.246 "foo.pred"() [^bb1, ^bb2, ^bb3, ^bb4] : () -> ()247 ^bb1:248 // CHECK-NOT: cf.switch249 // CHECK: cf.br ^[[BB4:[a-zA-Z0-9_]+]](%[[CASE_OPERAND_2]]250 %c0_i32 = arith.constant 1 : i32251 cf.switch %c0_i32 : i32, [252 default: ^bb2(%caseOperand0 : f32),253 -1: ^bb3(%caseOperand1 : f32),254 1: ^bb4(%caseOperand2 : f32)255 ]256 ^bb2(%bb2Arg : f32):257 "foo.bb2Terminator"(%bb2Arg) : (f32) -> ()258 ^bb3(%bb3Arg : f32):259 "foo.bb3Terminator"(%bb3Arg) : (f32) -> ()260 // CHECK: ^[[BB4]]({{.*}}):261 // CHECK-NEXT: "foo.bb4Terminator"262 ^bb4(%bb4Arg : f32):263 "foo.bb4Terminator"(%bb4Arg) : (f32) -> ()264}265 266// CHECK-LABEL: func @switch_passthrough(267// CHECK-SAME: %[[FLAG:[a-zA-Z0-9_]+]]268// CHECK-SAME: %[[CASE_OPERAND_0:[a-zA-Z0-9_]+]]269// CHECK-SAME: %[[CASE_OPERAND_1:[a-zA-Z0-9_]+]]270// CHECK-SAME: %[[CASE_OPERAND_2:[a-zA-Z0-9_]+]]271// CHECK-SAME: %[[CASE_OPERAND_3:[a-zA-Z0-9_]+]]272func.func @switch_passthrough(%flag : i32,273 %caseOperand0 : f32,274 %caseOperand1 : f32,275 %caseOperand2 : f32,276 %caseOperand3 : f32) {277 // add predecessors for all blocks to avoid other canonicalizations.278 "foo.pred"() [^bb1, ^bb2, ^bb3, ^bb4, ^bb5, ^bb6] : () -> ()279 280 ^bb1:281 // CHECK: cf.switch %[[FLAG]]282 // CHECK-NEXT: default: ^[[BB5:[a-zA-Z0-9_]+]](%[[CASE_OPERAND_0]]283 // CHECK-NEXT: 43: ^[[BB6:[a-zA-Z0-9_]+]](%[[CASE_OPERAND_1]]284 // CHECK-NEXT: 44: ^[[BB4:[a-zA-Z0-9_]+]](%[[CASE_OPERAND_2]]285 // CHECK-NEXT: ]286 cf.switch %flag : i32, [287 default: ^bb2(%caseOperand0 : f32),288 43: ^bb3(%caseOperand1 : f32),289 44: ^bb4(%caseOperand2 : f32)290 ]291 ^bb2(%bb2Arg : f32):292 cf.br ^bb5(%bb2Arg : f32)293 ^bb3(%bb3Arg : f32):294 cf.br ^bb6(%bb3Arg : f32)295 ^bb4(%bb4Arg : f32):296 "foo.bb4Terminator"(%bb4Arg) : (f32) -> ()297 298 // CHECK: ^[[BB5]]({{.*}}):299 // CHECK-NEXT: "foo.bb5Terminator"300 ^bb5(%bb5Arg : f32):301 "foo.bb5Terminator"(%bb5Arg) : (f32) -> ()302 303 // CHECK: ^[[BB6]]({{.*}}):304 // CHECK-NEXT: "foo.bb6Terminator"305 ^bb6(%bb6Arg : f32):306 "foo.bb6Terminator"(%bb6Arg) : (f32) -> ()307}308 309// CHECK-LABEL: func @switch_from_switch_with_same_value_with_match(310// CHECK-SAME: %[[FLAG:[a-zA-Z0-9_]+]]311// CHECK-SAME: %[[CASE_OPERAND_0:[a-zA-Z0-9_]+]]312// CHECK-SAME: %[[CASE_OPERAND_1:[a-zA-Z0-9_]+]]313func.func @switch_from_switch_with_same_value_with_match(%flag : i32, %caseOperand0 : f32, %caseOperand1 : f32) {314 // add predecessors for all blocks except ^bb3 to avoid other canonicalizations.315 "foo.pred"() [^bb1, ^bb2, ^bb4, ^bb5] : () -> ()316 317 ^bb1:318 // CHECK: cf.switch %[[FLAG]]319 cf.switch %flag : i32, [320 default: ^bb2,321 42: ^bb3322 ]323 324 ^bb2:325 "foo.bb2Terminator"() : () -> ()326 ^bb3:327 // prevent this block from being simplified away328 "foo.op"() : () -> ()329 // CHECK-NOT: cf.switch %[[FLAG]]330 // CHECK: cf.br ^[[BB5:[a-zA-Z0-9_]+]](%[[CASE_OPERAND_1]]331 cf.switch %flag : i32, [332 default: ^bb4(%caseOperand0 : f32),333 42: ^bb5(%caseOperand1 : f32)334 ]335 336 ^bb4(%bb4Arg : f32):337 "foo.bb4Terminator"(%bb4Arg) : (f32) -> ()338 339 // CHECK: ^[[BB5]]({{.*}}):340 // CHECK-NEXT: "foo.bb5Terminator"341 ^bb5(%bb5Arg : f32):342 "foo.bb5Terminator"(%bb5Arg) : (f32) -> ()343}344 345// CHECK-LABEL: func @switch_from_switch_with_same_value_no_match(346// CHECK-SAME: %[[FLAG:[a-zA-Z0-9_]+]]347// CHECK-SAME: %[[CASE_OPERAND_0:[a-zA-Z0-9_]+]]348// CHECK-SAME: %[[CASE_OPERAND_1:[a-zA-Z0-9_]+]]349// CHECK-SAME: %[[CASE_OPERAND_2:[a-zA-Z0-9_]+]]350func.func @switch_from_switch_with_same_value_no_match(%flag : i32, %caseOperand0 : f32, %caseOperand1 : f32, %caseOperand2 : f32) {351 // add predecessors for all blocks except ^bb3 to avoid other canonicalizations.352 "foo.pred"() [^bb1, ^bb2, ^bb4, ^bb5, ^bb6] : () -> ()353 354 ^bb1:355 // CHECK: cf.switch %[[FLAG]]356 cf.switch %flag : i32, [357 default: ^bb2,358 42: ^bb3359 ]360 361 ^bb2:362 "foo.bb2Terminator"() : () -> ()363 ^bb3:364 "foo.op"() : () -> ()365 // CHECK-NOT: cf.switch %[[FLAG]]366 // CHECK: cf.br ^[[BB4:[a-zA-Z0-9_]+]](%[[CASE_OPERAND_0]]367 cf.switch %flag : i32, [368 default: ^bb4(%caseOperand0 : f32),369 0: ^bb5(%caseOperand1 : f32),370 43: ^bb6(%caseOperand2 : f32)371 ]372 373 // CHECK: ^[[BB4]]({{.*}})374 // CHECK-NEXT: "foo.bb4Terminator"375 ^bb4(%bb4Arg : f32):376 "foo.bb4Terminator"(%bb4Arg) : (f32) -> ()377 378 ^bb5(%bb5Arg : f32):379 "foo.bb5Terminator"(%bb5Arg) : (f32) -> ()380 381 ^bb6(%bb6Arg : f32):382 "foo.bb6Terminator"(%bb6Arg) : (f32) -> ()383}384 385// CHECK-LABEL: func @switch_from_switch_default_with_same_value(386// CHECK-SAME: %[[FLAG:[a-zA-Z0-9_]+]]387// CHECK-SAME: %[[CASE_OPERAND_0:[a-zA-Z0-9_]+]]388// CHECK-SAME: %[[CASE_OPERAND_1:[a-zA-Z0-9_]+]]389// CHECK-SAME: %[[CASE_OPERAND_2:[a-zA-Z0-9_]+]]390func.func @switch_from_switch_default_with_same_value(%flag : i32, %caseOperand0 : f32, %caseOperand1 : f32, %caseOperand2 : f32) {391 // add predecessors for all blocks except ^bb3 to avoid other canonicalizations.392 "foo.pred"() [^bb1, ^bb2, ^bb4, ^bb5, ^bb6] : () -> ()393 394 ^bb1:395 // CHECK: cf.switch %[[FLAG]]396 cf.switch %flag : i32, [397 default: ^bb3,398 42: ^bb2399 ]400 401 ^bb2:402 "foo.bb2Terminator"() : () -> ()403 ^bb3:404 "foo.op"() : () -> ()405 // CHECK: cf.switch %[[FLAG]]406 // CHECK-NEXT: default: ^[[BB4:[a-zA-Z0-9_]+]](%[[CASE_OPERAND_0]]407 // CHECK-NEXT: 43: ^[[BB6:[a-zA-Z0-9_]+]](%[[CASE_OPERAND_2]]408 // CHECK-NOT: 42409 cf.switch %flag : i32, [410 default: ^bb4(%caseOperand0 : f32),411 42: ^bb5(%caseOperand1 : f32),412 43: ^bb6(%caseOperand2 : f32)413 ]414 415 // CHECK: ^[[BB4]]({{.*}}):416 // CHECK-NEXT: "foo.bb4Terminator"417 ^bb4(%bb4Arg : f32):418 "foo.bb4Terminator"(%bb4Arg) : (f32) -> ()419 420 ^bb5(%bb5Arg : f32):421 "foo.bb5Terminator"(%bb5Arg) : (f32) -> ()422 423 // CHECK: ^[[BB6]]({{.*}}):424 // CHECK-NEXT: "foo.bb6Terminator"425 ^bb6(%bb6Arg : f32):426 "foo.bb6Terminator"(%bb6Arg) : (f32) -> ()427}428 429/// Test folding conditional branches that are successors of conditional430/// branches with the same condition.431 432// CHECK-LABEL: func @cond_br_from_cond_br_with_same_condition433func.func @cond_br_from_cond_br_with_same_condition(%cond : i1) {434 // CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2435 // CHECK: ^bb1:436 // CHECK: return437 438 cf.cond_br %cond, ^bb1, ^bb2439 440^bb1:441 cf.cond_br %cond, ^bb3, ^bb2442 443^bb2:444 "foo.terminator"() : () -> ()445 446^bb3:447 return448}449 450// -----451 452// Erase assertion if condition is known to be true at compile time.453// CHECK-LABEL: @assert_true454func.func @assert_true() {455 // CHECK-NOT: cf.assert456 %true = arith.constant true457 cf.assert %true, "Computer says no"458 return459}460 461// -----462 463// Keep assertion if condition unknown at compile time.464// CHECK-LABEL: @cf.assert465// CHECK-SAME: (%[[ARG:.*]]: i1)466func.func @cf.assert(%arg : i1) {467 // CHECK: cf.assert %[[ARG]], "Computer says no"468 cf.assert %arg, "Computer says no"469 return470}471 472// -----473 474// CHECK-LABEL: @branchCondProp475// CHECK: %[[trueval:.+]] = arith.constant true476// CHECK: %[[falseval:.+]] = arith.constant false477// CHECK: "test.consumer1"(%[[trueval]]) : (i1) -> ()478// CHECK: "test.consumer2"(%[[falseval]]) : (i1) -> ()479func.func @branchCondProp(%arg0: i1) {480 cf.cond_br %arg0, ^trueB, ^falseB481 482^trueB:483 "test.consumer1"(%arg0) : (i1) -> ()484 cf.br ^exit485 486^falseB:487 "test.consumer2"(%arg0) : (i1) -> ()488 cf.br ^exit489 490^exit:491 return492}493 494// -----495 496/// Test that control-flow cycles are not simplified infinitely.497 498// CHECK-LABEL: @cycle_2_blocks499// CHECK: cf.br ^bb1500// CHECK: ^bb1:501// CHECK: cf.br ^bb1502func.func @cycle_2_blocks() {503 cf.br ^bb1504^bb1:505 cf.br ^bb2506^bb2:507 cf.br ^bb1508}509 510// CHECK-LABEL: @no_cycle_2_blocks511// CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32512// CHECK: return %[[VAL_0]] : i32513func.func @no_cycle_2_blocks() -> i32 {514 cf.br ^bb1515^bb1:516 cf.br ^bb2517^bb2:518 cf.br ^bb3519^bb3:520 %ret = arith.constant 1 : i32521 return %ret : i32522}523 524// CHECK-LABEL: @cycle_4_blocks525// CHECK: cf.br ^bb1526// CHECK: ^bb1:527// CHECK: cf.br ^bb1528func.func @cycle_4_blocks() {529 cf.br ^bb1530^bb1:531 cf.br ^bb2532^bb2:533 cf.br ^bb3534^bb3:535 cf.br ^bb4536^bb4:537 cf.br ^bb1538}539 540// CHECK-LABEL: @no_cycle_4_blocks541// CHECK: %[[VAL_0:.*]] = arith.constant 1 : i32542// CHECK: return %[[VAL_0]] : i32543func.func @no_cycle_4_blocks() -> i32 {544 cf.br ^bb1545^bb1:546 cf.br ^bb2547^bb2:548 cf.br ^bb3549^bb3:550 cf.br ^bb4551^bb4:552 cf.br ^bb5553^bb5:554 %ret = arith.constant 1 : i32555 return %ret : i32556}557 558// CHECK-LABEL: @delayed_3_cycle559// CHECK: cf.br ^bb1560// CHECK: ^bb1:561// CHECK: cf.br ^bb1562func.func @delayed_3_cycle() {563 cf.br ^bb1564^bb1:565 cf.br ^bb2566^bb2:567 cf.br ^bb3568^bb3:569 cf.br ^bb4570^bb4:571 cf.br ^bb5572^bb5:573 cf.br ^bb3574}575 576// CHECK-LABEL: @cycle_1_block577// CHECK: cf.br ^bb1578// CHECK: ^bb1:579// CHECK: cf.br ^bb1580func.func @cycle_1_block() {581 cf.br ^bb1582^bb1:583 cf.br ^bb2584^bb2:585 cf.br ^bb2586}587 588// CHECK-LABEL: @unsimplified_cycle_1589// CHECK-SAME: %[[ARG0:.*]]: i1) {590// CHECK: cf.cond_br %[[ARG0]], ^bb1, ^bb2591// CHECK: ^bb1:592// CHECK: cf.br ^bb2593// CHECK: ^bb2:594// CHECK: cf.br ^bb3595// CHECK: ^bb3:596// CHECK: cf.br ^bb3597func.func @unsimplified_cycle_1(%c : i1) {598 cf.cond_br %c, ^bb1, ^bb2599^bb1:600 cf.br ^bb2601^bb2:602 cf.br ^bb3603^bb3:604 cf.br ^bb4605^bb4:606 cf.br ^bb3607}608 609// Make sure we terminate when other cf passes can't help us.610 611// CHECK-LABEL: @unsimplified_cycle_2612// CHECK-SAME: %[[ARG0:.*]]: i1) {613// CHECK: cf.cond_br %[[ARG0]], ^bb1, ^bb3614// CHECK: ^bb1:615// CHECK: cf.br ^bb2 {A}616// CHECK: ^bb2:617// CHECK: cf.br ^bb2 {E}618// CHECK: ^bb3:619// CHECK: cf.br ^bb1620func.func @unsimplified_cycle_2(%c : i1) {621 cf.cond_br %c, ^bb6, ^bb7622^bb6:623 cf.br ^bb5 {F}624^bb5:625 cf.br ^bb1 {A}626^bb1:627 cf.br ^bb2 {B}628^bb2:629 cf.br ^bb3 {C}630^bb3:631 cf.br ^bb4 {D}632^bb4:633 cf.br ^bb1 {E}634^bb7:635 cf.br ^bb6636}637 638// CHECK-LABEL: @drop_unreachable_branch_1639// CHECK-NEXT: "test.foo"() : () -> ()640// CHECK-NEXT: return641func.func @drop_unreachable_branch_1(%c: i1) {642 cf.cond_br %c, ^bb1, ^bb2643^bb1:644 "test.foo"() : () -> ()645 return646^bb2:647 ub.unreachable648}649 650// CHECK-LABEL: @drop_unreachable_branch_2651// CHECK-NEXT: ub.unreachable652func.func @drop_unreachable_branch_2(%c: i1) {653 cf.cond_br %c, ^bb1, ^bb2654^bb1:655 ub.unreachable656^bb2:657 ub.unreachable658}659