File tree Expand file tree Collapse file tree 2 files changed +35
-0
lines changed
lib/SILOptimizer/SILCombiner Expand file tree Collapse file tree 2 files changed +35
-0
lines changed Original file line number Diff line number Diff line change @@ -371,6 +371,18 @@ struct AllocStackAnalyzer : SILInstructionVisitor<AllocStackAnalyzer> {
371371 // anything other than the init_existential_addr/open_existential_addr
372372 // container.
373373
374+ // There is no interesting scenario where a non-copyable type should have
375+ // its allocation eliminated. A destroy_addr cannot be removed because it
376+ // may run the struct-deinit, and the lifetime cannot be shortened. A
377+ // copy_addr [take] [init] cannot be replaced by a destroy_addr because the
378+ // destination may hold a 'discard'ed value, which is never destroyed. This
379+ // analysis assumes memory is deinitialized on all paths, which is not the
380+ // case for discarded values. Eventually copyable types may also be
381+ // discarded; to support that, we will leave a drop_deinit_addr in place.
382+ if (ASI->getType ().isPureMoveOnly ()) {
383+ LegalUsers = false ;
384+ return ;
385+ }
374386 for (auto *Op : getNonDebugUses (ASI)) {
375387 visit (Op->getUser ());
376388
Original file line number Diff line number Diff line change @@ -24,6 +24,12 @@ enum MaybeFileDescriptor: ~Copyable {
2424 deinit
2525}
2626
27+ struct Wrapper<T>: ~Copyable {
28+ var t: T
29+ }
30+
31+ sil @getWrappedValue : $@convention(thin) <T> (@in_guaranteed Wrapper<T>) -> @out T
32+
2733// Test that a release_value is not removed for a struct-with-deinit.
2834// Doing so would forget the deinit.
2935//
7177 %9 = tuple ()
7278 return %9 : $()
7379}
80+
81+ // Test that a move into a discarded value does not result in a destroy_addr
82+ //
83+ // CHECK-LABEL: sil @testNoDeinit : $@convention(method) <T> (@in Wrapper<T>) -> @out T {
84+ // CHECK-NOT: destroy_addr
85+ // CHECK-LABEL: } // end sil function 'testNoDeinit'
86+ sil @testNoDeinit : $@convention(method) <T> (@in Wrapper<T>) -> @out T {
87+ bb0(%0 : $*T, %1 : $*Wrapper<T>):
88+ %2 = function_ref @getWrappedValue : $@convention(thin) <T> (@in_guaranteed Wrapper<T>) -> @out T
89+ %3 = apply %2<T>(%0, %1) : $@convention(thin) <τ_0_0> (@in_guaranteed Wrapper<τ_0_0>) -> @out τ_0_0
90+ %4 = alloc_stack $Wrapper<T>
91+ copy_addr [take] %1 to [init] %4 : $*Wrapper<T>
92+ // discard
93+ dealloc_stack %4 : $*Wrapper<T>
94+ %9 = tuple ()
95+ return %9 : $()
96+ }
You can’t perform that action at this time.
0 commit comments