Skip to content

Commit e5433cd

Browse files
authored
Merge pull request #41026 from eeckstein/fix-availability-checks
Disable deployment target specific optimizations for inlinable functions
2 parents 8849acf + dde4311 commit e5433cd

File tree

11 files changed

+82
-19
lines changed

11 files changed

+82
-19
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionPasses/SimplifyStrongRetainRelease.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,18 @@ private func isNotReferenceCounted(value: Value, context: PassContext) -> Bool {
7676
return isNotReferenceCounted(value: uci.operand, context: context)
7777
case let urc as UncheckedRefCastInst:
7878
return isNotReferenceCounted(value: urc.operand, context: context)
79-
case is GlobalValueInst:
79+
case let gvi as GlobalValueInst:
8080
// Since Swift 5.1, statically allocated objects have "immortal" reference
8181
// counts. Therefore we can safely eliminate unbalaced retains and
8282
// releases, because they are no-ops on immortal objects.
8383
// Note that the `simplifyGlobalValuePass` pass is deleting balanced
8484
// retains/releases, which doesn't require a Swift 5.1 minimum deployment
8585
// targert.
86-
return context.isSwift51RuntimeAvailable
86+
return gvi.function.isSwift51RuntimeAvailable
8787
case let rptr as RawPointerToRefInst:
8888
// Like `global_value` but for the empty collection singletons from the
8989
// stdlib, e.g. the empty Array singleton.
90-
if context.isSwift51RuntimeAvailable {
90+
if rptr.function.isSwift51RuntimeAvailable {
9191
// The pattern generated for empty collection singletons is:
9292
// %0 = global_addr @_swiftEmptyArrayStorage
9393
// %1 = address_to_pointer %0

SwiftCompilerSources/Sources/Optimizer/PassManager/PassUtils.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ struct PassContext {
2222

2323
let _bridged: BridgedPassContext
2424

25-
var isSwift51RuntimeAvailable: Bool {
26-
PassContext_isSwift51RuntimeAvailable(_bridged) != 0
27-
}
28-
2925
var aliasAnalysis: AliasAnalysis {
3026
let bridgedAA = PassContext_getAliasAnalysis(_bridged)
3127
return AliasAnalysis(bridged: bridgedAA)

SwiftCompilerSources/Sources/SIL/Function.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ final public class Function : CustomStringConvertible, HasName {
5252
public var argumentTypes: ArgumentTypeArray { ArgumentTypeArray(function: self) }
5353
public var resultType: Type { SILFunction_getSILResultType(bridged).type }
5454

55+
/// True, if the function runs with a swift 5.1 runtime.
56+
/// Note that this is function specific, because inlinable functions are de-serialized
57+
/// in a client module, which might be compiled with a different deployment target.
58+
public var isSwift51RuntimeAvailable: Bool {
59+
SILFunction_isSwift51RuntimeAvailable(bridged) != 0
60+
}
61+
5562
// Only to be called by PassContext
5663
public func _modifyEffects(_ body: (inout FunctionEffects) -> ()) {
5764
body(&effects)

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ SwiftInt SILFunction_getSelfArgumentIndex(BridgedFunction function);
205205
SwiftInt SILFunction_getNumSILArguments(BridgedFunction function);
206206
BridgedType SILFunction_getSILArgumentType(BridgedFunction function, SwiftInt idx);
207207
BridgedType SILFunction_getSILResultType(BridgedFunction function);
208+
SwiftInt SILFunction_isSwift51RuntimeAvailable(BridgedFunction function);
208209

209210
BridgedStringRef SILGlobalVariable_getName(BridgedGlobalVar global);
210211
BridgedStringRef SILGlobalVariable_debugDescription(BridgedGlobalVar global);

include/swift/SILOptimizer/OptimizerBridging.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,6 @@ void SILPassManager_registerFunctionPass(BridgedStringRef name,
8686
void SILCombine_registerInstructionPass(BridgedStringRef name,
8787
BridgedInstructionPassRunFn runFn);
8888

89-
SwiftInt PassContext_isSwift51RuntimeAvailable(BridgedPassContext context);
90-
9189
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context);
9290

9391
BridgedMemoryBehavior AliasAnalysis_getMemBehavior(BridgedAliasAnalysis aa,

lib/SIL/Utils/SILBridging.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,16 @@ BridgedType SILFunction_getSILResultType(BridgedFunction function) {
213213
return {resTy.getOpaqueValue()};
214214
}
215215

216+
SwiftInt SILFunction_isSwift51RuntimeAvailable(BridgedFunction function) {
217+
SILFunction *f = castToFunction(function);
218+
if (f->getResilienceExpansion() != ResilienceExpansion::Maximal)
219+
return 0;
220+
221+
ASTContext &ctxt = f->getModule().getASTContext();
222+
return AvailabilityContext::forDeploymentTarget(ctxt).isContainedIn(
223+
ctxt.getSwift51Availability());
224+
}
225+
216226
//===----------------------------------------------------------------------===//
217227
// SILBasicBlock
218228
//===----------------------------------------------------------------------===//

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,13 +1240,6 @@ void PassContext_fixStackNesting(BridgedPassContext passContext,
12401240
}
12411241
}
12421242

1243-
SwiftInt PassContext_isSwift51RuntimeAvailable(BridgedPassContext context) {
1244-
SILPassManager *pm = castToPassInvocation(context)->getPassManager();
1245-
ASTContext &ctxt = pm->getModule()->getASTContext();
1246-
return AvailabilityContext::forDeploymentTarget(ctxt).isContainedIn(
1247-
ctxt.getSwift51Availability());
1248-
}
1249-
12501243
BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context) {
12511244
SwiftPassInvocation *invocation = castToPassInvocation(context);
12521245
SILPassManager *pm = invocation->getPassManager();

lib/SILOptimizer/Utils/ConstantFolding.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,11 @@ static bool isApplyOfBuiltin(SILInstruction &I, BuiltinValueKind kind) {
14081408
}
14091409

14101410
static bool isApplyOfKnownAvailability(SILInstruction &I) {
1411+
// Inlinable functions can be deserialized in other modules which can be
1412+
// compiled with a different deployment target.
1413+
if (I.getFunction()->getResilienceExpansion() != ResilienceExpansion::Maximal)
1414+
return false;
1415+
14111416
auto apply = FullApplySite::isa(&I);
14121417
if (!apply)
14131418
return false;

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2512,7 +2512,20 @@ usePrespecialized(SILOptFunctionBuilder &funcBuilder, ApplySite apply,
25122512
auto specializationAvail = SA->getAvailability();
25132513
auto &ctxt = funcBuilder.getModule().getSwiftModule()->getASTContext();
25142514
auto deploymentAvail = AvailabilityContext::forDeploymentTarget(ctxt);
2515-
auto currentFnAvailability = apply.getFunction()->getAvailabilityForLinkage();
2515+
auto currentFn = apply.getFunction();
2516+
auto isInlinableCtxt = (currentFn->getResilienceExpansion()
2517+
== ResilienceExpansion::Minimal);
2518+
auto currentFnAvailability = currentFn->getAvailabilityForLinkage();
2519+
2520+
// If we are in an inlineable function we can't use the specialization except
2521+
// the inlinable function itself has availability we can use.
2522+
if (currentFnAvailability.isAlwaysAvailable() && isInlinableCtxt) {
2523+
continue;
2524+
}
2525+
else if (isInlinableCtxt) {
2526+
deploymentAvail = currentFnAvailability;
2527+
}
2528+
25162529
if (!currentFnAvailability.isAlwaysAvailable() &&
25172530
!deploymentAvail.isContainedIn(currentFnAvailability))
25182531
deploymentAvail = currentFnAvailability;

test/SILOptimizer/constant_propagation_availability.swift

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
// RUN: %target-swift-frontend -target %target-cpu-apple-macos10.15 -emit-sil %s | %FileCheck --check-prefix=CHECK-macosx10_15 %s
22
// RUN: %target-swift-frontend -target %target-cpu-apple-macos10.14 -emit-sil %s | %FileCheck --check-prefix=CHECK-macosx10_14 %s
3-
// RUN: %target-swift-frontend -O -target %target-cpu-apple-macos10.15 -emit-sil %s | %FileCheck --check-prefix=CHECK-macosx10_15 %s
3+
// RUN: %target-swift-frontend -O -target %target-cpu-apple-macos10.15 -emit-sil %s | %FileCheck --check-prefix=CHECK-macosx10_15 --check-prefix=CHECK-macosx10_15_opt %s
44
// RUN: %target-swift-frontend -O -target %target-cpu-apple-macos10.14 -emit-sil %s | %FileCheck --check-prefix=CHECK-macosx10_14 %s
55

6+
// RUN: %empty-directory(%t)
7+
// RUN: %target-swift-frontend -O -target %target-cpu-apple-macos10.15 -module-name=Test -emit-module -emit-module-path %t/Test.swiftmodule %s
8+
// RUN: %sil-opt -target %target-cpu-apple-macos10.15 %t/Test.swiftmodule | %FileCheck --check-prefix=CHECK-inlinable %s
9+
610
// REQUIRES: OS=macosx
711

812
@available(macOS 10.15, *)
@@ -24,13 +28,31 @@ public func testAvailabilityPropagation() -> Int {
2428
}
2529
}
2630

31+
@inlinable
32+
public func testInlinable() -> Int {
33+
if #available(macOS 10.15, *) {
34+
return newFunction()
35+
} else {
36+
return 0
37+
}
38+
}
39+
2740
// CHECK-macosx10_15-LABEL: sil @$s33constant_propagation_availability27testAvailabilityPropagationSiyF : $@convention(thin) () -> Int {
2841
// CHECK-macosx10_15-NOT: apply
2942
// CHECK-macosx10_15: [[F:%.*]] = function_ref @$s33constant_propagation_availability11newFunctionSiyF
3043
// CHECK-macosx10_15: apply [[F]]() : $@convention(thin) () -> Int
3144
// CHECK-macosx10_15-NOT: apply
3245
// CHECK-macosx10_15: } // end sil function '$s33constant_propagation_availability27testAvailabilityPropagationSiyF'
3346

47+
// After serialization, availability checks can be constant folded.
48+
49+
// CHECK-macosx10_15_opt-LABEL: sil @$s33constant_propagation_availability13testInlinableSiyF : $@convention(thin) () -> Int {
50+
// CHECK-macosx10_15_opt-NOT: apply
51+
// CHECK-macosx10_15_opt: [[F:%.*]] = function_ref @$s33constant_propagation_availability11newFunctionSiyF
52+
// CHECK-macosx10_15_opt: apply [[F]]() : $@convention(thin) () -> Int
53+
// CHECK-macosx10_15_opt-NOT: apply
54+
// CHECK-macosx10_15_opt: } // end sil function '$s33constant_propagation_availability13testInlinableSiyF'
55+
3456
// CHECK-macosx10_14-LABEL: sil @$s33constant_propagation_availability27testAvailabilityPropagationSiyF : $@convention(thin) () -> Int {
3557
// CHECK-macosx10_14: [[F:%.*]] = function_ref @$ss26_stdlib_isOSVersionAtLeastyBi1_Bw_BwBwtF
3658
// CHECK-macosx10_14: apply [[F]]
@@ -41,3 +63,10 @@ public func testAvailabilityPropagation() -> Int {
4163
// CHECK-macosx10_14: } // end sil function '$s33constant_propagation_availability27testAvailabilityPropagationSiyF'
4264

4365
// CHECK-macosx10_14: sil [readnone] [_semantics "availability.osversion"] @$ss26_stdlib_isOSVersionAtLeastyBi1_Bw_BwBwtF
66+
67+
// CHECK-inlinable-LABEL: sil {{.*}} @$s4Test13testInlinableSiyF : $@convention(thin) () -> Int {
68+
// CHECK-inlinable: [[F:%.*]] = function_ref @$ss26_stdlib_isOSVersionAtLeastyBi1_Bw_BwBwtF
69+
// CHECK-inlinable: apply [[F]]
70+
// CHECK-inlinable: [[F:%.*]] = function_ref @$s4Test11newFunctionSiyF
71+
// CHECK-inlinable: apply [[F]]() : $@convention(thin) () -> Int
72+
// CHECK-inlinable: } // end sil function '$s4Test13testInlinableSiyF'

0 commit comments

Comments
 (0)