Skip to content

Commit 7c685ba

Browse files
authored
Merge pull request #78915 from kubamracek/embedded-string-switch-with-cache
[embedded] Support _findStringSwitchCaseWithCache in Embedded Swift
2 parents 2eb43a6 + 500f8ad commit 7c685ba

File tree

3 files changed

+66
-4
lines changed

3 files changed

+66
-4
lines changed

SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,17 @@ fileprivate struct PathFunctionTuple: Hashable {
8080

8181
private func optimize(function: Function, _ context: FunctionPassContext, _ moduleContext: ModulePassContext, _ worklist: inout FunctionWorklist) {
8282
var alreadyInlinedFunctions: Set<PathFunctionTuple> = Set()
83+
84+
// ObjectOutliner replaces calls to findStringSwitchCase with _findStringSwitchCaseWithCache, but this happens as a late SIL optimization,
85+
// which is a problem for Embedded Swift, because _findStringSwitchCaseWithCache will then reference non-specialized code. Solve this by
86+
// eagerly linking and specializing _findStringSwitchCaseWithCache whenever findStringSwitchCase is found in the module.
87+
if context.options.enableEmbeddedSwift {
88+
if function.hasSemanticsAttribute("findStringSwitchCase"),
89+
let f = context.lookupStdlibFunction(name: "_findStringSwitchCaseWithCache"),
90+
context.loadFunction(function: f, loadCalleesRecursively: true) {
91+
worklist.pushIfNotVisited(f)
92+
}
93+
}
8394

8495
var changed = true
8596
while changed {

lib/SILOptimizer/IPO/DeadFunctionElimination.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class DeadFunctionAndGlobalElimination {
9090
llvm::SmallPtrSet<void *, 32> AliveFunctionsAndTables;
9191

9292
bool keepExternalWitnessTablesAlive;
93+
bool keepStringSwitchIntrinsicAlive;
9394

9495
/// Checks is a function is alive, e.g. because it is visible externally.
9596
bool isAnchorFunction(SILFunction *F) {
@@ -124,6 +125,15 @@ class DeadFunctionAndGlobalElimination {
124125
if (F->getRepresentation() == SILFunctionTypeRepresentation::ObjCMethod)
125126
return true;
126127

128+
// To support ObjectOutliner's replacing of calls to findStringSwitchCase
129+
// with _findStringSwitchCaseWithCache. In Embedded Swift, we have to load
130+
// the body of this function early and specialize it, so that ObjectOutliner
131+
// can reference it later. To make this work we have to avoid DFE'ing it in
132+
// the early DFE pass. Late DFE will take care of it if actually unused.
133+
if (keepStringSwitchIntrinsicAlive &&
134+
F->hasSemanticsAttr("findStringSwitchCaseWithCache"))
135+
return true;
136+
127137
return false;
128138
}
129139

@@ -713,9 +723,11 @@ class DeadFunctionAndGlobalElimination {
713723

714724
public:
715725
DeadFunctionAndGlobalElimination(SILModule *module,
716-
bool keepExternalWitnessTablesAlive) :
726+
bool keepExternalWitnessTablesAlive,
727+
bool keepStringSwitchIntrinsicAlive) :
717728
Module(module),
718-
keepExternalWitnessTablesAlive(keepExternalWitnessTablesAlive) {}
729+
keepExternalWitnessTablesAlive(keepExternalWitnessTablesAlive),
730+
keepStringSwitchIntrinsicAlive(keepStringSwitchIntrinsicAlive) {}
719731

720732
/// The main entry point of the optimization.
721733
void eliminateFunctionsAndGlobals(SILModuleTransform *DFEPass) {
@@ -799,8 +811,10 @@ class DeadFunctionAndGlobalEliminationPass : public SILModuleTransform {
799811
// can eliminate such functions.
800812
getModule()->invalidateSILLoaderCaches();
801813

802-
DeadFunctionAndGlobalElimination deadFunctionElimination(getModule(),
803-
/*keepExternalWitnessTablesAlive*/ !isLateDFE);
814+
DeadFunctionAndGlobalElimination deadFunctionElimination(
815+
getModule(),
816+
/*keepExternalWitnessTablesAlive*/ !isLateDFE,
817+
/*keepStringSwitchIntrinsicAlive*/ !isLateDFE);
804818
deadFunctionElimination.eliminateFunctionsAndGlobals(this);
805819
}
806820
};

test/embedded/string-switch2.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %target-run-simple-swift(-enable-experimental-feature Embedded -wmo -O -Xlinker %swift_obj_root/lib/swift/embedded/%target-cpu-apple-macos/libswiftUnicodeDataTables.a) | %FileCheck %s
2+
3+
// REQUIRES: swift_in_compiler
4+
// REQUIRES: executable_test
5+
// REQUIRES: optimized_stdlib
6+
// REQUIRES: swift_stdlib_no_asserts
7+
// REQUIRES: OS=macosx
8+
// REQUIRES: swift_feature_Embedded
9+
10+
enum MyEnum: String {
11+
case case1
12+
case case2
13+
case case3
14+
case case4
15+
case case5
16+
case case6
17+
case case7
18+
case case8
19+
case case9
20+
case case10
21+
case case11
22+
case case12
23+
case case13
24+
case case14
25+
case case15
26+
case case16
27+
case case17
28+
case case18
29+
case case19
30+
}
31+
32+
var e = MyEnum.case1
33+
print(e.rawValue)
34+
e = MyEnum.case2
35+
print(e.rawValue)
36+
// CHECK: case1
37+
// CHECK: case2

0 commit comments

Comments
 (0)