Skip to content

Commit e328435

Browse files
authored
Merge pull request #80653 from atrick/62-address-escape-effect
[6.2] Fix escape analysis: addressable parameters.
2 parents 8802395 + bf6ed01 commit e328435

File tree

3 files changed

+109
-6
lines changed

3 files changed

+109
-6
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/EscapeUtils.swift

+7-5
Original file line numberDiff line numberDiff line change
@@ -641,11 +641,13 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
641641

642642
// Indirect arguments cannot escape the function, but loaded values from such can.
643643
if !followLoads(at: path) {
644-
guard let beginApply = apply as? BeginApplyInst else {
645-
return .continueWalk
646-
}
647-
// Except for begin_apply: it can yield an address value.
648-
if !indirectResultEscapes(of: beginApply, path: path) {
644+
if let beginApply = apply as? BeginApplyInst {
645+
// begin_apply can yield an address value.
646+
if !indirectResultEscapes(of: beginApply, path: path) {
647+
return .continueWalk
648+
}
649+
} else if !apply.isAddressable(operand: argOp) {
650+
// The result does not depend on the argument's address.
649651
return .continueWalk
650652
}
651653
}

SwiftCompilerSources/Sources/SIL/ApplySite.swift

+7
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,13 @@ extension ApplySite {
229229
functionConvention.resultDependencies != nil
230230
}
231231

232+
public func isAddressable(operand: Operand) -> Bool {
233+
if let dep = resultDependence(on: operand) {
234+
return dep.isAddressable(for: operand.value)
235+
}
236+
return false
237+
}
238+
232239
public var hasLifetimeDependence: Bool {
233240
functionConvention.hasLifetimeDependencies()
234241
}

test/SILOptimizer/addr_escape_info.sil

+95-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
// RUN: %target-sil-opt %s -dump-addr-escape-info -o /dev/null | %FileCheck %s
1+
// RUN: %target-sil-opt %s -dump-addr-escape-info -o /dev/null \
2+
// RUN: -enable-experimental-feature LifetimeDependence \
3+
// RUN: -enable-experimental-feature AddressableTypes \
4+
// RUN: | %FileCheck %s
5+
6+
// REQUIRES: swift_feature_LifetimeDependence
7+
// REQUIRES: swift_feature_AddressableTypes
28

39
// REQUIRES: swift_in_compiler
410

@@ -37,6 +43,13 @@ protocol P {}
3743

3844
extension Int : P {}
3945

46+
@_addressableForDependencies
47+
struct Addressable {
48+
@_hasStorage var a: Int
49+
}
50+
51+
struct NE : ~Escapable {}
52+
4053
sil @no_arguments : $@convention(thin) () -> ()
4154
sil @indirect_argument : $@convention(thin) (@in Int) -> ()
4255
sil @indirect_struct_argument : $@convention(thin) (@in Str) -> ()
@@ -69,6 +82,14 @@ sil @modifyStr : $@convention(method) (@inout Str) -> ()
6982
sil @guaranteed_yield_coroutine : $@yield_once @convention(thin) (@inout X) -> @yields @inout X
7083
sil @in_ptr : $@convention(thin) (@in Builtin.RawPointer) -> ()
7184

85+
sil @addressable_independent_arg : $@convention(thin) (@in_guaranteed Addressable) -> Builtin.RawPointer
86+
87+
sil @addressable_dependent_arg : $@convention(thin) (@in_guaranteed Addressable) -> @lifetime(borrow address_for_deps 0) @owned NE
88+
89+
sil @addressable_noescape_arg : $@convention(thin) (@in_guaranteed Addressable) -> @lifetime(borrow address_for_deps 0) @owned NE {
90+
[%0: noescape]
91+
}
92+
7293
// CHECK-LABEL: Address escape information for test_simple:
7394
// CHECK: value: %1 = struct_element_addr %0 : $*Str, #Str.a
7495
// CHECK-NEXT: ==> %7 = apply %6(%5) : $@convention(thin) (@in Int) -> ()
@@ -862,3 +883,76 @@ bb0(%0 : @guaranteed $X):
862883
return %3 : $()
863884
}
864885

