File tree 2 files changed +35
-0
lines changed
lib/SILOptimizer/SILCombiner 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> {
371
371
// anything other than the init_existential_addr/open_existential_addr
372
372
// container.
373
373
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
+ }
374
386
for (auto *Op : getNonDebugUses (ASI)) {
375
387
visit (Op->getUser ());
376
388
Original file line number Diff line number Diff line change @@ -24,6 +24,12 @@ enum MaybeFileDescriptor: ~Copyable {
24
24
deinit
25
25
}
26
26
27
+ struct Wrapper<T>: ~Copyable {
28
+ var t: T
29
+ }
30
+
31
+ sil @getWrappedValue : $@convention(thin) <T> (@in_guaranteed Wrapper<T>) -> @out T
32
+
27
33
// Test that a release_value is not removed for a struct-with-deinit.
28
34
// Doing so would forget the deinit.
29
35
//
71
77
%9 = tuple ()
72
78
return %9 : $()
73
79
}
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