Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/SILOptimizer/Utils/ConstantFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,11 @@ static bool isApplyOfBuiltin(SILInstruction &I, BuiltinValueKind kind) {
}

static bool isApplyOfKnownAvailability(SILInstruction &I) {
// Inlinable functions can be deserialized in other modules which can be
// compiled with a different deployment target.
if (I.getFunction()->getResilienceExpansion() != ResilienceExpansion::Maximal)
return false;

auto apply = FullApplySite::isa(&I);
if (!apply)
return false;
Expand Down
15 changes: 14 additions & 1 deletion lib/SILOptimizer/Utils/Generics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2496,7 +2496,20 @@ usePrespecialized(SILOptFunctionBuilder &funcBuilder, ApplySite apply,
auto specializationAvail = SA->getAvailability();
auto &ctxt = funcBuilder.getModule().getSwiftModule()->getASTContext();
auto deploymentAvail = AvailabilityContext::forDeploymentTarget(ctxt);
auto currentFnAvailability = apply.getFunction()->getAvailabilityForLinkage();
auto currentFn = apply.getFunction();
auto isInlinableCtxt = (currentFn->getResilienceExpansion()
== ResilienceExpansion::Minimal);
auto currentFnAvailability = currentFn->getAvailabilityForLinkage();

// If we are in an inlineable function we can't use the specialization except
// the inlinable function itself has availability we can use.
if (currentFnAvailability.isAlwaysAvailable() && isInlinableCtxt) {
continue;
}
else if (isInlinableCtxt) {
deploymentAvail = currentFnAvailability;
}

if (!currentFnAvailability.isAlwaysAvailable() &&
!deploymentAvail.isContainedIn(currentFnAvailability))
deploymentAvail = currentFnAvailability;
Expand Down
31 changes: 30 additions & 1 deletion test/SILOptimizer/constant_propagation_availability.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
// RUN: %target-swift-frontend -target %target-cpu-apple-macos10.15 -emit-sil %s | %FileCheck --check-prefix=CHECK-macosx10_15 %s
// RUN: %target-swift-frontend -target %target-cpu-apple-macos10.14 -emit-sil %s | %FileCheck --check-prefix=CHECK-macosx10_14 %s
// RUN: %target-swift-frontend -O -target %target-cpu-apple-macos10.15 -emit-sil %s | %FileCheck --check-prefix=CHECK-macosx10_15 %s
// 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
// RUN: %target-swift-frontend -O -target %target-cpu-apple-macos10.14 -emit-sil %s | %FileCheck --check-prefix=CHECK-macosx10_14 %s

// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -O -target %target-cpu-apple-macos10.15 -module-name=Test -emit-module -emit-module-path %t/Test.swiftmodule %s
// RUN: %sil-opt -target %target-cpu-apple-macos10.15 %t/Test.swiftmodule | %FileCheck --check-prefix=CHECK-inlinable %s

// REQUIRES: OS=macosx

@available(macOS 10.15, *)
Expand All @@ -24,13 +28,31 @@ public func testAvailabilityPropagation() -> Int {
}
}

@inlinable
public func testInlinable() -> Int {
if #available(macOS 10.15, *) {
return newFunction()
} else {
return 0
}
}

// CHECK-macosx10_15-LABEL: sil @$s33constant_propagation_availability27testAvailabilityPropagationSiyF : $@convention(thin) () -> Int {
// CHECK-macosx10_15-NOT: apply
// CHECK-macosx10_15: [[F:%.*]] = function_ref @$s33constant_propagation_availability11newFunctionSiyF
// CHECK-macosx10_15: apply [[F]]() : $@convention(thin) () -> Int
// CHECK-macosx10_15-NOT: apply
// CHECK-macosx10_15: } // end sil function '$s33constant_propagation_availability27testAvailabilityPropagationSiyF'

// After serialization, availability checks can be constant folded.

// CHECK-macosx10_15_opt-LABEL: sil @$s33constant_propagation_availability13testInlinableSiyF : $@convention(thin) () -> Int {
// CHECK-macosx10_15_opt-NOT: apply
// CHECK-macosx10_15_opt: [[F:%.*]] = function_ref @$s33constant_propagation_availability11newFunctionSiyF
// CHECK-macosx10_15_opt: apply [[F]]() : $@convention(thin) () -> Int
// CHECK-macosx10_15_opt-NOT: apply
// CHECK-macosx10_15_opt: } // end sil function '$s33constant_propagation_availability13testInlinableSiyF'

// CHECK-macosx10_14-LABEL: sil @$s33constant_propagation_availability27testAvailabilityPropagationSiyF : $@convention(thin) () -> Int {
// CHECK-macosx10_14: [[F:%.*]] = function_ref @$ss26_stdlib_isOSVersionAtLeastyBi1_Bw_BwBwtF
// CHECK-macosx10_14: apply [[F]]
Expand All @@ -41,3 +63,10 @@ public func testAvailabilityPropagation() -> Int {
// CHECK-macosx10_14: } // end sil function '$s33constant_propagation_availability27testAvailabilityPropagationSiyF'

// CHECK-macosx10_14: sil [readnone] [_semantics "availability.osversion"] @$ss26_stdlib_isOSVersionAtLeastyBi1_Bw_BwBwtF

// CHECK-inlinable-LABEL: sil {{.*}} @$s4Test13testInlinableSiyF : $@convention(thin) () -> Int {
// CHECK-inlinable: [[F:%.*]] = function_ref @$ss26_stdlib_isOSVersionAtLeastyBi1_Bw_BwBwtF
// CHECK-inlinable: apply [[F]]
// CHECK-inlinable: [[F:%.*]] = function_ref @$s4Test11newFunctionSiyF
// CHECK-inlinable: apply [[F]]() : $@convention(thin) () -> Int
// CHECK-inlinable: } // end sil function '$s4Test13testInlinableSiyF'