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() 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 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 SILBridging
import AST
/// Clones the initializer value of a GlobalVariable. /// Clones the initializer value of a GlobalVariable.
/// ///
@@ -161,3 +162,34 @@ public struct Cloner<Context: MutatingContext> {
bridged.recordFoldedValue(origValue.bridged, mappedValue.bridged) 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 SILLoopInfo;
class SILLoop; class SILLoop;
class BridgedClonerImpl; class BridgedClonerImpl;
class BridgedTypeSubstClonerImpl;
class SILDebugLocation; class SILDebugLocation;
class NominalTypeDecl; class NominalTypeDecl;
class VarDecl; class VarDecl;
@@ -1541,6 +1542,17 @@ struct BridgedCloner {
BridgedInstruction clone(BridgedInstruction inst) const; 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 { struct BridgedVerifier {
typedef void (* _Nonnull VerifyFunctionFn)(BridgedContext, BridgedFunction); typedef void (* _Nonnull VerifyFunctionFn)(BridgedContext, BridgedFunction);

View File

@@ -22,6 +22,7 @@
#include "swift/Basic/Assertions.h" #include "swift/Basic/Assertions.h"
#include "swift/SIL/SILContext.h" #include "swift/SIL/SILContext.h"
#include "swift/SIL/SILCloner.h" #include "swift/SIL/SILCloner.h"
#include "swift/SIL/TypeSubstCloner.h"
#include "swift/SIL/MemAccessUtils.h" #include "swift/SIL/MemAccessUtils.h"
#include "swift/SIL/OwnershipUtils.h" #include "swift/SIL/OwnershipUtils.h"
#include "swift/SIL/ParseTestSpecification.h" #include "swift/SIL/ParseTestSpecification.h"
@@ -620,7 +621,32 @@ public:
result = Cloned; result = Cloned;
SILCloner<BridgedClonerImpl>::postProcess(Orig, 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 } // namespace swift
@@ -687,6 +713,32 @@ void BridgedCloner::cloneFunctionBody(BridgedFunction originalFunction) const {
cloner->cloneFunction(originalFunction.getFunction()); 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 // BridgedContext
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//