From 45b1a21e74cef77c7985d3be141697052b414018 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Wed, 3 Sep 2025 09:36:07 +0200 Subject: [PATCH] Optimizer: make `ModulePassContext.specialize()` also available in `FunctionPassContext` and add two argument flags add `convertIndirectToDirect` and `isMandatory` --- .../PassManager/FunctionPassContext.swift | 10 ++++++++++ .../Optimizer/PassManager/ModulePassContext.swift | 9 +++++++-- .../Utilities/GenericSpecialization.swift | 15 +++++++++------ include/swift/SILOptimizer/OptimizerBridging.h | 4 +++- lib/SILOptimizer/Utils/OptimizerBridging.cpp | 12 +++++++----- test/embedded/managed-buffer.swift | 2 +- 6 files changed, 37 insertions(+), 15 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/FunctionPassContext.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/FunctionPassContext.swift index 20d37b7665f..37faa365b8e 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/FunctionPassContext.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/FunctionPassContext.swift @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +import AST import SIL import OptimizerBridging @@ -97,6 +98,15 @@ struct FunctionPassContext : MutatingContext { return false } + func specialize(function: Function, + for substitutions: SubstitutionMap, + convertIndirectToDirect: Bool, + isMandatory: Bool + ) -> Function? { + return bridgedPassContext.specializeFunction(function.bridged, substitutions.bridged, + convertIndirectToDirect, isMandatory).function + } + func mangleOutlinedVariable(from function: Function) -> String { return String(taking: bridgedPassContext.mangleOutlinedVariable(function.bridged)) } diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift index bded40fe51c..9042bbbb1ce 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/ModulePassContext.swift @@ -131,8 +131,13 @@ struct ModulePassContext : Context, CustomStringConvertible { return function.isDefinition } - func specialize(function: Function, for substitutions: SubstitutionMap) -> Function? { - return bridgedPassContext.specializeFunction(function.bridged, substitutions.bridged).function + func specialize(function: Function, + for substitutions: SubstitutionMap, + convertIndirectToDirect: Bool, + isMandatory: Bool + ) -> Function? { + return bridgedPassContext.specializeFunction(function.bridged, substitutions.bridged, + convertIndirectToDirect, isMandatory).function } enum DeserializationMode { diff --git a/SwiftCompilerSources/Sources/Optimizer/Utilities/GenericSpecialization.swift b/SwiftCompilerSources/Sources/Optimizer/Utilities/GenericSpecialization.swift index 5dae6422dd5..ef8dbc679af 100644 --- a/SwiftCompilerSources/Sources/Optimizer/Utilities/GenericSpecialization.swift +++ b/SwiftCompilerSources/Sources/Optimizer/Utilities/GenericSpecialization.swift @@ -89,8 +89,9 @@ private struct VTableSpecializer { guard !methodSubs.conformances.contains(where: {!$0.isValid}), context.loadFunction(function: entry.implementation, loadCalleesRecursively: true), - let specializedMethod = context.specialize(function: entry.implementation, for: methodSubs) else - { + let specializedMethod = context.specialize(function: entry.implementation, for: methodSubs, + convertIndirectToDirect: true, isMandatory: true) + else { return entry } notifyNewFunction(specializedMethod) @@ -146,8 +147,9 @@ func specializeWitnessTable(for conformance: Conformance, _ context: ModulePassC guard !methodSubs.conformances.contains(where: {!$0.isValid}), context.loadFunction(function: origMethod, loadCalleesRecursively: true), - let specializedMethod = context.specialize(function: origMethod, for: methodSubs) else - { + let specializedMethod = context.specialize(function: origMethod, for: methodSubs, + convertIndirectToDirect: true, isMandatory: true) + else { return origEntry } return .method(requirement: requirement, witness: specializedMethod) @@ -212,8 +214,9 @@ private func specializeDefaultMethods(for conformance: Conformance, guard !methodSubs.conformances.contains(where: {!$0.isValid}), context.loadFunction(function: origMethod, loadCalleesRecursively: true), - let specializedMethod = context.specialize(function: origMethod, for: methodSubs) else - { + let specializedMethod = context.specialize(function: origMethod, for: methodSubs, + convertIndirectToDirect: true, isMandatory: true) + else { return origEntry } specialized = true diff --git a/include/swift/SILOptimizer/OptimizerBridging.h b/include/swift/SILOptimizer/OptimizerBridging.h index b849f6d401c..87ce899aefa 100644 --- a/include/swift/SILOptimizer/OptimizerBridging.h +++ b/include/swift/SILOptimizer/OptimizerBridging.h @@ -178,7 +178,9 @@ struct BridgedPassContext { bool tryOptimizeKeypath(BridgedInstruction apply) const; SWIFT_IMPORT_UNSAFE OptionalBridgedValue constantFoldBuiltin(BridgedInstruction builtin) const; SWIFT_IMPORT_UNSAFE OptionalBridgedFunction specializeFunction(BridgedFunction function, - BridgedSubstitutionMap substitutions) const; + BridgedSubstitutionMap substitutions, + bool convertIndirectToDirect, + bool isMandatory) const; void deserializeAllCallees(BridgedFunction function, bool deserializeAll) const; bool specializeClassMethodInst(BridgedInstruction cm) const; bool specializeWitnessMethodInst(BridgedInstruction wm) const; diff --git a/lib/SILOptimizer/Utils/OptimizerBridging.cpp b/lib/SILOptimizer/Utils/OptimizerBridging.cpp index 3c4f94eefeb..74b5c72b4a9 100644 --- a/lib/SILOptimizer/Utils/OptimizerBridging.cpp +++ b/lib/SILOptimizer/Utils/OptimizerBridging.cpp @@ -173,13 +173,15 @@ bool BridgedPassContext::canMakeStaticObjectReadOnly(BridgedType type) const { } OptionalBridgedFunction BridgedPassContext::specializeFunction(BridgedFunction function, - BridgedSubstitutionMap substitutions) const { + BridgedSubstitutionMap substitutions, + bool convertIndirectToDirect, + bool isMandatory) const { swift::SILModule *mod = invocation->getPassManager()->getModule(); SILFunction *origFunc = function.getFunction(); SubstitutionMap subs = substitutions.unbridged(); ReabstractionInfo ReInfo(mod->getSwiftModule(), mod->isWholeModule(), - ApplySite(), origFunc, subs, IsNotSerialized, - /*ConvertIndirectToDirect=*/true, + ApplySite(), origFunc, subs, origFunc->getSerializedKind(), + convertIndirectToDirect, /*dropUnusedArguments=*/false); if (!ReInfo.canBeSpecialized()) { @@ -188,8 +190,8 @@ OptionalBridgedFunction BridgedPassContext::specializeFunction(BridgedFunction f SILOptFunctionBuilder FunctionBuilder(*invocation->getTransform()); - GenericFuncSpecializer FuncSpecializer(FunctionBuilder, origFunc, subs, - ReInfo, /*isMandatory=*/true); + GenericFuncSpecializer FuncSpecializer(FunctionBuilder, origFunc, ReInfo.getClonerParamSubstitutionMap(), + ReInfo, isMandatory); SILFunction *SpecializedF = FuncSpecializer.lookupSpecialization(); if (!SpecializedF) SpecializedF = FuncSpecializer.tryCreateSpecialization(); if (!SpecializedF || SpecializedF->getLoweredFunctionType()->hasError()) { diff --git a/test/embedded/managed-buffer.swift b/test/embedded/managed-buffer.swift index d7ae6e06607..b133fbbb0cd 100644 --- a/test/embedded/managed-buffer.swift +++ b/test/embedded/managed-buffer.swift @@ -4,7 +4,7 @@ // REQUIRES: swift_feature_Embedded // CHECK: @"$e4main8MyBufferCN" = {{.*global.*}} <{ ptr @"$es13ManagedBufferCySis5UInt8VGN", ptr @"$e4main8MyBufferCfD{{[^"]*}}", ptr null, ptr @"$e4main8MyBufferC12_doNotCallMeACyt_tcfC{{[^"]*}}" }> -// CHECK: @"$es13ManagedBufferCySis5UInt8VGN" = {{.*global.*}} <{ ptr null, ptr @"$es13ManagedBufferCfDSi_s5UInt8VTg5{{[^"]*}}", ptr null, ptr @"$es13ManagedBufferC12_doNotCallMeAByxq_Gyt_tcfCSi_s5UInt8VTg5{{[^"]*}}" }> +// CHECK: @"$es13ManagedBufferCySis5UInt8VGN" = {{.*global.*}} <{ ptr null, ptr @"$es13ManagedBufferCfDSi_s5UInt8VTgq5{{[^"]*}}", ptr null, ptr @"$es13ManagedBufferC12_doNotCallMeAByxq_Gyt_tcfCSi_s5UInt8VTgq5{{[^"]*}}" }> final public class MyBuffer: ManagedBuffer { }