diff --git a/lib/SILOptimizer/LoopTransforms/ArrayOpt.h b/lib/SILOptimizer/LoopTransforms/ArrayOpt.h index 72ce2058b04ec..b1fd9efb4a577 100644 --- a/lib/SILOptimizer/LoopTransforms/ArrayOpt.h +++ b/lib/SILOptimizer/LoopTransforms/ArrayOpt.h @@ -31,7 +31,7 @@ namespace swift { /// Projections over the aggregate that do not access the struct are ignored. /// /// StructLoads records loads of the struct value. -/// StructAddressUsers records other uses of the struct address. +/// StructAddressUsers records all uses of the struct address. /// StructValueUsers records direct uses of the loaded struct. /// /// Projections of the struct over its elements are all similarly recorded in diff --git a/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp b/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp index 3f49ba9213fcc..93d8b4198e486 100644 --- a/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp +++ b/lib/SILOptimizer/LoopTransforms/ArrayPropertyOpt.cpp @@ -254,7 +254,6 @@ class ArrayPropertiesAnalysis { /// new array onto it. bool checkSafeArrayAddressUses(UserList &AddressUsers) { for (auto *UseInst : AddressUsers) { - if (UseInst->isDebugInstruction()) continue; @@ -263,6 +262,10 @@ class ArrayPropertiesAnalysis { continue; } + if (isa(UseInst)) { + continue; + } + if (auto *AI = dyn_cast(UseInst)) { if (ArraySemanticsCall(AI)) continue; diff --git a/test/SILOptimizer/array_specialize.sil b/test/SILOptimizer/array_specialize.sil index a59611c5a7c6b..82db3dbaf0e85 100644 --- a/test/SILOptimizer/array_specialize.sil +++ b/test/SILOptimizer/array_specialize.sil @@ -1,4 +1,4 @@ -// RUN: %target-sil-opt -enable-sil-verify-all %s -array-property-opt +// RUN: %target-sil-opt -enable-sil-verify-all %s -array-property-opt | %FileCheck %s sil_stage canonical @@ -21,6 +21,18 @@ enum MyBool{ class MyClass { } +// CHECK-LABEL: sil @clone_switch_enum_exit : +// CHECK: bb1: +// CHECK: [[FUNC1:%.*]] = function_ref @arrayPropertyIsNative +// CHECK: apply [[FUNC1]] +// CHECK: cond_br {{.*}}, bb11, bb2 +// CHECK: bb2: +// CHECK: br bb3 +// CHECK: bb3: +// CHECK: [[FUNC2:%.*]] = function_ref @arrayPropertyIsNative +// CHECK: apply [[FUNC2]] +// CHECK_LABEL: } // end sil function 'clone_switch_enum_exit' + /// We need to split the loop exit edge from bb1 to bb3 before updating ssa form /// after cloning. sil @clone_switch_enum_exit : $@convention(thin) (@inout MyArray, @inout MyBool) -> MyBool { @@ -55,6 +67,13 @@ bb6: protocol AProtocol : class { } +// CHECK-LABEL: sil @cant_handle_open_existential_use_outside_loop : +// CHECK: bb1: +// CHECK: [[FUNC1:%.*]] = function_ref @arrayPropertyIsNative +// CHECK: apply [[FUNC1]] +// CHECK-NOT: [[FUNC2:%.*]] = function_ref @arrayPropertyIsNative +// CHECK-NOT: apply [[FUNC2]] +// CHECK-LABEL: } // end sil function 'cant_handle_open_existential_use_outside_loop' sil @cant_handle_open_existential_use_outside_loop : $@convention(thin) (@inout MyArray, @inout MyBool, @owned AProtocol) -> MyBool { bb0(%0 : $*MyArray, %1 : $*MyBool, %10 : $AProtocol): %3 = load %0 : $*MyArray @@ -95,6 +114,17 @@ bb0(%0: $MyArray): sil @throwing_fun : $@convention(thin) () -> (MyBool, @error Error) +// CHECK-LABEL: sil @clone_try_apply_exit : +// CHECK: bb1: +// CHECK: [[FUNC1:%.*]] = function_ref @arrayPropertyIsNative +// CHECK: apply [[FUNC1]] +// CHECK: cond_br {{.*}}, bb10, bb2 +// CHECK: bb2: +// CHECK: br bb3 +// CHECK: bb3: +// CHECK: [[FUNC2:%.*]] = function_ref @arrayPropertyIsNative +// CHECK: apply [[FUNC2]] +// CHECK_LABEL: } // end sil function 'clone_try_apply_exit' sil @clone_try_apply_exit : $@convention(thin) (@inout MyArray, @inout MyBool) -> (MyBool, @error Error) { bb0(%0 : $*MyArray, %1 : $*MyBool): %3 = load %0 : $*MyArray @@ -122,6 +152,17 @@ bb6(%9 : $Error): throw %9 : $Error } +// CHECK-LABEL: sil @dominator_update_outside_non_exit_block : +// CHECK: bb1: +// CHECK: [[FUNC1:%.*]] = function_ref @arrayPropertyIsNative +// CHECK: apply [[FUNC1]] +// CHECK: cond_br {{.*}}, bb16, bb2 +// CHECK: bb2: +// CHECK: br bb3 +// CHECK: bb3: +// CHECK: [[FUNC2:%.*]] = function_ref @arrayPropertyIsNative +// CHECK: apply [[FUNC2]] +// CHECK_LABEL: } // end sil function 'dominator_update_outside_non_exit_block' sil @dominator_update_outside_non_exit_block : $@convention(thin) (@inout MyArray, @inout Builtin.Int1) -> Builtin.Int1 { bb0(%0 : $*MyArray, %1 : $*Builtin.Int1): %3 = load %0 : $*MyArray @@ -163,6 +204,17 @@ bb10: return %4 : $Builtin.Int1 } +// CHECK-LABEL: sil @dominator_update_outside_non_exit_block_2 : +// CHECK: bb1: +// CHECK: [[FUNC1:%.*]] = function_ref @arrayPropertyIsNative +// CHECK: apply [[FUNC1]] +// CHECK: cond_br {{.*}}, bb17, bb2 +// CHECK: bb2: +// CHECK: br bb3 +// CHECK: bb3: +// CHECK: [[FUNC2:%.*]] = function_ref @arrayPropertyIsNative +// CHECK: apply [[FUNC2]] +// CHECK_LABEL: } // end sil function 'dominator_update_outside_non_exit_block_2' sil @dominator_update_outside_non_exit_block_2 : $@convention(thin) (@inout MyArray, @inout Builtin.Int1) -> Builtin.Int1 { bb0(%0 : $*MyArray, %1 : $*Builtin.Int1): %3 = load %0 : $*MyArray diff --git a/unittests/runtime/Array.cpp b/unittests/runtime/Array.cpp index 9907d1e1e9796..aa3eec9a45a3a 100644 --- a/unittests/runtime/Array.cpp +++ b/unittests/runtime/Array.cpp @@ -43,6 +43,7 @@ extern "C" void swift_arrayInitWithCopy(OpaqueValue *dest, #define COPY_POD_TEST(kind) \ ValueWitnessTable pod_witnesses; \ + memset(&pod_witnesses, 0, sizeof(pod_witnesses)); \ initialize_pod_witness_table_size_uint32_t_stride_uint64_t(pod_witnesses); \ uint64_t srcArray[3] = {0, 1, 2}; \ uint64_t destArray[3] = {0x5A5A5A5AU, 0x5A5A5A5AU, 0x5A5A5A5AU}; \ @@ -296,6 +297,7 @@ extern "C" void swift_arrayDestroy(OpaqueValue *begin, size_t count, TEST(TestArrayCopy, test_swift_arrayDestroyPOD) { ValueWitnessTable pod_witnesses; + memset(&pod_witnesses, 0, sizeof(pod_witnesses)); initialize_pod_witness_table_size_uint32_t_stride_uint64_t(pod_witnesses); uint64_t array[3] = {0, 1, 2}; FullOpaqueMetadata testMetadata = {{&pod_witnesses},