| // RUN: %target-sil-opt -enable-sil-verify-all -predictable-memaccess-opts %s | %FileCheck %s |
| |
| sil_stage raw |
| |
| import Builtin |
| import Swift |
| |
| ////////////////// |
| // Declarations // |
| ////////////////// |
| |
| class Klass {} |
| |
| struct NativeObjectPair { |
| var x: Builtin.NativeObject |
| var y: Builtin.NativeObject |
| } |
| |
| struct IntPair { |
| var x: Builtin.Int32 |
| var y: Builtin.Int32 |
| } |
| |
| sil @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| sil @intpair_user : $@convention(thin) (IntPair) -> () |
| sil @nativeobjectpair_user : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| sil @inout_int32_user : $@convention(thin) (@inout Builtin.Int32) -> () |
| sil @get_object : $@convention(thin) () -> @owned Builtin.NativeObject |
| sil @nativeobject_tuple_user : $@convention(thin) (@guaranteed (Builtin.NativeObject, Builtin.NativeObject)) -> () |
| |
| /// Needed to avoid tuple scalarization code in the use gatherer. |
| struct NativeObjectAndTuple { |
| var first: Builtin.NativeObject |
| var second: (Builtin.NativeObject, Builtin.NativeObject) |
| } |
| |
| /////////// |
| // Tests // |
| /////////// |
| |
| //===--- |
| // Fully Available Leaf Node Values |
| // |
| |
| // CHECK-LABEL: sil [ossa] @simple_trivial_load_promotion : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 { |
| // CHECK: bb0([[ARG:%.*]] : |
| // CHECK: return [[ARG]] |
| // CHECK: } // end sil function 'simple_trivial_load_promotion' |
| sil [ossa] @simple_trivial_load_promotion : $@convention(thin) (Builtin.Int32) -> Builtin.Int32 { |
| bb0(%0 : $Builtin.Int32): |
| %1 = alloc_stack $Builtin.Int32 |
| store %0 to [trivial] %1 : $*Builtin.Int32 |
| %2 = load [trivial] %1 : $*Builtin.Int32 |
| dealloc_stack %1 : $*Builtin.Int32 |
| return %2 : $Builtin.Int32 |
| } |
| |
| // CHECK-LABEL: sil [ossa] @simple_nontrivial_load_promotion : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| // CHECK: bb0([[ARG:%.*]] : |
| // CHECK: [[STACK:%.*]] = alloc_stack $Builtin.NativeObject |
| // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] |
| // CHECK: store [[ARG]] to [init] [[STACK]] |
| // CHECK: [[ARG_COPY_2:%.*]] = copy_value [[ARG_COPY]] |
| // CHECK: destroy_value [[ARG_COPY]] |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[ARG_COPY_2]] |
| // CHECK: } // end sil function 'simple_nontrivial_load_promotion' |
| sil [ossa] @simple_nontrivial_load_promotion : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = alloc_stack $Builtin.NativeObject |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| %2 = load [copy] %1 : $*Builtin.NativeObject |
| destroy_addr %1 : $*Builtin.NativeObject |
| dealloc_stack %1 : $*Builtin.NativeObject |
| return %2 : $Builtin.NativeObject |
| } |
| |
| // CHECK-LABEL: sil [ossa] @struct_nontrivial_load_promotion : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned NativeObjectPair { |
| // CHECK: bb0([[ARG1:%.*]] : @owned $Builtin.NativeObject, [[ARG2:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[STACK:%.*]] = alloc_stack $NativeObjectPair |
| // CHECK: [[FIRST_ADDR:%.*]] = struct_element_addr [[STACK]] |
| // CHECK: [[SECOND_ADDR:%.*]] = struct_element_addr [[STACK]] |
| // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] |
| // CHECK: store [[ARG1]] to [init] [[FIRST_ADDR]] |
| // CHECK: [[ARG2_COPY:%.*]] = copy_value [[ARG2]] |
| // CHECK: store [[ARG2]] to [init] [[SECOND_ADDR]] |
| // CHECK: [[ARG1_COPY_BORROW:%.*]] = begin_borrow [[ARG1_COPY]] |
| // CHECK: [[ARG2_COPY_BORROW:%.*]] = begin_borrow [[ARG2_COPY]] |
| // CHECK: [[RESULT:%.*]] = struct $NativeObjectPair ([[ARG1_COPY_BORROW:%.*]] : $Builtin.NativeObject, [[ARG2_COPY_BORROW:%.*]] : $Builtin.NativeObject) |
| // CHECK: [[RESULT_COPY_1:%.*]] = copy_value [[RESULT]] |
| // CHECK: [[RESULT_COPY_2:%.*]] = copy_value [[RESULT_COPY_1]] |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[RESULT_COPY_2]] |
| // CHECK: } // end sil function 'struct_nontrivial_load_promotion' |
| sil [ossa] @struct_nontrivial_load_promotion : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned NativeObjectPair { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject): |
| %2 = alloc_stack $NativeObjectPair |
| %3 = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.x |
| %4 = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.y |
| store %0 to [init] %3 : $*Builtin.NativeObject |
| store %1 to [init] %4 : $*Builtin.NativeObject |
| %5 = load [copy] %2 : $*NativeObjectPair |
| destroy_addr %2 : $*NativeObjectPair |
| dealloc_stack %2 : $*NativeObjectPair |
| return %5 : $NativeObjectPair |
| } |
| |
| // CHECK-LABEL: sil [ossa] @tuple_nontrivial_load_promotion : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned (Builtin.NativeObject, Builtin.NativeObject) { |
| // CHECK: bb0([[ARG1:%.*]] : @owned $Builtin.NativeObject, [[ARG2:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[STACK:%.*]] = alloc_stack $(Builtin.NativeObject, Builtin.NativeObject) |
| // CHECK: [[FIRST_ADDR:%.*]] = tuple_element_addr [[STACK]] |
| // CHECK: [[SECOND_ADDR:%.*]] = tuple_element_addr [[STACK]] |
| // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] |
| // CHECK: store [[ARG1]] to [init] [[FIRST_ADDR]] |
| // CHECK: [[ARG2_COPY:%.*]] = copy_value [[ARG2]] |
| // CHECK: store [[ARG2]] to [init] [[SECOND_ADDR]] |
| // CHECK: [[RESULT:%.*]] = tuple ([[ARG1_COPY:%.*]] : $Builtin.NativeObject, [[ARG2_COPY:%.*]] : $Builtin.NativeObject) |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[RESULT]] |
| // CHECK: } // end sil function 'tuple_nontrivial_load_promotion' |
| sil [ossa] @tuple_nontrivial_load_promotion : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned (Builtin.NativeObject, Builtin.NativeObject) { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject): |
| %2 = alloc_stack $(Builtin.NativeObject, Builtin.NativeObject) |
| %3 = tuple_element_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject), 0 |
| %4 = tuple_element_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject), 1 |
| store %0 to [init] %3 : $*Builtin.NativeObject |
| store %1 to [init] %4 : $*Builtin.NativeObject |
| %5 = load [copy] %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| destroy_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| dealloc_stack %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| return %5 : $(Builtin.NativeObject, Builtin.NativeObject) |
| } |
| |
| // CHECK-LABEL: sil [ossa] @simple_nontrivial_load_promotion_multi_insertpt : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| // CHECK: bb0([[ARG:%.*]] : |
| // CHECK: [[STACK:%.*]] = alloc_stack $Builtin.NativeObject |
| // CHECK: cond_br undef, bb1, bb2 |
| // |
| // CHECK: bb1: |
| // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] |
| // CHECK: store [[ARG]] to [init] [[STACK]] |
| // CHECK: br bb3([[ARG_COPY]] : |
| // |
| // CHECK: bb2: |
| // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] |
| // CHECK: store [[ARG]] to [init] [[STACK]] |
| // CHECK: br bb3([[ARG_COPY]] : |
| // |
| // CHECK: bb3([[RESULT:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[RESULT_COPY_1:%.*]] = copy_value [[RESULT]] |
| // CHECK: [[RESULT_COPY_2:%.*]] = copy_value [[RESULT_COPY_1]] |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[RESULT_COPY_2]] |
| // CHECK: } // end sil function 'simple_nontrivial_load_promotion_multi_insertpt' |
| sil [ossa] @simple_nontrivial_load_promotion_multi_insertpt : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = alloc_stack $Builtin.NativeObject |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| %2 = load [copy] %1 : $*Builtin.NativeObject |
| destroy_addr %1 : $*Builtin.NativeObject |
| dealloc_stack %1 : $*Builtin.NativeObject |
| return %2 : $Builtin.NativeObject |
| } |
| |
| // CHECK-LABEL: sil [ossa] @struct_nontrivial_load_promotion_multi_insertpt : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned NativeObjectPair { |
| // CHECK: bb0([[ARG1:%.*]] : @owned $Builtin.NativeObject, [[ARG2:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[STACK:%.*]] = alloc_stack $NativeObjectPair |
| // CHECK: cond_br undef, bb1, bb2 |
| // |
| // CHECK: bb1: |
| // CHECK: [[FIRST_ADDR:%.*]] = struct_element_addr [[STACK]] |
| // CHECK: [[SECOND_ADDR:%.*]] = struct_element_addr [[STACK]] |
| // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] |
| // CHECK: store [[ARG1]] to [init] [[FIRST_ADDR]] |
| // CHECK: [[ARG2_COPY:%.*]] = copy_value [[ARG2]] |
| // CHECK: store [[ARG2]] to [init] [[SECOND_ADDR]] |
| // CHECK: br bb3([[ARG1_COPY]] : $Builtin.NativeObject, [[ARG2_COPY]] : $Builtin.NativeObject) |
| // |
| // CHECK: bb2: |
| // CHECK: [[FIRST_ADDR:%.*]] = struct_element_addr [[STACK]] |
| // CHECK: [[SECOND_ADDR:%.*]] = struct_element_addr [[STACK]] |
| // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] |
| // CHECK: store [[ARG1]] to [init] [[FIRST_ADDR]] |
| // CHECK: [[ARG2_COPY:%.*]] = copy_value [[ARG2]] |
| // CHECK: store [[ARG2]] to [init] [[SECOND_ADDR]] |
| // CHECK: br bb3([[ARG1_COPY]] : $Builtin.NativeObject, [[ARG2_COPY]] : $Builtin.NativeObject) |
| // |
| // CHECK: bb3([[ARG1_COPY:%.*]] : @owned $Builtin.NativeObject, [[ARG2_COPY:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[ARG1_COPY_COPY:%.*]] = copy_value [[ARG1_COPY]] |
| // CHECK: [[ARG2_COPY_COPY:%.*]] = copy_value [[ARG2_COPY]] |
| // CHECK: [[ARG1_COPY_COPY_BORROW:%.*]] = begin_borrow [[ARG1_COPY_COPY]] |
| // CHECK: [[ARG2_COPY_COPY_BORROW:%.*]] = begin_borrow [[ARG2_COPY_COPY]] |
| // CHECK: [[RESULT:%.*]] = struct $NativeObjectPair ([[ARG1_COPY_COPY_BORROW:%.*]] : $Builtin.NativeObject, [[ARG2_COPY_COPY_BORROW:%.*]] : $Builtin.NativeObject) |
| // CHECK: [[RESULT_COPY:%.*]] = copy_value [[RESULT]] |
| // CHECK: [[RESULT_COPY_2:%.*]] = copy_value [[RESULT_COPY]] |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[RESULT_COPY_2]] |
| // CHECK: } // end sil function 'struct_nontrivial_load_promotion_multi_insertpt' |
| sil [ossa] @struct_nontrivial_load_promotion_multi_insertpt : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned NativeObjectPair { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject): |
| %2 = alloc_stack $NativeObjectPair |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| %3a = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.x |
| %4a = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.y |
| store %0 to [init] %3a : $*Builtin.NativeObject |
| store %1 to [init] %4a : $*Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| %3b = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.x |
| %4b = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.y |
| store %0 to [init] %3b : $*Builtin.NativeObject |
| store %1 to [init] %4b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| %5 = load [copy] %2 : $*NativeObjectPair |
| destroy_addr %2 : $*NativeObjectPair |
| dealloc_stack %2 : $*NativeObjectPair |
| return %5 : $NativeObjectPair |
| } |
| |
| // CHECK-LABEL: sil [ossa] @tuple_nontrivial_load_promotion_multi_insertpt : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned (Builtin.NativeObject, Builtin.NativeObject) { |
| // CHECK: bb0([[ARG1:%.*]] : @owned $Builtin.NativeObject, [[ARG2:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[STACK:%.*]] = alloc_stack $(Builtin.NativeObject, Builtin.NativeObject) |
| // CHECK: cond_br undef, bb1, bb2 |
| // |
| // CHECK: bb1: |
| // CHECK: [[FIRST_ADDR:%.*]] = tuple_element_addr [[STACK]] |
| // CHECK: [[SECOND_ADDR:%.*]] = tuple_element_addr [[STACK]] |
| // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] |
| // CHECK: store [[ARG1]] to [init] [[FIRST_ADDR]] |
| // CHECK: [[ARG2_COPY:%.*]] = copy_value [[ARG2]] |
| // CHECK: store [[ARG2]] to [init] [[SECOND_ADDR]] |
| // CHECK: br bb3([[ARG1_COPY]] : $Builtin.NativeObject, [[ARG2_COPY]] : $Builtin.NativeObject) |
| // |
| // CHECK: bb2: |
| // CHECK: [[FIRST_ADDR:%.*]] = tuple_element_addr [[STACK]] |
| // CHECK: [[SECOND_ADDR:%.*]] = tuple_element_addr [[STACK]] |
| // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] |
| // CHECK: store [[ARG1]] to [init] [[FIRST_ADDR]] |
| // CHECK: [[ARG2_COPY:%.*]] = copy_value [[ARG2]] |
| // CHECK: store [[ARG2]] to [init] [[SECOND_ADDR]] |
| // CHECK: br bb3([[ARG1_COPY]] : $Builtin.NativeObject, [[ARG2_COPY]] : $Builtin.NativeObject) |
| // |
| // CHECK: bb3([[ARG1_COPY:%.*]] : @owned $Builtin.NativeObject, [[ARG2_COPY:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[RESULT:%.*]] = tuple ([[ARG1_COPY:%.*]] : $Builtin.NativeObject, [[ARG2_COPY:%.*]] : $Builtin.NativeObject) |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[RESULT]] |
| // CHECK: } // end sil function 'tuple_nontrivial_load_promotion_multi_insertpt' |
| sil [ossa] @tuple_nontrivial_load_promotion_multi_insertpt : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned (Builtin.NativeObject, Builtin.NativeObject) { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject): |
| %2 = alloc_stack $(Builtin.NativeObject, Builtin.NativeObject) |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| %3a = tuple_element_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject), 0 |
| %4a = tuple_element_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject), 1 |
| store %0 to [init] %3a : $*Builtin.NativeObject |
| store %1 to [init] %4a : $*Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| %3b = tuple_element_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject), 0 |
| %4b = tuple_element_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject), 1 |
| store %0 to [init] %3b : $*Builtin.NativeObject |
| store %1 to [init] %4b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| %5 = load [copy] %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| destroy_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| dealloc_stack %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| return %5 : $(Builtin.NativeObject, Builtin.NativeObject) |
| } |
| |
| //===--- |
| // Value Not Fully Available |
| // |
| |
| // CHECK-LABEL: sil [ossa] @struct_nontrivial_load_promotion_multi_insertpt_value_not_fully_available : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned NativeObjectPair { |
| // CHECK: bb0([[ARG1:%.*]] : @owned $Builtin.NativeObject, [[ARG2:%.*]] : @owned $Builtin.NativeObject, [[ARG3:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[STACK:%.*]] = alloc_stack $NativeObjectPair |
| // CHECK: cond_br undef, bb1, bb2 |
| // |
| // CHECK: bb1: |
| // CHECK: [[FIRST_ADDR:%.*]] = struct_element_addr [[STACK]] |
| // CHECK: [[SECOND_ADDR:%.*]] = struct_element_addr [[STACK]] |
| // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] |
| // CHECK: store [[ARG1]] to [init] [[FIRST_ADDR]] |
| // CHECK: store [[ARG2]] to [init] [[SECOND_ADDR]] |
| // CHECK: destroy_value [[ARG3]] |
| // CHECK: br bb3([[ARG1_COPY]] : $Builtin.NativeObject) |
| // |
| // CHECK: bb2: |
| // CHECK: [[FIRST_ADDR:%.*]] = struct_element_addr [[STACK]] |
| // CHECK: [[SECOND_ADDR:%.*]] = struct_element_addr [[STACK]] |
| // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] |
| // CHECK: store [[ARG1]] to [init] [[FIRST_ADDR]] |
| // CHECK: destroy_value [[ARG2]] |
| // CHECK: store [[ARG3]] to [init] [[SECOND_ADDR]] |
| // CHECK: br bb3([[ARG1_COPY]] : $Builtin.NativeObject) |
| // |
| // CHECK: bb3([[ARG1_COPY:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[ARG1_COPY_COPY:%.*]] = copy_value [[ARG1_COPY]] |
| // CHECK: [[SECOND_ADDR:%.*]] = struct_element_addr [[STACK]] |
| // CHECK: [[SECOND_VAL_COPY:%.*]] = load [copy] [[SECOND_ADDR]] |
| // CHECK: [[ARG1_COPY_COPY_BORROW:%.*]] = begin_borrow [[ARG1_COPY_COPY]] |
| // CHECK: [[SECOND_VAL_COPY_BORROW:%.*]] = begin_borrow [[SECOND_VAL_COPY]] |
| // CHECK: [[RESULT:%.*]] = struct $NativeObjectPair ([[ARG1_COPY_COPY_BORROW:%.*]] : $Builtin.NativeObject, [[SECOND_VAL_COPY_BORROW]] : $Builtin.NativeObject) |
| // CHECK: [[RESULT_COPY_1:%.*]] = copy_value [[RESULT]] |
| // CHECK: [[RESULT_COPY_2:%.*]] = copy_value [[RESULT_COPY_1]] |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[RESULT_COPY_2]] |
| // CHECK: } // end sil function 'struct_nontrivial_load_promotion_multi_insertpt_value_not_fully_available' |
| sil [ossa] @struct_nontrivial_load_promotion_multi_insertpt_value_not_fully_available : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned NativeObjectPair { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject, %arg2 : @owned $Builtin.NativeObject): |
| %2 = alloc_stack $NativeObjectPair |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| %3a = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.x |
| %4a = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.y |
| store %0 to [init] %3a : $*Builtin.NativeObject |
| store %1 to [init] %4a : $*Builtin.NativeObject |
| destroy_value %arg2 : $Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| %3b = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.x |
| %4b = struct_element_addr %2 : $*NativeObjectPair, #NativeObjectPair.y |
| store %0 to [init] %3b : $*Builtin.NativeObject |
| destroy_value %1 : $Builtin.NativeObject |
| store %arg2 to [init] %4b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| %5 = load [copy] %2 : $*NativeObjectPair |
| destroy_addr %2 : $*NativeObjectPair |
| dealloc_stack %2 : $*NativeObjectPair |
| return %5 : $NativeObjectPair |
| } |
| |
| // CHECK-LABEL: sil [ossa] @tuple_nontrivial_load_promotion_multi_insertpt_value_not_fully_available : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned (Builtin.NativeObject, Builtin.NativeObject) { |
| // CHECK: bb0([[ARG1:%.*]] : @owned $Builtin.NativeObject, [[ARG2:%.*]] : @owned $Builtin.NativeObject, [[ARG3:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[STACK:%.*]] = alloc_stack $(Builtin.NativeObject, Builtin.NativeObject) |
| // This is here b/c we scalarize loads in our use list. Really, PMO shouldn't scalarize. |
| // CHECK: [[SCALARIZED_TUPLE_GEP:%.*]] = tuple_element_addr [[STACK]] |
| // CHECK: cond_br undef, bb1, bb2 |
| // |
| // CHECK: bb1: |
| // CHECK: [[FIRST_ADDR:%.*]] = tuple_element_addr [[STACK]] |
| // CHECK: [[SECOND_ADDR:%.*]] = tuple_element_addr [[STACK]] |
| // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] |
| // CHECK: store [[ARG1]] to [init] [[FIRST_ADDR]] |
| // CHECK: store [[ARG2]] to [init] [[SECOND_ADDR]] |
| // CHECK: destroy_value [[ARG3]] |
| // CHECK: br bb3([[ARG1_COPY]] : $Builtin.NativeObject) |
| // |
| // CHECK: bb2: |
| // CHECK: [[FIRST_ADDR:%.*]] = tuple_element_addr [[STACK]] |
| // CHECK: [[SECOND_ADDR:%.*]] = tuple_element_addr [[STACK]] |
| // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] |
| // CHECK: store [[ARG1]] to [init] [[FIRST_ADDR]] |
| // CHECK: destroy_value [[ARG2]] |
| // CHECK: store [[ARG3]] to [init] [[SECOND_ADDR]] |
| // CHECK: br bb3([[ARG1_COPY]] : $Builtin.NativeObject) |
| // |
| // CHECK: bb3([[ARG1_COPY:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[SECOND_VAL_COPY:%.*]] = load [copy] [[SCALARIZED_TUPLE_GEP]] |
| // CHECK: [[RESULT:%.*]] = tuple ([[ARG1_COPY:%.*]] : $Builtin.NativeObject, [[SECOND_VAL_COPY]] : $Builtin.NativeObject) |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[RESULT]] |
| // CHECK: } // end sil function 'tuple_nontrivial_load_promotion_multi_insertpt_value_not_fully_available' |
| sil [ossa] @tuple_nontrivial_load_promotion_multi_insertpt_value_not_fully_available : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned (Builtin.NativeObject, Builtin.NativeObject) { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject, %arg2 : @owned $Builtin.NativeObject): |
| %2 = alloc_stack $(Builtin.NativeObject, Builtin.NativeObject) |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| %3a = tuple_element_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject), 0 |
| %4a = tuple_element_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject), 1 |
| store %0 to [init] %3a : $*Builtin.NativeObject |
| store %1 to [init] %4a : $*Builtin.NativeObject |
| destroy_value %arg2 : $Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| %3b = tuple_element_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject), 0 |
| %4b = tuple_element_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject), 1 |
| store %0 to [init] %3b : $*Builtin.NativeObject |
| destroy_value %1 : $Builtin.NativeObject |
| store %arg2 to [init] %4b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| %5 = load [copy] %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| destroy_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| dealloc_stack %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| return %5 : $(Builtin.NativeObject, Builtin.NativeObject) |
| } |
| |
| //===--- |
| // Tests For Partial Uses Of Available Value |
| // |
| |
| // CHECK-LABEL: sil [ossa] @simple_partialstructuse_load_promotion : $@convention(thin) (@owned NativeObjectPair) -> @owned Builtin.NativeObject { |
| // CHECK: bb0([[ARG:%.*]] : @owned $NativeObjectPair): |
| // CHECK: [[STACK:%.*]] = alloc_stack |
| // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]] |
| // CHECK: [[BORROWED_ARG_FIELD:%.*]] = struct_extract [[BORROWED_ARG]] |
| // CHECK: [[COPIED_ARG_FIELD:%.*]] = copy_value [[BORROWED_ARG_FIELD]] |
| // CHECK: end_borrow [[BORROWED_ARG]] |
| // CHECK: store [[ARG]] to [init] [[STACK]] |
| // CHECK: [[COPIED_ARG_FIELD_COPY_1:%.*]] = copy_value [[COPIED_ARG_FIELD]] |
| // CHECK: [[COPIED_ARG_FIELD_COPY_2:%.*]] = copy_value [[COPIED_ARG_FIELD_COPY_1]] |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[COPIED_ARG_FIELD_COPY_2]] |
| // CHECK: } // end sil function 'simple_partialstructuse_load_promotion' |
| sil [ossa] @simple_partialstructuse_load_promotion : $@convention(thin) (@owned NativeObjectPair) -> (@owned Builtin.NativeObject) { |
| bb0(%0 : @owned $NativeObjectPair): |
| %1 = alloc_stack $NativeObjectPair |
| store %0 to [init] %1 : $*NativeObjectPair |
| %2 = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| %3 = load [copy] %2 : $*Builtin.NativeObject |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| return %3 : $Builtin.NativeObject |
| } |
| |
| // CHECK-LABEL: sil [ossa] @simple_partialtupleuse_load_promotion : $@convention(thin) (@owned NativeObjectAndTuple) -> @owned Builtin.NativeObject { |
| // CHECK: bb0([[ARG:%.*]] : @owned $NativeObjectAndTuple): |
| // CHECK: [[STACK:%.*]] = alloc_stack |
| // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]] |
| // CHECK: [[BORROWED_ARG_FIELD_1:%.*]] = struct_extract [[BORROWED_ARG]] |
| // CHECK: [[BORROWED_ARG_FIELD_2:%.*]] = tuple_extract [[BORROWED_ARG_FIELD_1]] |
| // CHECK: [[COPIED_ARG_FIELD:%.*]] = copy_value [[BORROWED_ARG_FIELD_2]] |
| // CHECK: end_borrow [[BORROWED_ARG]] |
| // CHECK: store [[ARG]] to [init] [[STACK]] |
| // CHECK: [[COPIED_ARG_FIELD_COPY_1:%.*]] = copy_value [[COPIED_ARG_FIELD]] |
| // CHECK: [[COPIED_ARG_FIELD_COPY_2:%.*]] = copy_value [[COPIED_ARG_FIELD_COPY_1]] |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[COPIED_ARG_FIELD_COPY_2]] |
| // CHECK: } // end sil function 'simple_partialtupleuse_load_promotion' |
| sil [ossa] @simple_partialtupleuse_load_promotion : $@convention(thin) (@owned NativeObjectAndTuple) -> (@owned Builtin.NativeObject) { |
| bb0(%0 : @owned $NativeObjectAndTuple): |
| %1 = alloc_stack $NativeObjectAndTuple |
| store %0 to [init] %1 : $*NativeObjectAndTuple |
| %2 = struct_element_addr %1 : $*NativeObjectAndTuple, #NativeObjectAndTuple.second |
| %3 = tuple_element_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject), 0 |
| %4 = load [copy] %3 : $*Builtin.NativeObject |
| destroy_addr %1 : $*NativeObjectAndTuple |
| dealloc_stack %1 : $*NativeObjectAndTuple |
| return %4 : $Builtin.NativeObject |
| } |
| |
| // CHECK-LABEL: sil [ossa] @simple_assignstore : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| // CHECK: bb0([[ARG0:%.*]] : @owned $Builtin.NativeObject, [[ARG1:%.*]] : @owned $Builtin.NativeObject): |
| // CHECK: [[STACK:%.*]] = alloc_stack $Builtin.NativeObject |
| // CHECK: store [[ARG0]] to [init] [[STACK]] |
| // CHECK: [[ARG1_COPY:%.*]] = copy_value [[ARG1]] |
| // CHECK: store [[ARG1]] to [assign] [[STACK]] |
| // CHECK: [[ARG1_COPY_1:%.*]] = copy_value [[ARG1_COPY]] |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[ARG1_COPY_1]] |
| // CHECK: } // end sil function 'simple_assignstore' |
| sil [ossa] @simple_assignstore : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject): |
| %2 = alloc_stack $Builtin.NativeObject |
| store %0 to [init] %2 : $*Builtin.NativeObject |
| store %1 to [assign] %2 : $*Builtin.NativeObject |
| %3 = load [copy] %2 : $*Builtin.NativeObject |
| destroy_addr %2 : $*Builtin.NativeObject |
| dealloc_stack %2 : $*Builtin.NativeObject |
| return %3 : $Builtin.NativeObject |
| } |
| |
| // CHECK-LABEL: sil [ossa] @diamond_test_2 : $@convention(thin) (@owned NativeObjectPair) -> @owned Builtin.NativeObject { |
| // CHECK: bb0([[ARG:%.*]] : @owned $NativeObjectPair): |
| // CHECK: [[STACK:%.*]] = alloc_stack $NativeObjectPair |
| // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]] |
| // CHECK: [[LHS1:%.*]] = struct_extract [[BORROWED_ARG]] : $NativeObjectPair, #NativeObjectPair.x |
| // CHECK: [[LHS1_COPY:%.*]] = copy_value [[LHS1]] |
| // CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]] |
| // CHECK: [[LHS2:%.*]] = struct_extract [[BORROWED_ARG]] : $NativeObjectPair, #NativeObjectPair.x |
| // CHECK: [[LHS2_COPY:%.*]] = copy_value [[LHS2]] |
| // CHECK: store [[ARG]] to [init] [[STACK]] |
| // CHECK: cond_br undef, bb1, bb2 |
| // |
| // CHECK: bb1: |
| // CHECK: destroy_value [[LHS1_COPY]] |
| // CHECK: [[LHS2_COPY_1:%.*]] = copy_value [[LHS2_COPY]] |
| // CHECK: [[LHS2_COPY_2:%.*]] = copy_value [[LHS2_COPY_1]] |
| // CHECK: br bb3([[LHS2_COPY_2]] : |
| // |
| // CHECK: bb2: |
| // CHECK: destroy_value [[LHS2_COPY]] |
| // CHECK: [[LHS1_COPY_1:%.*]] = copy_value [[LHS1_COPY]] |
| // CHECK: [[LHS1_COPY_2:%.*]] = copy_value [[LHS1_COPY_1]] |
| // CHECK: br bb3([[LHS1_COPY_2]] : |
| // |
| // CHECK: bb3([[PHI:%.*]] : |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[PHI]] |
| // CHECK: } // end sil function 'diamond_test_2' |
| sil [ossa] @diamond_test_2 : $@convention(thin) (@owned NativeObjectPair) -> @owned Builtin.NativeObject { |
| bb0(%0 : @owned $NativeObjectPair): |
| %1 = alloc_stack $NativeObjectPair |
| store %0 to [init] %1 : $*NativeObjectPair |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| %2 = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| %3 = load [copy] %2 : $*Builtin.NativeObject |
| br bb3(%3 : $Builtin.NativeObject) |
| |
| bb2: |
| %4 = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| %5 = load [copy] %4 : $*Builtin.NativeObject |
| br bb3(%5 : $Builtin.NativeObject) |
| |
| bb3(%6 : @owned $Builtin.NativeObject): |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| return %6 : $Builtin.NativeObject |
| } |
| |
| //////////////////// |
| // Negative Tests // |
| //////////////////// |
| |
| // CHECK-LABEL: sil [ossa] @simple_nontrivial_loadtake_no_promote : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| // CHECK: bb0([[ARG:%.*]] : |
| // CHECK: [[STACK:%.*]] = alloc_stack $Builtin.NativeObject |
| // CHECK: store [[ARG]] to [init] [[STACK]] |
| // CHECK: [[RESULT:%.*]] = load [take] [[STACK]] |
| // CHECK: dealloc_stack [[STACK]] |
| // CHECK: return [[RESULT]] |
| // CHECK: } // end sil function 'simple_nontrivial_loadtake_no_promote' |
| sil [ossa] @simple_nontrivial_loadtake_no_promote : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = alloc_stack $Builtin.NativeObject |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| %2 = load [take] %1 : $*Builtin.NativeObject |
| dealloc_stack %1 : $*Builtin.NativeObject |
| return %2 : $Builtin.NativeObject |
| } |
| |
| /////////////////////// |
| // Load Borrow Tests // |
| /////////////////////// |
| |
| // CHECK-LABEL: sil [ossa] @load_borrow_promotion : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| // CHECK: bb0([[ARG:%.*]] : |
| // Block where we have our store and do our lifetime extending copy_value. |
| // CHECK: [[STACK:%.*]] = alloc_stack $Builtin.NativeObject |
| // CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] |
| // CHECK: store [[ARG]] to [init] [[STACK]] |
| // CHECK: br bb1 |
| // |
| // Our load block. Here, we insert our copy_value + begin_borrow that is |
| // associated with the load_borrow. We can not use the original copy since even |
| // though in this situation we know that our copy/borrow would be strongly |
| // control equivalent, this is not always true. To simplify the algorithm, we |
| // always insert the copy here. We insert a destroy_value to end the lifetime of |
| // ARG_COPY since we do not have a loop here. |
| // |
| // CHECK: bb1: |
| // CHECK: [[CONTROL_EQUIVALENT_ARG_COPY:%.*]] = copy_value [[ARG_COPY]] |
| // CHECK: [[BORROWED_ARG_COPY:%.*]] = begin_borrow [[CONTROL_EQUIVALENT_ARG_COPY]] |
| // CHECK: destroy_value [[ARG_COPY]] |
| // CHECK: br bb2 |
| // |
| // The block where the load_borrow is actually used. We destroy the control |
| // equivalent arg copy here after the end_borrow. |
| // |
| // CHECK: bb2: |
| // CHECK: [[RESULT:%.*]] = copy_value [[BORROWED_ARG_COPY]] |
| // CHECK: end_borrow [[BORROWED_ARG_COPY]] |
| // CHECK: destroy_value [[CONTROL_EQUIVALENT_ARG_COPY]] |
| // CHECK: br bb3 |
| // |
| // The block after the load_borrow is ever used. |
| // CHECK: bb3: |
| // CHECK: destroy_addr [[STACK]] |
| // CHECK: return [[RESULT]] |
| // CHECK: } // end sil function 'load_borrow_promotion' |
| sil [ossa] @load_borrow_promotion : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = alloc_stack $Builtin.NativeObject |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| br bb1 |
| |
| bb1: |
| %2 = load_borrow %1 : $*Builtin.NativeObject |
| br bb2 |
| |
| bb2: |
| %3 = copy_value %2 : $Builtin.NativeObject |
| end_borrow %2 : $Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| destroy_addr %1 : $*Builtin.NativeObject |
| dealloc_stack %1 : $*Builtin.NativeObject |
| return %3 : $Builtin.NativeObject |
| } |
| |
| // CHECK-LABEL: sil [ossa] @promote_with_loop_1 : $@convention(thin) (@owned NativeObjectPair) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'promote_with_loop_1' |
| sil [ossa] @promote_with_loop_1 : $@convention(thin) (@owned NativeObjectPair) -> () { |
| bb0(%0 : @owned $NativeObjectPair): |
| %1 = alloc_stack $NativeObjectPair |
| store %0 to [init] %1 : $*NativeObjectPair |
| %2 = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| br bb2 |
| |
| bb2: |
| %3 = load_borrow %2 : $*Builtin.NativeObject |
| %4 = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| apply %4(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| end_borrow %3 : $Builtin.NativeObject |
| br bb2 |
| } |
| |
| // CHECK-LABEL: sil [ossa] @load_borrow_loop_promote_with_loop_2 : $@convention(thin) (@owned NativeObjectPair) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'load_borrow_loop_promote_with_loop_2' |
| sil [ossa] @load_borrow_loop_promote_with_loop_2 : $@convention(thin) (@owned NativeObjectPair) -> () { |
| bb0(%0 : @owned $NativeObjectPair): |
| %1 = alloc_stack $NativeObjectPair |
| store %0 to [init] %1 : $*NativeObjectPair |
| %2 = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| br bb2 |
| |
| bb2: |
| %3 = load_borrow %2 : $*Builtin.NativeObject |
| %4 = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| apply %4(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| end_borrow %3 : $Builtin.NativeObject |
| cond_br undef, bb3, bb4 |
| |
| bb3: |
| br bb2 |
| |
| bb4: |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @load_borrow_promote_two_backedge_loop : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'load_borrow_promote_two_backedge_loop' |
| sil [ossa] @load_borrow_promote_two_backedge_loop : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = alloc_stack $Builtin.NativeObject |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| br bb1 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| cond_br undef, bb3, bb4 |
| |
| bb3: |
| %2 = load_borrow %1 : $*Builtin.NativeObject |
| end_borrow %2 : $Builtin.NativeObject |
| cond_br undef, bb5, bb6 |
| |
| bb4: |
| %3 = load_borrow %1 : $*Builtin.NativeObject |
| end_borrow %3 : $Builtin.NativeObject |
| cond_br undef, bb7, bb8 |
| |
| bb5: |
| br bb2 |
| |
| bb6: |
| br bb9 |
| |
| bb7: |
| br bb2 |
| |
| bb8: |
| br bb9 |
| |
| bb9: |
| destroy_addr %1 : $*Builtin.NativeObject |
| dealloc_stack %1 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [canonical] [ossa] @load_borrow_tuple_scalarize : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () { |
| // CHECK: bb0([[ARG0:%.*]] : @owned ${{.*}}, [[ARG1:%.*]] : |
| // CHECK: [[TUP:%.*]] = tuple ([[ARG0]] : ${{.*}}, [[ARG1]] : |
| // CHECK: ([[TUP_0:%.*]], [[TUP_1:%.*]]) = destructure_tuple [[TUP]] |
| // CHECK: [[TUP_0_COPY:%.*]] = copy_value [[TUP_0]] |
| // CHECK: [[TUP_1_COPY:%.*]] = copy_value [[TUP_1]] |
| // CHECK: [[CONTROL_EQUIVALENT_TUP_0_COPY:%.*]] = copy_value [[TUP_0_COPY]] |
| // CHECK: [[BORROWED_TUP_0_COPY:%.*]] = begin_borrow [[CONTROL_EQUIVALENT_TUP_0_COPY]] |
| // CHECK: destroy_value [[TUP_0_COPY]] |
| // CHECK: [[CONTROL_EQUIVALENT_TUP_1_COPY:%.*]] = copy_value [[TUP_1_COPY]] |
| // CHECK: [[BORROWED_TUP_1_COPY:%.*]] = begin_borrow [[CONTROL_EQUIVALENT_TUP_1_COPY]] |
| // CHECK: destroy_value [[TUP_1_COPY]] |
| // CHECK: [[BORROWED_TUP:%.*]] = tuple ([[BORROWED_TUP_0_COPY]] : ${{.*}}, [[BORROWED_TUP_1_COPY]] : |
| // CHECK: [[TUP_EXT_1:%.*]] = tuple_extract [[BORROWED_TUP]] : |
| // CHECK: [[TUP_EXT_2:%.*]] = tuple_extract [[BORROWED_TUP]] : |
| // CHECK: apply {{%.*}}([[TUP_EXT_1]]) |
| // CHECK: apply {{%.*}}([[TUP_EXT_2]]) |
| // CHECK: end_borrow [[BORROWED_TUP_0_COPY]] |
| // CHECK: destroy_value [[CONTROL_EQUIVALENT_TUP_0_COPY]] |
| // CHECK: end_borrow [[BORROWED_TUP_1_COPY]] |
| // CHECK: destroy_value [[CONTROL_EQUIVALENT_TUP_1_COPY]] |
| // CHECK: } // end sil function 'load_borrow_tuple_scalarize' |
| sil [canonical] [ossa] @load_borrow_tuple_scalarize : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject, %1 : @owned $Builtin.NativeObject): |
| %2 = alloc_stack $(Builtin.NativeObject, Builtin.NativeObject) |
| %3 = tuple (%0 : $Builtin.NativeObject, %1 : $Builtin.NativeObject) |
| store %3 to [init] %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| |
| %4 = load_borrow %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| %5 = tuple_extract %4 : $(Builtin.NativeObject, Builtin.NativeObject), 0 |
| %6 = tuple_extract %4 : $(Builtin.NativeObject, Builtin.NativeObject), 1 |
| %7 = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| apply %7(%5) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| apply %7(%6) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| end_borrow %4 : $(Builtin.NativeObject, Builtin.NativeObject) |
| |
| destroy_addr %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| dealloc_stack %2 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @trivial_multiple_available_values_diamond_followed_by_loop_trivial : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> () { |
| // CHECK: bb0( |
| // CHECK-NOT: load [trivial] %{{[0-9][0-9]*}} : $*IntPair |
| // CHECK-NOT: bb{{[0-9][0-9]*}}( |
| // CHECK: } // end sil function 'trivial_multiple_available_values_diamond_followed_by_loop_trivial' |
| sil [ossa] @trivial_multiple_available_values_diamond_followed_by_loop_trivial : $@convention(thin) (Builtin.Int32, Builtin.Int32) -> () { |
| bb0(%0a : $Builtin.Int32, %0b : $Builtin.Int32): |
| %func = function_ref @intpair_user : $@convention(thin) (IntPair) -> () |
| %1 = alloc_stack $IntPair |
| %1a = struct_element_addr %1 : $*IntPair, #IntPair.x |
| %1b = struct_element_addr %1 : $*IntPair, #IntPair.y |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| store %0a to [trivial] %1a : $*Builtin.Int32 |
| store %0b to [trivial] %1b : $*Builtin.Int32 |
| br bb3 |
| |
| bb2: |
| store %0a to [trivial] %1a : $*Builtin.Int32 |
| store %0b to [trivial] %1b : $*Builtin.Int32 |
| br bb3 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| br bb5 |
| |
| bb5: |
| %2 = load [trivial] %1 : $*IntPair |
| cond_br undef, bb6, bb7 |
| |
| bb6: |
| apply %func(%2) : $@convention(thin) (IntPair) -> () |
| br bb5 |
| |
| bb7: |
| apply %func(%2) : $@convention(thin) (IntPair) -> () |
| dealloc_stack %1 : $*IntPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @trivial_multiple_available_values_diamond_followed_by_loop_trivial_reload : $@convention(thin) (Builtin.Int32, Builtin.Int32, Builtin.Int32) -> () { |
| // CHECK: bb0( |
| // CHECK-NOT: load [trivial] %{{[0-9][0-9]*}} : $*IntPair |
| // CHECK-NOT: bb{{[0-9][0-9]*}}( |
| // CHECK: } // end sil function 'trivial_multiple_available_values_diamond_followed_by_loop_trivial_reload' |
| sil [ossa] @trivial_multiple_available_values_diamond_followed_by_loop_trivial_reload : $@convention(thin) (Builtin.Int32, Builtin.Int32, Builtin.Int32) -> () { |
| bb0(%0a : $Builtin.Int32, %0b : $Builtin.Int32, %0c : $Builtin.Int32): |
| %func = function_ref @intpair_user : $@convention(thin) (IntPair) -> () |
| %1 = alloc_stack $IntPair |
| %1a = struct_element_addr %1 : $*IntPair, #IntPair.x |
| %1b = struct_element_addr %1 : $*IntPair, #IntPair.y |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| store %0a to [trivial] %1a : $*Builtin.Int32 |
| store %0c to [trivial] %1b : $*Builtin.Int32 |
| br bb3 |
| |
| bb2: |
| store %0a to [trivial] %1a : $*Builtin.Int32 |
| store %0b to [trivial] %1b : $*Builtin.Int32 |
| br bb3 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| br bb5 |
| |
| bb5: |
| %2 = load [trivial] %1 : $*IntPair |
| cond_br undef, bb6, bb7 |
| |
| bb6: |
| apply %func(%2) : $@convention(thin) (IntPair) -> () |
| br bb5 |
| |
| bb7: |
| apply %func(%2) : $@convention(thin) (IntPair) -> () |
| dealloc_stack %1 : $*IntPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @trivial_multiple_available_values_diamond_followed_by_loop_trivial_store_in_loop : $@convention(thin) (Builtin.Int32, Builtin.Int32, Builtin.Int32) -> () { |
| // CHECK-NOT: load |
| // CHECK: } // end sil function 'trivial_multiple_available_values_diamond_followed_by_loop_trivial_store_in_loop' |
| sil [ossa] @trivial_multiple_available_values_diamond_followed_by_loop_trivial_store_in_loop : $@convention(thin) (Builtin.Int32, Builtin.Int32, Builtin.Int32) -> () { |
| bb0(%0a : $Builtin.Int32, %0b : $Builtin.Int32, %0c : $Builtin.Int32): |
| %func = function_ref @intpair_user : $@convention(thin) (IntPair) -> () |
| %1 = alloc_stack $IntPair |
| %1a = struct_element_addr %1 : $*IntPair, #IntPair.x |
| %1b = struct_element_addr %1 : $*IntPair, #IntPair.y |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| store %0a to [trivial] %1a : $*Builtin.Int32 |
| store %0b to [trivial] %1b : $*Builtin.Int32 |
| br bb3 |
| |
| bb2: |
| store %0a to [trivial] %1a : $*Builtin.Int32 |
| store %0b to [trivial] %1b : $*Builtin.Int32 |
| br bb3 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| br bb5 |
| |
| bb5: |
| %2 = load [trivial] %1 : $*IntPair |
| cond_br undef, bb6, bb7 |
| |
| bb6: |
| apply %func(%2) : $@convention(thin) (IntPair) -> () |
| store %0b to [trivial] %1b : $*Builtin.Int32 |
| br bb5 |
| |
| bb7: |
| apply %func(%2) : $@convention(thin) (IntPair) -> () |
| dealloc_stack %1 : $*IntPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @multiple_available_values_diamond_followed_by_loop : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () { |
| // CHECK: bb0( |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'multiple_available_values_diamond_followed_by_loop' |
| sil [ossa] @multiple_available_values_diamond_followed_by_loop : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () { |
| bb0(%0a : @owned $Builtin.NativeObject, %0b : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobjectpair_user : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| %1 = alloc_stack $NativeObjectPair |
| %1a = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| %1b = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.y |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| br bb5 |
| |
| bb5: |
| %2 = load_borrow %1 : $*NativeObjectPair |
| cond_br undef, bb6, bb7 |
| |
| bb6: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| end_borrow %2 : $NativeObjectPair |
| br bb5 |
| |
| bb7: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| end_borrow %2 : $NativeObjectPair |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @multiple_available_values_diamond_followed_by_loop_reload : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'multiple_available_values_diamond_followed_by_loop_reload' |
| sil [ossa] @multiple_available_values_diamond_followed_by_loop_reload : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () { |
| bb0(%0a : @owned $Builtin.NativeObject, %0b : @owned $Builtin.NativeObject, %0c : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobjectpair_user : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| %1 = alloc_stack $NativeObjectPair |
| %1a = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| %1b = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.y |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0c to [init] %1b : $*Builtin.NativeObject |
| destroy_value %0b : $Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| destroy_value %0c : $Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| br bb5 |
| |
| bb5: |
| %2 = load_borrow %1 : $*NativeObjectPair |
| cond_br undef, bb6, bb7 |
| |
| bb6: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| end_borrow %2 : $NativeObjectPair |
| br bb5 |
| |
| bb7: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| end_borrow %2 : $NativeObjectPair |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @multiple_available_values_diamond_followed_by_loop_store_in_loop : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'multiple_available_values_diamond_followed_by_loop_store_in_loop' |
| sil [ossa] @multiple_available_values_diamond_followed_by_loop_store_in_loop : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| bb0(%0a : @owned $Builtin.NativeObject, %0b : @owned $Builtin.NativeObject, %0c : @guaranteed $Builtin.NativeObject): |
| %func = function_ref @nativeobjectpair_user : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| %1 = alloc_stack $NativeObjectPair |
| %1a = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| %1b = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.y |
| %0bhat = copy_value %0b : $Builtin.NativeObject |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| br bb5 |
| |
| bb5: |
| %2 = load_borrow %1 : $*NativeObjectPair |
| cond_br undef, bb6, bb7 |
| |
| bb6: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| end_borrow %2 : $NativeObjectPair |
| destroy_addr %1b : $*Builtin.NativeObject |
| %0bhat2 = copy_value %0bhat : $Builtin.NativeObject |
| store %0bhat2 to [init] %1b : $*Builtin.NativeObject |
| br bb5 |
| |
| bb7: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| end_borrow %2 : $NativeObjectPair |
| destroy_value %0bhat : $Builtin.NativeObject |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [canonical] [ossa] @loop_carry_loadborrow : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'loop_carry_loadborrow' |
| sil [canonical] [ossa] @loop_carry_loadborrow : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| %1 = alloc_stack $Builtin.NativeObject |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| cond_br undef, bb1, bb7 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| %2 = load_borrow %1 : $*Builtin.NativeObject |
| cond_br undef, bb4, bb5 |
| |
| bb4: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| end_borrow %2 : $Builtin.NativeObject |
| br bb2 |
| |
| bb5: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| end_borrow %2 : $Builtin.NativeObject |
| br bb6 |
| |
| bb6: |
| br bb8 |
| |
| bb7: |
| br bb8 |
| |
| bb8: |
| destroy_addr %1 : $*Builtin.NativeObject |
| dealloc_stack %1 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [canonical] [ossa] @loop_carry_loadborrow_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'loop_carry_loadborrow_2' |
| sil [canonical] [ossa] @loop_carry_loadborrow_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| %1 = alloc_stack $Builtin.NativeObject |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| cond_br undef, bb1, bb7 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| %2 = load_borrow %1 : $*Builtin.NativeObject |
| cond_br undef, bb4, bb5 |
| |
| bb4: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| end_borrow %2 : $Builtin.NativeObject |
| br bb2 |
| |
| bb5: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| end_borrow %2 : $Builtin.NativeObject |
| br bb6 |
| |
| bb6: |
| br bb8 |
| |
| bb7: |
| br bb8 |
| |
| bb8: |
| destroy_addr %1 : $*Builtin.NativeObject |
| dealloc_stack %1 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [canonical] [ossa] @loop_carry_loadborrow_3 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'loop_carry_loadborrow_3' |
| sil [canonical] [ossa] @loop_carry_loadborrow_3 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| bb0(%0a : @owned $Builtin.NativeObject, %0b : @owned $Builtin.NativeObject, %0c : @guaranteed $Builtin.NativeObject): |
| %func = function_ref @nativeobject_tuple_user : $@convention(thin) (@guaranteed (Builtin.NativeObject, Builtin.NativeObject)) -> () |
| %1 = alloc_stack $(Builtin.NativeObject, Builtin.NativeObject) |
| %1a = tuple_element_addr %1 : $*(Builtin.NativeObject, Builtin.NativeObject), 0 |
| %1b = tuple_element_addr %1 : $*(Builtin.NativeObject, Builtin.NativeObject), 1 |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| cond_br undef, bb1, bb7 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| %0ccopy = copy_value %0c : $Builtin.NativeObject |
| destroy_addr %1a : $*Builtin.NativeObject |
| store %0ccopy to [init] %1a : $*Builtin.NativeObject |
| %2 = load_borrow %1 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| cond_br undef, bb4, bb5 |
| |
| bb4: |
| apply %func(%2) : $@convention(thin) (@guaranteed (Builtin.NativeObject, Builtin.NativeObject)) -> () |
| end_borrow %2 : $(Builtin.NativeObject, Builtin.NativeObject) |
| br bb2 |
| |
| bb5: |
| apply %func(%2) : $@convention(thin) (@guaranteed (Builtin.NativeObject, Builtin.NativeObject)) -> () |
| end_borrow %2 : $(Builtin.NativeObject, Builtin.NativeObject) |
| br bb6 |
| |
| bb6: |
| br bb8 |
| |
| bb7: |
| br bb8 |
| |
| bb8: |
| destroy_addr %1 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| dealloc_stack %1 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [canonical] [ossa] @loop_carry_loadborrow_4 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'loop_carry_loadborrow_4' |
| sil [canonical] [ossa] @loop_carry_loadborrow_4 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| bb0(%0a : @owned $Builtin.NativeObject, %0b : @owned $Builtin.NativeObject, %0c : @guaranteed $Builtin.NativeObject): |
| %func = function_ref @nativeobjectpair_user : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| %1 = alloc_stack $NativeObjectPair |
| %1a = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| %1b = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.y |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| cond_br undef, bb1, bb7 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| %0ccopy = copy_value %0c : $Builtin.NativeObject |
| destroy_addr %1a : $*Builtin.NativeObject |
| store %0ccopy to [init] %1a : $*Builtin.NativeObject |
| %2 = load_borrow %1 : $*NativeObjectPair |
| cond_br undef, bb4, bb5 |
| |
| bb4: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| end_borrow %2 : $NativeObjectPair |
| br bb2 |
| |
| bb5: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| end_borrow %2 : $NativeObjectPair |
| br bb6 |
| |
| bb6: |
| br bb8 |
| |
| bb7: |
| br bb8 |
| |
| bb8: |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @loop_carry_load_borrow_phi_not_control_equivalent : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'loop_carry_load_borrow_phi_not_control_equivalent' |
| sil [ossa] @loop_carry_load_borrow_phi_not_control_equivalent : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%arg : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| %0 = alloc_stack $Builtin.NativeObject |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| cond_br undef, bb3, bb4 |
| |
| bb2: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb5 |
| |
| bb3: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb6 |
| |
| bb4: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb7 |
| |
| bb5: |
| br bb8 |
| |
| bb6: |
| br bb8 |
| |
| bb7: |
| br bbPreLoopHeader |
| |
| bb8: |
| br bbPreLoopHeader |
| |
| bbPreLoopHeader: |
| br bbLoop |
| |
| bbLoop: |
| br bbLoop1 |
| |
| bbLoop1: |
| br bbLoop2 |
| |
| bbLoop2: |
| %2 = load_borrow %0 : $*Builtin.NativeObject |
| cond_br undef, bbLoop3, bbLoop4 |
| |
| bbLoop3: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| end_borrow %2 : $Builtin.NativeObject |
| br bbLoop2 |
| |
| bbLoop4: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| end_borrow %2 : $Builtin.NativeObject |
| br bbEnd |
| |
| bbEnd: |
| destroy_addr %0 : $*Builtin.NativeObject |
| dealloc_stack %0 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // In this case, we will have that we need to separately lifetime extend our phi |
| // node's copy to prevent leaks along the edge skipping the loop. |
| // CHECK-LABEL: sil [ossa] @loop_carry_load_borrow_phi_not_control_equivalent_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'loop_carry_load_borrow_phi_not_control_equivalent_2' |
| sil [ossa] @loop_carry_load_borrow_phi_not_control_equivalent_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%arg : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| %0 = alloc_stack $Builtin.NativeObject |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| cond_br undef, bb3, bb4 |
| |
| bb2: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb5 |
| |
| bb3: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb6 |
| |
| bb4: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb7 |
| |
| bb5: |
| br bb8a |
| |
| bb6: |
| br bb8a |
| |
| bb7: |
| br bbPreLoopHeader |
| |
| bb8a: |
| br bb8 |
| |
| bb8: |
| cond_br undef, bbPreLoopHeader1, bbSkipLoop |
| |
| bbPreLoopHeader: |
| br bbLoop |
| |
| bbPreLoopHeader1: |
| br bbLoop |
| |
| bbLoop: |
| br bbLoop1 |
| |
| bbLoop1: |
| br bbLoop2 |
| |
| bbLoop2: |
| %2 = load_borrow %0 : $*Builtin.NativeObject |
| br bbLoop6 |
| |
| bbLoop6: |
| cond_br undef, bbLoop3, bbLoop4 |
| |
| bbLoop3: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| end_borrow %2 : $Builtin.NativeObject |
| br bbLoop5 |
| |
| bbLoop5: |
| br bbLoop2 |
| |
| bbLoop4: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| end_borrow %2 : $Builtin.NativeObject |
| br bbEnd |
| |
| bbSkipLoop: |
| br bbEnd |
| |
| bbEnd: |
| destroy_addr %0 : $*Builtin.NativeObject |
| dealloc_stack %0 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| //--- |
| |
| // CHECK-LABEL: sil [ossa] @load_copy_promote_with_loop_1 : $@convention(thin) (@owned NativeObjectPair) -> () { |
| // CHECK-NOT: load_borrow |
| // CHECK: } // end sil function 'load_copy_promote_with_loop_1' |
| sil [ossa] @load_copy_promote_with_loop_1 : $@convention(thin) (@owned NativeObjectPair) -> () { |
| bb0(%0 : @owned $NativeObjectPair): |
| %1 = alloc_stack $NativeObjectPair |
| store %0 to [init] %1 : $*NativeObjectPair |
| %2 = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| br bb2 |
| |
| bb2: |
| %3 = load [copy] %2 : $*Builtin.NativeObject |
| %4 = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| apply %4(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| destroy_value %3 : $Builtin.NativeObject |
| br bb2 |
| } |
| |
| // CHECK-LABEL: sil [ossa] @load_copy_loop_promote_with_loop_2 : $@convention(thin) (@owned NativeObjectPair) -> () { |
| // CHECK-NOT: load [copy] |
| // CHECK: } // end sil function 'load_copy_loop_promote_with_loop_2' |
| sil [ossa] @load_copy_loop_promote_with_loop_2 : $@convention(thin) (@owned NativeObjectPair) -> () { |
| bb0(%0 : @owned $NativeObjectPair): |
| %1 = alloc_stack $NativeObjectPair |
| store %0 to [init] %1 : $*NativeObjectPair |
| %2 = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| br bb2 |
| |
| bb2: |
| %3 = load [copy] %2 : $*Builtin.NativeObject |
| %4 = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| apply %4(%3) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| destroy_value %3 : $Builtin.NativeObject |
| cond_br undef, bb3, bb4 |
| |
| bb3: |
| br bb2 |
| |
| bb4: |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @load_copy_promote_two_backedge_loop : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load [copy] |
| // CHECK: } // end sil function 'load_copy_promote_two_backedge_loop' |
| sil [ossa] @load_copy_promote_two_backedge_loop : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %1 = alloc_stack $Builtin.NativeObject |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| br bb1 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| cond_br undef, bb3, bb4 |
| |
| bb3: |
| %2 = load [copy] %1 : $*Builtin.NativeObject |
| destroy_value %2 : $Builtin.NativeObject |
| cond_br undef, bb5, bb6 |
| |
| bb4: |
| %3 = load [copy] %1 : $*Builtin.NativeObject |
| destroy_value %3 : $Builtin.NativeObject |
| cond_br undef, bb7, bb8 |
| |
| bb5: |
| br bb2 |
| |
| bb6: |
| br bb9 |
| |
| bb7: |
| br bb2 |
| |
| bb8: |
| br bb9 |
| |
| bb9: |
| destroy_addr %1 : $*Builtin.NativeObject |
| dealloc_stack %1 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @load_copy_multiple_available_values_diamond_followed_by_loop : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () { |
| // CHECK: bb0( |
| // CHECK-NOT: load [copy] |
| // CHECK: } // end sil function 'load_copy_multiple_available_values_diamond_followed_by_loop' |
| sil [ossa] @load_copy_multiple_available_values_diamond_followed_by_loop : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () { |
| bb0(%0a : @owned $Builtin.NativeObject, %0b : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobjectpair_user : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| %1 = alloc_stack $NativeObjectPair |
| %1a = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| %1b = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.y |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| br bb5 |
| |
| bb5: |
| %2 = load [copy] %1 : $*NativeObjectPair |
| cond_br undef, bb6, bb7 |
| |
| bb6: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| destroy_value %2 : $NativeObjectPair |
| br bb5 |
| |
| bb7: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| destroy_value %2 : $NativeObjectPair |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @load_copy_multiple_available_values_diamond_followed_by_loop_reload : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load [copy] {{%.*}} : $*NativeObjectPair |
| // CHECK: } // end sil function 'load_copy_multiple_available_values_diamond_followed_by_loop_reload' |
| sil [ossa] @load_copy_multiple_available_values_diamond_followed_by_loop_reload : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @owned Builtin.NativeObject) -> () { |
| bb0(%0a : @owned $Builtin.NativeObject, %0b : @owned $Builtin.NativeObject, %0c : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobjectpair_user : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| %1 = alloc_stack $NativeObjectPair |
| %1a = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| %1b = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.y |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0c to [init] %1b : $*Builtin.NativeObject |
| destroy_value %0b : $Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| destroy_value %0c : $Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| br bb5 |
| |
| bb5: |
| %2 = load [copy] %1 : $*NativeObjectPair |
| cond_br undef, bb6, bb7 |
| |
| bb6: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| destroy_value %2 : $NativeObjectPair |
| br bb5 |
| |
| bb7: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| destroy_value %2 : $NativeObjectPair |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @load_copy_multiple_available_values_diamond_followed_by_loop_store_in_loop : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| // CHECK-NOT: load [copy] {{%.*}} : $*NativeObjectPair |
| // CHECK: } // end sil function 'load_copy_multiple_available_values_diamond_followed_by_loop_store_in_loop' |
| sil [ossa] @load_copy_multiple_available_values_diamond_followed_by_loop_store_in_loop : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| bb0(%0a : @owned $Builtin.NativeObject, %0b : @owned $Builtin.NativeObject, %0c : @guaranteed $Builtin.NativeObject): |
| %func = function_ref @nativeobjectpair_user : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| %1 = alloc_stack $NativeObjectPair |
| %1a = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| %1b = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.y |
| %0bhat = copy_value %0b : $Builtin.NativeObject |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb2: |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| br bb3 |
| |
| bb3: |
| br bb4 |
| |
| bb4: |
| br bb5 |
| |
| bb5: |
| %2 = load [copy] %1 : $*NativeObjectPair |
| cond_br undef, bb6, bb7 |
| |
| bb6: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| destroy_value %2 : $NativeObjectPair |
| destroy_addr %1b : $*Builtin.NativeObject |
| %0bhat2 = copy_value %0bhat : $Builtin.NativeObject |
| store %0bhat2 to [init] %1b : $*Builtin.NativeObject |
| br bb5 |
| |
| bb7: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| destroy_value %2 : $NativeObjectPair |
| destroy_value %0bhat : $Builtin.NativeObject |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [canonical] [ossa] @loop_carry_loadcopy : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load [copy] |
| // CHECK: } // end sil function 'loop_carry_loadcopy' |
| sil [canonical] [ossa] @loop_carry_loadcopy : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| %1 = alloc_stack $Builtin.NativeObject |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| cond_br undef, bb1, bb7 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| %2 = load [copy] %1 : $*Builtin.NativeObject |
| cond_br undef, bb4, bb5 |
| |
| bb4: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| destroy_value %2 : $Builtin.NativeObject |
| br bb2 |
| |
| bb5: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| destroy_value %2 : $Builtin.NativeObject |
| br bb6 |
| |
| bb6: |
| br bb8 |
| |
| bb7: |
| br bb8 |
| |
| bb8: |
| destroy_addr %1 : $*Builtin.NativeObject |
| dealloc_stack %1 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [canonical] [ossa] @loop_carry_loadcopy_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load [copy] |
| // CHECK: } // end sil function 'loop_carry_loadcopy_2' |
| sil [canonical] [ossa] @loop_carry_loadcopy_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%0 : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| %1 = alloc_stack $Builtin.NativeObject |
| store %0 to [init] %1 : $*Builtin.NativeObject |
| cond_br undef, bb1, bb7 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| %2 = load [copy] %1 : $*Builtin.NativeObject |
| cond_br undef, bb4, bb5 |
| |
| bb4: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| destroy_value %2 : $Builtin.NativeObject |
| br bb2 |
| |
| bb5: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| destroy_value %2 : $Builtin.NativeObject |
| br bb6 |
| |
| bb6: |
| br bb8 |
| |
| bb7: |
| br bb8 |
| |
| bb8: |
| destroy_addr %1 : $*Builtin.NativeObject |
| dealloc_stack %1 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [canonical] [ossa] @loop_carry_loadcopy_3 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| // CHECK-NOT: load [copy] |
| // CHECK: } // end sil function 'loop_carry_loadcopy_3' |
| sil [canonical] [ossa] @loop_carry_loadcopy_3 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| bb0(%0a : @owned $Builtin.NativeObject, %0b : @owned $Builtin.NativeObject, %0c : @guaranteed $Builtin.NativeObject): |
| %func = function_ref @nativeobject_tuple_user : $@convention(thin) (@guaranteed (Builtin.NativeObject, Builtin.NativeObject)) -> () |
| %1 = alloc_stack $(Builtin.NativeObject, Builtin.NativeObject) |
| %1a = tuple_element_addr %1 : $*(Builtin.NativeObject, Builtin.NativeObject), 0 |
| %1b = tuple_element_addr %1 : $*(Builtin.NativeObject, Builtin.NativeObject), 1 |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| cond_br undef, bb1, bb7 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| %0ccopy = copy_value %0c : $Builtin.NativeObject |
| destroy_addr %1a : $*Builtin.NativeObject |
| store %0ccopy to [init] %1a : $*Builtin.NativeObject |
| %2 = load [copy] %1 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| cond_br undef, bb4, bb5 |
| |
| bb4: |
| apply %func(%2) : $@convention(thin) (@guaranteed (Builtin.NativeObject, Builtin.NativeObject)) -> () |
| destroy_value %2 : $(Builtin.NativeObject, Builtin.NativeObject) |
| br bb2 |
| |
| bb5: |
| apply %func(%2) : $@convention(thin) (@guaranteed (Builtin.NativeObject, Builtin.NativeObject)) -> () |
| destroy_value %2 : $(Builtin.NativeObject, Builtin.NativeObject) |
| br bb6 |
| |
| bb6: |
| br bb8 |
| |
| bb7: |
| br bb8 |
| |
| bb8: |
| destroy_addr %1 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| dealloc_stack %1 : $*(Builtin.NativeObject, Builtin.NativeObject) |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [canonical] [ossa] @loop_carry_loadcopy_4 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| // CHECK-NOT: load [copy] |
| // CHECK: } // end sil function 'loop_carry_loadcopy_4' |
| sil [canonical] [ossa] @loop_carry_loadcopy_4 : $@convention(thin) (@owned Builtin.NativeObject, @owned Builtin.NativeObject, @guaranteed Builtin.NativeObject) -> () { |
| bb0(%0a : @owned $Builtin.NativeObject, %0b : @owned $Builtin.NativeObject, %0c : @guaranteed $Builtin.NativeObject): |
| %func = function_ref @nativeobjectpair_user : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| %1 = alloc_stack $NativeObjectPair |
| %1a = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.x |
| %1b = struct_element_addr %1 : $*NativeObjectPair, #NativeObjectPair.y |
| store %0a to [init] %1a : $*Builtin.NativeObject |
| store %0b to [init] %1b : $*Builtin.NativeObject |
| cond_br undef, bb1, bb7 |
| |
| bb1: |
| br bb2 |
| |
| bb2: |
| br bb3 |
| |
| bb3: |
| %0ccopy = copy_value %0c : $Builtin.NativeObject |
| destroy_addr %1a : $*Builtin.NativeObject |
| store %0ccopy to [init] %1a : $*Builtin.NativeObject |
| %2 = load [copy] %1 : $*NativeObjectPair |
| cond_br undef, bb4, bb5 |
| |
| bb4: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| destroy_value %2 : $NativeObjectPair |
| br bb2 |
| |
| bb5: |
| apply %func(%2) : $@convention(thin) (@guaranteed NativeObjectPair) -> () |
| destroy_value %2 : $NativeObjectPair |
| br bb6 |
| |
| bb6: |
| br bb8 |
| |
| bb7: |
| br bb8 |
| |
| bb8: |
| destroy_addr %1 : $*NativeObjectPair |
| dealloc_stack %1 : $*NativeObjectPair |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // CHECK-LABEL: sil [ossa] @load_copy_loop_carry_load_copy_phi_not_control_equivalent : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load [copy] |
| // CHECK: } // end sil function 'load_copy_loop_carry_load_copy_phi_not_control_equivalent' |
| sil [ossa] @load_copy_loop_carry_load_copy_phi_not_control_equivalent : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%arg : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| %0 = alloc_stack $Builtin.NativeObject |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| cond_br undef, bb3, bb4 |
| |
| bb2: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb5 |
| |
| bb3: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb6 |
| |
| bb4: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb7 |
| |
| bb5: |
| br bb8 |
| |
| bb6: |
| br bb8 |
| |
| bb7: |
| br bbPreLoopHeader |
| |
| bb8: |
| br bbPreLoopHeader |
| |
| bbPreLoopHeader: |
| br bbLoop |
| |
| bbLoop: |
| br bbLoop1 |
| |
| bbLoop1: |
| br bbLoop2 |
| |
| bbLoop2: |
| %2 = load [copy] %0 : $*Builtin.NativeObject |
| cond_br undef, bbLoop3, bbLoop4 |
| |
| bbLoop3: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| destroy_value %2 : $Builtin.NativeObject |
| br bbLoop2 |
| |
| bbLoop4: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| destroy_value %2 : $Builtin.NativeObject |
| br bbEnd |
| |
| bbEnd: |
| destroy_addr %0 : $*Builtin.NativeObject |
| dealloc_stack %0 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |
| // In this case, we will have that we need to separately lifetime extend our phi |
| // node's copy to prevent leaks along the edge skipping the loop. |
| // CHECK-LABEL: sil [ossa] @load_copy_loop_carry_load_copy_phi_not_control_equivalent_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| // CHECK-NOT: load [copy] |
| // CHECK: } // end sil function 'load_copy_loop_carry_load_copy_phi_not_control_equivalent_2' |
| sil [ossa] @load_copy_loop_carry_load_copy_phi_not_control_equivalent_2 : $@convention(thin) (@owned Builtin.NativeObject) -> () { |
| bb0(%arg : @owned $Builtin.NativeObject): |
| %func = function_ref @nativeobject_user : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| %0 = alloc_stack $Builtin.NativeObject |
| cond_br undef, bb1, bb2 |
| |
| bb1: |
| cond_br undef, bb3, bb4 |
| |
| bb2: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb5 |
| |
| bb3: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb6 |
| |
| bb4: |
| store %arg to [init] %0 : $*Builtin.NativeObject |
| br bb7 |
| |
| bb5: |
| br bb8a |
| |
| bb6: |
| br bb8a |
| |
| bb7: |
| br bbPreLoopHeader |
| |
| bb8a: |
| br bb8 |
| |
| bb8: |
| cond_br undef, bbPreLoopHeader1, bbSkipLoop |
| |
| bbPreLoopHeader: |
| br bbLoop |
| |
| bbPreLoopHeader1: |
| br bbLoop |
| |
| bbLoop: |
| br bbLoop1 |
| |
| bbLoop1: |
| br bbLoop2 |
| |
| bbLoop2: |
| %2 = load [copy] %0 : $*Builtin.NativeObject |
| br bbLoop6 |
| |
| bbLoop6: |
| cond_br undef, bbLoop3, bbLoop4 |
| |
| bbLoop3: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| destroy_value %2 : $Builtin.NativeObject |
| br bbLoop5 |
| |
| bbLoop5: |
| br bbLoop2 |
| |
| bbLoop4: |
| apply %func(%2) : $@convention(thin) (@guaranteed Builtin.NativeObject) -> () |
| destroy_value %2 : $Builtin.NativeObject |
| br bbEnd |
| |
| bbSkipLoop: |
| br bbEnd |
| |
| bbEnd: |
| destroy_addr %0 : $*Builtin.NativeObject |
| dealloc_stack %0 : $*Builtin.NativeObject |
| %9999 = tuple() |
| return %9999 : $() |
| } |
| |