Skip to content

Commit b642d77

Browse files
committed
[embedded] Compile-time (literal) KeyPaths for Embedded Swift
Enable KeyPath/AnyKeyPath/PartialKeyPath/WritableKeyPath in Embedded Swift, but for compile-time use only: - Add keypath optimizations into the mandatory optimizations pipeline - Allow keypath optimizations to look through begin_borrow, to make them work even in OSSA. - If a use of a KeyPath doesn't optimize away, diagnose in PerformanceDiagnostics - Make UnsafePointer.pointer(to:) transparent to allow the keypath optimization to happen in the callers of UnsafePointer.pointer(to:).
1 parent 4389ae2 commit b642d77

File tree

18 files changed

+272
-119
lines changed

18 files changed

+272
-119
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ swift_compiler_sources(Optimizer
2121
SimplifyDestructure.swift
2222
SimplifyGlobalValue.swift
2323
SimplifyInitEnumDataAddr.swift
24+
SimplifyKeyPath.swift
2425
SimplifyLoad.swift
2526
SimplifyPartialApply.swift
2627
SimplifyPointerToAddress.swift

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ extension ApplyInst : OnoneSimplifyable {
1717
if tryTransformThickToThinCallee(of: self, context) {
1818
return
1919
}
20+
if context.tryOptimizeKeypath(apply: self) {
21+
context.erase(instruction: self)
22+
return
23+
}
2024
_ = context.tryDevirtualize(apply: self, isMandatory: false)
2125
}
2226
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===--- SimplifyKeyPath.swift --------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SIL
14+
15+
extension KeyPathInst : OnoneSimplifyable {
16+
func simplify(_ context: SimplifyContext) {
17+
if allUsesRemovable(instruction: self) {
18+
context.erase(instructionIncludingAllUsers: self)
19+
}
20+
}
21+
}
22+
23+
fileprivate func allUsesRemovable(instruction: Instruction) -> Bool {
24+
for result in instruction.results {
25+
for use in result.uses {
26+
if !(use.instruction is UpcastInst || use.instruction is DestroyValueInst || use.instruction is BeginBorrowInst || use.instruction is EndBorrowInst) {
27+
return false
28+
}
29+
if !allUsesRemovable(instruction: use.instruction) {
30+
return false
31+
}
32+
}
33+
}
34+
return true
35+
}

SwiftCompilerSources/Sources/Optimizer/PassManager/Context.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ extension MutatingContext {
170170
}
171171
return nil
172172
}
173+
174+
func tryOptimizeKeypath(apply: FullApplySite) -> Bool {
175+
return _bridged.tryOptimizeKeypath(apply.bridged)
176+
}
173177

174178
func inlineFunction(apply: FullApplySite, mandatoryInline: Bool) {
175179
// This is only a best-effort attempt to notity the new cloned instructions as changed.

include/swift/AST/DiagnosticsSIL.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,8 @@ ERROR(embedded_swift_metatype_type,none,
379379
"cannot use metatype of type %0 in embedded Swift", (Type))
380380
ERROR(embedded_swift_metatype,none,
381381
"cannot use metatype in embedded Swift", ())
382+
ERROR(embedded_swift_keypath,none,
383+
"cannot use key path in embedded Swift", ())
382384
ERROR(embedded_swift_allocating_type,none,
383385
"cannot use allocating type %0 in -no-allocations mode", (Type))
384386
ERROR(embedded_swift_allocating,none,

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ struct BridgedPassContext {
214214
bool tryOptimizeApplyOfPartialApply(BridgedInstruction closure) const;
215215
bool tryDeleteDeadClosure(BridgedInstruction closure, bool needKeepArgsAlive) const;
216216
SWIFT_IMPORT_UNSAFE DevirtResult tryDevirtualizeApply(BridgedInstruction apply, bool isMandatory) const;
217+
bool tryOptimizeKeypath(BridgedInstruction apply) const;
217218
SWIFT_IMPORT_UNSAFE OptionalBridgedValue constantFoldBuiltin(BridgedInstruction builtin) const;
218219
SWIFT_IMPORT_UNSAFE swift::SILVTable * _Nullable specializeVTableForType(BridgedType type,
219220
BridgedFunction function) const;

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,13 @@ bool specializeAppliesInFunction(SILFunction &F,
599599
SILTransform *transform,
600600
bool isMandatory);
601601

602+
bool tryOptimizeKeypath(ApplyInst *AI, SILBuilder Builder);
603+
bool tryOptimizeKeypathApplication(ApplyInst *AI, SILFunction *callee, SILBuilder Builder);
604+
bool tryOptimizeKeypathOffsetOf(ApplyInst *AI, FuncDecl *calleeFn,
605+
KeyPathInst *kp, SILBuilder Builder);
606+
bool tryOptimizeKeypathKVCString(ApplyInst *AI, FuncDecl *calleeFn,
607+
KeyPathInst *kp, SILBuilder Builder);
608+
602609
/// Instantiate the specified type by recursively tupling and structing the
603610
/// unique instances of the empty types and undef "instances" of the non-empty
604611
/// types aggregated together at each level.

lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,10 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
519519
diagnose(loc, diag::embedded_swift_value_deinit, impactType.getASTType());
520520
return true;
521521
}
522+
if (isa<KeyPathInst>(inst)) {
523+
diagnose(loc, diag::embedded_swift_keypath);
524+
return true;
525+
}
522526
if (!allowedMetadataUseInEmbeddedSwift(inst)) {
523527
PrettyStackTracePerformanceDiagnostics stackTrace("metatype", inst);
524528
if (impactType) {

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,11 @@ BridgedPassContext::DevirtResult BridgedPassContext::tryDevirtualizeApply(Bridge
16001600
return {{nullptr}, false};
16011601
}
16021602

1603+
bool BridgedPassContext::tryOptimizeKeypath(BridgedInstruction apply) const {
1604+
SILBuilder builder(apply.unbridged());
1605+
return ::tryOptimizeKeypath(apply.getAs<ApplyInst>(), builder);
1606+
}
1607+
16031608
OptionalBridgedValue BridgedPassContext::constantFoldBuiltin(BridgedInstruction builtin) const {
16041609
auto bi = builtin.getAs<BuiltinInst>();
16051610
std::optional<bool> resultsInError;

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -330,13 +330,7 @@ class SILCombiner :
330330
SILInstruction *optimizeApplyOfConvertFunctionInst(FullApplySite AI,
331331
ConvertFunctionInst *CFI);
332332

333-
bool tryOptimizeKeypath(ApplyInst *AI);
334333
bool tryOptimizeInoutKeypath(BeginApplyInst *AI);
335-
bool tryOptimizeKeypathApplication(ApplyInst *AI, SILFunction *callee);
336-
bool tryOptimizeKeypathOffsetOf(ApplyInst *AI, FuncDecl *calleeFn,
337-
KeyPathInst *kp);
338-
bool tryOptimizeKeypathKVCString(ApplyInst *AI, FuncDecl *calleeFn,
339-
KeyPathInst *kp);
340334

341335
/// Sinks owned forwarding instructions to their uses if they do not have
342336
/// non-debug non-consuming uses. Deletes any debug_values and destroy_values

0 commit comments

Comments
 (0)