Optimizer: add TypeSubstitutionCloner and func cloneAndSpecializeFunction

Also move `func cloneFunction` from ContextCommon.swift to OptUtils.swift
This commit is contained in:
Erik Eckstein
2025-09-03 09:27:31 +02:00
parent c15f76f316
commit b8a49692eb
5 changed files with 113 additions and 6 deletions

View File

@@ -163,9 +163,3 @@ extension Instruction {
context.notifyInstructionsChanged()
}
}
func cloneFunction(from originalFunction: Function, toEmpty targetFunction: Function, _ context: FunctionPassContext) {
var cloner = Cloner(cloneToEmptyFunction: targetFunction, context)
defer { cloner.deinitialize() }
cloner.cloneFunctionBody(from: originalFunction)
}

View File

@@ -1092,3 +1092,20 @@ func isInLoop(block startBlock: BasicBlock, _ context: FunctionPassContext) -> B
}
return false
}
func cloneFunction(from originalFunction: Function, toEmpty targetFunction: Function, _ context: FunctionPassContext) {
var cloner = Cloner(cloneToEmptyFunction: targetFunction, context)
defer { cloner.deinitialize() }
cloner.cloneFunctionBody(from: originalFunction)
}
func cloneAndSpecializeFunction(from originalFunction: Function,
toEmpty targetFunction: Function,
substitutions: SubstitutionMap,
_ context: FunctionPassContext
) {
var cloner = TypeSubstitutionCloner(fromFunction: originalFunction, toEmptyFunction: targetFunction,
substitutions: substitutions, context)
defer { cloner.deinitialize() }
cloner.cloneFunctionBody()
}

View File

@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
import SILBridging
import AST
/// Clones the initializer value of a GlobalVariable.
///
@@ -161,3 +162,34 @@ public struct Cloner<Context: MutatingContext> {
bridged.recordFoldedValue(origValue.bridged, mappedValue.bridged)
}
}
public struct TypeSubstitutionCloner<Context: MutatingContext> {
public private(set) var bridged: BridgedTypeSubstCloner
public let context: Context
public init(fromFunction: Function,
toEmptyFunction: Function,
substitutions: SubstitutionMap, _ context: Context
) {
context.verifyIsTransforming(function: toEmptyFunction)
self.bridged = BridgedTypeSubstCloner(fromFunction.bridged, toEmptyFunction.bridged,
substitutions.bridged, context._bridged)
self.context = context
}
public mutating func deinitialize() {
bridged.destroy(context._bridged)
}
public mutating func getClonedValue(of originalValue: Value) -> Value {
bridged.getClonedValue(originalValue.bridged).value
}
public func getClonedBlock(for originalBlock: BasicBlock) -> BasicBlock {
bridged.getClonedBasicBlock(originalBlock.bridged).block
}
public func cloneFunctionBody() {
bridged.cloneFunctionBody()
}
}

View File

@@ -63,6 +63,7 @@ class SILDefaultWitnessTable;
class SILLoopInfo;
class SILLoop;
class BridgedClonerImpl;
class BridgedTypeSubstClonerImpl;
class SILDebugLocation;
class NominalTypeDecl;
class VarDecl;
@@ -1541,6 +1542,17 @@ struct BridgedCloner {
BridgedInstruction clone(BridgedInstruction inst) const;
};
struct BridgedTypeSubstCloner {
swift::BridgedTypeSubstClonerImpl * _Nonnull cloner;
BridgedTypeSubstCloner(BridgedFunction fromFunction, BridgedFunction toFunction,
BridgedSubstitutionMap substitutions, BridgedContext context);
void destroy(BridgedContext context);
void cloneFunctionBody() const;
SWIFT_IMPORT_UNSAFE BridgedBasicBlock getClonedBasicBlock(BridgedBasicBlock originalBasicBlock) const;
SWIFT_IMPORT_UNSAFE BridgedValue getClonedValue(BridgedValue v);
};
struct BridgedVerifier {
typedef void (* _Nonnull VerifyFunctionFn)(BridgedContext, BridgedFunction);

View File

@@ -22,6 +22,7 @@
#include "swift/Basic/Assertions.h"
#include "swift/SIL/SILContext.h"
#include "swift/SIL/SILCloner.h"
#include "swift/SIL/TypeSubstCloner.h"
#include "swift/SIL/MemAccessUtils.h"
#include "swift/SIL/OwnershipUtils.h"
#include "swift/SIL/ParseTestSpecification.h"
@@ -620,7 +621,32 @@ public:
result = Cloned;
SILCloner<BridgedClonerImpl>::postProcess(Orig, Cloned);
}
};
class BridgedTypeSubstClonerImpl : public TypeSubstCloner<BridgedTypeSubstClonerImpl> {
SILInstruction *result = nullptr;
public:
BridgedTypeSubstClonerImpl(SILFunction &from, SILFunction &toEmptyFunction, SubstitutionMap subs)
: TypeSubstCloner<BridgedTypeSubstClonerImpl>(toEmptyFunction, from, subs) {}
SILValue getClonedValue(SILValue v) {
return getMappedValue(v);
}
SILInstruction *cloneInst(SILInstruction *inst) {
result = nullptr;
visit(inst);
ASSERT(result && "instruction not cloned");
return result;
}
void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
result = Cloned;
SILClonerWithScopes<BridgedTypeSubstClonerImpl>::postProcess(Orig, Cloned);
}
SILFunction *getOriginal() { return &Original; }
};
} // namespace swift
@@ -687,6 +713,32 @@ void BridgedCloner::cloneFunctionBody(BridgedFunction originalFunction) const {
cloner->cloneFunction(originalFunction.getFunction());
}
BridgedTypeSubstCloner::BridgedTypeSubstCloner(BridgedFunction fromFunction, BridgedFunction toFunction,
BridgedSubstitutionMap substitutions,
BridgedContext context)
: cloner(new BridgedTypeSubstClonerImpl(*fromFunction.getFunction(), *toFunction.getFunction(),
substitutions.unbridged())) {
context.context->notifyNewCloner();
}
void BridgedTypeSubstCloner::destroy(BridgedContext context) {
delete cloner;
cloner = nullptr;
context.context->notifyClonerDestroyed();
}
void BridgedTypeSubstCloner::cloneFunctionBody() const {
cloner->cloneFunction(cloner->getOriginal());
}
BridgedBasicBlock BridgedTypeSubstCloner::getClonedBasicBlock(BridgedBasicBlock originalBasicBlock) const {
return { cloner->getOpBasicBlock(originalBasicBlock.unbridged()) };
}
BridgedValue BridgedTypeSubstCloner::getClonedValue(BridgedValue v) {
return {cloner->getClonedValue(v.getSILValue())};
}
//===----------------------------------------------------------------------===//
// BridgedContext
//===----------------------------------------------------------------------===//