xref: /llvm-project/mlir/test/Conversion/ControlFlowToSCF/test.mlir (revision 30fe8762446ca91a34174ab9c5dde34bde4d4394)
13b45fe2eSMarkus Böck// RUN: mlir-opt --lift-cf-to-scf -split-input-file %s | FileCheck %s
23b45fe2eSMarkus Böck
33b45fe2eSMarkus Böckfunc.func @simple_if() {
43b45fe2eSMarkus Böck  %cond = "test.test1"() : () -> i1
53b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb1, ^bb2
63b45fe2eSMarkus Böck^bb1:
73b45fe2eSMarkus Böck  "test.test2"() : () -> ()
83b45fe2eSMarkus Böck  cf.br ^bb3
93b45fe2eSMarkus Böck^bb2:
103b45fe2eSMarkus Böck  "test.test3"() : () -> ()
113b45fe2eSMarkus Böck  cf.br ^bb3
123b45fe2eSMarkus Böck^bb3:
133b45fe2eSMarkus Böck  "test.test4"() : () -> ()
143b45fe2eSMarkus Böck  return
153b45fe2eSMarkus Böck}
163b45fe2eSMarkus Böck
173b45fe2eSMarkus Böck// CHECK-LABEL: func @simple_if
183b45fe2eSMarkus Böck// CHECK:      %[[COND:.*]] = "test.test1"()
193b45fe2eSMarkus Böck// CHECK-NEXT: scf.if %[[COND]]
203b45fe2eSMarkus Böck// CHECK-NEXT:   "test.test2"()
213b45fe2eSMarkus Böck// CHECK-NEXT: else
223b45fe2eSMarkus Böck// CHECK-NEXT:   "test.test3"()
233b45fe2eSMarkus Böck// CHECK-NEXT: }
243b45fe2eSMarkus Böck// CHECK-NEXT: "test.test4"()
253b45fe2eSMarkus Böck// CHECK-NEXT: return
263b45fe2eSMarkus Böck
273b45fe2eSMarkus Böck// -----
283b45fe2eSMarkus Böck
293b45fe2eSMarkus Böckfunc.func @if_with_block_args() -> index {
303b45fe2eSMarkus Böck  %cond = "test.test1"() : () -> i1
313b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb1, ^bb2
323b45fe2eSMarkus Böck^bb1:
333b45fe2eSMarkus Böck  %1 = "test.test2"() : () -> (index)
343b45fe2eSMarkus Böck  cf.br ^bb3(%1: index)
353b45fe2eSMarkus Böck^bb2:
363b45fe2eSMarkus Böck  %2 = "test.test3"() : () -> (index)
373b45fe2eSMarkus Böck  cf.br ^bb3(%2: index)
383b45fe2eSMarkus Böck^bb3(%3: index):
393b45fe2eSMarkus Böck  "test.test4"() : () -> ()
403b45fe2eSMarkus Böck  return %3 : index
413b45fe2eSMarkus Böck}
423b45fe2eSMarkus Böck
433b45fe2eSMarkus Böck// CHECK-LABEL: func @if_with_block_args
443b45fe2eSMarkus Böck// CHECK:      %[[COND:.*]] = "test.test1"()
453b45fe2eSMarkus Böck// CHECK-NEXT: %[[RES:.*]] = scf.if %[[COND]]
463b45fe2eSMarkus Böck// CHECK-NEXT:   %[[VAL1:.*]]  = "test.test2"()
473b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[VAL1]]
483b45fe2eSMarkus Böck// CHECK-NEXT: else
493b45fe2eSMarkus Böck// CHECK-NEXT:   %[[VAL2:.*]]  = "test.test3"()
503b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[VAL2]]
513b45fe2eSMarkus Böck// CHECK:      "test.test4"()
523b45fe2eSMarkus Böck// CHECK-NEXT: return %[[RES]]
533b45fe2eSMarkus Böck
543b45fe2eSMarkus Böck// -----
553b45fe2eSMarkus Böck
563b45fe2eSMarkus Böckfunc.func @empty_else() {
573b45fe2eSMarkus Böck  %cond = "test.test1"() : () -> i1
583b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb1, ^bb3
593b45fe2eSMarkus Böck^bb1:
603b45fe2eSMarkus Böck  "test.test2"() : () -> ()
613b45fe2eSMarkus Böck  cf.br ^bb3
623b45fe2eSMarkus Böck^bb3:
633b45fe2eSMarkus Böck  "test.test4"() : () -> ()
643b45fe2eSMarkus Böck  return
653b45fe2eSMarkus Böck}
663b45fe2eSMarkus Böck
673b45fe2eSMarkus Böck// CHECK-LABEL: func @empty_else
683b45fe2eSMarkus Böck// CHECK:      %[[COND:.*]] = "test.test1"()
693b45fe2eSMarkus Böck// CHECK-NEXT: scf.if %[[COND]]
703b45fe2eSMarkus Böck// CHECK-NEXT:   "test.test2"()
713b45fe2eSMarkus Böck// CHECK:      else
723b45fe2eSMarkus Böck// CHECK-NEXT:      }
733b45fe2eSMarkus Böck// CHECK-NEXT: "test.test4"()
743b45fe2eSMarkus Böck// CHECK-NEXT: return
753b45fe2eSMarkus Böck
763b45fe2eSMarkus Böck// -----
773b45fe2eSMarkus Böck
783b45fe2eSMarkus Böckfunc.func @while_loop() {
793b45fe2eSMarkus Böck  "test.test1"() : () -> ()
803b45fe2eSMarkus Böck  cf.br ^bb1
813b45fe2eSMarkus Böck^bb1:
823b45fe2eSMarkus Böck  %cond = "test.test2"() : () -> i1
833b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb2, ^bb3
843b45fe2eSMarkus Böck^bb2:
853b45fe2eSMarkus Böck  "test.test3"() : () -> ()
863b45fe2eSMarkus Böck  cf.br ^bb1
873b45fe2eSMarkus Böck^bb3:
883b45fe2eSMarkus Böck  "test.test4"() : () -> ()
893b45fe2eSMarkus Böck  return
903b45fe2eSMarkus Böck}
913b45fe2eSMarkus Böck
923b45fe2eSMarkus Böck// CHECK-LABEL: func @while_loop
933b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
943b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
953b45fe2eSMarkus Böck// CHECK-NEXT: "test.test1"()
963b45fe2eSMarkus Böck// CHECK-NEXT: scf.while
973b45fe2eSMarkus Böck// CHECK-NEXT:   %[[COND:.*]] = "test.test2"()
983b45fe2eSMarkus Böck// CHECK-NEXT:   %[[RES:.*]]:2 = scf.if %[[COND]]
993b45fe2eSMarkus Böck// CHECK-NEXT:     "test.test3"()
1003b45fe2eSMarkus Böck// CHECK-NEXT:     scf.yield %[[C0]], %[[C1]]
1013b45fe2eSMarkus Böck// CHECK-NEXT:   else
1023b45fe2eSMarkus Böck// CHECK-NEXT:     scf.yield %[[C1]], %[[C0]]
1033b45fe2eSMarkus Böck// CHECK:        %[[COND:.*]] = arith.trunci %[[RES]]#1
1043b45fe2eSMarkus Böck// CHECK-NEXT:   scf.condition(%[[COND]])
1053b45fe2eSMarkus Böck// CHECK-NEXT: do
1063b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield
1073b45fe2eSMarkus Böck// CHECK:      "test.test4"()
1083b45fe2eSMarkus Böck// CHECK-NEXT: return
1093b45fe2eSMarkus Böck
1103b45fe2eSMarkus Böck// -----
1113b45fe2eSMarkus Böck
1123b45fe2eSMarkus Böckfunc.func @while_loop_with_block_args() -> i64{
1133b45fe2eSMarkus Böck  %1 = "test.test1"() : () -> index
1143b45fe2eSMarkus Böck  cf.br ^bb1(%1: index)
1153b45fe2eSMarkus Böck^bb1(%2: index):
1163b45fe2eSMarkus Böck  %cond:2 = "test.test2"() : () -> (i1, i64)
1173b45fe2eSMarkus Böck  cf.cond_br %cond#0, ^bb2(%cond#1: i64), ^bb3(%cond#1: i64)
1183b45fe2eSMarkus Böck^bb2(%3: i64):
1193b45fe2eSMarkus Böck  %4 = "test.test3"(%3) : (i64) -> index
1203b45fe2eSMarkus Böck  cf.br ^bb1(%4: index)
1213b45fe2eSMarkus Böck^bb3(%5: i64):
1223b45fe2eSMarkus Böck  "test.test4"() : () -> ()
1233b45fe2eSMarkus Böck  return %5 : i64
1243b45fe2eSMarkus Böck}
1253b45fe2eSMarkus Böck
1263b45fe2eSMarkus Böck// CHECK-LABEL: func @while_loop_with_block_args
1273b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
1283b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
1293b45fe2eSMarkus Böck// CHECK-DAG: %[[POISON_i64:.*]] = ub.poison : i64
1303b45fe2eSMarkus Böck// CHECK-DAG: %[[POISON_index:.*]] = ub.poison : index
1313b45fe2eSMarkus Böck// CHECK-NEXT: %[[VAL1:.*]] = "test.test1"()
1323b45fe2eSMarkus Böck// CHECK-NEXT: %[[RES:.*]]:2 = scf.while (%[[ARG0:.*]] = %[[VAL1]], %[[ARG1:.*]] = %[[POISON_i64]])
1333b45fe2eSMarkus Böck// CHECK-NEXT:   %[[COND:.*]]:2 = "test.test2"()
1343b45fe2eSMarkus Böck// CHECK-NEXT:   %[[IF_VALS:.*]]:4 = scf.if %[[COND]]#0
1353b45fe2eSMarkus Böck// CHECK-NEXT:     %[[VAL:.*]] = "test.test3"(%[[COND]]#1)
1363b45fe2eSMarkus Böck// CHECK-NEXT:     scf.yield %[[VAL]], %[[POISON_i64]], %[[C0]], %[[C1]]
1373b45fe2eSMarkus Böck// CHECK-NEXT:   else
1383b45fe2eSMarkus Böck// CHECK-NEXT:     scf.yield %[[POISON_index]], %[[COND]]#1, %[[C1]], %[[C0]]
1393b45fe2eSMarkus Böck// CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_VALS]]#3
1403b45fe2eSMarkus Böck// CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[IF_VALS]]#0, %[[IF_VALS]]#1
1413b45fe2eSMarkus Böck// CHECK-NEXT: do
1423b45fe2eSMarkus Böck// CHECK-NEXT:   ^{{.+}}(
1433b45fe2eSMarkus Böck// CHECK-SAME: [[ARG0:[[:alnum:]]+]]:
1443b45fe2eSMarkus Böck// CHECK-SAME: [[ARG1:[[:alnum:]]+]]:
1453b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[ARG0]], %[[ARG1]]
1463b45fe2eSMarkus Böck// CHECK:      "test.test4"() : () -> ()
1473b45fe2eSMarkus Böck// CHECK-NEXT: return %[[RES]]#1 : i64
1483b45fe2eSMarkus Böck
1493b45fe2eSMarkus Böck// -----
1503b45fe2eSMarkus Böck
1513b45fe2eSMarkus Böckfunc.func @multi_exit_loop() {
1523b45fe2eSMarkus Böck  "test.test1"() : () -> ()
1533b45fe2eSMarkus Böck  cf.br ^bb1
1543b45fe2eSMarkus Böck^bb1:
1553b45fe2eSMarkus Böck  %cond = "test.test2"() : () -> i1
1563b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb2, ^bb3
1573b45fe2eSMarkus Böck^bb2:
1583b45fe2eSMarkus Böck  %cond2 = "test.test3"() : () -> i1
1593b45fe2eSMarkus Böck  cf.cond_br %cond2, ^bb3, ^bb1
1603b45fe2eSMarkus Böck^bb3:
1613b45fe2eSMarkus Böck  "test.test4"() : () -> ()
1623b45fe2eSMarkus Böck  return
1633b45fe2eSMarkus Böck}
1643b45fe2eSMarkus Böck
1653b45fe2eSMarkus Böck// CHECK-LABEL: func @multi_exit_loop
1663b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
1673b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
1683b45fe2eSMarkus Böck// CHECK-NEXT: "test.test1"()
1693b45fe2eSMarkus Böck// CHECK-NEXT: scf.while
1703b45fe2eSMarkus Böck// CHECK-NEXT:   %[[COND:.*]] = "test.test2"()
1713b45fe2eSMarkus Böck// CHECK-NEXT:   %[[IF_PAIR:.*]]:2 = scf.if %[[COND]]
1723b45fe2eSMarkus Böck// CHECK-NEXT:     %[[COND2:.*]] = "test.test3"()
1733b45fe2eSMarkus Böck// CHECK-NEXT:     %[[IF_PAIR2:.*]]:2 = scf.if %[[COND2]]
1743b45fe2eSMarkus Böck// CHECK-NEXT:       scf.yield %[[C1]], %[[C0]]
1753b45fe2eSMarkus Böck// CHECK-NEXT:     else
1763b45fe2eSMarkus Böck// CHECK-NEXT:       scf.yield %[[C0]], %[[C1]]
1773b45fe2eSMarkus Böck// CHECK:          scf.yield %[[IF_PAIR2]]#0, %[[IF_PAIR2]]#1
1783b45fe2eSMarkus Böck// CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_PAIR]]#1
1793b45fe2eSMarkus Böck// CHECK-NEXT:   scf.condition(%[[TRUNC]])
1803b45fe2eSMarkus Böck// CHECK-NEXT: do
1813b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield
1823b45fe2eSMarkus Böck// CHECK:      "test.test4"()
1833b45fe2eSMarkus Böck// CHECK-NEXT: return
1843b45fe2eSMarkus Böck
1853b45fe2eSMarkus Böck// -----
1863b45fe2eSMarkus Böck
1873b45fe2eSMarkus Böckfunc.func private @foo(%arg: f32) -> f32
1883b45fe2eSMarkus Böckfunc.func private @bar(%arg: f32)
1893b45fe2eSMarkus Böck
1903b45fe2eSMarkus Böckfunc.func @switch_with_fallthrough(%flag: i32, %arg1 : f32, %arg2 : f32) {
1913b45fe2eSMarkus Böck  cf.switch %flag : i32, [
1923b45fe2eSMarkus Böck    default: ^bb1(%arg1 : f32),
1933b45fe2eSMarkus Böck    0: ^bb2(%arg2 : f32),
1943b45fe2eSMarkus Böck    1: ^bb3
1953b45fe2eSMarkus Böck  ]
1963b45fe2eSMarkus Böck
1973b45fe2eSMarkus Böck^bb1(%arg3 : f32):
1983b45fe2eSMarkus Böck  %0 = call @foo(%arg3) : (f32) -> f32
1993b45fe2eSMarkus Böck  cf.br ^bb2(%0 : f32)
2003b45fe2eSMarkus Böck
2013b45fe2eSMarkus Böck^bb2(%arg4 : f32):
2023b45fe2eSMarkus Böck  call @bar(%arg4) : (f32) -> ()
2033b45fe2eSMarkus Böck  cf.br ^bb3
2043b45fe2eSMarkus Böck
2053b45fe2eSMarkus Böck^bb3:
2063b45fe2eSMarkus Böck  return
2073b45fe2eSMarkus Böck}
2083b45fe2eSMarkus Böck
2093b45fe2eSMarkus Böck// CHECK-LABEL: func @switch_with_fallthrough
2103b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG0:[[:alnum:]]+]]
2113b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG1:[[:alnum:]]+]]
2123b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG2:[[:alnum:]]+]]
2133b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
2143b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
2153b45fe2eSMarkus Böck// CHECK-DAG: %[[POISON:.*]] = ub.poison
2163b45fe2eSMarkus Böck// CHECK-NEXT: %[[INDEX_CAST:.*]] = arith.index_castui %[[ARG0]]
2173b45fe2eSMarkus Böck// CHECK-NEXT: %[[SWITCH_PAIR:.*]]:2 = scf.index_switch %[[INDEX_CAST]]
2183b45fe2eSMarkus Böck// CHECK-NEXT: case 0
2193b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[ARG2]], %[[C0]]
2203b45fe2eSMarkus Böck// CHECK:      case 1
2213b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[POISON]], %[[C1]]
2223b45fe2eSMarkus Böck// CHECK:      default
2233b45fe2eSMarkus Böck// CHECK-NEXT:   %[[RES:.*]] = func.call @foo(%[[ARG1]])
2243b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[RES]], %[[C0]]
2253b45fe2eSMarkus Böck// CHECK:      %[[INDEX_CAST:.*]] = arith.index_castui %[[SWITCH_PAIR]]#1
2263b45fe2eSMarkus Böck// CHECK-NEXT: scf.index_switch %[[INDEX_CAST]]
2273b45fe2eSMarkus Böck// CHECK-NEXT: case 0
2283b45fe2eSMarkus Böck// CHECK-NEXT:   call @bar(%[[SWITCH_PAIR]]#0)
2293b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield
2303b45fe2eSMarkus Böck// CHECK:      default {
2313b45fe2eSMarkus Böck// CHECK-NEXT: }
2323b45fe2eSMarkus Böck// CHECK-NEXT: return
2333b45fe2eSMarkus Böck
2343b45fe2eSMarkus Böck// -----
2353b45fe2eSMarkus Böck
2363b45fe2eSMarkus Böckfunc.func private @bar(%arg: f32) -> (i1, f32)
2373b45fe2eSMarkus Böck
2383b45fe2eSMarkus Böckfunc.func @already_structured_loop(%arg: f32) -> f32 {
2393b45fe2eSMarkus Böck  cf.br ^bb0
2403b45fe2eSMarkus Böck
2413b45fe2eSMarkus Böck^bb0:
2423b45fe2eSMarkus Böck  %cond, %value = call @bar(%arg) : (f32) -> (i1, f32)
2433b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb1, ^bb0
2443b45fe2eSMarkus Böck
2453b45fe2eSMarkus Böck^bb1:
2463b45fe2eSMarkus Böck  return %value : f32
2473b45fe2eSMarkus Böck}
2483b45fe2eSMarkus Böck
2493b45fe2eSMarkus Böck// CHECK-LABEL: @already_structured_loop
2503b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG:.*]]: f32
2513b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
2523b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
2533b45fe2eSMarkus Böck// CHECK-DAG: %[[POISON:.*]] = ub.poison
2543b45fe2eSMarkus Böck// CHECK-NEXT: %[[RES:.*]] = scf.while (%[[ARG1:.*]] = %[[POISON]])
2553b45fe2eSMarkus Böck// CHECK-NEXT:   %[[CALL_PAIR:.*]]:2 = func.call @bar(%[[ARG]])
2563b45fe2eSMarkus Böck// CHECK-NEXT:   %[[IF_PAIR:.*]]:2 = scf.if %[[CALL_PAIR]]#0
2573b45fe2eSMarkus Böck// CHECK-NEXT:     scf.yield %[[C1]], %[[C0]]
2583b45fe2eSMarkus Böck// CHECK-NEXT:   else
2593b45fe2eSMarkus Böck// CHECK-NEXT:     scf.yield %[[C0]], %[[C1]]
2603b45fe2eSMarkus Böck// CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_PAIR]]#1
2613b45fe2eSMarkus Böck// CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[CALL_PAIR]]#1
2623b45fe2eSMarkus Böck// CHECK: return %[[RES]]
2633b45fe2eSMarkus Böck
2643b45fe2eSMarkus Böck// -----
2653b45fe2eSMarkus Böck
2663b45fe2eSMarkus Böckfunc.func private @bar(%arg: f32) -> (i1, f32)
2673b45fe2eSMarkus Böck
2683b45fe2eSMarkus Böck// This test makes sure that the exit block using an iteration variable works
2693b45fe2eSMarkus Böck// correctly.
2703b45fe2eSMarkus Böck
2713b45fe2eSMarkus Böckfunc.func @exit_loop_iter_use(%arg: f32) -> f32 {
2723b45fe2eSMarkus Böck  cf.br ^bb0(%arg : f32)
2733b45fe2eSMarkus Böck
2743b45fe2eSMarkus Böck^bb0(%arg1: f32):
2753b45fe2eSMarkus Böck  %cond, %value = call @bar(%arg1) : (f32) -> (i1, f32)
2763b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb1, ^bb0(%value : f32)
2773b45fe2eSMarkus Böck
2783b45fe2eSMarkus Böck^bb1:
2793b45fe2eSMarkus Böck  return %arg1 : f32
2803b45fe2eSMarkus Böck}
2813b45fe2eSMarkus Böck
2823b45fe2eSMarkus Böck// CHECK-LABEL: @exit_loop_iter_use
2833b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG:.*]]:
2843b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
2853b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
2863b45fe2eSMarkus Böck// CHECK-DAG: %[[POISON:.*]] = ub.poison
2873b45fe2eSMarkus Böck// CHECK-NEXT: %[[RES:.*]]:2 = scf.while
2883b45fe2eSMarkus Böck// CHECK-SAME:   %[[ARG1:.*]] = %[[ARG]]
2893b45fe2eSMarkus Böck// CHECK-SAME:   %[[ARG2:.*]] = %[[POISON]]
2903b45fe2eSMarkus Böck// CHECK-NEXT:   %[[CALL_PAIR:.*]]:2 = func.call @bar(%[[ARG1]])
2913b45fe2eSMarkus Böck// CHECK-NEXT:   %[[IF_RES:.*]]:3 = scf.if %[[CALL_PAIR]]#0
2923b45fe2eSMarkus Böck// CHECK-NEXT:     scf.yield %[[POISON]], %[[C1]], %[[C0]]
2933b45fe2eSMarkus Böck// CHECK-NEXT:   else
2943b45fe2eSMarkus Böck// CHECK-NEXT:     scf.yield %[[CALL_PAIR]]#1, %[[C0]], %[[C1]]
2953b45fe2eSMarkus Böck// CHECK:        %[[TRUNC:.*]] = arith.trunci %[[IF_RES]]#2
2963b45fe2eSMarkus Böck// CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[IF_RES]]#0, %[[ARG1]]
2973b45fe2eSMarkus Böck// CHECK: return %[[RES]]#1
2983b45fe2eSMarkus Böck
2993b45fe2eSMarkus Böck// -----
3003b45fe2eSMarkus Böck
3013b45fe2eSMarkus Böckfunc.func private @bar(%arg: f32) -> f32
3023b45fe2eSMarkus Böck
3033b45fe2eSMarkus Böckfunc.func @infinite_loop(%arg: f32) -> f32 {
3043b45fe2eSMarkus Böck  cf.br ^bb1(%arg: f32)
3053b45fe2eSMarkus Böck
3063b45fe2eSMarkus Böck^bb1(%arg1: f32):
3073b45fe2eSMarkus Böck  %0 = call @bar(%arg1) : (f32) -> f32
3083b45fe2eSMarkus Böck  cf.br ^bb1(%0 : f32)
3093b45fe2eSMarkus Böck}
3103b45fe2eSMarkus Böck
3113b45fe2eSMarkus Böck// CHECK-LABEL: @infinite_loop
3123b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG:.*]]:
3133b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
3143b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
3153b45fe2eSMarkus Böck// CHECK-NEXT: scf.while
3163b45fe2eSMarkus Böck// CHECK-SAME:   %[[ARG1:.*]] = %[[ARG]]
3173b45fe2eSMarkus Böck// CHECK-NEXT:   %[[CALL:.*]] = func.call @bar(%[[ARG1]])
3183b45fe2eSMarkus Böck// CHECK-NEXT:   %[[TRUNC:.*]] = arith.trunci %[[C1]]
3193b45fe2eSMarkus Böck// CHECK-NEXT:   scf.condition(%[[TRUNC]]) %[[CALL]]
3203b45fe2eSMarkus Böck// CHECK: %[[POISON:.*]] = ub.poison
3213b45fe2eSMarkus Böck// CHECK: return %[[POISON]]
3223b45fe2eSMarkus Böck
3233b45fe2eSMarkus Böck// -----
3243b45fe2eSMarkus Böck
3253b45fe2eSMarkus Böckfunc.func @multi_return() -> i32 {
3263b45fe2eSMarkus Böck  %cond = "test.test1"() : () -> i1
3273b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb1, ^bb3
3283b45fe2eSMarkus Böck^bb1:
3293b45fe2eSMarkus Böck  %0 = "test.test2"() : () -> i32
3303b45fe2eSMarkus Böck  return %0 : i32
3313b45fe2eSMarkus Böck^bb3:
3323b45fe2eSMarkus Böck  %1 = "test.test4"() : () -> i32
3333b45fe2eSMarkus Böck  return %1 : i32
3343b45fe2eSMarkus Böck}
3353b45fe2eSMarkus Böck
3363b45fe2eSMarkus Böck// CHECK-LABEL: func @multi_return
3373b45fe2eSMarkus Böck// CHECK:      %[[COND:.*]] = "test.test1"()
3383b45fe2eSMarkus Böck// CHECK-NEXT: %[[RES:.*]] = scf.if %[[COND]]
3393b45fe2eSMarkus Böck// CHECK-NEXT:   %[[VAL2:.*]] = "test.test2"()
3403b45fe2eSMarkus Böck// CHECK:        scf.yield %[[VAL2]]
3413b45fe2eSMarkus Böck// CHECK-NEXT: else
3423b45fe2eSMarkus Böck// CHECK-NEXT:   %[[VAL4:.*]] = "test.test4"()
3433b45fe2eSMarkus Böck// CHECK:        scf.yield %[[VAL4]]
3443b45fe2eSMarkus Böck// CHECK:      return %[[RES]]
3453b45fe2eSMarkus Böck
3463b45fe2eSMarkus Böck// -----
3473b45fe2eSMarkus Böck
3483b45fe2eSMarkus Böckfunc.func private @bar(%arg: f32) -> f32
3493b45fe2eSMarkus Böck
3503b45fe2eSMarkus Böckfunc.func @conditional_infinite_loop(%arg: f32, %cond: i1) -> f32 {
3513b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb1(%arg: f32), ^bb2
3523b45fe2eSMarkus Böck
3533b45fe2eSMarkus Böck^bb1(%arg1: f32):
3543b45fe2eSMarkus Böck  %0 = call @bar(%arg1) : (f32) -> f32
3553b45fe2eSMarkus Böck  cf.br ^bb1(%0 : f32)
3563b45fe2eSMarkus Böck
3573b45fe2eSMarkus Böck^bb2:
3583b45fe2eSMarkus Böck  return %arg : f32
3593b45fe2eSMarkus Böck}
3603b45fe2eSMarkus Böck
3613b45fe2eSMarkus Böck// CHECK-LABEL: @conditional_infinite_loop
3623b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG0:[[:alnum:]]+]]:
3633b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG1:[[:alnum:]]+]]:
3643b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
3653b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
3663b45fe2eSMarkus Böck// CHECK-NEXT: %[[RES:.*]] = scf.if %[[ARG1]]
3673b45fe2eSMarkus Böck// CHECK-NEXT:   scf.while
3683b45fe2eSMarkus Böck// CHECK-SAME:     %[[ARG2:.*]] = %[[ARG0]]
3693b45fe2eSMarkus Böck// CHECK-NEXT:     %[[CALL:.*]] = func.call @bar(%[[ARG2]])
3703b45fe2eSMarkus Böck// CHECK-NEXT:     %[[TRUNC:.*]] = arith.trunci %[[C1]]
3713b45fe2eSMarkus Böck// CHECK-NEXT:     scf.condition(%[[TRUNC]]) %[[CALL]]
3723b45fe2eSMarkus Böck// CHECK:      else
3733b45fe2eSMarkus Böck// CHECK:        scf.yield %[[ARG0]]
3743b45fe2eSMarkus Böck// CHECK:      return %[[RES]]
3753b45fe2eSMarkus Böck
3763b45fe2eSMarkus Böck// -----
3773b45fe2eSMarkus Böck
3783b45fe2eSMarkus Böck// Different return-like terminators lead one control flow op remaining in the top level region.
3793b45fe2eSMarkus Böck// Each of the blocks the control flow op leads to are transformed into regions nevertheless.
3803b45fe2eSMarkus Böck
3813b45fe2eSMarkus Böckfunc.func private @bar(%arg: i32)
3823b45fe2eSMarkus Böck
3833b45fe2eSMarkus Böckfunc.func @mixing_return_like(%cond: i1, %cond2: i1, %cond3: i1) {
3843b45fe2eSMarkus Böck  %0 = arith.constant 0 : i32
3853b45fe2eSMarkus Böck  %1 = arith.constant 1 : i32
3863b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb1, ^bb3
3873b45fe2eSMarkus Böck
3883b45fe2eSMarkus Böck^bb1:
3893b45fe2eSMarkus Böck  cf.cond_br %cond2, ^bb2(%0 : i32), ^bb2(%1 : i32)
3903b45fe2eSMarkus Böck^bb2(%arg: i32):
3913b45fe2eSMarkus Böck  call @bar(%arg) : (i32) -> ()
3923b45fe2eSMarkus Böck  "test.returnLike"() : () -> ()
3933b45fe2eSMarkus Böck
3943b45fe2eSMarkus Böck^bb3:
3953b45fe2eSMarkus Böck  cf.cond_br %cond3, ^bb4(%1 : i32), ^bb4(%0 : i32)
3963b45fe2eSMarkus Böck^bb4(%arg2: i32):
3973b45fe2eSMarkus Böck  call @bar(%arg2) : (i32) -> ()
3983b45fe2eSMarkus Böck  return
3993b45fe2eSMarkus Böck}
4003b45fe2eSMarkus Böck
4013b45fe2eSMarkus Böck// CHECK-LABEL: @mixing_return_like
4023b45fe2eSMarkus Böck// CHECK-SAME: %[[COND1:[[:alnum:]]+]]:
4033b45fe2eSMarkus Böck// CHECK-SAME: %[[COND2:[[:alnum:]]+]]:
4043b45fe2eSMarkus Böck// CHECK-SAME: %[[COND3:[[:alnum:]]+]]:
4053b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
4063b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
4073b45fe2eSMarkus Böck// CHECK: cf.cond_br %[[COND1]], ^[[BB1:.*]], ^[[BB2:[[:alnum:]]+]]
4083b45fe2eSMarkus Böck
4093b45fe2eSMarkus Böck// CHECK: ^[[BB1]]:
4103b45fe2eSMarkus Böck// CHECK: scf.if
4113b45fe2eSMarkus Böck// CHECK-NOT: cf.{{(switch|(cond_)?br)}}
4123b45fe2eSMarkus Böck// CHECK: call @bar
4133b45fe2eSMarkus Böck// CHECK: "test.returnLike"
4143b45fe2eSMarkus Böck
4153b45fe2eSMarkus Böck// CHECK: ^[[BB2]]:
4163b45fe2eSMarkus Böck// CHECK: scf.if
4173b45fe2eSMarkus Böck// CHECK-NOT: cf.{{(switch|(cond_)?br)}}
4183b45fe2eSMarkus Böck// CHECK: call @bar
4193b45fe2eSMarkus Böck// CHECK: return
4203b45fe2eSMarkus Böck
4213b45fe2eSMarkus Böck// -----
4223b45fe2eSMarkus Böck
4233b45fe2eSMarkus Böck// cf.switch here only has some successors with different return-like ops.
4243b45fe2eSMarkus Böck// This test makes sure that if there are at least two successors branching to
4253b45fe2eSMarkus Böck// the same region, that this region gets properly turned to structured control
4263b45fe2eSMarkus Böck// flow.
4273b45fe2eSMarkus Böck
4283b45fe2eSMarkus Böckfunc.func @some_successors_with_different_return(%flag: i32) -> i32 {
4293b45fe2eSMarkus Böck  %0 = arith.constant 5 : i32
4303b45fe2eSMarkus Böck  %1 = arith.constant 6 : i32
4313b45fe2eSMarkus Böck  cf.switch %flag : i32, [
4323b45fe2eSMarkus Böck    default: ^bb1,
4333b45fe2eSMarkus Böck    0: ^bb3(%0 : i32),
4343b45fe2eSMarkus Böck    1: ^bb3(%1 : i32)
4353b45fe2eSMarkus Böck  ]
4363b45fe2eSMarkus Böck
4373b45fe2eSMarkus Böck^bb1:
4383b45fe2eSMarkus Böck  "test.returnLike"() : () -> ()
4393b45fe2eSMarkus Böck
4403b45fe2eSMarkus Böck^bb3(%arg: i32):
4413b45fe2eSMarkus Böck  cf.br ^bb3(%arg : i32)
4423b45fe2eSMarkus Böck}
4433b45fe2eSMarkus Böck
4443b45fe2eSMarkus Böck// CHECK-LABEL: @some_successors_with_different_return
4453b45fe2eSMarkus Böck// CHECK-SAME: %[[FLAG:[[:alnum:]]+]]:
4463b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0 : i32
4473b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1 : i32
4483b45fe2eSMarkus Böck// CHECK-DAG: %[[POISON:.*]] = ub.poison
4493b45fe2eSMarkus Böck// CHECK-DAG: %[[C5:.*]] = arith.constant 5 : i32
4503b45fe2eSMarkus Böck// CHECK-DAG: %[[C6:.*]] = arith.constant 6 : i32
4513b45fe2eSMarkus Böck// CHECK:      %[[INDEX_CAST:.*]] = arith.index_castui %[[FLAG]]
4523b45fe2eSMarkus Böck// CHECK-NEXT: %[[INDEX_SWITCH:.*]]:2 = scf.index_switch %[[INDEX_CAST]]
4533b45fe2eSMarkus Böck// CHECK:      case 0
4543b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[C5]], %[[C1]]
4553b45fe2eSMarkus Böck// CHECK:      case 1
4563b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[C6]], %[[C1]]
4573b45fe2eSMarkus Böck// CHECK:      default
4583b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[POISON]], %[[C0]]
4593b45fe2eSMarkus Böck// CHECK:      cf.switch %[[INDEX_SWITCH]]#1
4603b45fe2eSMarkus Böck// CHECK-NEXT: default: ^[[BB2:[[:alnum:]]+]]
4613b45fe2eSMarkus Böck// CHECK-SAME: %[[INDEX_SWITCH]]#0
4623b45fe2eSMarkus Böck// CHECK-NEXT: 0: ^[[BB1:[[:alnum:]]+]]
4633b45fe2eSMarkus Böck// CHECK-NEXT: ]
4643b45fe2eSMarkus Böck
4653b45fe2eSMarkus Böck// CHECK: ^[[BB2]]{{.*}}:
4663b45fe2eSMarkus Böck// CHECK: scf.while
4673b45fe2eSMarkus Böck// CHECK-NOT: cf.{{(switch|(cond_)?br)}}
4683b45fe2eSMarkus Böck// CHECK: return
4693b45fe2eSMarkus Böck
4703b45fe2eSMarkus Böck// CHECK: ^[[BB1]]:
4713b45fe2eSMarkus Böck// CHECK-NEXT: "test.returnLike"
4723b45fe2eSMarkus Böck
4733b45fe2eSMarkus Böck// -----
4743b45fe2eSMarkus Böck
4753b45fe2eSMarkus Böckfunc.func @select_like(%cond: i1) -> i32 {
4763b45fe2eSMarkus Böck  %0 = arith.constant 0 : i32
4773b45fe2eSMarkus Böck  %1 = arith.constant 1 : i32
4783b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb0(%0 : i32), ^bb0(%1 : i32)
4793b45fe2eSMarkus Böck^bb0(%arg: i32):
4803b45fe2eSMarkus Böck  return %arg : i32
4813b45fe2eSMarkus Böck}
4823b45fe2eSMarkus Böck
4833b45fe2eSMarkus Böck// CHECK-LABEL: func @select_like
4843b45fe2eSMarkus Böck// CHECK-SAME: %[[COND:.*]]: i1
4853b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
4863b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
4873b45fe2eSMarkus Böck// CHECK-NEXT: %[[RES:.*]] = scf.if %[[COND]]
4883b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[C0]]
4893b45fe2eSMarkus Böck// CHECK-NEXT: else
4903b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[C1]]
4913b45fe2eSMarkus Böck// CHECK:      return %[[RES]]
4923b45fe2eSMarkus Böck
4933b45fe2eSMarkus Böck// -----
4943b45fe2eSMarkus Böck
4953b45fe2eSMarkus Böckfunc.func @return_like_dominated_by_condition(%cond1: i1, %cond2: i1, %cond3: i1) {
4963b45fe2eSMarkus Böck  cf.cond_br %cond1, ^bb1, ^bb2
4973b45fe2eSMarkus Böck
4983b45fe2eSMarkus Böck^bb1:
4993b45fe2eSMarkus Böck  return
5003b45fe2eSMarkus Böck
5013b45fe2eSMarkus Böck^bb2:
5023b45fe2eSMarkus Böck  cf.cond_br %cond2, ^bb3, ^bb4
5033b45fe2eSMarkus Böck
5043b45fe2eSMarkus Böck^bb3:
5053b45fe2eSMarkus Böck  "test.unreachable"() : () -> ()
5063b45fe2eSMarkus Böck
5073b45fe2eSMarkus Böck^bb4:
5083b45fe2eSMarkus Böck  cf.cond_br %cond3, ^bb3, ^bb5
5093b45fe2eSMarkus Böck
5103b45fe2eSMarkus Böck^bb5:
5113b45fe2eSMarkus Böck  return
5123b45fe2eSMarkus Böck}
5133b45fe2eSMarkus Böck
5143b45fe2eSMarkus Böck// CHECK-LABEL: func @return_like_dominated_by_condition
5153b45fe2eSMarkus Böck// CHECK-SAME: %[[COND1:[[:alnum:]]+]]
5163b45fe2eSMarkus Böck// CHECK-SAME: %[[COND2:[[:alnum:]]+]]
5173b45fe2eSMarkus Böck// CHECK-SAME: %[[COND3:[[:alnum:]]+]]
5183b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
5193b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
5203b45fe2eSMarkus Böck// CHECK: %[[IF:.*]] = scf.if %[[COND1]]
5213b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield
5223b45fe2eSMarkus Böck// CHECK: else
5233b45fe2eSMarkus Böck// CHECK:   scf.if %[[COND2]]
5243b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield
5253b45fe2eSMarkus Böck// CHECK:   else
5263b45fe2eSMarkus Böck// CHECK:      scf.if %[[COND3]]
5273b45fe2eSMarkus Böck// CHECK-NEXT:    scf.yield
5283b45fe2eSMarkus Böck// CHECK-NEXT: else
5293b45fe2eSMarkus Böck// CHECK-NEXT:    scf.yield
5303b45fe2eSMarkus Böck
5313b45fe2eSMarkus Böck// CHECK: cf.switch %[[IF]]
5323b45fe2eSMarkus Böck// CHECK-NEXT: default: ^[[BB1:.*]],
5333b45fe2eSMarkus Böck// CHECK-NEXT: 0: ^[[BB2:[[:alnum:]]+]]
5343b45fe2eSMarkus Böck
5353b45fe2eSMarkus Böck// CHECK: ^[[BB2]]:
5363b45fe2eSMarkus Böck// CHECK-NEXT: return
5373b45fe2eSMarkus Böck
5383b45fe2eSMarkus Böck// CHECK: ^[[BB1]]:
5393b45fe2eSMarkus Böck// CHECK-NEXT: "test.unreachable"
5403b45fe2eSMarkus Böck
5413b45fe2eSMarkus Böck// -----
5423b45fe2eSMarkus Böck
5433b45fe2eSMarkus Böckfunc.func @dominator_issue(%cond: i1, %cond2: i1) -> i32 {
5443b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb1, ^bb2
5453b45fe2eSMarkus Böck
5463b45fe2eSMarkus Böck^bb1:
5473b45fe2eSMarkus Böck  "test.unreachable"() : () -> ()
5483b45fe2eSMarkus Böck
5493b45fe2eSMarkus Böck^bb2:
5503b45fe2eSMarkus Böck  %value = "test.def"() : () -> i32
5513b45fe2eSMarkus Böck  cf.cond_br %cond2, ^bb1, ^bb4
5523b45fe2eSMarkus Böck
5533b45fe2eSMarkus Böck^bb4:
5543b45fe2eSMarkus Böck  return %value : i32
5553b45fe2eSMarkus Böck}
5563b45fe2eSMarkus Böck
5573b45fe2eSMarkus Böck// CHECK-LABEL: func @dominator_issue
5583b45fe2eSMarkus Böck// CHECK-SAME: %[[COND1:[[:alnum:]]+]]
5593b45fe2eSMarkus Böck// CHECK-SAME: %[[COND2:[[:alnum:]]+]]
5603b45fe2eSMarkus Böck// CHECK: %[[IF:.*]]:2 = scf.if %[[COND1]]
5613b45fe2eSMarkus Böck// CHECK: else
5623b45fe2eSMarkus Böck// CHECK:   %[[VALUE:.*]] = "test.def"
5633b45fe2eSMarkus Böck// CHECK:   %[[IF_RES:.*]]:2 = scf.if %[[COND2]]
5643b45fe2eSMarkus Böck// CHECK:   else
5653b45fe2eSMarkus Böck// CHECK-NEXT: scf.yield %[[VALUE]]
5663b45fe2eSMarkus Böck// CHECK:   scf.yield %[[IF_RES]]#0
5673b45fe2eSMarkus Böck// CHECK: cf.switch %[[IF]]#1
5683b45fe2eSMarkus Böck// CHECK-NEXT: default: ^[[BB2:[[:alnum:]]+]](
5693b45fe2eSMarkus Böck// CHECK-SAME: %[[IF]]#0
5703b45fe2eSMarkus Böck// CHECK-NEXT: 0: ^[[BB1:[[:alnum:]]+]]
5713b45fe2eSMarkus Böck// CHECK: ^[[BB1]]:
5723b45fe2eSMarkus Böck// CHECK-NEXT: "test.unreachable"
5733b45fe2eSMarkus Böck// CHECK: ^[[BB2]]
5743b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG:[[:alnum:]]+]]
5753b45fe2eSMarkus Böck// CHECK-NEXT: return %[[ARG]]
5763b45fe2eSMarkus Böck
5773b45fe2eSMarkus Böck// -----
5783b45fe2eSMarkus Böck
5793b45fe2eSMarkus Böck// Test that %value gets properly passed to ^bb4.
5803b45fe2eSMarkus Böck
5813b45fe2eSMarkus Böckfunc.func private @bar(i32)
5823b45fe2eSMarkus Böck
5833b45fe2eSMarkus Böckfunc.func @dominator_issue_loop(%cond: i1, %cond2: i1) -> i32 {
5843b45fe2eSMarkus Böck  %0 = arith.constant 5 : i32
5853b45fe2eSMarkus Böck  cf.br ^bb0
5863b45fe2eSMarkus Böck
5873b45fe2eSMarkus Böck^bb0:
5883b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb1, ^bb3
5893b45fe2eSMarkus Böck
5903b45fe2eSMarkus Böck^bb1:
5913b45fe2eSMarkus Böck  %value = "test.def"() : () -> i32
5923b45fe2eSMarkus Böck  cf.cond_br %cond2, ^bb0, ^bb4
5933b45fe2eSMarkus Böck
5943b45fe2eSMarkus Böck^bb3:
5953b45fe2eSMarkus Böck  return %0 : i32
5963b45fe2eSMarkus Böck
5973b45fe2eSMarkus Böck^bb4:
5983b45fe2eSMarkus Böck  return %value : i32
5993b45fe2eSMarkus Böck}
6003b45fe2eSMarkus Böck
6013b45fe2eSMarkus Böck// CHECK-LABEL: func @dominator_issue_loop
6023b45fe2eSMarkus Böck// CHECK-SAME: %[[COND1:[[:alnum:]]+]]
6033b45fe2eSMarkus Böck// CHECK-SAME: %[[COND2:[[:alnum:]]+]]
6043b45fe2eSMarkus Böck// CHECK: %[[WHILE:.*]]:2 = scf.while
6053b45fe2eSMarkus Böck// CHECK:   %[[IF:.*]]:3 = scf.if %[[COND1]]
6063b45fe2eSMarkus Böck// CHECK:     %[[DEF:.*]] = "test.def"
6073b45fe2eSMarkus Böck// CHECK:     %[[IF2:.*]]:3 = scf.if %[[COND2]]
6083b45fe2eSMarkus Böck// CHECK:       scf.yield
6093b45fe2eSMarkus Böck// CHECK-SAME:   %[[DEF]]
6103b45fe2eSMarkus Böck// CHECK:     else
6113b45fe2eSMarkus Böck// CHECK:       scf.yield %{{.*}}, %{{.*}}, %[[DEF]]
6123b45fe2eSMarkus Böck// CHECK:     scf.yield %[[IF2]]#0, %[[IF2]]#1, %[[IF2]]#2
6133b45fe2eSMarkus Böck// CHECK:   scf.condition(%{{.*}}) %[[IF]]#2, %[[IF]]#0
6143b45fe2eSMarkus Böck
6153b45fe2eSMarkus Böck// CHECK: %[[SWITCH:.*]] = scf.index_switch
6163b45fe2eSMarkus Böck// CHECK:   scf.yield %[[WHILE]]#0
6173b45fe2eSMarkus Böck// CHECK: return %[[SWITCH]]
6183b45fe2eSMarkus Böck
6193b45fe2eSMarkus Böck// -----
6203b45fe2eSMarkus Böck
6213b45fe2eSMarkus Böck// Multi entry loops generally produce code in dire need of canonicalization.
6223b45fe2eSMarkus Böck
6233b45fe2eSMarkus Böckfunc.func private @comp1(%arg: i32) -> i1
6243b45fe2eSMarkus Böckfunc.func private @comp2(%arg: i32) -> i1
6253b45fe2eSMarkus Böckfunc.func private @foo(%arg: i32)
6263b45fe2eSMarkus Böck
6273b45fe2eSMarkus Böckfunc.func @multi_entry_loop(%cond: i1) {
6283b45fe2eSMarkus Böck  %0 = arith.constant 6 : i32
6293b45fe2eSMarkus Böck  %1 = arith.constant 5 : i32
6303b45fe2eSMarkus Böck  cf.cond_br %cond, ^bb0, ^bb1
6313b45fe2eSMarkus Böck
6323b45fe2eSMarkus Böck^bb0:
6333b45fe2eSMarkus Böck  %exit = call @comp1(%0) : (i32) -> i1
6343b45fe2eSMarkus Böck  cf.cond_br %exit, ^bb2(%0 : i32), ^bb1
6353b45fe2eSMarkus Böck
6363b45fe2eSMarkus Böck^bb1:
6373b45fe2eSMarkus Böck  %exit2 = call @comp2(%1) : (i32) -> i1
6383b45fe2eSMarkus Böck  cf.cond_br %exit2, ^bb2(%1 : i32), ^bb0
6393b45fe2eSMarkus Böck
6403b45fe2eSMarkus Böck^bb2(%arg3 : i32):
6413b45fe2eSMarkus Böck  call @foo(%arg3) : (i32) -> ()
6423b45fe2eSMarkus Böck  return
6433b45fe2eSMarkus Böck}
6443b45fe2eSMarkus Böck
6453b45fe2eSMarkus Böck// CHECK-LABEL: func @multi_entry_loop
6463b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG0:[[:alnum:]]+]]
6473b45fe2eSMarkus Böck// CHECK-DAG: %[[C0:.*]] = arith.constant 0
6483b45fe2eSMarkus Böck// CHECK-DAG: %[[UB:.*]] = ub.poison
6493b45fe2eSMarkus Böck// CHECK-DAG: %[[C1:.*]] = arith.constant 1
6503b45fe2eSMarkus Böck// CHECK-DAG: %[[C6:.*]] = arith.constant 6
6513b45fe2eSMarkus Böck// CHECK-DAG: %[[C5:.*]] = arith.constant 5
6523b45fe2eSMarkus Böck// CHECK:      %[[IF:.*]]:{{.*}} = scf.if %[[ARG0]]
6533b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[C1]], %[[UB]]
6543b45fe2eSMarkus Böck// CHECK-NEXT: else
6553b45fe2eSMarkus Böck// CHECK-NEXT:   scf.yield %[[C0]], %[[UB]]
6563b45fe2eSMarkus Böck// CHECK:      %[[WHILE:.*]]:{{.*}} = scf.while
6573b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG1:.*]] = %[[IF]]#0
6583b45fe2eSMarkus Böck// CHECK-SAME: %[[ARG2:.*]] = %[[IF]]#1
6593b45fe2eSMarkus Böck// CHECK-NEXT:   %[[FLAG:.*]] = arith.index_castui %[[ARG1]]
6603b45fe2eSMarkus Böck// CHECK-NEXT:   %[[SWITCH:.*]]:{{.*}} = scf.index_switch %[[FLAG]]
6613b45fe2eSMarkus Böck// CHECK-NEXT:   case 0
6623b45fe2eSMarkus Böck// CHECK-NEXT:     %[[EXIT:.*]] = func.call @comp2(%[[C5]])
6633b45fe2eSMarkus Böck// CHECK-NEXT:     %[[IF_RES:.*]]:{{.*}} = scf.if %[[EXIT]]
6643b45fe2eSMarkus Böck// CHECK-NEXT:       scf.yield %[[UB]], %[[C5]], %[[C1]], %[[C0]]
6653b45fe2eSMarkus Böck// CHECK-NEXT:     else
6663b45fe2eSMarkus Böck// CHECK-NEXT:       scf.yield %[[C1]], %[[UB]], %[[C0]], %[[C1]]
6673b45fe2eSMarkus Böck// CHECK:          scf.yield %[[IF_RES]]#0, %[[IF_RES]]#1, %[[IF_RES]]#2, %[[IF_RES]]#3
6683b45fe2eSMarkus Böck// CHECK:        default
6693b45fe2eSMarkus Böck// CHECK-NEXT:     %[[EXIT:.*]] = func.call @comp1(%[[C6]])
6703b45fe2eSMarkus Böck// CHECK-NEXT:     %[[IF_RES:.*]]:{{.*}} = scf.if %[[EXIT]]
6713b45fe2eSMarkus Böck// CHECK-NEXT:       scf.yield %[[UB]], %[[C6]], %[[C1]], %[[C0]]
6723b45fe2eSMarkus Böck// CHECK-NEXT:     else
6733b45fe2eSMarkus Böck// CHECK-NEXT:       scf.yield %[[C0]], %[[UB]], %[[C0]], %[[C1]]
6743b45fe2eSMarkus Böck// CHECK:          scf.yield %[[IF_RES]]#0, %[[IF_RES]]#1, %[[IF_RES]]#2, %[[IF_RES]]#3
6753b45fe2eSMarkus Böck// CHECK:        %[[COND:.*]] = arith.trunci %[[SWITCH]]#3
6763b45fe2eSMarkus Böck// CHECK-NEXT:   scf.condition(%[[COND]]) %[[SWITCH]]#0, %[[SWITCH]]#1
6773b45fe2eSMarkus Böck// CHECK:      do
6783b45fe2eSMarkus Böck// CHECK:        scf.yield
6793b45fe2eSMarkus Böck// CHECK:      call @foo(%[[WHILE]]#1)
6803b45fe2eSMarkus Böck// CHECK-NEXT: return
6810db1ae3eSIvan Butygin
6820db1ae3eSIvan Butygin// -----
6830db1ae3eSIvan Butygin
6840db1ae3eSIvan Butyginfunc.func @nested_region() {
6850db1ae3eSIvan Butygin  scf.execute_region {
6860db1ae3eSIvan Butygin    %cond = "test.test1"() : () -> i1
6870db1ae3eSIvan Butygin    cf.cond_br %cond, ^bb1, ^bb2
6880db1ae3eSIvan Butygin  ^bb1:
6890db1ae3eSIvan Butygin    "test.test2"() : () -> ()
6900db1ae3eSIvan Butygin    cf.br ^bb3
6910db1ae3eSIvan Butygin  ^bb2:
6920db1ae3eSIvan Butygin    "test.test3"() : () -> ()
6930db1ae3eSIvan Butygin    cf.br ^bb3
6940db1ae3eSIvan Butygin  ^bb3:
6950db1ae3eSIvan Butygin    "test.test4"() : () -> ()
6960db1ae3eSIvan Butygin    scf.yield
6970db1ae3eSIvan Butygin  }
6980db1ae3eSIvan Butygin  return
6990db1ae3eSIvan Butygin}
7000db1ae3eSIvan Butygin
7010db1ae3eSIvan Butygin// CHECK-LABEL: func @nested_region
7020db1ae3eSIvan Butygin// CHECK:      scf.execute_region {
7030db1ae3eSIvan Butygin// CHECK:      %[[COND:.*]] = "test.test1"()
7040db1ae3eSIvan Butygin// CHECK-NEXT: scf.if %[[COND]]
7050db1ae3eSIvan Butygin// CHECK-NEXT:   "test.test2"()
7060db1ae3eSIvan Butygin// CHECK-NEXT: else
7070db1ae3eSIvan Butygin// CHECK-NEXT:   "test.test3"()
7080db1ae3eSIvan Butygin// CHECK-NEXT: }
7090db1ae3eSIvan Butygin// CHECK-NEXT: "test.test4"()
7100db1ae3eSIvan Butygin// CHECK-NEXT: scf.yield
7110db1ae3eSIvan Butygin// CHECK-NEXT: }
7120db1ae3eSIvan Butygin// CHECK-NEXT: return
713*30fe8762SMarkus Böck
714*30fe8762SMarkus Böck// -----
715*30fe8762SMarkus Böck
716*30fe8762SMarkus Böckfunc.func @nested_region_inside_loop_use() {
717*30fe8762SMarkus Böck  cf.br ^bb1
718*30fe8762SMarkus Böck
719*30fe8762SMarkus Böck^bb1:
720*30fe8762SMarkus Böck  %3 = "test.test1"() : () -> i32
721*30fe8762SMarkus Böck  scf.execute_region {
722*30fe8762SMarkus Böck    "test.foo"(%3) : (i32) -> ()
723*30fe8762SMarkus Böck    scf.yield
724*30fe8762SMarkus Böck  }
725*30fe8762SMarkus Böck  cf.br ^bb1
726*30fe8762SMarkus Böck}
727*30fe8762SMarkus Böck
728*30fe8762SMarkus Böck// CHECK-LABEL: func @nested_region_inside_loop_use
729*30fe8762SMarkus Böck// CHECK: scf.while
730*30fe8762SMarkus Böck// CHECK-NEXT: %[[DEF:.*]] = "test.test1"()
731*30fe8762SMarkus Böck// CHECK-NEXT: scf.execute_region
732*30fe8762SMarkus Böck// CHECK-NEXT: "test.foo"(%[[DEF]])
733*30fe8762SMarkus Böck
734*30fe8762SMarkus Böck// -----
735*30fe8762SMarkus Böck
736*30fe8762SMarkus Böckfunc.func @nested_region_outside_loop_use() {
737*30fe8762SMarkus Böck  cf.br ^bb1
738*30fe8762SMarkus Böck
739*30fe8762SMarkus Böck^bb1:
740*30fe8762SMarkus Böck  %3 = "test.test1"() : () -> i32
741*30fe8762SMarkus Böck  %cond = "test.test2"() : () -> i1
742*30fe8762SMarkus Böck  cf.cond_br %cond, ^bb1, ^bb2
743*30fe8762SMarkus Böck
744*30fe8762SMarkus Böck^bb2:
745*30fe8762SMarkus Böck  scf.execute_region {
746*30fe8762SMarkus Böck    "test.foo"(%3) : (i32) -> ()
747*30fe8762SMarkus Böck    scf.yield
748*30fe8762SMarkus Böck  }
749*30fe8762SMarkus Böck  return
750*30fe8762SMarkus Böck}
751*30fe8762SMarkus Böck
752*30fe8762SMarkus Böck// CHECK-LABEL: func @nested_region_outside_loop_use
753*30fe8762SMarkus Böck// CHECK: %[[RES:.*]] = scf.while
754*30fe8762SMarkus Böck// CHECK: %[[DEF:.*]] = "test.test1"()
755*30fe8762SMarkus Böck// CHECK: scf.condition(%{{.*}}) %[[DEF]]
756*30fe8762SMarkus Böck
757*30fe8762SMarkus Böck// CHECK: scf.execute_region
758*30fe8762SMarkus Böck// CHECK-NEXT: "test.foo"(%[[RES]])
759