Files
swift-mirror/lib/SILOptimizer/Utils/FunctionSignatureOptUtils.cpp
Xin Tong 633ca2e92b Simplify function signature optimzation.
Several functionalities have been added to FSO over time and the logic has become
muddled.

We were always looking at a static image of the SIL and try to reason about what kind of
function signature related optimizations we can do.

This can easily lead to muddled logic. e.g. we need to consider 2 different function
signature optimizations together instead of independently.

Split 1 single function to do all sorts of different analyses in FSO into several
small transformations, each of which does a specific job. After every analysis, we produce
a new function and eventually we collapse all intermediate thunks to in a single thunk.

With this change, it will be easier to implement function signature optimization as now
we can do them independently now.

Minimal modifications to the test cases.
2016-04-25 15:28:51 -07:00

102 lines
3.4 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/SIL/DebugUtils.h"
#include "swift/SILOptimizer/Utils/FunctionSignatureOptUtils.h"
#include "swift/SILOptimizer/Utils/Local.h"
#include "swift/SIL/Mangle.h"
using namespace swift;
bool swift::hasNonTrivialNonDebugUse(SILArgument *Arg) {
llvm::SmallVector<SILInstruction *, 8> Worklist;
llvm::SmallPtrSet<SILInstruction *, 8> SeenInsts;
for (Operand *I : getNonDebugUses(SILValue(Arg)))
Worklist.push_back(I->getUser());
while (!Worklist.empty()) {
SILInstruction *U = Worklist.pop_back_val();
if (!SeenInsts.insert(U).second)
continue;
// If U is a terminator inst, return false.
if (isa<TermInst>(U))
return true;
// If U has side effects...
if (U->mayHaveSideEffects())
return true;
// Otherwise add all non-debug uses of I to the worklist.
for (Operand *I : getNonDebugUses(SILValue(U)))
Worklist.push_back(I->getUser());
}
return false;
}
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;
// For now ignore functions with indirect results.
if (F->getLoweredFunctionType()->hasIndirectResults())
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;
}