Skip to content

Commit 2aeabbf

Browse files
committed
Optimizer: Always respect deinit barriers when hoisting destroys.
Also for non-lexical lifetimes
1 parent 76799ce commit 2aeabbf

File tree

13 files changed

+58
-33
lines changed

13 files changed

+58
-33
lines changed

include/swift/SILOptimizer/Utils/OSSACanonicalizeOwned.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -480,11 +480,16 @@ class OSSACanonicalizeOwned final {
480480
}
481481

482482
bool respectsDeinitBarriers() const {
483-
if (!currentDef->isLexical())
483+
auto &module = currentDef->getFunction()->getModule();
484+
485+
// The move-only checker (which runs in raw SIL) relies on ignoring deinit
486+
// barriers for non-lexical lifetimes.
487+
// Optimizations, on the other hand, should always respect deinit barriers.
488+
if (module.getStage() == SILStage::Raw && !currentDef->isLexical())
484489
return false;
490+
485491
if (currentDef->getFunction()->forceEnableLexicalLifetimes())
486492
return true;
487-
auto &module = currentDef->getFunction()->getModule();
488493
return module.getASTContext().SILOpts.supportsLexicalLifetimes(module);
489494
}
490495

lib/SILOptimizer/SemanticARC/CopyValueOpts.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -408,19 +408,16 @@ static bool tryJoinIfDestroyConsumingUseInSameBlock(
408408
return true;
409409
}
410410

411-
// The lifetime of the original ends after the lifetime of the copy. If the
412-
// original is lexical, its lifetime must not be shortened through deinit
413-
// barriers.
414-
if (cvi->getOperand()->isLexical()) {
415-
// At this point, visitedInsts contains all the instructions between the
416-
// consuming use of the copy and the destroy. If any of those instructions
417-
// is a deinit barrier, it would be illegal to shorten the original lexical
418-
// value's lifetime to end at that consuming use. Bail if any are.
419-
if (llvm::any_of(visitedInsts, [](auto *inst) {
420-
return mayBeDeinitBarrierNotConsideringSideEffects(inst);
421-
}))
422-
return false;
423-
}
411+
// The lifetime of the original ends after the lifetime of the copy.
412+
// Its lifetime must not be shortened through deinit barriers.
413+
// At this point, visitedInsts contains all the instructions between the
414+
// consuming use of the copy and the destroy. If any of those instructions
415+
// is a deinit barrier, it would be illegal to shorten the original lexical
416+
// value's lifetime to end at that consuming use. Bail if any are.
417+
if (llvm::any_of(visitedInsts, [](auto *inst) {
418+
return mayBeDeinitBarrierNotConsideringSideEffects(inst);
419+
}))
420+
return false;
424421

425422
// If we reached this point, isUseBetweenInstAndBlockEnd succeeded implying
426423
// that we found destroy_value to be after our consuming use. Noting that

lib/SILOptimizer/Transforms/DestroyAddrHoisting.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ void DestroyAddrHoisting::hoistDestroys(
990990
if (!continueWithNextSubpassRun(asi))
991991
return;
992992
changed |= ::hoistDestroys(asi,
993-
/*ignoreDeinitBarriers=*/!asi->isLexical(),
993+
/*ignoreDeinitBarriers=*/false,
994994
remainingDestroyAddrs, deleter, calleeAnalysis);
995995
}
996996
// Arguments enclose everything.

test/DebugInfo/debug_fragment_merge.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
// REQUIRES: CPU=arm64 || CPU=x86_64 || CPU=arm64e
55

