Skip to content

Commit da5857d

Browse files
committed
EscapeInfo: improve handling of begin_applys which yield an address value
Instead of just aborting if a `begin_apply` gets an address argument, follow the yielded values and see if they actually escape
1 parent 8f25313 commit da5857d

File tree

2 files changed

+36
-15
lines changed

2 files changed

+36
-15
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/EscapeUtils.swift

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -615,10 +615,14 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
615615
}
616616

617617
// Indirect arguments cannot escape the function, but loaded values from such can.
618-
if !followLoads(at: path) &&
619-
// Except for begin_apply: it can yield an address value.
620-
!apply.isBeginApplyWithIndirectResults {
621-
return .continueWalk
618+
if !followLoads(at: path) {
619+
guard let beginApply = apply as? BeginApplyInst else {
620+
return .continueWalk
621+
}
622+
// Except for begin_apply: it can yield an address value.
623+
if !indirectResultEscapes(of: beginApply, path: path) {
624+
return .continueWalk
625+
}
622626
}
623627

624628
if argOp.value.type.isNoEscapeFunction {
@@ -658,7 +662,16 @@ fileprivate struct EscapeWalker<V: EscapeVisitor> : ValueDefUseWalker,
658662
}
659663
return .continueWalk
660664
}
661-
665+
666+
private mutating func indirectResultEscapes(of beginApply: BeginApplyInst, path: Path) -> Bool {
667+
for result in beginApply.yieldedValues where result.type.isAddress {
668+
if walkDownUses(ofAddress: result, path: path) == .abortWalk {
669+
return true
670+
}
671+
}
672+
return false
673+
}
674+
662675
/// Handle `.escaping` effects for an apply argument during the walk-down.
663676
private mutating
664677
func walkDownArgument(calleeArgIdx: Int, argPath: Path,
@@ -928,13 +941,3 @@ private extension SmallProjectionPath {
928941
EscapeUtilityTypes.EscapePath(projectionPath: self, followStores: false, addressIsStored: false, knownType: nil)
929942
}
930943
}
931-
932-
private extension ApplySite {
933-
var isBeginApplyWithIndirectResults: Bool {
934-
guard let ba = self as? BeginApplyInst else {
935-
return false
936-
}
937-
// Note that the token result is always a non-address type.
938-
return ba.results.contains { $0.type.isAddress }
939-
}
940-
}

test/SILOptimizer/mem-behavior.sil

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,24 @@ bb2:
380380
unreachable
381381
}
382382

383+
// CHECK-LABEL: @test_indirect_yield
384+
// CHECK: PAIR #3.
385+
// CHECK-NEXT: store %0 to %4 : $*Int32
386+
// CHECK-NEXT: %1 = alloc_stack $Int32
387+
// CHECK-NEXT: r=0,w=1
388+
sil @test_indirect_yield : $@convention(thin) (Int32) -> () {
389+
bb0(%0 : $Int32):
390+
%1 = alloc_stack $Int32
391+
store %0 to %1 : $*Int32
392+
%3 = function_ref @indirect_yield_coroutine : $@yield_once @convention(thin) (@inout Int32) -> @yields @inout Int32
393+
(%4, %5) = begin_apply %3(%1) : $@yield_once @convention(thin) (@inout Int32) -> @yields @inout Int32
394+
store %0 to %4 : $*Int32
395+
end_apply %5 as $()
396+
dealloc_stack %1 : $*Int32
397+
%9 = tuple ()
398+
return %9 : $()
399+
}
400+
383401
// CHECK-LABEL: @refelementaddr_and_reference
384402
// CHECK: PAIR #0.
385403
// CHECK-NEXT: %3 = apply %2(%0) : $@convention(thin) (@guaranteed X) -> Int32

0 commit comments

Comments
 (0)