886+
// CHECK-LABEL: Address escape information for noescape_via_independent_addressable:
887+
// CHECK: pair 0 - 1
888+
// CHECK-NEXT: apply %{{.*}}(%{{.*}}) : $@convention(thin) (@in_guaranteed Addressable) -> Builtin.RawPointer
889+
// CHECK-NEXT: alloc_stack $Addressable
890+
// CHECK-NEXT: no alias
891+
// CHECK-LABEL: End function noescape_via_independent_addressable
892+
sil [ossa] @noescape_via_independent_addressable : $@convention(thin) (Int) -> () {
893+
bb0(%0 : $Int):
894+
%1 = alloc_stack $Addressable
895+
%2 = struct_element_addr %1 : $*Addressable, #Addressable.a
896+
store %0 to [trivial] %2
897+
898+
%f = function_ref @addressable_independent_arg : $@convention(thin) (@in_guaranteed Addressable) -> Builtin.RawPointer
899+
%a = apply %f(%1) : $@convention(thin) (@in_guaranteed Addressable) -> Builtin.RawPointer
900+
901+
fix_lifetime %a
902+
fix_lifetime %1
903+
destroy_addr %1
904+
dealloc_stack %1
905+
906+
%9 = tuple ()
907+
return %9 : $()
908+
}
909+
910+
// CHECK-LABEL: Address escape information for escape_via_dependent_addressable:
911+
// CHECK: pair 0 - 1
912+
// CHECK-NEXT: %{{.*}} = apply %{{.*}}(%{{.*}}) : $@convention(thin) (@in_guaranteed Addressable) -> @lifetime(borrow address_for_deps 0) @owned NE
913+
// CHECK-NEXT: %{{.*}} = alloc_stack $Addressable
914+
// CHECK-NEXT: may alias
915+
// CHECK-LABEL: End function escape_via_dependent_addressable
916+
sil [ossa] @escape_via_dependent_addressable : $@convention(thin) (Int) -> () {
917+
bb0(%0 : $Int):
918+
%1 = alloc_stack $Addressable
919+
%2 = struct_element_addr %1 : $*Addressable, #Addressable.a
920+
store %0 to [trivial] %2
921+
922+
%f = function_ref @addressable_dependent_arg : $@convention(thin) (@in_guaranteed Addressable) -> @lifetime(borrow address_for_deps 0) @owned NE
923+
%a = apply %f(%1) : $@convention(thin) (@in_guaranteed Addressable) -> @lifetime(borrow address_for_deps 0) @owned NE
924+
925+
fix_lifetime %a
926+
fix_lifetime %1
927+
destroy_value %a
928+
destroy_addr %1
929+
dealloc_stack %1
930+
931+
%9 = tuple ()
932+
return %9 : $()
933+
}
934+
935+
// CHECK-LABEL: Address escape information for escape_via_noescape_addressable:
936+
// CHECK: pair 0 - 1
937+
// CHECK-NEXT: %{{.*}} = apply %{{.*}}(%{{.*}}) : $@convention(thin) (@in_guaranteed Addressable) -> @lifetime(borrow address_for_deps 0) @owned NE
938+
// CHECK-NEXT: %{{.*}} = alloc_stack $Addressable
939+
// CHECK-NEXT: no alias
940+
// CHECK-LABEL: End function escape_via_noescape_addressable
941+
sil [ossa] @escape_via_noescape_addressable : $@convention(thin) (Int) -> () {
942+
bb0(%0 : $Int):
943+
%1 = alloc_stack $Addressable
944+
%2 = struct_element_addr %1 : $*Addressable, #Addressable.a
945+
store %0 to [trivial] %2
946+
947+
%f = function_ref @addressable_noescape_arg : $@convention(thin) (@in_guaranteed Addressable) -> @lifetime(borrow address_for_deps 0) @owned NE
948+
%a = apply %f(%1) : $@convention(thin) (@in_guaranteed Addressable) -> @lifetime(borrow address_for_deps 0) @owned NE
949+
950+
fix_lifetime %a
951+
fix_lifetime %1
952+
destroy_value %a
953+
destroy_addr %1
954+
dealloc_stack %1
955+
956+
%9 = tuple ()
957+
return %9 : $()
958+
}

0 commit comments

Comments
 (0)