Skip to content

Commit 3c9eba5

Browse files
authored
Merge pull request #3278 from swiftix/optimize-dynamic-self
[sil-perf-inliner] Allow for inlining of functions using dynamic Sef if it is the same Self as used by the caller
2 parents ae65e1c + f5dbcfc commit 3c9eba5

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

lib/SILOptimizer/Transforms/PerformanceInliner.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,14 +1124,23 @@ SILFunction *SILPerformanceInliner::getEligibleFunction(FullApplySite AI) {
11241124
return nullptr;
11251125
}
11261126

1127+
SILFunction *Caller = AI.getFunction();
1128+
11271129
// We don't support inlining a function that binds dynamic self because we
11281130
// have no mechanism to preserve the original function's local self metadata.
11291131
if (computeMayBindDynamicSelf(Callee)) {
1130-
return nullptr;
1132+
// Check if passed Self is the same as the Self of the caller.
1133+
// In this case, it is safe to inline because both functions
1134+
// use the same Self.
1135+
if (AI.hasSelfArgument() && Caller->hasSelfParam()) {
1136+
auto CalleeSelf = stripCasts(AI.getSelfArgument());
1137+
auto CallerSelf = Caller->getSelfArgument();
1138+
if (CalleeSelf != SILValue(CallerSelf))
1139+
return nullptr;
1140+
} else
1141+
return nullptr;
11311142
}
11321143

1133-
SILFunction *Caller = AI.getFunction();
1134-
11351144
// Detect self-recursive calls.
11361145
if (Caller == Callee) {
11371146
return nullptr;

test/SILOptimizer/inline_self.swift

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,31 @@ func callIt(fn: () -> ()) {
3333
fn()
3434
}
3535

36+
class BaseZ {
37+
final func baseCapturesSelf() -> Self {
38+
let fn = { [weak self] in _ = self }
39+
callIt(fn: fn)
40+
return self
41+
}
42+
}
43+
3644
// Do not inline C.capturesSelf() into main either.
37-
class Z {
38-
func capturesSelf() -> Self {
45+
class Z : BaseZ {
46+
final func capturesSelf() -> Self {
3947
let fn = { [weak self] in _ = self }
4048
callIt(fn: fn)
4149
return self
4250
}
51+
52+
// Inline captureSelf into callCaptureSelf,
53+
// because their respective Self types refer to the same type.
54+
final func callCapturesSelf() -> Self {
55+
return capturesSelf()
56+
}
57+
58+
final func callBaseCapturesSelf() -> Self {
59+
return baseCapturesSelf()
60+
}
4361
}
4462

4563
_ = Z().capturesSelf()
@@ -49,7 +67,16 @@ _ = Z().capturesSelf()
4967
// CHECK: [[F:%[0-9]+]] = function_ref @_TZFC11inline_self1C7factory{{.*}} : $@convention(method) (Int, @thick C.Type) -> @owned C
5068
// CHECK: apply [[F]](%{{.+}}, %{{.+}}) : $@convention(method) (Int, @thick C.Type) -> @owned C
5169

52-
// CHECK: [[Z:%.*]] = alloc_ref $Z
5370
// CHECK: function_ref inline_self.Z.capturesSelf () -> Self
5471
// CHECK: [[F:%[0-9]+]] = function_ref @_TFC11inline_self1Z12capturesSelffT_DS0_ : $@convention(method) (@guaranteed Z) -> @owned Z
55-
// CHECK: apply [[F]]([[Z]]) : $@convention(method) (@guaranteed Z) -> @owned Z
72+
// CHECK: [[Z:%.*]] = alloc_ref $Z
73+
// CHECK: apply [[F]]([[Z]]) : $@convention(method) (@guaranteed Z) -> @owned
74+
// CHECK: return
75+
76+
// CHECK-LABEL: sil hidden @_TFC11inline_self1Z16callCapturesSelffT_DS0_ : $@convention(method)
77+
// CHECK-NOT: function_ref @_TFC11inline_self1Z12capturesSelffT_DS0_
78+
// CHECK: }
79+
80+
// CHECK-LABEL: sil hidden @_TFC11inline_self1Z20callBaseCapturesSelffT_DS0_
81+
// CHECK-NOT: function_ref @_TFC11inline_self5BaseZ16baseCapturesSelffT_DS0_
82+
// CHECK: }

0 commit comments

Comments
 (0)