Skip to content

CapturePropagation: handle keypaths which are upcast. #78160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion lib/SILOptimizer/IPO/CapturePropagation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ static SILInstruction *getConstant(SILValue V) {
if (auto *lit = dyn_cast<LiteralInst>(V))
return lit;

if (auto *uc = dyn_cast<UpcastInst>(V))
V = uc->getOperand();

if (auto *kp = dyn_cast<KeyPathInst>(V)) {
// We could support operands, if they are constants, to enable propagation
// of subscript keypaths. This would require to add the operands in the
Expand Down Expand Up @@ -567,7 +570,11 @@ bool CapturePropagation::optimizePartialApply(PartialApplyInst *PAI) {
// keypath instruction in this pass, but let dead-object-elimination clean
// it up later.
if (!PAI->isOnStack()) {
if (getSingleNonDebugUser(kp) != PAI)
SILInstruction *user = getSingleNonDebugUser(kp);
if (auto *uc = dyn_cast_or_null<UpcastInst>(user))
user = getSingleNonDebugUser(uc);

if (user != PAI)
return false;
toDelete.push_back(kp);
}
Expand Down
20 changes: 20 additions & 0 deletions test/SILOptimizer/capture_propagate_keypath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@ struct GenStr<T> {
}
}

struct GetID<C: RandomAccessCollection, ID> {
var getID: (C.Element) -> ID

@inline(__always)
init(id: KeyPath<C.Element, ID>) {
getID = { $0[keyPath: id] }
}
}

// CHECK-LABEL: sil {{.*}} @$s4test0A6SimpleyyySiAA3StrVXEXEF :
// CHECK-NOT: keypath
Expand All @@ -50,6 +57,14 @@ func testGenStr(_ mymap: ((GenStr<Int>)->Int) -> ()) {
mymap(\.c)
}

// CHECK-LABEL: sil {{.*}} @$s4test0A22GenericEscapingClosureAA5GetIDVySayAA3StrVGSiGyF :
// CHECK-NOT: keypath
// CHECK-LABEL: } // end sil function '$s4test0A22GenericEscapingClosureAA5GetIDVySayAA3StrVGSiGyF'
@inline(never)
func testGenericEscapingClosure() -> GetID<[Str], Int> {
GetID(id: \.i)
}

// CHECK-LABEL: sil {{.*}} @$s4test0A7GenericyyyxAA6GenStrVyxGXEXElF :
// CHECK: keypath
// CHECK: keypath
Expand Down Expand Up @@ -103,6 +118,11 @@ func calltests() {
print(c(s))
}

// CHECK-OUTPUT-LABEL: testGenericEscapingClosure:
print("testGenericEscapingClosure:")

// CHECK-OUTPUT-NEXT: 27
print(testGenericEscapingClosure().getID(Str()))
}

calltests()
Expand Down
35 changes: 35 additions & 0 deletions test/SILOptimizer/capture_propagation.sil
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,23 @@ bb0:
return %7 : $()
}

// CHECK-LABEL: sil @testCastKeypath :
// CHECK-NOT: keypath
// CHECK: } // end sil function 'testCastKeypath'
sil @testCastKeypath : $@convention(thin) () -> () {
bb0:
%0 = keypath $WritableKeyPath<Str, Int>, (root $Str; stored_property #Str.a : $Int)
%c = upcast %0 to $KeyPath<Str, Int>
%1 = function_ref @closureWithKeypath : $@convention(thin) (Str, @guaranteed KeyPath<Str, Int>) -> Int
%2 = partial_apply [callee_guaranteed] %1(%c) : $@convention(thin) (Str, @guaranteed KeyPath<Str, Int>) -> Int
%3 = convert_escape_to_noescape %2 : $@callee_guaranteed (Str) -> Int to $@noescape @callee_guaranteed (Str) -> Int
%4 = function_ref @calleeWithKeypath : $@convention(thin) (@noescape @callee_guaranteed (Str) -> Int) -> ()
%5 = apply %4(%3) : $@convention(thin) (@noescape @callee_guaranteed (Str) -> Int) -> ()
strong_release %2 : $@callee_guaranteed (Str) -> Int
%7 = tuple ()
return %7 : $()
}

// CHECK-LABEL: sil shared @$s18closureWithKeypath{{.*}}main3StrVSiTf3npk_n : $@convention(thin) (Str) -> Int {
// CHECK: [[K:%[0-9]+]] = keypath
// CHECK: [[F:%[0-9]+]] = function_ref @swift_getAtKeyPath
Expand Down Expand Up @@ -566,6 +583,24 @@ bb0:
return %7 : $()
}

// CHECK-LABEL: sil [ossa] @testCastKeypathOSSA :
// CHECK-NOT: keypath
// CHECK: } // end sil function 'testCastKeypathOSSA'
sil [ossa] @testCastKeypathOSSA : $@convention(thin) () -> () {
bb0:
%0 = keypath $WritableKeyPath<Str, Int>, (root $Str; stored_property #Str.a : $Int)
%c = upcast %0 to $KeyPath<Str, Int>
%1 = function_ref @closureWithKeypathOSSA : $@convention(thin) (Str, @guaranteed KeyPath<Str, Int>) -> Int
%2 = partial_apply [callee_guaranteed] %1(%c) : $@convention(thin) (Str, @guaranteed KeyPath<Str, Int>) -> Int
%3 = convert_escape_to_noescape %2 : $@callee_guaranteed (Str) -> Int to $@noescape @callee_guaranteed (Str) -> Int
%4 = function_ref @calleeWithKeypath : $@convention(thin) (@noescape @callee_guaranteed (Str) -> Int) -> ()
%5 = apply %4(%3) : $@convention(thin) (@noescape @callee_guaranteed (Str) -> Int) -> ()
destroy_value %3 : $@noescape @callee_guaranteed (Str) -> Int
destroy_value %2 : $@callee_guaranteed (Str) -> Int
%7 = tuple ()
return %7 : $()
}

// CHECK-LABEL: sil [ossa] @testKeypathNoescapeOSSA
// CHECK: [[K:%[0-9]+]] = keypath
// CHECK: [[C:%[0-9]+]] = function_ref @$s22closureWithKeypathOSSA{{.*}}main3StrVSiTf3npk_n
Expand Down