brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.7 KiB · 21a1678 Raw
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