6+
// The test currently fails because various optimizations optimize away most parts of the SIL.
7+
// TODO: re-write this test so that it's testing what it's intended to test.
8+
// REQUIRES: fix_this_test
9+
610
protocol External {
711
func use(str: String);
812
func decode<T>(_: T.Type) -> T

test/Interop/CxxToSwiftToCxx/consuming-cxx-struct-parameter-back-to-cxx-execution.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,9 @@ int main() {
175175
// CHECK-NEXT: take shared frt x 2
176176
UseCxx::consumeSharedFRT(&sfrt);
177177
// CHECK-NEXT: retainShared
178-
// CHECK-NEXT: releaseShared
179178
// CHECK-NEXT: consume shared frt x 2
180179
SharedFRT *sfrtptr = UseCxx::returnSharedFRT(&sfrt);
180+
// CHECK-NEXT: releaseShared
181181
// CHECK-NEXT: retainShared
182182
// CHECK-NEXT: return shared frt x 2
183183
SharedFRT *sfrtptr2 = UseCxx::returnSharedFRT2();
@@ -191,9 +191,9 @@ int main() {
191191
UseCxx::consumeValueWrapper(wrapper);
192192
// CHECK-NEXT: retainShared
193193
// CHECK-NEXT: retainShared
194-
// CHECK-NEXT: releaseShared
195194
// CHECK-NEXT: return shared frt x 4
196195
// CHECK-NEXT: releaseShared
196+
// CHECK-NEXT: releaseShared
197197
}
198198
{
199199
SharedFRT sfrt;

test/SILOptimizer/consuming_parameter.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
// CHECK-LABEL: sil [ossa] @async_dead_arg_call : {{.*}} {
66
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @noImplicitCopy @_eagerMove @owned
7-
// CHECK: destroy_value [[INSTANCE]]
87
// CHECK: [[EXECUTOR:%[^,]+]] = enum $Optional<any Actor>, #Optional.none!enumelt
98
// CHECK: [[CALLEE:%[^,]+]] = function_ref @async_callee
109
// CHECK: apply [[CALLEE]]()
1110
// CHECK: hop_to_executor [[EXECUTOR]]
11+
// CHECK: destroy_value [[INSTANCE]]
1212
// CHECK-LABEL: } // end sil function 'async_dead_arg_call'
1313
@_silgen_name("async_dead_arg_call")
1414
public func async_dead_arg_call(o: consuming AnyObject) async {
@@ -46,11 +46,11 @@ extension C {
4646
public class C {
4747
// CHECK-LABEL: sil [ossa] @async_dead_arg_call_method : {{.*}} {
4848
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @noImplicitCopy @_eagerMove @owned
49-
// CHECK: destroy_value [[INSTANCE]]
5049
// CHECK: [[EXECUTOR:%[^,]+]] = enum $Optional<any Actor>, #Optional.none!enumelt
5150
// CHECK: [[CALLEE:%[^,]+]] = function_ref @async_callee : $@convention(thin) @async () -> ()
5251
// CHECK: apply [[CALLEE]]() : $@convention(thin) @async () -> ()
5352
// CHECK: hop_to_executor [[EXECUTOR]]
53+
// CHECK: destroy_value [[INSTANCE]]
5454
// CHECK-LABEL: } // end sil function 'async_dead_arg_call_method'
5555
@_silgen_name("async_dead_arg_call_method")
5656
consuming

test/SILOptimizer/copy_propagation.sil

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,13 @@ struct MOS : ~Copyable {
2020
deinit {}
2121
}
2222

23-
sil [ossa] @dummy : $@convention(thin) () -> ()
23+
sil [ossa] @dummy : $@convention(thin) () -> () {
24+
[global:]
25+
}
2426
sil [ossa] @barrier : $@convention(thin) () -> ()
25-
sil [ossa] @getOwnedC : $@convention(thin) () -> (@owned C)
27+
sil [ossa] @getOwnedC : $@convention(thin) () -> (@owned C) {
28+
[global:]
29+
}
2630
sil [ossa] @getOwnedB : $@convention(thin) () -> (@owned B)
2731
sil [ossa] @takeOwnedC : $@convention(thin) (@owned C) -> ()
2832
sil [ossa] @takeOwnedCTwice : $@convention(thin) (@owned C, @owned C) -> ()
@@ -1076,7 +1080,7 @@ sil [ossa] @dontShortenDeadMoveOnlyLifetime : $@convention(thin) () -> () {
10761080

10771081
// CHECK-LABEL: sil [ossa] @look_through_end_init_let_ref :
10781082
// CHECK: [[E:%.*]] = end_init_let_ref
1079-
// CHECK: [[D:%.*]] = function_ref @dummy
1083+
// CHECK: [[D:%.*]] = function_ref @barrier
10801084
// CHECK: apply [[D]]
10811085
// CHECK: destroy_value [[E]]
10821086
// CHECK-LABEL: } // end sil function 'look_through_end_init_let_ref'
@@ -1087,7 +1091,7 @@ bb0:
10871091
%2 = end_init_let_ref %1
10881092
%4 = function_ref @takeGuaranteedC : $@convention(thin) (@guaranteed C) -> ()
10891093
apply %4(%2) : $@convention(thin) (@guaranteed C) -> ()
1090-
%6 = function_ref @dummy : $@convention(thin) () -> ()
1094+
%6 = function_ref @barrier : $@convention(thin) () -> ()
10911095
apply %6() : $@convention(thin) () -> ()
10921096
destroy_value %2
10931097
%3 = tuple ()

test/SILOptimizer/copy_propagation_borrow.sil

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ class C {
4141

4242
sil [ossa] @dummy : $@convention(thin) () -> ()
4343
sil [ossa] @getOwnedC : $@convention(thin) () -> (@owned C)
44-
sil [ossa] @takeOwnedC : $@convention(thin) (@owned C) -> ()
44+
sil [ossa] @takeOwnedC : $@convention(thin) (@owned C) -> () {
45+
[global:]
46+
}
4547
sil [ossa] @getOwnedWrapper : $@convention(thin) () -> (@owned Wrapper)
4648
sil [ossa] @getOwnedMultiWrapper : $@convention(thin) () -> (@owned MultiWrapper)
4749
sil [ossa] @getOwnedHasObjectAndInt : $@convention(thin) () -> (@owned HasObjectAndInt)

test/SILOptimizer/copy_propagation_canonicalize_with_reborrows.sil

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ enum FakeOptional<T> {
1010
}
1111

1212
sil [ossa] @getX : $@convention(thin) () -> (@owned X)
13-
sil [ossa] @holdX : $@convention(thin) (@guaranteed X) -> ()
13+
sil [ossa] @holdX : $@convention(thin) (@guaranteed X) -> () {
14+
[global:]
15+
}
1416

1517
// CHECK-LABEL: sil [ossa] @nohoist_destroy_over_reborrow_endborrow : {{.*}} {
1618
// CHECK: {{bb[0-9]+}}([[REBORROW:%[^,]+]] : @reborrow $X, [[VALUE:%[^,]+]] : @owned $X):

test/SILOptimizer/hoist_destroy_addr.sil

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ struct UnsafeMutablePointer<T> {
8989
}
9090

9191
sil @unknown : $@convention(thin) () -> ()
92+
sil @nobarrier : $@convention(thin) () -> () {
93+
[global:]
94+
}
9295
sil @use_S : $@convention(thin) (@in_guaranteed S) -> ()
9396

9497
// This function is not a synchronization point.
@@ -99,6 +102,9 @@ sil @empty : $@convention(thin) () -> () {
99102

100103
sil @f_out : $@convention(thin) <T> () -> @out T
101104
sil @f_bool : $@convention(thin) () -> Builtin.Int1
105+
sil @f_bool_no_barrier : $@convention(thin) () -> Builtin.Int1 {
106+
[global:]
107+
}
102108
sil [ossa] @take_trivial_struct : $@convention(thin) (TrivialStruct) -> ()
103109
sil [ossa] @get_change_out : $@convention(thin) () -> @out Change
104110
sil [ossa] @coro : $@yield_once @convention(thin) (@inout X) -> @yields ()
@@ -283,7 +289,7 @@ bb0(%0 : $*T, %1 : $Builtin.Int1):
283289
cond_br %1, bb1, bb2
284290

285291
bb1:
286-
%8 = function_ref @unknown : $@convention(thin) () -> ()
292+
%8 = function_ref @nobarrier : $@convention(thin) () -> ()
287293
%9 = apply %8() : $@convention(thin) () -> ()
288294
br bb3
289295

@@ -356,7 +362,7 @@ bb0(%0 : $*T):
356362
br bb1
357363

358364
bb1:
359-
%f = function_ref @f_bool : $@convention(thin) () -> Builtin.Int1
365+
%f = function_ref @f_bool_no_barrier : $@convention(thin) () -> Builtin.Int1
360366
%c = apply %f() : $@convention(thin) () -> Builtin.Int1
361367
cond_br %c, bb2, bb3
362368

@@ -492,7 +498,8 @@ entry(%instance : @owned $S):
492498
br applier
493499

494500
applier:
495-
apply undef() : $@convention(thin) () -> ()
501+
%f = function_ref @nobarrier : $@convention(thin) () -> ()
502+
apply %f() : $@convention(thin) () -> ()
496503
br good
497504

498505
good:
@@ -731,7 +738,7 @@ entry(%instance : @owned $S):
731738
end_access %store_scope : $*S
732739
%load_scope = begin_access [modify] [static] %addr : $*S
733740
%value = load [copy] %load_scope : $*S
734-
%unknown = function_ref @unknown : $@convention(thin) () -> ()
741+
%unknown = function_ref @nobarrier : $@convention(thin) () -> ()
735742
apply %unknown() : $@convention(thin) () -> ()
736743
end_access %load_scope : $*S
737744
destroy_addr %addr : $*S

0 commit comments

Comments
 (0)