| // RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all -compute-dominance-info -compute-loop-info -loop-canonicalizer %s | %FileCheck %s |
| |
| sil_stage canonical |
| |
| import Builtin |
| |
| // CHECK-LABEL: sil @insert_preheader_1 : $@convention(thin) () -> () { |
| // CHECK: bb0: |
| // CHECK: cond_br undef, bb1, bb4 |
| // CHECK: bb1: |
| // CHECK: br bb2 |
| // CHECK: bb2: |
| // CHECK: cond_br undef, bb2, bb3 |
| // CHECK: bb3: |
| // CHECK: br bb4 |
| // CHECK: bb4: |
| // CHECK: return undef |
| sil @insert_preheader_1 : $@convention(thin) () -> () { |
| bb0: |
| cond_br undef, bb1, bb3 |
| |
| // A bb will be inserted along the edge from bb0 -> bb1. |
| bb1: |
| cond_br undef, bb1, bb2 |
| |
| // This is the exit block of the loop on bb1. We do this so this test *only* |
| // tests the preheader insertion vs the exit block canonicalization. |
| bb2: |
| br bb3 |
| |
| bb3: |
| return undef : $() |
| } |
| |
| // Make sure that we insert the pre-header correctly given a header with |
| // multiple predecessors. |
| // |
| // CHECK-LABEL: sil @insert_preheader_2 : $@convention(thin) () -> () { |
| // CHECK: bb0: |
| // CHECK: cond_br undef, bb1, [[PREHEADER:bb[0-9]+]] |
| // CHECK: bb1: |
| // CHECK: br [[PREHEADER]] |
| // CHECK: [[PREHEADER]]: |
| // CHECK: br bb3 |
| // CHECK: bb3: |
| // CHECK: cond_br undef, bb3, bb4 |
| // CHECK: return undef : $() |
| sil @insert_preheader_2 : $@convention(thin) () -> () { |
| bb0: |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| cond_br undef, bb2, bb3 |
| |
| bb3: |
| return undef : $() |
| } |
| |
| // Make sure that we can handle pre-header insertion for loops in sequence |
| // (i.e. where one loop branches into another loop) correctly in terms of |
| // updating loop info. |
| // |
| // CHECK-LABEL: sil @insert_preheader_3 : $@convention(thin) () -> () { |
| // CHECK: bb0: |
| // CHECK: cond_br undef, bb1, bb4 |
| // CHECK: bb1: |
| // CHECK: br bb2 |
| // CHECK: bb2: |
| // CHECK: cond_br undef, bb2, bb3 |
| // CHECK: bb3: |
| // CHECK: br bb7 |
| // CHECK: bb4: |
| // CHECK: br bb5 |
| // CHECK: bb5: |
| // CHECK: cond_br undef, bb5, bb6 |
| // CHECK: bb6: |
| // CHECK: br bb7 |
| // CHECK: bb7 |
| // CHECK: br bb8 |
| // CHECK: bb8: |
| // CHECK: cond_br undef, bb8, bb9 |
| // CHECK: bb9: |
| // CHECK: return undef |
| sil @insert_preheader_3 : $@convention(thin) () -> () { |
| bb0: |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| cond_br undef, bb1, bb3 |
| |
| bb2: |
| cond_br undef, bb2, bb3 |
| |
| bb3: |
| cond_br undef, bb3, bb4 |
| |
| bb4: |
| return undef : $() |
| } |
| |
| // Make sure that we insert pre-headers correctly for nested loops I am using |
| // patterns in more places than I need to, to make the test case more obvious to |
| // the reader. |
| // |
| // CHECK-LABEL: sil @insert_preheader_4 : $@convention(thin) () -> () { |
| // CHECK: bb0: |
| // CHECK: br bb1 |
| // CHECK: bb1: |
| // CHECK: cond_br undef, bb2, [[PREHEADER_1:bb[0-9]+]] |
| // CHECK: bb2: |
| // CHECK: br [[PREHEADER_1]] |
| // First pre-header |
| // CHECK: [[PREHEADER_1]]: |
| // CHECK: br bb4 |
| // CHECK: bb4: |
| // CHECK: cond_br undef, bb8, [[PREHEADER_2:bb[0-9]+]] |
| // CHECK: [[PREHEADER_2]]: |
| // CHECK: br bb6 |
| // CHECK: bb6: |
| // CHECK: cond_br undef, bb6, bb7 |
| // This is an exit bb for bb6. |
| // CHECK: bb7: |
| // CHECK: cond_br undef, bb8, bb9 |
| // CHECK: bb8: |
| // CHECK: br bb4 |
| // CHECK: bb9: |
| // CHECK: return undef |
| sil @insert_preheader_4 : $@convention(thin) () -> () { |
| bb0: |
| br bb1 |
| |
| bb1: |
| cond_br undef, bb2, bb3 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| cond_br undef, bb3, bb4 |
| |
| bb4: |
| cond_br undef, bb4, bb5 |
| |
| bb5: |
| cond_br undef, bb3, bb6 |
| |
| bb6: |
| return undef : $() |
| } |
| |
| // Test insertBackedgeBlock. |
| // |
| // CHECK-LABEL: insert_backedge_block |
| // CHECK: bb2: |
| // CHECK: cond_br undef, bb3, bb4 |
| // CHECK: bb3: |
| // CHECK: br bb1 |
| // CHECK: bb4: |
| // CHECK: cond_br undef, bb3, bb5 |
| sil @insert_backedge_block : $@convention(thin) () -> () { |
| bb0: |
| br bb1 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| cond_br undef, bb1, bb3 |
| |
| bb3: |
| cond_br undef, bb1, bb4 |
| |
| bb4: |
| return undef : $() |
| } |
| |
| // CHECK-LABEL: sil @insert_backedge_block_inner_loop : $@convention(thin) () -> () { |
| // CHECK: bb1: |
| // CHECK: br bb2 |
| // CHECK: bb2: |
| // CHECK: br bb3 |
| // CHECK: bb3: |
| // CHECK: cond_br undef, bb4, bb5 |
| // CHECK: bb4: |
| // CHECK: br bb2 |
| // CHECK: bb5: |
| // CHECK: cond_br undef, bb4, bb6 |
| // CHECK: bb6: |
| // CHECK: cond_br undef, bb1, bb7 |
| // CHECK: bb7: |
| // CHECK: return undef |
| sil @insert_backedge_block_inner_loop : $@convention(thin) () -> () { |
| bb0: |
| br bb1 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| cond_br undef, bb2, bb4 |
| |
| bb4: |
| cond_br undef, bb2, bb5 |
| |
| bb5: |
| cond_br undef, bb1, bb6 |
| |
| bb6: |
| return undef : $() |
| } |
| |
| // CHECK-LABEL: sil @exit_blocks_should_only_have_exiting_blocks_as_predecessors : $@convention(thin) () -> () { |
| // CHECK: bb0: |
| // CHECK: cond_br undef, bb1, bb4 |
| // CHECK: bb1: |
| // CHECK: br bb2 |
| // CHECK: bb2: |
| // CHECK: cond_br undef, bb2, bb3 |
| // CHECK: bb3: |
| // CHECK: br bb4 |
| // CHECK: bb4: |
| // CHECK: return undef |
| sil @exit_blocks_should_only_have_exiting_blocks_as_predecessors : $@convention(thin) () -> () { |
| bb0: |
| cond_br undef, bb1, bb3 |
| |
| // Header |
| bb1: |
| br bb2 |
| |
| bb2: |
| cond_br undef, bb2, bb3 |
| |
| // Exit with multiple predecessors. The edge from bb2 -> bb3 will be split. |
| bb3: |
| return undef : $() |
| } |