From 41dd3dc453a1cd8df099a7d28fb80d2632bcc92e Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Tue, 24 Dec 2024 11:56:34 +0100 Subject: [PATCH] DeadObjectElimination: handle OSSA instructions when analyzing class destructors Handle typical patterns which are generated by SILGen. --- lib/SIL/Utils/InstructionUtils.cpp | 1 + .../Transforms/DeadObjectElimination.cpp | 4 ++ test/SILOptimizer/dead_alloc_elim_ossa.sil | 38 +++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/lib/SIL/Utils/InstructionUtils.cpp b/lib/SIL/Utils/InstructionUtils.cpp index 60c1af0df33f8..f7af093151587 100644 --- a/lib/SIL/Utils/InstructionUtils.cpp +++ b/lib/SIL/Utils/InstructionUtils.cpp @@ -172,6 +172,7 @@ SILValue swift::stripCasts(SILValue v) { if (auto *svi = dyn_cast(v)) { if (isIdentityPreservingRefCast(svi) || isa(v) || isa(v) || + isa(v) || isa(v)) { v = cast(v)->getOperand(0); continue; diff --git a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp index feb7d98ca3bb1..6766f7b5ae5a4 100644 --- a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp +++ b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp @@ -204,6 +204,10 @@ static DestructorEffects doesDestructorHaveSideEffects(AllocRefInstBase *ARI) { continue; } + if (isa(I) || isa(I) || isa(I)) { + continue; + } + // dealloc_ref on self can be ignored, but dealloc_ref on anything else // cannot be eliminated. if (auto *DeallocRef = dyn_cast(&I)) { diff --git a/test/SILOptimizer/dead_alloc_elim_ossa.sil b/test/SILOptimizer/dead_alloc_elim_ossa.sil index 4a7f6846765fe..ed31b2c4eab7f 100644 --- a/test/SILOptimizer/dead_alloc_elim_ossa.sil +++ b/test/SILOptimizer/dead_alloc_elim_ossa.sil @@ -28,6 +28,11 @@ class ArrayStorage { init() } +class Kl2 { + @_hasStorage var i: Int +} + + protocol P { } struct X : P { } @@ -65,6 +70,19 @@ bb0(%0 : @owned $NontrivialDestructor): return %7 : $() } +sil [ossa] @$s4main3Kl2CfD : $@convention(method) (@owned Kl2) -> () { +bb0(%0 : @owned $Kl2): + %1 = begin_borrow %0 + %2 = unchecked_ref_cast %1 to $Builtin.NativeObject + %3 = unchecked_ownership_conversion %2, @guaranteed to @owned + end_borrow %1 + end_lifetime %0 + %6 = unchecked_ref_cast %3 to $Kl2 + dealloc_ref %6 + %8 = tuple () + return %8 +} + sil @ptr_user : $@convention(thin) (Builtin.NativeObject) -> () sil @int_user : $@convention(thin) (Builtin.Int32) -> () @@ -541,3 +559,23 @@ bb0(%0 : @owned $_ContiguousArrayStorage): return %15 : $() } +// CHECK-LABEL: sil [ossa] @dead_alloc_with_complex_ossa_destructor +// CHECK-NOT: alloc_ref +// CHECK: } // end sil function 'dead_alloc_with_complex_ossa_destructor' +sil [ossa] @dead_alloc_with_complex_ossa_destructor : $@convention(thin) () -> Int { +bb0: + %0 = alloc_ref $Kl2 + %1 = move_value [lexical] %0 + %2 = end_init_let_ref %1 + %3 = begin_borrow %2 + %4 = integer_literal $Builtin.Int64, 27 + %5 = struct $Int (%4) + %6 = ref_element_addr %3, #Kl2.i + store %5 to [trivial] %6 + end_borrow %3 + %9 = move_value [lexical] [var_decl] %2 + debug_value %9, let, name "k" + destroy_value %9 + return %5 +} +