mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
694 lines
28 KiB
C++
694 lines
28 KiB
C++
//===--- OptimizerBridging.cpp --------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/SILOptimizer/OptimizerBridging.h"
|
|
#include "swift/SILOptimizer/Analysis/Analysis.h"
|
|
#include "swift/SILOptimizer/Utils/CFGOptUtils.h"
|
|
#include "swift/SILOptimizer/Utils/ConstantFolding.h"
|
|
#include "swift/SILOptimizer/Utils/Devirtualize.h"
|
|
#include "swift/SILOptimizer/Utils/Generics.h"
|
|
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
|
|
#include "swift/SILOptimizer/Utils/SILInliner.h"
|
|
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
|
|
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
|
|
#include "swift/SILOptimizer/Utils/StackNesting.h"
|
|
#include "swift/SILOptimizer/IPO/ClosureSpecializer.h"
|
|
#include "swift/SIL/DynamicCasts.h"
|
|
#include "swift/SIL/OSSALifetimeCompletion.h"
|
|
#include "swift/SIL/SILCloner.h"
|
|
#include "../../IRGen/IRGenModule.h"
|
|
|
|
using namespace swift;
|
|
|
|
llvm::cl::list<std::string>
|
|
SimplifyInstructionTest("simplify-instruction", llvm::cl::CommaSeparated,
|
|
llvm::cl::desc("Simplify instruction of specified kind(s)"));
|
|
|
|
llvm::cl::opt<bool> DisableSwiftVerification(
|
|
"disable-swift-verification", llvm::cl::init(false),
|
|
llvm::cl::desc("Disable verification which is implemented in the SwiftCompilerSources"));
|
|
|
|
|
|
#ifdef PURE_BRIDGING_MODE
|
|
// In PURE_BRIDGING_MODE, briding functions are not inlined and therefore inluded in the cpp file.
|
|
#include "swift/SILOptimizer/OptimizerBridgingImpl.h"
|
|
#endif
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// PassManager
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
static BridgedUtilities::VerifyFunctionFn verifyFunctionFunction;
|
|
|
|
void BridgedUtilities::registerVerifier(VerifyFunctionFn verifyFunctionFn) {
|
|
verifyFunctionFunction = verifyFunctionFn;
|
|
}
|
|
|
|
void SILPassManager::runSwiftFunctionVerification(SILFunction *f) {
|
|
if (!verifyFunctionFunction)
|
|
return;
|
|
|
|
if (f->getModule().getOptions().VerifyNone)
|
|
return;
|
|
|
|
if (DisableSwiftVerification)
|
|
return;
|
|
|
|
getSwiftPassInvocation()->beginVerifyFunction(f);
|
|
verifyFunctionFunction({getSwiftPassInvocation()}, {f});
|
|
getSwiftPassInvocation()->endVerifyFunction();
|
|
}
|
|
|
|
void SILPassManager::runSwiftModuleVerification() {
|
|
for (SILFunction &f : *Mod) {
|
|
runSwiftFunctionVerification(&f);
|
|
}
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// OptimizerBridging
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void BridgedChangeNotificationHandler::notifyChanges(Kind changeKind) const {
|
|
switch (changeKind) {
|
|
case Kind::instructionsChanged:
|
|
invocation->notifyChanges(SILAnalysis::InvalidationKind::Instructions);
|
|
break;
|
|
case Kind::callsChanged:
|
|
invocation->notifyChanges(SILAnalysis::InvalidationKind::CallsAndInstructions);
|
|
break;
|
|
case Kind::branchesChanged:
|
|
invocation->notifyChanges(SILAnalysis::InvalidationKind::BranchesAndInstructions);
|
|
break;
|
|
case Kind::effectsChanged:
|
|
invocation->notifyChanges(SILAnalysis::InvalidationKind::Effects);
|
|
break;
|
|
case Kind::functionTablesChanged:
|
|
invocation->notifyFunctionTablesChanged();
|
|
break;
|
|
}
|
|
}
|
|
|
|
BridgedOwnedString BridgedPassContext::getModuleDescription() const {
|
|
std::string str;
|
|
llvm::raw_string_ostream os(str);
|
|
invocation->getPassManager()->getModule()->print(os);
|
|
str.pop_back(); // Remove trailing newline.
|
|
return BridgedOwnedString(str);
|
|
}
|
|
|
|
bool BridgedPassContext::tryOptimizeApplyOfPartialApply(BridgedInstruction closure) const {
|
|
auto *pa = closure.getAs<PartialApplyInst>();
|
|
SILBuilder builder(pa);
|
|
return ::tryOptimizeApplyOfPartialApply(pa, builder.getBuilderContext(), InstModCallbacks());
|
|
}
|
|
|
|
bool BridgedPassContext::tryDeleteDeadClosure(BridgedInstruction closure, bool needKeepArgsAlive) const {
|
|
return ::tryDeleteDeadClosure(closure.getAs<SingleValueInstruction>(), InstModCallbacks(), needKeepArgsAlive);
|
|
}
|
|
|
|
BridgedPassContext::DevirtResult BridgedPassContext::tryDevirtualizeApply(BridgedInstruction apply,
|
|
bool isMandatory) const {
|
|
SILPassManager *pm = invocation->getPassManager();
|
|
auto cha = pm->getAnalysis<ClassHierarchyAnalysis>();
|
|
auto result = ::tryDevirtualizeApply(pm, ApplySite(apply.unbridged()), cha,
|
|
nullptr, isMandatory);
|
|
if (result.first) {
|
|
OptionalBridgedInstruction newApply(result.first.getInstruction()->asSILNode());
|
|
return {newApply, result.second};
|
|
}
|
|
return {{nullptr}, false};
|
|
}
|
|
|
|
bool BridgedPassContext::tryOptimizeKeypath(BridgedInstruction apply) const {
|
|
SILBuilder builder(apply.unbridged());
|
|
return ::tryOptimizeKeypath(apply.getAs<ApplyInst>(), builder);
|
|
}
|
|
|
|
OptionalBridgedValue BridgedPassContext::constantFoldBuiltin(BridgedInstruction builtin) const {
|
|
auto bi = builtin.getAs<BuiltinInst>();
|
|
std::optional<bool> resultsInError;
|
|
return {::constantFoldBuiltin(bi, resultsInError)};
|
|
}
|
|
|
|
void BridgedPassContext::inlineFunction(BridgedInstruction apply, bool mandatoryInline) const {
|
|
SILOptFunctionBuilder funcBuilder(*invocation->getTransform());
|
|
InstructionDeleter deleter;
|
|
SILInliner::inlineFullApply(FullApplySite(apply.unbridged()),
|
|
mandatoryInline
|
|
? SILInliner::InlineKind::MandatoryInline
|
|
: SILInliner::InlineKind::PerformanceInline,
|
|
funcBuilder, deleter);
|
|
}
|
|
|
|
static const irgen::TypeInfo &getTypeInfoOfBuiltin(swift::SILType type, irgen::IRGenModule &IGM) {
|
|
SILType lowered = IGM.getLoweredType(swift::Lowering::AbstractionPattern::getOpaque(), type.getASTType());
|
|
return IGM.getTypeInfo(lowered);
|
|
}
|
|
|
|
static SwiftInt integerValueFromConstant(llvm::Constant *c, SwiftInt add = 0) {
|
|
auto *intConst = dyn_cast_or_null<llvm::ConstantInt>(c);
|
|
if (!intConst)
|
|
return -1;
|
|
APInt value = intConst->getValue();
|
|
return value.getLimitedValue() + add;
|
|
}
|
|
|
|
SwiftInt BridgedPassContext::getStaticSize(BridgedType type) const {
|
|
irgen::IRGenModule *IGM = invocation->getIRGenModule();
|
|
if (!IGM)
|
|
return -1;
|
|
auto &ti = getTypeInfoOfBuiltin(type.unbridged(), *IGM);
|
|
llvm::Constant *c = ti.getStaticSize(*IGM);
|
|
return integerValueFromConstant(c);
|
|
}
|
|
|
|
SwiftInt BridgedPassContext::getStaticAlignment(BridgedType type) const {
|
|
irgen::IRGenModule *IGM = invocation->getIRGenModule();
|
|
if (!IGM)
|
|
return -1;
|
|
auto &ti = getTypeInfoOfBuiltin(type.unbridged(), *IGM);
|
|
llvm::Constant *c = ti.getStaticAlignmentMask(*IGM);
|
|
return integerValueFromConstant(c, 1);
|
|
}
|
|
|
|
SwiftInt BridgedPassContext::getStaticStride(BridgedType type) const {
|
|
irgen::IRGenModule *IGM = invocation->getIRGenModule();
|
|
if (!IGM)
|
|
return -1;
|
|
auto &ti = getTypeInfoOfBuiltin(type.unbridged(), *IGM);
|
|
llvm::Constant *c = ti.getStaticStride(*IGM);
|
|
return integerValueFromConstant(c);
|
|
}
|
|
|
|
bool BridgedPassContext::canMakeStaticObjectReadOnly(BridgedType type) const {
|
|
if (irgen::IRGenModule *IGM = invocation->getIRGenModule()) {
|
|
return IGM->canMakeStaticObjectReadOnly(type.unbridged());
|
|
}
|
|
return false;
|
|
}
|
|
|
|
OptionalBridgedFunction BridgedPassContext::specializeFunction(BridgedFunction function,
|
|
BridgedSubstitutionMap substitutions) 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,
|
|
/*dropMetatypeArgs=*/false);
|
|
|
|
if (!ReInfo.canBeSpecialized()) {
|
|
return {nullptr};
|
|
}
|
|
|
|
SILOptFunctionBuilder FunctionBuilder(*invocation->getTransform());
|
|
|
|
GenericFuncSpecializer FuncSpecializer(FunctionBuilder, origFunc, subs,
|
|
ReInfo, /*isMandatory=*/true);
|
|
SILFunction *SpecializedF = FuncSpecializer.lookupSpecialization();
|
|
if (!SpecializedF) SpecializedF = FuncSpecializer.tryCreateSpecialization();
|
|
if (!SpecializedF || SpecializedF->getLoweredFunctionType()->hasError()) {
|
|
return {nullptr};
|
|
}
|
|
return {SpecializedF};
|
|
}
|
|
|
|
void BridgedPassContext::deserializeAllCallees(BridgedFunction function, bool deserializeAll) const {
|
|
swift::SILModule *mod = invocation->getPassManager()->getModule();
|
|
mod->linkFunction(function.getFunction(), deserializeAll ? SILModule::LinkingMode::LinkAll :
|
|
SILModule::LinkingMode::LinkNormal);
|
|
}
|
|
|
|
bool BridgedPassContext::specializeClassMethodInst(BridgedInstruction cm) const {
|
|
return ::specializeClassMethodInst(cm.getAs<ClassMethodInst>());
|
|
}
|
|
|
|
bool BridgedPassContext::specializeWitnessMethodInst(BridgedInstruction wm) const {
|
|
return ::specializeWitnessMethodInst(wm.getAs<WitnessMethodInst>());
|
|
}
|
|
|
|
bool BridgedPassContext::specializeAppliesInFunction(BridgedFunction function, bool isMandatory) const {
|
|
return ::specializeAppliesInFunction(*function.getFunction(), invocation->getTransform(), isMandatory);
|
|
}
|
|
|
|
namespace {
|
|
class GlobalVariableMangler : public Mangle::ASTMangler {
|
|
public:
|
|
GlobalVariableMangler(ASTContext &Ctx) : ASTMangler(Ctx) {}
|
|
std::string mangleOutlinedVariable(SILFunction *F, int &uniqueIdx) {
|
|
std::string GlobName;
|
|
do {
|
|
beginManglingWithoutPrefix();
|
|
appendOperator(F->getName());
|
|
appendOperator("Tv", Index(uniqueIdx++));
|
|
GlobName = finalize();
|
|
} while (F->getModule().lookUpGlobalVariable(GlobName));
|
|
|
|
return GlobName;
|
|
}
|
|
};
|
|
} // namespace
|
|
|
|
BridgedOwnedString BridgedPassContext::mangleOutlinedVariable(BridgedFunction function) const {
|
|
int idx = 0;
|
|
SILFunction *f = function.getFunction();
|
|
SILModule &mod = f->getModule();
|
|
while (true) {
|
|
GlobalVariableMangler mangler(f->getASTContext());
|
|
std::string name = mangler.mangleOutlinedVariable(f, idx);
|
|
if (!mod.lookUpGlobalVariable(name))
|
|
return BridgedOwnedString(name);
|
|
idx++;
|
|
}
|
|
}
|
|
|
|
BridgedOwnedString BridgedPassContext::mangleAsyncRemoved(BridgedFunction function) const {
|
|
SILFunction *F = function.getFunction();
|
|
|
|
// FIXME: hard assumption on what pass is requesting this.
|
|
auto P = Demangle::SpecializationPass::AsyncDemotion;
|
|
|
|
Mangle::FunctionSignatureSpecializationMangler Mangler(F->getASTContext(),
|
|
P, F->getSerializedKind(), F);
|
|
Mangler.setRemovedEffect(EffectKind::Async);
|
|
return BridgedOwnedString(Mangler.mangle());
|
|
}
|
|
|
|
BridgedOwnedString BridgedPassContext::mangleWithDeadArgs(const SwiftInt * _Nullable deadArgs,
|
|
SwiftInt numDeadArgs,
|
|
BridgedFunction function) const {
|
|
SILFunction *f = function.getFunction();
|
|
Mangle::FunctionSignatureSpecializationMangler Mangler(f->getASTContext(),
|
|
Demangle::SpecializationPass::FunctionSignatureOpts,
|
|
f->getSerializedKind(), f);
|
|
for (SwiftInt idx = 0; idx < numDeadArgs; idx++) {
|
|
Mangler.setArgumentDead((unsigned)idx);
|
|
}
|
|
return BridgedOwnedString(Mangler.mangle());
|
|
}
|
|
|
|
BridgedOwnedString BridgedPassContext::mangleWithClosureArgs(
|
|
BridgedValueArray bridgedClosureArgs,
|
|
BridgedArrayRef bridgedClosureArgIndices,
|
|
BridgedFunction applySiteCallee
|
|
) const {
|
|
auto pass = Demangle::SpecializationPass::ClosureSpecializer;
|
|
auto serializedKind = applySiteCallee.getFunction()->getSerializedKind();
|
|
Mangle::FunctionSignatureSpecializationMangler mangler(applySiteCallee.getFunction()->getASTContext(),
|
|
pass, serializedKind, applySiteCallee.getFunction());
|
|
|
|
llvm::SmallVector<swift::SILValue, 16> closureArgsStorage;
|
|
auto closureArgs = bridgedClosureArgs.getValues(closureArgsStorage);
|
|
auto closureArgIndices = bridgedClosureArgIndices.unbridged<SwiftInt>();
|
|
|
|
assert(closureArgs.size() == closureArgIndices.size() &&
|
|
"Number of closures arguments and number of closure indices do not match!");
|
|
|
|
for (size_t i = 0; i < closureArgs.size(); i++) {
|
|
auto closureArg = closureArgs[i];
|
|
auto closureArgIndex = closureArgIndices[i];
|
|
|
|
if (auto *PAI = dyn_cast<PartialApplyInst>(closureArg)) {
|
|
mangler.setArgumentClosureProp(closureArgIndex,
|
|
const_cast<PartialApplyInst *>(PAI));
|
|
} else {
|
|
auto *TTTFI = cast<ThinToThickFunctionInst>(closureArg);
|
|
mangler.setArgumentClosureProp(closureArgIndex,
|
|
const_cast<ThinToThickFunctionInst *>(TTTFI));
|
|
}
|
|
}
|
|
|
|
return BridgedOwnedString(mangler.mangle());
|
|
}
|
|
|
|
BridgedGlobalVar BridgedPassContext::createGlobalVariable(BridgedStringRef name, BridgedType type, BridgedLinkage linkage, bool isLet) const {
|
|
auto *global = SILGlobalVariable::create(
|
|
*invocation->getPassManager()->getModule(),
|
|
(swift::SILLinkage)linkage, IsNotSerialized,
|
|
name.unbridged(), type.unbridged());
|
|
if (isLet)
|
|
global->setLet(true);
|
|
return {global};
|
|
}
|
|
|
|
void BridgedPassContext::fixStackNesting(BridgedFunction function) const {
|
|
switch (StackNesting::fixNesting(function.getFunction())) {
|
|
case StackNesting::Changes::None:
|
|
break;
|
|
case StackNesting::Changes::Instructions:
|
|
invocation->notifyChanges(SILAnalysis::InvalidationKind::Instructions);
|
|
break;
|
|
case StackNesting::Changes::CFG:
|
|
invocation->notifyChanges(SILAnalysis::InvalidationKind::BranchesAndInstructions);
|
|
break;
|
|
}
|
|
invocation->setNeedFixStackNesting(false);
|
|
}
|
|
|
|
OptionalBridgedFunction BridgedPassContext::lookupStdlibFunction(BridgedStringRef name) const {
|
|
swift::SILModule *mod = invocation->getPassManager()->getModule();
|
|
SmallVector<ValueDecl *, 1> results;
|
|
mod->getASTContext().lookupInSwiftModule(name.unbridged(), results);
|
|
if (results.size() != 1)
|
|
return {nullptr};
|
|
|
|
auto *decl = dyn_cast<FuncDecl>(results.front());
|
|
if (!decl)
|
|
return {nullptr};
|
|
|
|
SILDeclRef declRef(decl, SILDeclRef::Kind::Func);
|
|
SILOptFunctionBuilder funcBuilder(*invocation->getTransform());
|
|
return {funcBuilder.getOrCreateFunction(SILLocation(decl), declRef, NotForDefinition)};
|
|
}
|
|
|
|
OptionalBridgedFunction BridgedPassContext::lookUpNominalDeinitFunction(BridgedDeclObj nominal) const {
|
|
swift::SILModule *mod = invocation->getPassManager()->getModule();
|
|
return {mod->lookUpMoveOnlyDeinitFunction(nominal.getAs<swift::NominalTypeDecl>())};
|
|
}
|
|
|
|
bool BridgedPassContext::enableSimplificationFor(BridgedInstruction inst) const {
|
|
// Fast-path check.
|
|
if (SimplifyInstructionTest.empty() && !SILPassManager::isAnyPassDisabled())
|
|
return true;
|
|
|
|
StringRef instName = getSILInstructionName(inst.unbridged()->getKind());
|
|
|
|
if (SILPassManager::isInstructionPassDisabled(instName))
|
|
return false;
|
|
|
|
if (SimplifyInstructionTest.empty())
|
|
return true;
|
|
|
|
for (const std::string &testName : SimplifyInstructionTest) {
|
|
if (testName == instName)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
BridgedFunction BridgedPassContext::
|
|
createEmptyFunction(BridgedStringRef name,
|
|
const BridgedParameterInfo * _Nullable bridgedParams,
|
|
SwiftInt paramCount,
|
|
bool hasSelfParam,
|
|
BridgedFunction fromFunc) const {
|
|
swift::SILModule *mod = invocation->getPassManager()->getModule();
|
|
SILFunction *fromFn = fromFunc.getFunction();
|
|
|
|
llvm::SmallVector<SILParameterInfo> params;
|
|
for (unsigned idx = 0; idx < paramCount; ++idx) {
|
|
params.push_back(bridgedParams[idx].unbridged());
|
|
}
|
|
|
|
CanSILFunctionType fTy = fromFn->getLoweredFunctionType();
|
|
assert(fromFn->getGenericSignature().isNull() && "generic functions are not supported");
|
|
|
|
auto extInfo = fTy->getExtInfo();
|
|
if (fTy->hasSelfParam() && !hasSelfParam)
|
|
extInfo = extInfo.withRepresentation(SILFunctionTypeRepresentation::Thin);
|
|
|
|
CanSILFunctionType newTy = SILFunctionType::get(
|
|
/*GenericSignature=*/nullptr, extInfo, fTy->getCoroutineKind(),
|
|
fTy->getCalleeConvention(), params, fTy->getYields(),
|
|
fTy->getResults(), fTy->getOptionalErrorResult(),
|
|
SubstitutionMap(), SubstitutionMap(),
|
|
mod->getASTContext());
|
|
|
|
SILOptFunctionBuilder functionBuilder(*invocation->getTransform());
|
|
|
|
SILFunction *newF = functionBuilder.createFunction(
|
|
fromFn->getLinkage(), name.unbridged(), newTy, nullptr,
|
|
fromFn->getLocation(), fromFn->isBare(), fromFn->isTransparent(),
|
|
fromFn->getSerializedKind(), IsNotDynamic, IsNotDistributed,
|
|
IsNotRuntimeAccessible, fromFn->getEntryCount(), fromFn->isThunk(),
|
|
fromFn->getClassSubclassScope(), fromFn->getInlineStrategy(),
|
|
fromFn->getEffectsKind(), nullptr, fromFn->getDebugScope());
|
|
|
|
return {newF};
|
|
}
|
|
|
|
void BridgedPassContext::moveFunctionBody(BridgedFunction sourceFunc, BridgedFunction destFunc) const {
|
|
SILFunction *sourceFn = sourceFunc.getFunction();
|
|
SILFunction *destFn = destFunc.getFunction();
|
|
destFn->moveAllBlocksFromOtherFunction(sourceFn);
|
|
invocation->getPassManager()->invalidateAnalysis(sourceFn, SILAnalysis::InvalidationKind::Everything);
|
|
invocation->getPassManager()->invalidateAnalysis(destFn, SILAnalysis::InvalidationKind::Everything);
|
|
}
|
|
|
|
BridgedFunction BridgedPassContext::
|
|
ClosureSpecializer_createEmptyFunctionWithSpecializedSignature(BridgedStringRef specializedName,
|
|
const BridgedParameterInfo * _Nullable specializedBridgedParams,
|
|
SwiftInt paramCount,
|
|
BridgedFunction bridgedApplySiteCallee,
|
|
bool isSerialized) const {
|
|
auto *applySiteCallee = bridgedApplySiteCallee.getFunction();
|
|
auto applySiteCalleeType = applySiteCallee->getLoweredFunctionType();
|
|
|
|
llvm::SmallVector<SILParameterInfo> specializedParams;
|
|
for (unsigned idx = 0; idx < paramCount; ++idx) {
|
|
specializedParams.push_back(specializedBridgedParams[idx].unbridged());
|
|
}
|
|
|
|
// The specialized function is always a thin function. This is important
|
|
// because we may add additional parameters after the Self parameter of
|
|
// witness methods. In this case the new function is not a method anymore.
|
|
auto extInfo = applySiteCalleeType->getExtInfo();
|
|
extInfo = extInfo.withRepresentation(SILFunctionTypeRepresentation::Thin);
|
|
|
|
auto ClonedTy = SILFunctionType::get(
|
|
applySiteCalleeType->getInvocationGenericSignature(), extInfo,
|
|
applySiteCalleeType->getCoroutineKind(),
|
|
applySiteCalleeType->getCalleeConvention(), specializedParams,
|
|
applySiteCalleeType->getYields(), applySiteCalleeType->getResults(),
|
|
applySiteCalleeType->getOptionalErrorResult(),
|
|
applySiteCalleeType->getPatternSubstitutions(),
|
|
applySiteCalleeType->getInvocationSubstitutions(),
|
|
applySiteCallee->getModule().getASTContext());
|
|
|
|
SILOptFunctionBuilder functionBuilder(*invocation->getTransform());
|
|
|
|
// We make this function bare so we don't have to worry about decls in the
|
|
// SILArgument.
|
|
auto *specializedApplySiteCallee = functionBuilder.createFunction(
|
|
// It's important to use a shared linkage for the specialized function
|
|
// and not the original linkage.
|
|
// Otherwise the new function could have an external linkage (in case the
|
|
// original function was de-serialized) and would not be code-gen'd.
|
|
// It's also important to disconnect this specialized function from any
|
|
// classes (the classSubclassScope), because that may incorrectly
|
|
// influence the linkage.
|
|
getSpecializedLinkage(applySiteCallee, applySiteCallee->getLinkage()), specializedName.unbridged(),
|
|
ClonedTy, applySiteCallee->getGenericEnvironment(),
|
|
applySiteCallee->getLocation(), IsBare, applySiteCallee->isTransparent(),
|
|
isSerialized ? IsSerialized : IsNotSerialized, IsNotDynamic, IsNotDistributed,
|
|
IsNotRuntimeAccessible, applySiteCallee->getEntryCount(),
|
|
applySiteCallee->isThunk(),
|
|
/*classSubclassScope=*/SubclassScope::NotApplicable,
|
|
applySiteCallee->getInlineStrategy(), applySiteCallee->getEffectsKind(),
|
|
applySiteCallee, applySiteCallee->getDebugScope());
|
|
|
|
if (!applySiteCallee->hasOwnership()) {
|
|
specializedApplySiteCallee->setOwnershipEliminated();
|
|
}
|
|
|
|
for (auto &Attr : applySiteCallee->getSemanticsAttrs())
|
|
specializedApplySiteCallee->addSemanticsAttr(Attr);
|
|
|
|
return {specializedApplySiteCallee};
|
|
}
|
|
|
|
bool BridgedPassContext::completeLifetime(BridgedValue value) const {
|
|
SILValue v = value.getSILValue();
|
|
SILFunction *f = v->getFunction();
|
|
DeadEndBlocks *deb = invocation->getPassManager()->getAnalysis<DeadEndBlocksAnalysis>()->get(f);
|
|
DominanceInfo *domInfo = invocation->getPassManager()->getAnalysis<DominanceAnalysis>()->get(f);
|
|
OSSALifetimeCompletion completion(f, domInfo, *deb);
|
|
auto result = completion.completeOSSALifetime(v, OSSALifetimeCompletion::Boundary::Availability);
|
|
return result == LifetimeCompletion::WasCompleted;
|
|
}
|
|
|
|
bool BeginApply_canInline(BridgedInstruction beginApply) {
|
|
return swift::SILInliner::canInlineBeginApply(beginApply.getAs<BeginApplyInst>());
|
|
}
|
|
|
|
BridgedDynamicCastResult classifyDynamicCastBridged(BridgedCanType sourceTy, BridgedCanType destTy,
|
|
BridgedFunction function,
|
|
bool sourceTypeIsExact) {
|
|
static_assert((int)DynamicCastFeasibility::WillSucceed == (int)BridgedDynamicCastResult::willSucceed);
|
|
static_assert((int)DynamicCastFeasibility::MaySucceed == (int)BridgedDynamicCastResult::maySucceed);
|
|
static_assert((int)DynamicCastFeasibility::WillFail == (int)BridgedDynamicCastResult::willFail);
|
|
|
|
return static_cast<BridgedDynamicCastResult>(
|
|
classifyDynamicCast(function.getFunction(), sourceTy.unbridged(), destTy.unbridged(), sourceTypeIsExact));
|
|
}
|
|
|
|
BridgedDynamicCastResult classifyDynamicCastBridged(BridgedInstruction inst) {
|
|
SILDynamicCastInst castInst(inst.unbridged());
|
|
return static_cast<BridgedDynamicCastResult>(castInst.classifyFeasibility(/*allowWholeModule=*/ false));
|
|
}
|
|
|
|
// TODO: can't be inlined to work around https://github.com/apple/swift/issues/64502
|
|
BridgedCalleeAnalysis::CalleeList BridgedCalleeAnalysis::getCallees(BridgedValue callee) const {
|
|
return ca->getCalleeListOfValue(callee.getSILValue());
|
|
}
|
|
|
|
// TODO: can't be inlined to work around https://github.com/apple/swift/issues/64502
|
|
BridgedCalleeAnalysis::CalleeList BridgedCalleeAnalysis::getDestructors(BridgedType type, bool isExactType) const {
|
|
return ca->getDestructors(type.unbridged(), isExactType);
|
|
}
|
|
|
|
// Need to put ClonerWithFixedLocation into namespace swift to forward reference
|
|
// it in OptimizerBridging.h.
|
|
namespace swift {
|
|
|
|
class ClonerWithFixedLocation : public SILCloner<ClonerWithFixedLocation> {
|
|
friend class SILInstructionVisitor<ClonerWithFixedLocation>;
|
|
friend class SILCloner<ClonerWithFixedLocation>;
|
|
|
|
SILDebugLocation insertLoc;
|
|
|
|
public:
|
|
ClonerWithFixedLocation(SILGlobalVariable *gVar)
|
|
: SILCloner<ClonerWithFixedLocation>(gVar),
|
|
insertLoc(ArtificialUnreachableLocation(), nullptr) {}
|
|
|
|
ClonerWithFixedLocation(SILInstruction *insertionPoint)
|
|
: SILCloner<ClonerWithFixedLocation>(*insertionPoint->getFunction()),
|
|
insertLoc(insertionPoint->getDebugLocation()) {
|
|
Builder.setInsertionPoint(insertionPoint);
|
|
}
|
|
|
|
SILValue getClonedValue(SILValue v) {
|
|
return getMappedValue(v);
|
|
}
|
|
|
|
void cloneInst(SILInstruction *inst) {
|
|
visit(inst);
|
|
}
|
|
|
|
protected:
|
|
|
|
SILLocation remapLocation(SILLocation loc) {
|
|
return insertLoc.getLocation();
|
|
}
|
|
|
|
const SILDebugScope *remapScope(const SILDebugScope *DS) {
|
|
return insertLoc.getScope();
|
|
}
|
|
};
|
|
|
|
} // namespace swift
|
|
|
|
BridgedCloner::BridgedCloner(BridgedGlobalVar var, BridgedPassContext context)
|
|
: cloner(new ClonerWithFixedLocation(var.getGlobal())) {
|
|
context.invocation->notifyNewCloner();
|
|
}
|
|
|
|
BridgedCloner::BridgedCloner(BridgedInstruction inst,
|
|
BridgedPassContext context)
|
|
: cloner(new ClonerWithFixedLocation(inst.unbridged())) {
|
|
context.invocation->notifyNewCloner();
|
|
}
|
|
|
|
void BridgedCloner::destroy(BridgedPassContext context) {
|
|
delete cloner;
|
|
cloner = nullptr;
|
|
context.invocation->notifyClonerDestroyed();
|
|
}
|
|
|
|
BridgedValue BridgedCloner::getClonedValue(BridgedValue v) {
|
|
return {cloner->getClonedValue(v.getSILValue())};
|
|
}
|
|
|
|
bool BridgedCloner::isValueCloned(BridgedValue v) const {
|
|
return cloner->isValueCloned(v.getSILValue());
|
|
}
|
|
|
|
void BridgedCloner::clone(BridgedInstruction inst) {
|
|
cloner->cloneInst(inst.unbridged());
|
|
}
|
|
|
|
void BridgedCloner::recordFoldedValue(BridgedValue origValue, BridgedValue mappedValue) {
|
|
cloner->recordFoldedValue(origValue.getSILValue(), mappedValue.getSILValue());
|
|
}
|
|
|
|
namespace swift {
|
|
class ClosureSpecializationCloner: public SILClonerWithScopes<ClosureSpecializationCloner> {
|
|
friend class SILInstructionVisitor<ClosureSpecializationCloner>;
|
|
friend class SILCloner<ClosureSpecializationCloner>;
|
|
public:
|
|
using SuperTy = SILClonerWithScopes<ClosureSpecializationCloner>;
|
|
ClosureSpecializationCloner(SILFunction &emptySpecializedFunction): SuperTy(emptySpecializedFunction) {}
|
|
};
|
|
} // namespace swift
|
|
|
|
BridgedSpecializationCloner::BridgedSpecializationCloner(BridgedFunction emptySpecializedFunction):
|
|
closureSpecCloner(new ClosureSpecializationCloner(*emptySpecializedFunction.getFunction())) {}
|
|
|
|
BridgedFunction BridgedSpecializationCloner::getCloned() const {
|
|
return { &closureSpecCloner->getBuilder().getFunction() };
|
|
}
|
|
|
|
BridgedBasicBlock BridgedSpecializationCloner::getClonedBasicBlock(BridgedBasicBlock originalBasicBlock) const {
|
|
return { closureSpecCloner->getOpBasicBlock(originalBasicBlock.unbridged()) };
|
|
}
|
|
|
|
void BridgedSpecializationCloner::cloneFunctionBody(BridgedFunction originalFunction, BridgedBasicBlock clonedEntryBlock, BridgedValueArray clonedEntryBlockArgs) const {
|
|
llvm::SmallVector<swift::SILValue, 16> clonedEntryBlockArgsStorage;
|
|
auto clonedEntryBlockArgsArrayRef = clonedEntryBlockArgs.getValues(clonedEntryBlockArgsStorage);
|
|
closureSpecCloner->cloneFunctionBody(originalFunction.getFunction(), clonedEntryBlock.unbridged(), clonedEntryBlockArgsArrayRef);
|
|
}
|
|
|
|
void BridgedBuilder::destroyCapturedArgs(BridgedInstruction partialApply) const {
|
|
if (auto *pai = llvm::dyn_cast<PartialApplyInst>(partialApply.unbridged()); pai->isOnStack()) {
|
|
auto b = unbridged();
|
|
return swift::insertDestroyOfCapturedArguments(pai, b);
|
|
} else {
|
|
assert(false && "`destroyCapturedArgs` must only be called on a `partial_apply` on stack!");
|
|
}
|
|
}
|
|
|
|
void verifierError(BridgedStringRef message,
|
|
OptionalBridgedInstruction atInstruction,
|
|
OptionalBridgedArgument atArgument) {
|
|
Twine msg(message.unbridged());
|
|
verificationFailure(msg, atInstruction.unbridged(), atArgument.unbridged(), /*extraContext=*/nullptr);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// SIL Bridging functions which call C++ functions in the optimizer
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool BridgedFunction::isTrapNoReturn() const {
|
|
return swift::isTrapNoReturnFunction(getFunction());
|
|
}
|
|
|
|
bool BridgedFunction::isConvertPointerToPointerArgument() const {
|
|
if (auto declRef = getFunction()->getDeclRef()) {
|
|
auto *conversionDecl =
|
|
declRef.getASTContext().getConvertPointerToPointerArgument();
|
|
return declRef.getFuncDecl() == conversionDecl;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool BridgedFunction::isAutodiffVJP() const {
|
|
return swift::isDifferentiableFuncComponent(
|
|
getFunction(), swift::AutoDiffFunctionComponent::VJP);
|
|
}
|
|
|
|
SwiftInt BridgedFunction::specializationLevel() const {
|
|
return swift::getSpecializationLevel(getFunction());
|
|
}
|