Skip to content

Commit 89cd626

Browse files
authored
Merge pull request #72472 from kubamracek/embedded-keypaths
[embedded] Compile-time (literal) KeyPaths for Embedded Swift
2 parents 423cfcf + 595ea99 commit 89cd626

File tree

22 files changed

+332
-122
lines changed

22 files changed

+332
-122
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ swift_compiler_sources(Optimizer
2222
SimplifyDestructure.swift
2323
SimplifyGlobalValue.swift
2424
SimplifyInitEnumDataAddr.swift
25+
SimplifyKeyPath.swift
2526
SimplifyLoad.swift
2627
SimplifyPartialApply.swift
2728
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: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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+
if parentFunction.hasOwnership {
19+
let builder = Builder(after: self, context)
20+
for operand in self.operands {
21+
if !operand.value.type.isTrivial(in: parentFunction) {
22+
builder.createDestroyValue(operand: operand.value)
23+
}
24+
}
25+
}
26+
context.erase(instructionIncludingAllUsers: self)
27+
}
28+
}
29+
}
30+
31+
fileprivate func allUsesRemovable(instruction: Instruction) -> Bool {
32+
for result in instruction.results {
33+
for use in result.uses {
34+
if !(use.instruction is UpcastInst || use.instruction is DestroyValueInst || use.instruction is BeginBorrowInst || use.instruction is EndBorrowInst) {
35+
return false
36+
}
37+
if !allUsesRemovable(instruction: use.instruction) {
38+
return false
39+
}
40+
}
41+
}
42+
return true
43+
}

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
@@ -224,6 +224,7 @@ struct BridgedPassContext {
224224
bool tryOptimizeApplyOfPartialApply(BridgedInstruction closure) const;
225225
bool tryDeleteDeadClosure(BridgedInstruction closure, bool needKeepArgsAlive) const;
226226
SWIFT_IMPORT_UNSAFE DevirtResult tryDevirtualizeApply(BridgedInstruction apply, bool isMandatory) const;
227+
bool tryOptimizeKeypath(BridgedInstruction apply) const;
227228
SWIFT_IMPORT_UNSAFE OptionalBridgedValue constantFoldBuiltin(BridgedInstruction builtin) const;
228229
SWIFT_IMPORT_UNSAFE swift::SILVTable * _Nullable specializeVTableForType(BridgedType type,
229230
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
@@ -1628,6 +1628,11 @@ BridgedPassContext::DevirtResult BridgedPassContext::tryDevirtualizeApply(Bridge
16281628
return {{nullptr}, false};
16291629
}
16301630

1631+
bool BridgedPassContext::tryOptimizeKeypath(BridgedInstruction apply) const {
1632+
SILBuilder builder(apply.unbridged());
1633+
return ::tryOptimizeKeypath(apply.getAs<ApplyInst>(), builder);
1634+
}
1635+
16311636
OptionalBridgedValue BridgedPassContext::constantFoldBuiltin(BridgedInstruction builtin) const {
16321637
auto bi = builtin.getAs<BuiltinInst>();
16331638
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)