Files
swift-mirror/lib/SILOptimizer/Utils/FunctionSignatureOptUtils.cpp
Xin Tong cff61d7fe7 Implement a function signature cloner and rewriter.
This split the function signature module pass into 2 functin passes.

By doing so,  this allows us to rewrite to using the FSO-optimized
function prior to attempting inlining, but allow us to do a substantial
amount of optimization on the current function before attempting to do
FSO on that function.

And also helps us to move to a model which module pass is NOT used unless
necesary.

I do not see regression nor improvement for on the performance test suite.

functionsignopts.sil and functionsignopt_sroa.sil are modified because the
mangler now takes into account of information in the projection tree.
2016-03-19 23:57:37 -07:00

132 lines
4.8 KiB
C++

//===--- FunctionSignatureOptUtils.cpp ------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/SIL/SILBasicBlock.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILValue.h"
#include "swift/SILOptimizer/Utils/FunctionSignatureOptUtils.h"
#include "swift/SILOptimizer/Utils/Local.h"
using namespace swift;
static bool isSpecializableRepresentation(SILFunctionTypeRepresentation Rep) {
switch (Rep) {
case SILFunctionTypeRepresentation::Method:
case SILFunctionTypeRepresentation::Thin:
case SILFunctionTypeRepresentation::Thick:
case SILFunctionTypeRepresentation::CFunctionPointer:
return true;
case SILFunctionTypeRepresentation::WitnessMethod:
case SILFunctionTypeRepresentation::ObjCMethod:
case SILFunctionTypeRepresentation::Block:
return false;
}
}
/// Returns true if F is a function which the pass know show to specialize
/// function signatures for.
bool swift::canSpecializeFunction(SILFunction *F) {
// Do not specialize the signature of SILFunctions that are external
// declarations since there is no body to optimize.
if (F->isExternalDeclaration())
return false;
// Do not specialize functions that are available externally. If an external
// function was able to be specialized, it would have been specialized in its
// own module. We will inline the original function as a thunk. The thunk will
// call the specialized function.
if (F->isAvailableExternally())
return false;
// Do not specialize the signature of always inline functions. We
// will just inline them and specialize each one of the individual
// functions that these sorts of functions are inlined into.
if (F->getInlineStrategy() == Inline_t::AlwaysInline)
return false;
// For now ignore generic functions to keep things simple...
if (F->getLoweredFunctionType()->isPolymorphic())
return false;
// Make sure F has a linkage that we can optimize.
if (!isSpecializableRepresentation(F->getRepresentation()))
return false;
return true;
}
void swift::
addReleasesForConvertedOwnedParameter(SILBuilder &Builder,
SILLocation Loc,
ArrayRef<SILArgument*> Parameters,
ArrayRef<ArgumentDescriptor> &ArgDescs) {
// If we have any arguments that were consumed but are now guaranteed,
// insert a release_value.
for (auto &ArgDesc : ArgDescs) {
if (ArgDesc.CalleeRelease.empty())
continue;
Builder.createReleaseValue(Loc, Parameters[ArgDesc.Index]);
}
}
void swift::
addReleasesForConvertedOwnedParameter(SILBuilder &Builder,
SILLocation Loc,
OperandValueArrayRef Parameters,
ArrayRef<ArgumentDescriptor> &ArgDescs) {
// If we have any arguments that were consumed but are now guaranteed,
// insert a release_value.
for (auto &ArgDesc : ArgDescs) {
// The argument is dead. Make sure we have a release to balance out
// the retain for creating the @owned parameter.
if (ArgDesc.IsEntirelyDead &&
ArgDesc.Arg->getKnownParameterInfo().getConvention() ==
ParameterConvention::Direct_Owned) {
Builder.createReleaseValue(Loc, Parameters[ArgDesc.Index]);
continue;
}
if (ArgDesc.CalleeRelease.empty())
continue;
Builder.createReleaseValue(Loc, Parameters[ArgDesc.Index]);
}
}
void swift::
addRetainsForConvertedDirectResults(SILBuilder &Builder,
SILLocation Loc,
SILValue ReturnValue,
SILInstruction *AI,
ArrayRef<ResultDescriptor> DirectResults) {
for (auto I : indices(DirectResults)) {
auto &RV = DirectResults[I];
if (RV.CalleeRetain.empty()) continue;
bool IsSelfRecursionEpilogueRetain = false;
for (auto &X : RV.CalleeRetain) {
IsSelfRecursionEpilogueRetain |= (AI == X);
}
// We do not create a retain if this ApplyInst is a self-recursion.
if (IsSelfRecursionEpilogueRetain)
continue;
// Extract the return value if necessary.
SILValue SpecificResultValue = ReturnValue;
if (DirectResults.size() != 1)
SpecificResultValue = Builder.createTupleExtract(Loc, ReturnValue, I);
Builder.createRetainValue(Loc, SpecificResultValue);
}
}