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
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,18 @@ private func isNotReferenceCounted(value: Value, context: PassContext) -> Bool {
return isNotReferenceCounted(value: uci.operand, context: context)
case let urc as UncheckedRefCastInst:
return isNotReferenceCounted(value: urc.operand, context: context)
case is GlobalValueInst:
case let gvi as GlobalValueInst:
// Since Swift 5.1, statically allocated objects have "immortal" reference
// counts. Therefore we can safely eliminate unbalaced retains and
// releases, because they are no-ops on immortal objects.
// Note that the `simplifyGlobalValuePass` pass is deleting balanced
// retains/releases, which doesn't require a Swift 5.1 minimum deployment
// targert.
return context.isSwift51RuntimeAvailable
return gvi.function.isSwift51RuntimeAvailable
case let rptr as RawPointerToRefInst:
// Like `global_value` but for the empty collection singletons from the
// stdlib, e.g. the empty Array singleton.
if context.isSwift51RuntimeAvailable {
if rptr.function.isSwift51RuntimeAvailable {
// The pattern generated for empty collection singletons is:
// %0 = global_addr @_swiftEmptyArrayStorage
// %1 = address_to_pointer %0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ struct PassContext {

let _bridged: BridgedPassContext

var isSwift51RuntimeAvailable: Bool {
PassContext_isSwift51RuntimeAvailable(_bridged) != 0
}

var aliasAnalysis: AliasAnalysis {
let bridgedAA = PassContext_getAliasAnalysis(_bridged)
return AliasAnalysis(bridged: bridgedAA)
Expand Down
7 changes: 7 additions & 0 deletions SwiftCompilerSources/Sources/SIL/Function.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ final public class Function : CustomStringConvertible, HasName {
public var argumentTypes: ArgumentTypeArray { ArgumentTypeArray(function: self) }
public var resultType: Type { SILFunction_getSILResultType(bridged).type }

/// True, if the function runs with a swift 5.1 runtime.
/// Note that this is function specific, because inlinable functions are de-serialized
/// in a client module, which might be compiled with a different deployment target.
public var isSwift51RuntimeAvailable: Bool {
SILFunction_isSwift51RuntimeAvailable(bridged) != 0
}

// Only to be called by PassContext
public func _modifyEffects(_ body: (inout FunctionEffects) -> ()) {
body(&effects)
Expand Down
1 change: 1 addition & 0 deletions include/swift/SIL/SILBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ SwiftInt SILFunction_getSelfArgumentIndex(BridgedFunction function);
SwiftInt SILFunction_getNumSILArguments(BridgedFunction function);
BridgedType SILFunction_getSILArgumentType(BridgedFunction function, SwiftInt idx);
BridgedType SILFunction_getSILResultType(BridgedFunction function);
SwiftInt SILFunction_isSwift51RuntimeAvailable(BridgedFunction function);

BridgedStringRef SILGlobalVariable_getName(BridgedGlobalVar global);
BridgedStringRef SILGlobalVariable_debugDescription(BridgedGlobalVar global);
Expand Down
2 changes: 0 additions & 2 deletions include/swift/SILOptimizer/OptimizerBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@ void SILPassManager_registerFunctionPass(BridgedStringRef name,
void SILCombine_registerInstructionPass(BridgedStringRef name,
BridgedInstructionPassRunFn runFn);

SwiftInt PassContext_isSwift51RuntimeAvailable(BridgedPassContext context);

BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context);

BridgedMemoryBehavior AliasAnalysis_getMemBehavior(BridgedAliasAnalysis aa,
Expand Down
10 changes: 10 additions & 0 deletions lib/SIL/Utils/SILBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,16 @@ BridgedType SILFunction_getSILResultType(BridgedFunction function) {
return {resTy.getOpaqueValue()};
}

SwiftInt SILFunction_isSwift51RuntimeAvailable(BridgedFunction function) {
SILFunction *f = castToFunction(function);
if (f->getResilienceExpansion() != ResilienceExpansion::Maximal)
return 0;

ASTContext &ctxt = f->getModule().getASTContext();
return AvailabilityContext::forDeploymentTarget(ctxt).isContainedIn(
ctxt.getSwift51Availability());
}

//===----------------------------------------------------------------------===//
// SILBasicBlock
//===----------------------------------------------------------------------===//
Expand Down
7 changes: 0 additions & 7 deletions lib/SILOptimizer/PassManager/PassManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1240,13 +1240,6 @@ void PassContext_fixStackNesting(BridgedPassContext passContext,
}
}

SwiftInt PassContext_isSwift51RuntimeAvailable(BridgedPassContext context) {
SILPassManager *pm = castToPassInvocation(context)->getPassManager();
ASTContext &ctxt = pm->getModule()->getASTContext();
return AvailabilityContext::forDeploymentTarget(ctxt).isContainedIn(
ctxt.getSwift51Availability());
}

BridgedAliasAnalysis PassContext_getAliasAnalysis(BridgedPassContext context) {
SwiftPassInvocation *invocation = castToPassInvocation(context);
SILPassManager *pm = invocation->getPassManager();
Expand Down
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 @@ -2512,7 +2512,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'
13 changes: 12 additions & 1 deletion test/SILOptimizer/immortal-arc-elimination.sil
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ bb0:
}


sil_global private @staticArray : $_ContiguousArrayStorage<Int> = {
sil_global @staticArray : $_ContiguousArrayStorage<Int> = {
%0 = integer_literal $Builtin.Int64, 0
%1 = struct $UInt (%0 : $Builtin.Int64)
%2 = struct $Int (%0 : $Builtin.Int64)
Expand All @@ -49,4 +49,15 @@ bb0:
return %1 : $Builtin.BridgeObject
}

// CHECK-LABEL: sil [serialized] @testGlobalValueSerialized
// CHECK: global_value
// CHECK: retain
// CHECK: } // end sil function 'testGlobalValueSerialized'
sil [serialized] @testGlobalValueSerialized : $@convention(thin) () -> @owned Builtin.BridgeObject {
bb0:
%0 = global_value @staticArray : $_ContiguousArrayStorage<Int>
%1 = unchecked_ref_cast %0 : $_ContiguousArrayStorage<Int> to $Builtin.BridgeObject
strong_retain %1 : $Builtin.BridgeObject
return %1 : $Builtin.BridgeObject
}