Skip to content

Commit 827df01

Browse files
Merge pull request #41310 from nate-chandler/lexical_lifetimes/destroy_hoisting/enable
[SILOpt] Enabled SSADestroyHoisting.
2 parents d870a9f + b516b04 commit 827df01

File tree

9 files changed

+77
-35
lines changed

9 files changed

+77
-35
lines changed

lib/SIL/IR/SILInstruction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1382,7 +1382,7 @@ bool SILInstruction::mayTrap() const {
13821382
bool SILInstruction::maySynchronize() const {
13831383
// TODO: We need side-effect analysis and library annotation for this to be
13841384
// a reasonable API. For now, this is just a placeholder.
1385-
return isa<FullApplySite>(this);
1385+
return isa<FullApplySite>(this) || isa<EndApplyInst>(this);
13861386
}
13871387

13881388
bool SILInstruction::isMetaInstruction() const {

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,42 +1959,34 @@ bool GatherUniqueStorageUses::visitUse(Operand *use, AccessUseType useTy) {
19591959
case SILArgumentConvention::Indirect_Inout:
19601960
case SILArgumentConvention::Indirect_InoutAliasable:
19611961
case SILArgumentConvention::Indirect_Out:
1962-
visitor.visitStore(use);
1963-
break;
1962+
return visitor.visitStore(use);
19641963
case SILArgumentConvention::Indirect_In_Guaranteed:
19651964
case SILArgumentConvention::Indirect_In:
19661965
case SILArgumentConvention::Indirect_In_Constant:
1967-
visitor.visitLoad(use);
1968-
break;
1966+
return visitor.visitLoad(use);
19691967
case SILArgumentConvention::Direct_Unowned:
19701968
case SILArgumentConvention::Direct_Owned:
19711969
case SILArgumentConvention::Direct_Guaranteed:
19721970
// most likely an escape of a box
1973-
visitor.visitUnknownUse(use);
1974-
break;
1971+
return visitor.visitUnknownUse(use);
19751972
}
1976-
return true;
19771973
}
19781974
switch (user->getKind()) {
19791975
case SILInstructionKind::DestroyAddrInst:
19801976
case SILInstructionKind::DestroyValueInst:
19811977
if (useTy == AccessUseType::Exact) {
1982-
visitor.visitDestroy(use);
1983-
return true;
1978+
return visitor.visitDestroy(use);
19841979
}
1985-
visitor.visitUnknownUse(use);
1986-
return true;
1980+
return visitor.visitUnknownUse(use);
19871981

19881982
case SILInstructionKind::DebugValueInst:
1989-
visitor.visitDebugUse(use);
1990-
return true;
1983+
return visitor.visitDebugUse(use);
19911984

19921985
case SILInstructionKind::LoadInst:
19931986
case SILInstructionKind::LoadWeakInst:
19941987
case SILInstructionKind::LoadUnownedInst:
19951988
case SILInstructionKind::ExistentialMetatypeInst:
1996-
visitor.visitLoad(use);
1997-
return true;
1989+
return visitor.visitLoad(use);
19981990

19991991
case SILInstructionKind::StoreInst:
20001992
case SILInstructionKind::StoreWeakInst:
@@ -2006,27 +1998,22 @@ bool GatherUniqueStorageUses::visitUse(Operand *use, AccessUseType useTy) {
20061998
break;
20071999

20082000
case SILInstructionKind::InjectEnumAddrInst:
2009-
visitor.visitStore(use);
2010-
return true;
2001+
return visitor.visitStore(use);
20112002

20122003
case SILInstructionKind::CopyAddrInst:
20132004
if (operIdx == CopyLikeInstruction::Dest) {
2014-
visitor.visitStore(use);
2015-
return true;
2005+
return visitor.visitStore(use);
20162006
}
20172007
assert(operIdx == CopyLikeInstruction::Src);
2018-
visitor.visitLoad(use);
2019-
return true;
2008+
return visitor.visitLoad(use);
20202009

20212010
case SILInstructionKind::DeallocStackInst:
2022-
visitor.visitDealloc(use);
2023-
return true;
2011+
return visitor.visitDealloc(use);
20242012

20252013
default:
20262014
break;
20272015
}
2028-
visitor.visitUnknownUse(use);
2029-
return true;
2016+
return visitor.visitUnknownUse(use);
20302017
}
20312018

20322019
//===----------------------------------------------------------------------===//

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ void addFunctionPasses(SILPassPipelinePlan &P,
346346
// Promote box allocations to stack allocations.
347347
P.addAllocBoxToStack();
348348

349+
P.addSSADestroyHoisting();
350+
349351
// Propagate copies through stack locations. Should run after
350352
// box-to-stack promotion since it is limited to propagating through
351353
// stack locations. Should run before aggregate lowering since that

lib/SILOptimizer/Transforms/SSADestroyHoisting.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212
///
1313
/// This is a light-weight utility for hoisting destroy instructions for unique
14-
/// storage--typically alloc_stac or owned incoming arguments. Shrinking an
14+
/// storage--typically alloc_stack or owned incoming arguments. Shrinking an
1515
/// object's memory lifetime can allow removal of copy_addr and other
1616
/// optimization.
1717
///
@@ -206,6 +206,9 @@ class DeinitBarriers {
206206
}
207207

208208
private:
209+
DeinitBarriers(DeinitBarriers const &) = delete;
210+
DeinitBarriers &operator=(DeinitBarriers const &) = delete;
211+
209212
// Conforms to BackwardReachability::BlockReachability
210213
class DestroyReachability {
211214
const KnownStorageUses &knownUses;
@@ -386,9 +389,13 @@ bool HoistDestroys::rewriteDestroys(const KnownStorageUses &knownUses,
386389
bool HoistDestroys::foldBarrier(SILInstruction *barrier) {
387390
if (auto *load = dyn_cast<LoadInst>(barrier)) {
388391
if (load->getOperand() == storageRoot) {
389-
assert(load->getOwnershipQualifier() == LoadOwnershipQualifier::Copy);
390-
load->setOwnershipQualifier(LoadOwnershipQualifier::Take);
391-
return true;
392+
if (load->getOwnershipQualifier() == LoadOwnershipQualifier::Copy) {
393+
load->setOwnershipQualifier(LoadOwnershipQualifier::Take);
394+
return true;
395+
} else {
396+
assert(load->getOperand()->getType().isTrivial(*load->getFunction()));
397+
return false;
398+
}
392399
}
393400
}
394401
if (auto *copy = dyn_cast<CopyAddrInst>(barrier)) {

test/SILOptimizer/bridged_casts_folding.sil

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@ bb3(%8 : @owned $NSObjectSubclass):
4949

5050
// CHECK-LABEL: sil @anyhashable_cast_take_on_success
5151
// CHECK: [[BRIDGED:%.*]] = apply {{.*}}(%0)
52-
// CHECK-NEXT: checked_cast_br [[BRIDGED]] : $NSObject to NSObjectSubclass, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
53-
// CHECK: [[YES]]{{.*}}:
5452
// CHECK-NEXT: destroy_addr %0
53+
// CHECK-NEXT: checked_cast_br [[BRIDGED]] : $NSObject to NSObjectSubclass, {{bb[0-9]+}}, {{bb[0-9]+}}
5554
sil [ossa] @anyhashable_cast_take_on_success : $@convention(thin) (@in AnyHashable, @owned NSObjectSubclass) -> @owned NSObjectSubclass {
5655
entry(%0 : $*AnyHashable, %1 : @owned $NSObjectSubclass):
5756
%2 = alloc_stack $NSObjectSubclass

test/SILOptimizer/bridged_casts_folding_ownership.sil

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,8 @@ bb3(%8 : @owned $NSObjectSubclass):
5151

5252
// CHECK-LABEL: sil @anyhashable_cast_take_on_success
5353
// CHECK: [[BRIDGED:%.*]] = apply {{.*}}(%0)
54-
// CHECK-NEXT: checked_cast_br [[BRIDGED]] : $NSObject to NSObjectSubclass, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
55-
// CHECK: [[YES]]{{.*}}:
5654
// CHECK-NEXT: destroy_addr %0
55+
// CHECK-NEXT: checked_cast_br [[BRIDGED]] : $NSObject to NSObjectSubclass, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
5756
sil [ossa] @anyhashable_cast_take_on_success : $@convention(thin) (@in AnyHashable, @owned NSObjectSubclass) -> @owned NSObjectSubclass {
5857
entry(%0 : $*AnyHashable, %1 : @owned $NSObjectSubclass):
5958
%2 = alloc_stack $NSObjectSubclass

test/SILOptimizer/capture_promotion_generic_context_ownership.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ entry(%0 : $*T, %b : @owned $<τ_0_0> { var τ_0_0 } <Int>):
5353

5454
// CHECK-LABEL: sil @call_generic_promotable_box_from_different_generic
5555
// CHECK: bb0([[ARG0:%.*]] : $*T, [[ARG1:%.*]] : $*U, [[ARG2:%.*]] : $Builtin.Int32):
56-
// CHECK-NEXT: destroy_addr [[ARG0]] : $*T
5756
// CHECK-NEXT: destroy_addr [[ARG1]] : $*U
57+
// CHECK-NEXT: destroy_addr [[ARG0]] : $*T
5858
// CHECK: [[F:%.*]] = function_ref @$s22generic_promotable_boxTf2ni_n : $@convention(thin) <τ_0_0> (@in τ_0_0, Builtin.Int32) -> Builtin.Int32
5959
// CHECK-NEXT: [[CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[F]]<U>([[ARG2]])
6060
// CHECK-NEXT: return [[CLOSURE]]

test/SILOptimizer/hoist_destroy_addr.sil

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,16 @@ public enum E {
3939
case B
4040
}
4141

42+
struct TrivialStruct {
43+
var e: E
44+
}
45+
4246
sil @unknown : $@convention(thin) () -> ()
4347
sil @use_S : $@convention(thin) (@in_guaranteed S) -> ()
4448

4549
sil @f_out : $@convention(thin) <T> () -> @out T
4650
sil @f_bool : $@convention(thin) () -> Builtin.Int1
51+
sil [ossa] @take_trivial_struct : $@convention(thin) (TrivialStruct) -> ()
4752

4853
// CHECK-LABEL: sil [ossa] @test_simple
4954
// CHECK: bb0(%0 : $*S):
@@ -229,3 +234,23 @@ bb3:
229234
return %16 : $()
230235
}
231236

237+
// Hoist a destroy_addr of a trivial value over a function_ref. DO NOT fold
238+
// with the load [trivial].
239+
//
240+
// CHECK-LABEL: sil [ossa] @test_hoist_trivial : {{.*}} {
241+
// CHECK: load [trivial]
242+
// CHECK: function_ref
243+
// CHECK-LABEL: } // end sil function 'test_hoist_trivial'
244+
sil [ossa] @test_hoist_trivial : $@convention(thin) (TrivialStruct) -> () {
245+
entry(%instance : @none $TrivialStruct):
246+
%addr = alloc_stack $TrivialStruct
247+
store %instance to [trivial] %addr : $*TrivialStruct
248+
%copy = load [trivial] %addr : $*TrivialStruct
249+
%take_trivial_struct = function_ref @take_trivial_struct : $@convention(thin) (TrivialStruct) -> ()
250+
destroy_addr %addr : $*TrivialStruct
251+
apply %take_trivial_struct(%copy) : $@convention(thin) (TrivialStruct) -> ()
252+
dealloc_stack %addr : $*TrivialStruct
253+
254+
%retval = tuple ()
255+
return %retval : $()
256+
}

test/SILOptimizer/shrink_borrow_scope.sil

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class C {
1111
weak var d: D?
1212
}
1313
class D {}
14+
struct S {}
1415
class DBox {
1516
var d: D
1617
}
@@ -32,6 +33,7 @@ sil [ossa] @callee_guaranteed: $@convention(thin) (@guaranteed C) -> ()
3233
sil [ossa] @callee_owned : $@convention(thin) (@owned C) -> ()
3334
sil [ossa] @callee_optional_d_guaranteed: $@convention(thin) (@guaranteed Optional<D>) -> ()
3435
sil [ossa] @synchronization_point : $@convention(thin) () -> ()
36+
sil [ossa] @modify_s : $@yield_once @convention(thin) () -> @yields @inout S
3537

3638
// =============================================================================
3739
// = DECLARATIONS }}
@@ -806,6 +808,27 @@ exit:
806808
return %retval : $()
807809
}
808810

811+
// Don't hoist over end_apply. These are lowered to calls to continuations
812+
// which can have the same sorts of side-effects as function calls.
813+
814+
// CHECK-LABEL: sil [ossa] @dont_hoist_over_end_apply : {{.*}} {
815+
// CHECK: end_apply
816+
// CHECK: end_borrow
817+
// CHECK-LABEL: } // end sil function 'dont_hoist_over_end_apply'
818+
sil [ossa] @dont_hoist_over_end_apply : $@convention(thin) (@owned C, S) -> () {
819+
entry(%instance : @owned $C, %input : $S):
820+
%lifetime = begin_borrow [lexical] %instance : $C
821+
%modify_s = function_ref @modify_s : $@yield_once @convention(thin) () -> @yields @inout S
822+
(%addr, %continuation) = begin_apply %modify_s() : $@yield_once @convention(thin) () -> @yields @inout S
823+
store %input to [trivial] %addr : $*S
824+
end_apply %continuation
825+
end_borrow %lifetime : $C
826+
destroy_value %instance : $C
827+
%retval = tuple ()
828+
return %retval : $()
829+
}
830+
831+
809832
// =============================================================================
810833
// instruction tests }}
811834
// =============================================================================

0 commit comments

Comments
 (0)