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