brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.2 KiB · f6e7fb2 Raw
759 lines · plain
1// RUN: mlir-opt --lift-cf-to-scf -split-input-file %s | FileCheck %s2 3func.func @simple_if() {4  %cond = "test.test1"() : () -> i15  cf.cond_br %cond, ^bb1, ^bb26^bb1:7  "test.test2"() : () -> ()8  cf.br ^bb39^bb2:10  "test.test3"() : () -> ()11  cf.br ^bb312^bb3:13  "test.test4"() : () -> ()14  return15}16 17// CHECK-LABEL: func @simple_if18// CHECK:      %[[COND:.*]] = "test.test1"()19// CHECK-NEXT: scf.if %[[COND]]20// CHECK-NEXT:   "test.test2"()21// CHECK-NEXT: else22// CHECK-NEXT:   "test.test3"()23// CHECK-NEXT: }24// CHECK-NEXT: "test.test4"()25// CHECK-NEXT: return26 27// -----28 29func.func @if_with_block_args() -> index {30  %cond = "test.test1"() : () -> i131  cf.cond_br %cond, ^bb1, ^bb232^bb1:33  %1 = "test.test2"() : () -> (index)34  cf.br ^bb3(%1: index)35^bb2:36  %2 = "test.test3"() : () -> (index)37  cf.br ^bb3(%2: index)38^bb3(%3: index):39  "test.test4"() : () -> ()40  return %3 : index41}42 43// CHECK-LABEL: func @if_with_block_args44// CHECK:      %[[COND:.*]] = "test.test1"()45// CHECK-NEXT: %[[RES:.*]] = scf.if %[[COND]]46// CHECK-NEXT:   %[[VAL1:.*]]  = "test.test2"()47// CHECK-NEXT:   scf.yield %[[VAL1]]48// CHECK-NEXT: else49// CHECK-NEXT:   %[[VAL2:.*]]  = "test.test3"()50// CHECK-NEXT:   scf.yield %[[VAL2]]51// CHECK:      "test.test4"()52// CHECK-NEXT: return %[[RES]]53 54// -----55 56func.func @empty_else() {57  %cond = "test.test1"() : () -> i158  cf.cond_br %cond, ^bb1, ^bb359^bb1:60  "test.test2"() : () -> ()61  cf.br ^bb362^bb3:63  "test.test4"() : () -> ()64  return65}66 67// CHECK-LABEL: func @empty_else68// CHECK:      %[[COND:.*]] = "test.test1"()69// CHECK-NEXT: scf.if %[[COND]]70// CHECK-NEXT:   "test.test2"()71// CHECK:      else72// CHECK-NEXT:      }73// CHECK-NEXT: "test.test4"()74// CHECK-NEXT: return75 76// -----77 78func.func @while_loop() {79  "test.test1"() : () -> ()80  cf.br ^bb181^bb1:82  %cond = "test.test2"() : () -> i183  cf.cond_br %cond, ^bb2, ^bb384^bb2:85  "test.test3"() : () -> ()86  cf.br ^bb187^bb3:88  "test.test4"() : () -> ()89  return90}91 92// CHECK-LABEL: func @while_loop93// CHECK-DAG: %[[C0:.*]] = arith.constant 094// CHECK-DAG: %[[C1:.*]] = arith.constant 195// CHECK-NEXT: "test.test1"()96// CHECK-NEXT: scf.while97// CHECK-NEXT:   %[[COND:.*]] = "test.test2"()98// CHECK-NEXT:   %[[RES:.*]]:2 = scf.if %[[COND]]99// CHECK-NEXT:     "test.test3"()100// CHECK-NEXT:     scf.yield %[[C0]], %[[C1]]101// CHECK-NEXT:   else102// CHECK-NEXT:     scf.yield %[[C1]], %[[C0]]103// CHECK:        %[[COND:.*]] = arith.trunci %[[RES]]#1104// CHECK-NEXT:   scf.condition(%[[COND]])105// CHECK-NEXT: do106// CHECK-NEXT:   scf.yield107// CHECK:      "test.test4"()108// CHECK-NEXT: return109 110// -----111 112func.func @while_loop_with_block_args() -> i64{113  %1 = "test.test1"() : () -> index114  cf.br ^bb1(%1: index)115^bb1(%2: index):116  %cond:2 = "test.test2"() : () -> (i1, i64)117  cf.cond_br %cond#0, ^bb2(%cond#1: i64), ^bb3(%cond#1: i64)118^bb2(%3: i64):119  %4 = "test.test3"(%3) : (i64) -> index120  cf.br ^bb1(%4: index)121^bb3(%5: i64):122  "test.test4"() : () -> ()123  return %5 : i64124}125 126// CHECK-LABEL: func @while_loop_with_block_args127// CHECK-DAG: %[[C0:.*]] = arith.constant 0128// CHECK-DAG: %[[C1:.*]] = arith.constant 1129// CHECK-DAG: %[[POISON_i64:.*]] = ub.poison : i64130// CHECK-DAG: %[[POISON_index:.*]] = ub.poison : index131// CHECK-NEXT: %[[VAL1:.*]] = "test.test1"()132// CHECK-NEXT: %[[RES:.*]]:2 = scf.while (%[[ARG0:.*]] = %[[VAL1]], %[[ARG1:.*]] = %[[POISON_i64]])133// CHECK-NEXT:   %[[COND:.*]]:2 = "test.test2"()134// CHECK-NEXT:   %[[IF_VALS:.*]]:4 = scf.if %[[COND]]#0135// CHECK-NEXT:     %[[VAL:.*]] = "test.test3"(%[[COND]]#1)136// CHECK-NEXT:     scf.yield %[[VAL]], %[[POISON_i64]], %[[C0]], %[[C1]]137// CHECK-NEXT:   else138// CHECK-NEXT:     scf.yield %[[POISON_index]], %[[COND]]#1, %[[C1]], %[[C0]]139// CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_VALS]]#3140// CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[IF_VALS]]#0, %[[IF_VALS]]#1141// CHECK-NEXT: do142// CHECK-NEXT:   ^{{.+}}(143// CHECK-SAME: [[ARG0:[[:alnum:]]+]]:144// CHECK-SAME: [[ARG1:[[:alnum:]]+]]:145// CHECK-NEXT:   scf.yield %[[ARG0]], %[[ARG1]]146// CHECK:      "test.test4"() : () -> ()147// CHECK-NEXT: return %[[RES]]#1 : i64148 149// -----150 151func.func @multi_exit_loop() {152  "test.test1"() : () -> ()153  cf.br ^bb1154^bb1:155  %cond = "test.test2"() : () -> i1156  cf.cond_br %cond, ^bb2, ^bb3157^bb2:158  %cond2 = "test.test3"() : () -> i1159  cf.cond_br %cond2, ^bb3, ^bb1160^bb3:161  "test.test4"() : () -> ()162  return163}164 165// CHECK-LABEL: func @multi_exit_loop166// CHECK-DAG: %[[C0:.*]] = arith.constant 0167// CHECK-DAG: %[[C1:.*]] = arith.constant 1168// CHECK-NEXT: "test.test1"()169// CHECK-NEXT: scf.while170// CHECK-NEXT:   %[[COND:.*]] = "test.test2"()171// CHECK-NEXT:   %[[IF_PAIR:.*]]:2 = scf.if %[[COND]]172// CHECK-NEXT:     %[[COND2:.*]] = "test.test3"()173// CHECK-NEXT:     %[[IF_PAIR2:.*]]:2 = scf.if %[[COND2]]174// CHECK-NEXT:       scf.yield %[[C1]], %[[C0]]175// CHECK-NEXT:     else176// CHECK-NEXT:       scf.yield %[[C0]], %[[C1]]177// CHECK:          scf.yield %[[IF_PAIR2]]#0, %[[IF_PAIR2]]#1178// CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_PAIR]]#1179// CHECK-NEXT:   scf.condition(%[[TRUNC]])180// CHECK-NEXT: do181// CHECK-NEXT:   scf.yield182// CHECK:      "test.test4"()183// CHECK-NEXT: return184 185// -----186 187func.func private @foo(%arg: f32) -> f32188func.func private @bar(%arg: f32)189 190func.func @switch_with_fallthrough(%flag: i32, %arg1 : f32, %arg2 : f32) {191  cf.switch %flag : i32, [192    default: ^bb1(%arg1 : f32),193    0: ^bb2(%arg2 : f32),194    1: ^bb3195  ]196 197^bb1(%arg3 : f32):198  %0 = call @foo(%arg3) : (f32) -> f32199  cf.br ^bb2(%0 : f32)200 201^bb2(%arg4 : f32):202  call @bar(%arg4) : (f32) -> ()203  cf.br ^bb3204 205^bb3:206  return207}208 209// CHECK-LABEL: func @switch_with_fallthrough210// CHECK-SAME: %[[ARG0:[[:alnum:]]+]]211// CHECK-SAME: %[[ARG1:[[:alnum:]]+]]212// CHECK-SAME: %[[ARG2:[[:alnum:]]+]]213// CHECK-DAG: %[[C0:.*]] = arith.constant 0214// CHECK-DAG: %[[C1:.*]] = arith.constant 1215// CHECK-DAG: %[[POISON:.*]] = ub.poison216// CHECK-NEXT: %[[INDEX_CAST:.*]] = arith.index_castui %[[ARG0]]217// CHECK-NEXT: %[[SWITCH_PAIR:.*]]:2 = scf.index_switch %[[INDEX_CAST]]218// CHECK-NEXT: case 0219// CHECK-NEXT:   scf.yield %[[ARG2]], %[[C0]]220// CHECK:      case 1221// CHECK-NEXT:   scf.yield %[[POISON]], %[[C1]]222// CHECK:      default223// CHECK-NEXT:   %[[RES:.*]] = func.call @foo(%[[ARG1]])224// CHECK-NEXT:   scf.yield %[[RES]], %[[C0]]225// CHECK:      %[[INDEX_CAST:.*]] = arith.index_castui %[[SWITCH_PAIR]]#1226// CHECK-NEXT: scf.index_switch %[[INDEX_CAST]]227// CHECK-NEXT: case 0228// CHECK-NEXT:   call @bar(%[[SWITCH_PAIR]]#0)229// CHECK-NEXT:   scf.yield230// CHECK:      default {231// CHECK-NEXT: }232// CHECK-NEXT: return233 234// -----235 236func.func private @bar(%arg: f32) -> (i1, f32)237 238func.func @already_structured_loop(%arg: f32) -> f32 {239  cf.br ^bb0240 241^bb0:242  %cond, %value = call @bar(%arg) : (f32) -> (i1, f32)243  cf.cond_br %cond, ^bb1, ^bb0244 245^bb1:246  return %value : f32247}248 249// CHECK-LABEL: @already_structured_loop250// CHECK-SAME: %[[ARG:.*]]: f32251// CHECK-DAG: %[[C0:.*]] = arith.constant 0252// CHECK-DAG: %[[C1:.*]] = arith.constant 1253// CHECK-DAG: %[[POISON:.*]] = ub.poison254// CHECK-NEXT: %[[RES:.*]] = scf.while (%[[ARG1:.*]] = %[[POISON]])255// CHECK-NEXT:   %[[CALL_PAIR:.*]]:2 = func.call @bar(%[[ARG]])256// CHECK-NEXT:   %[[IF_PAIR:.*]]:2 = scf.if %[[CALL_PAIR]]#0257// CHECK-NEXT:     scf.yield %[[C1]], %[[C0]]258// CHECK-NEXT:   else259// CHECK-NEXT:     scf.yield %[[C0]], %[[C1]]260// CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_PAIR]]#1261// CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[CALL_PAIR]]#1262// CHECK: return %[[RES]]263 264// -----265 266func.func private @bar(%arg: f32) -> (i1, f32)267 268// This test makes sure that the exit block using an iteration variable works269// correctly.270 271func.func @exit_loop_iter_use(%arg: f32) -> f32 {272  cf.br ^bb0(%arg : f32)273 274^bb0(%arg1: f32):275  %cond, %value = call @bar(%arg1) : (f32) -> (i1, f32)276  cf.cond_br %cond, ^bb1, ^bb0(%value : f32)277 278^bb1:279  return %arg1 : f32280}281 282// CHECK-LABEL: @exit_loop_iter_use283// CHECK-SAME: %[[ARG:.*]]:284// CHECK-DAG: %[[C0:.*]] = arith.constant 0285// CHECK-DAG: %[[C1:.*]] = arith.constant 1286// CHECK-DAG: %[[POISON:.*]] = ub.poison287// CHECK-NEXT: %[[RES:.*]]:2 = scf.while288// CHECK-SAME:   %[[ARG1:.*]] = %[[ARG]]289// CHECK-SAME:   %[[ARG2:.*]] = %[[POISON]]290// CHECK-NEXT:   %[[CALL_PAIR:.*]]:2 = func.call @bar(%[[ARG1]])291// CHECK-NEXT:   %[[IF_RES:.*]]:3 = scf.if %[[CALL_PAIR]]#0292// CHECK-NEXT:     scf.yield %[[POISON]], %[[C1]], %[[C0]]293// CHECK-NEXT:   else294// CHECK-NEXT:     scf.yield %[[CALL_PAIR]]#1, %[[C0]], %[[C1]]295// CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_RES]]#2296// CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[IF_RES]]#0, %[[ARG1]]297// CHECK: return %[[RES]]#1298 299// -----300 301func.func private @bar(%arg: f32) -> f32302 303func.func @infinite_loop(%arg: f32) -> f32 {304  cf.br ^bb1(%arg: f32)305 306^bb1(%arg1: f32):307  %0 = call @bar(%arg1) : (f32) -> f32308  cf.br ^bb1(%0 : f32)309}310 311// CHECK-LABEL: @infinite_loop312// CHECK-SAME: %[[ARG:.*]]:313// CHECK-DAG: %[[C0:.*]] = arith.constant 0314// CHECK-DAG: %[[C1:.*]] = arith.constant 1315// CHECK-NEXT: scf.while316// CHECK-SAME:   %[[ARG1:.*]] = %[[ARG]]317// CHECK-NEXT:   %[[CALL:.*]] = func.call @bar(%[[ARG1]])318// CHECK-NEXT:   %[[TRUNC:.*]] = arith.trunci %[[C1]]319// CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[CALL]]320// CHECK: %[[POISON:.*]] = ub.poison321// CHECK: return %[[POISON]]322 323// -----324 325func.func @multi_return() -> i32 {326  %cond = "test.test1"() : () -> i1327  cf.cond_br %cond, ^bb1, ^bb3328^bb1:329  %0 = "test.test2"() : () -> i32330  return %0 : i32331^bb3:332  %1 = "test.test4"() : () -> i32333  return %1 : i32334}335 336// CHECK-LABEL: func @multi_return337// CHECK:      %[[COND:.*]] = "test.test1"()338// CHECK-NEXT: %[[RES:.*]] = scf.if %[[COND]]339// CHECK-NEXT:   %[[VAL2:.*]] = "test.test2"()340// CHECK:        scf.yield %[[VAL2]]341// CHECK-NEXT: else342// CHECK-NEXT:   %[[VAL4:.*]] = "test.test4"()343// CHECK:        scf.yield %[[VAL4]]344// CHECK:      return %[[RES]]345 346// -----347 348func.func private @bar(%arg: f32) -> f32349 350func.func @conditional_infinite_loop(%arg: f32, %cond: i1) -> f32 {351  cf.cond_br %cond, ^bb1(%arg: f32), ^bb2352 353^bb1(%arg1: f32):354  %0 = call @bar(%arg1) : (f32) -> f32355  cf.br ^bb1(%0 : f32)356 357^bb2:358  return %arg : f32359}360 361// CHECK-LABEL: @conditional_infinite_loop362// CHECK-SAME: %[[ARG0:[[:alnum:]]+]]:363// CHECK-SAME: %[[ARG1:[[:alnum:]]+]]:364// CHECK-DAG: %[[C0:.*]] = arith.constant 0365// CHECK-DAG: %[[C1:.*]] = arith.constant 1366// CHECK-NEXT: %[[RES:.*]] = scf.if %[[ARG1]]367// CHECK-NEXT:   scf.while368// CHECK-SAME:     %[[ARG2:.*]] = %[[ARG0]]369// CHECK-NEXT:     %[[CALL:.*]] = func.call @bar(%[[ARG2]])370// CHECK-NEXT:     %[[TRUNC:.*]] = arith.trunci %[[C1]]371// CHECK-NEXT:     scf.condition(%[[TRUNC]]) %[[CALL]]372// CHECK:      else373// CHECK:        scf.yield %[[ARG0]]374// CHECK:      return %[[RES]]375 376// -----377 378// Different return-like terminators lead one control flow op remaining in the top level region.379// Each of the blocks the control flow op leads to are transformed into regions nevertheless.380 381func.func private @bar(%arg: i32)382 383func.func @mixing_return_like(%cond: i1, %cond2: i1, %cond3: i1) {384  %0 = arith.constant 0 : i32385  %1 = arith.constant 1 : i32386  cf.cond_br %cond, ^bb1, ^bb3387 388^bb1:389  cf.cond_br %cond2, ^bb2(%0 : i32), ^bb2(%1 : i32)390^bb2(%arg: i32):391  call @bar(%arg) : (i32) -> ()392  "test.returnLike"() : () -> ()393 394^bb3:395  cf.cond_br %cond3, ^bb4(%1 : i32), ^bb4(%0 : i32)396^bb4(%arg2: i32):397  call @bar(%arg2) : (i32) -> ()398  return399}400 401// CHECK-LABEL: @mixing_return_like402// CHECK-SAME: %[[COND1:[[:alnum:]]+]]:403// CHECK-SAME: %[[COND2:[[:alnum:]]+]]:404// CHECK-SAME: %[[COND3:[[:alnum:]]+]]:405// CHECK-DAG: %[[C0:.*]] = arith.constant 0406// CHECK-DAG: %[[C1:.*]] = arith.constant 1407// CHECK: cf.cond_br %[[COND1]], ^[[BB1:.*]], ^[[BB2:[[:alnum:]]+]]408 409// CHECK: ^[[BB1]]:410// CHECK: scf.if411// CHECK-NOT: cf.{{(switch|(cond_)?br)}}412// CHECK: call @bar413// CHECK: "test.returnLike"414 415// CHECK: ^[[BB2]]:416// CHECK: scf.if417// CHECK-NOT: cf.{{(switch|(cond_)?br)}}418// CHECK: call @bar419// CHECK: return420 421// -----422 423// cf.switch here only has some successors with different return-like ops.424// This test makes sure that if there are at least two successors branching to425// the same region, that this region gets properly turned to structured control426// flow.427 428func.func @some_successors_with_different_return(%flag: i32) -> i32 {429  %0 = arith.constant 5 : i32430  %1 = arith.constant 6 : i32431  cf.switch %flag : i32, [432    default: ^bb1,433    0: ^bb3(%0 : i32),434    1: ^bb3(%1 : i32)435  ]436 437^bb1:438  "test.returnLike"() : () -> ()439 440^bb3(%arg: i32):441  cf.br ^bb3(%arg : i32)442}443 444// CHECK-LABEL: @some_successors_with_different_return445// CHECK-SAME: %[[FLAG:[[:alnum:]]+]]:446// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32447// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : i32448// CHECK-DAG: %[[POISON:.*]] = ub.poison449// CHECK-DAG: %[[C5:.*]] = arith.constant 5 : i32450// CHECK-DAG: %[[C6:.*]] = arith.constant 6 : i32451// CHECK:      %[[INDEX_CAST:.*]] = arith.index_castui %[[FLAG]]452// CHECK-NEXT: %[[INDEX_SWITCH:.*]]:2 = scf.index_switch %[[INDEX_CAST]]453// CHECK:      case 0454// CHECK-NEXT:   scf.yield %[[C5]], %[[C1]]455// CHECK:      case 1456// CHECK-NEXT:   scf.yield %[[C6]], %[[C1]]457// CHECK:      default458// CHECK-NEXT:   scf.yield %[[POISON]], %[[C0]]459// CHECK:      cf.switch %[[INDEX_SWITCH]]#1460// CHECK-NEXT: default: ^[[BB2:[[:alnum:]]+]]461// CHECK-SAME: %[[INDEX_SWITCH]]#0462// CHECK-NEXT: 0: ^[[BB1:[[:alnum:]]+]]463// CHECK-NEXT: ]464 465// CHECK: ^[[BB2]]{{.*}}:466// CHECK: scf.while467// CHECK-NOT: cf.{{(switch|(cond_)?br)}}468// CHECK: return469 470// CHECK: ^[[BB1]]:471// CHECK-NEXT: "test.returnLike"472 473// -----474 475func.func @select_like(%cond: i1) -> i32 {476  %0 = arith.constant 0 : i32477  %1 = arith.constant 1 : i32478  cf.cond_br %cond, ^bb0(%0 : i32), ^bb0(%1 : i32)479^bb0(%arg: i32):480  return %arg : i32481}482 483// CHECK-LABEL: func @select_like484// CHECK-SAME: %[[COND:.*]]: i1485// CHECK-DAG: %[[C0:.*]] = arith.constant 0486// CHECK-DAG: %[[C1:.*]] = arith.constant 1487// CHECK-NEXT: %[[RES:.*]] = scf.if %[[COND]]488// CHECK-NEXT:   scf.yield %[[C0]]489// CHECK-NEXT: else490// CHECK-NEXT:   scf.yield %[[C1]]491// CHECK:      return %[[RES]]492 493// -----494 495func.func @return_like_dominated_by_condition(%cond1: i1, %cond2: i1, %cond3: i1) {496  cf.cond_br %cond1, ^bb1, ^bb2497 498^bb1:499  return500 501^bb2:502  cf.cond_br %cond2, ^bb3, ^bb4503 504^bb3:505  "test.unreachable"() : () -> ()506 507^bb4:508  cf.cond_br %cond3, ^bb3, ^bb5509 510^bb5:511  return512}513 514// CHECK-LABEL: func @return_like_dominated_by_condition515// CHECK-SAME: %[[COND1:[[:alnum:]]+]]516// CHECK-SAME: %[[COND2:[[:alnum:]]+]]517// CHECK-SAME: %[[COND3:[[:alnum:]]+]]518// CHECK-DAG: %[[C0:.*]] = arith.constant 0519// CHECK-DAG: %[[C1:.*]] = arith.constant 1520// CHECK: %[[IF:.*]] = scf.if %[[COND1]]521// CHECK-NEXT:   scf.yield522// CHECK: else523// CHECK:   scf.if %[[COND2]]524// CHECK-NEXT:   scf.yield525// CHECK:   else526// CHECK:      scf.if %[[COND3]]527// CHECK-NEXT:    scf.yield528// CHECK-NEXT: else529// CHECK-NEXT:    scf.yield530 531// CHECK: cf.switch %[[IF]]532// CHECK-NEXT: default: ^[[BB1:.*]],533// CHECK-NEXT: 0: ^[[BB2:[[:alnum:]]+]]534 535// CHECK: ^[[BB2]]:536// CHECK-NEXT: return537 538// CHECK: ^[[BB1]]:539// CHECK-NEXT: "test.unreachable"540 541// -----542 543func.func @dominator_issue(%cond: i1, %cond2: i1) -> i32 {544  cf.cond_br %cond, ^bb1, ^bb2545 546^bb1:547  "test.unreachable"() : () -> ()548 549^bb2:550  %value = "test.def"() : () -> i32551  cf.cond_br %cond2, ^bb1, ^bb4552 553^bb4:554  return %value : i32555}556 557// CHECK-LABEL: func @dominator_issue558// CHECK-SAME: %[[COND1:[[:alnum:]]+]]559// CHECK-SAME: %[[COND2:[[:alnum:]]+]]560// CHECK: %[[IF:.*]]:2 = scf.if %[[COND1]]561// CHECK: else562// CHECK:   %[[VALUE:.*]] = "test.def"563// CHECK:   %[[IF_RES:.*]]:2 = scf.if %[[COND2]]564// CHECK:   else565// CHECK-NEXT: scf.yield %[[VALUE]]566// CHECK:   scf.yield %[[IF_RES]]#0567// CHECK: cf.switch %[[IF]]#1568// CHECK-NEXT: default: ^[[BB2:[[:alnum:]]+]](569// CHECK-SAME: %[[IF]]#0570// CHECK-NEXT: 0: ^[[BB1:[[:alnum:]]+]]571// CHECK: ^[[BB1]]:572// CHECK-NEXT: "test.unreachable"573// CHECK: ^[[BB2]]574// CHECK-SAME: %[[ARG:[[:alnum:]]+]]575// CHECK-NEXT: return %[[ARG]]576 577// -----578 579// Test that %value gets properly passed to ^bb4.580 581func.func private @bar(i32)582 583func.func @dominator_issue_loop(%cond: i1, %cond2: i1) -> i32 {584  %0 = arith.constant 5 : i32585  cf.br ^bb0586 587^bb0:588  cf.cond_br %cond, ^bb1, ^bb3589 590^bb1:591  %value = "test.def"() : () -> i32592  cf.cond_br %cond2, ^bb0, ^bb4593 594^bb3:595  return %0 : i32596 597^bb4:598  return %value : i32599}600 601// CHECK-LABEL: func @dominator_issue_loop602// CHECK-SAME: %[[COND1:[[:alnum:]]+]]603// CHECK-SAME: %[[COND2:[[:alnum:]]+]]604// CHECK: %[[WHILE:.*]]:2 = scf.while605// CHECK:   %[[IF:.*]]:3 = scf.if %[[COND1]]606// CHECK:     %[[DEF:.*]] = "test.def"607// CHECK:     %[[IF2:.*]]:3 = scf.if %[[COND2]]608// CHECK:       scf.yield609// CHECK-SAME:   %[[DEF]]610// CHECK:     else611// CHECK:       scf.yield %{{.*}}, %{{.*}}, %[[DEF]]612// CHECK:     scf.yield %[[IF2]]#0, %[[IF2]]#1, %[[IF2]]#2613// CHECK:   scf.condition(%{{.*}}) %[[IF]]#2, %[[IF]]#0614 615// CHECK: %[[SWITCH:.*]] = scf.index_switch616// CHECK:   scf.yield %[[WHILE]]#0617// CHECK: return %[[SWITCH]]618 619// -----620 621// Multi entry loops generally produce code in dire need of canonicalization.622 623func.func private @comp1(%arg: i32) -> i1624func.func private @comp2(%arg: i32) -> i1625func.func private @foo(%arg: i32)626 627func.func @multi_entry_loop(%cond: i1) {628  %0 = arith.constant 6 : i32629  %1 = arith.constant 5 : i32630  cf.cond_br %cond, ^bb0, ^bb1631 632^bb0:633  %exit = call @comp1(%0) : (i32) -> i1634  cf.cond_br %exit, ^bb2(%0 : i32), ^bb1635 636^bb1:637  %exit2 = call @comp2(%1) : (i32) -> i1638  cf.cond_br %exit2, ^bb2(%1 : i32), ^bb0639 640^bb2(%arg3 : i32):641  call @foo(%arg3) : (i32) -> ()642  return643}644 645// CHECK-LABEL: func @multi_entry_loop646// CHECK-SAME: %[[ARG0:[[:alnum:]]+]]647// CHECK-DAG: %[[C0:.*]] = arith.constant 0648// CHECK-DAG: %[[UB:.*]] = ub.poison649// CHECK-DAG: %[[C1:.*]] = arith.constant 1650// CHECK-DAG: %[[C6:.*]] = arith.constant 6651// CHECK-DAG: %[[C5:.*]] = arith.constant 5652// CHECK:      %[[IF:.*]]:{{.*}} = scf.if %[[ARG0]]653// CHECK-NEXT:   scf.yield %[[C1]], %[[UB]]654// CHECK-NEXT: else655// CHECK-NEXT:   scf.yield %[[C0]], %[[UB]]656// CHECK:      %[[WHILE:.*]]:{{.*}} = scf.while657// CHECK-SAME: %[[ARG1:.*]] = %[[IF]]#0658// CHECK-SAME: %[[ARG2:.*]] = %[[IF]]#1659// CHECK-NEXT:   %[[FLAG:.*]] = arith.index_castui %[[ARG1]]660// CHECK-NEXT:   %[[SWITCH:.*]]:{{.*}} = scf.index_switch %[[FLAG]]661// CHECK-NEXT:   case 0662// CHECK-NEXT:     %[[EXIT:.*]] = func.call @comp2(%[[C5]])663// CHECK-NEXT:     %[[IF_RES:.*]]:{{.*}} = scf.if %[[EXIT]]664// CHECK-NEXT:       scf.yield %[[UB]], %[[C5]], %[[C1]], %[[C0]]665// CHECK-NEXT:     else666// CHECK-NEXT:       scf.yield %[[C1]], %[[UB]], %[[C0]], %[[C1]]667// CHECK:          scf.yield %[[IF_RES]]#0, %[[IF_RES]]#1, %[[IF_RES]]#2, %[[IF_RES]]#3668// CHECK:        default669// CHECK-NEXT:     %[[EXIT:.*]] = func.call @comp1(%[[C6]])670// CHECK-NEXT:     %[[IF_RES:.*]]:{{.*}} = scf.if %[[EXIT]]671// CHECK-NEXT:       scf.yield %[[UB]], %[[C6]], %[[C1]], %[[C0]]672// CHECK-NEXT:     else673// CHECK-NEXT:       scf.yield %[[C0]], %[[UB]], %[[C0]], %[[C1]]674// CHECK:          scf.yield %[[IF_RES]]#0, %[[IF_RES]]#1, %[[IF_RES]]#2, %[[IF_RES]]#3675// CHECK:        %[[COND:.*]] = arith.trunci %[[SWITCH]]#3676// CHECK-NEXT:   scf.condition(%[[COND]]) %[[SWITCH]]#0, %[[SWITCH]]#1677// CHECK:      do678// CHECK:        scf.yield679// CHECK:      call @foo(%[[WHILE]]#1)680// CHECK-NEXT: return681 682// -----683 684func.func @nested_region() {685  scf.execute_region {686    %cond = "test.test1"() : () -> i1687    cf.cond_br %cond, ^bb1, ^bb2688  ^bb1:689    "test.test2"() : () -> ()690    cf.br ^bb3691  ^bb2:692    "test.test3"() : () -> ()693    cf.br ^bb3694  ^bb3:695    "test.test4"() : () -> ()696    scf.yield697  }698  return699}700 701// CHECK-LABEL: func @nested_region702// CHECK:      scf.execute_region {703// CHECK:      %[[COND:.*]] = "test.test1"()704// CHECK-NEXT: scf.if %[[COND]]705// CHECK-NEXT:   "test.test2"()706// CHECK-NEXT: else707// CHECK-NEXT:   "test.test3"()708// CHECK-NEXT: }709// CHECK-NEXT: "test.test4"()710// CHECK-NEXT: scf.yield711// CHECK-NEXT: }712// CHECK-NEXT: return713 714// -----715 716func.func @nested_region_inside_loop_use() {717  cf.br ^bb1718 719^bb1:720  %3 = "test.test1"() : () -> i32721  scf.execute_region {722    "test.foo"(%3) : (i32) -> ()723    scf.yield724  }725  cf.br ^bb1726}727 728// CHECK-LABEL: func @nested_region_inside_loop_use729// CHECK: scf.while730// CHECK-NEXT: %[[DEF:.*]] = "test.test1"()731// CHECK-NEXT: scf.execute_region732// CHECK-NEXT: "test.foo"(%[[DEF]])733 734// -----735 736func.func @nested_region_outside_loop_use() {737  cf.br ^bb1738 739^bb1:740  %3 = "test.test1"() : () -> i32741  %cond = "test.test2"() : () -> i1742  cf.cond_br %cond, ^bb1, ^bb2743 744^bb2:745  scf.execute_region {746    "test.foo"(%3) : (i32) -> ()747    scf.yield748  }749  return750}751 752// CHECK-LABEL: func @nested_region_outside_loop_use753// CHECK: %[[RES:.*]] = scf.while754// CHECK: %[[DEF:.*]] = "test.test1"()755// CHECK: scf.condition(%{{.*}}) %[[DEF]]756 757// CHECK: scf.execute_region758// CHECK-NEXT: "test.foo"(%[[RES]])759