mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
introduce a common superclass, SILNode. This is in preparation for allowing instructions to have multiple results. It is also a somewhat more elegant representation for instructions that have zero results. Instructions that are known to have exactly one result inherit from a class, SingleValueInstruction, that subclasses both ValueBase and SILInstruction. Some care must be taken when working with SILNode pointers and testing for equality; please see the comment on SILNode for more information. A number of SIL passes needed to be updated in order to handle this new distinction between SIL values and SIL instructions. Note that the SIL parser is now stricter about not trying to assign a result value from an instruction (like 'return' or 'strong_retain') that does not produce any.
115 lines
4.0 KiB
C++
115 lines
4.0 KiB
C++
//===--- FunctionSignatureOptUtils.cpp ------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 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/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 "llvm/Support/CommandLine.h"
|
|
|
|
using namespace swift;
|
|
|
|
/// Set to true to enable the support for partial specialization.
|
|
llvm::cl::opt<bool> FSOEnableGenerics(
|
|
"sil-fso-enable-generics", llvm::cl::init(true),
|
|
llvm::cl::desc("Support function signature optimization "
|
|
"of generic functions"));
|
|
|
|
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 (auto result : U->getResults()) {
|
|
for (Operand *I : getNonDebugUses(result))
|
|
Worklist.push_back(I->getUser());
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool isSpecializableRepresentation(SILFunctionTypeRepresentation Rep,
|
|
bool OptForPartialApply) {
|
|
switch (Rep) {
|
|
case SILFunctionTypeRepresentation::Method:
|
|
case SILFunctionTypeRepresentation::Closure:
|
|
case SILFunctionTypeRepresentation::Thin:
|
|
case SILFunctionTypeRepresentation::Thick:
|
|
case SILFunctionTypeRepresentation::CFunctionPointer:
|
|
return true;
|
|
case SILFunctionTypeRepresentation::WitnessMethod:
|
|
return OptForPartialApply;
|
|
case SILFunctionTypeRepresentation::ObjCMethod:
|
|
case SILFunctionTypeRepresentation::Block:
|
|
return false;
|
|
}
|
|
|
|
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
|
|
}
|
|
|
|
/// Returns true if F is a function which the pass know show to specialize
|
|
/// function signatures for.
|
|
bool swift::canSpecializeFunction(SILFunction *F,
|
|
const CallerAnalysis::FunctionInfo *FuncInfo,
|
|
bool OptForPartialApply) {
|
|
// 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->getConventions().hasIndirectSILResults())
|
|
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.
|
|
// It is OK to specialize always inline functions if they are
|
|
// used by partial_apply instructions.
|
|
assert(!OptForPartialApply || FuncInfo);
|
|
if (F->getInlineStrategy() == Inline_t::AlwaysInline &&
|
|
(!OptForPartialApply || !FuncInfo->getMinPartialAppliedArgs()))
|
|
return false;
|
|
|
|
// For now ignore generic functions to keep things simple...
|
|
if (!FSOEnableGenerics && F->getLoweredFunctionType()->isPolymorphic())
|
|
return false;
|
|
|
|
// Make sure F has a linkage that we can optimize.
|
|
if (!isSpecializableRepresentation(F->getRepresentation(),
|
|
OptForPartialApply))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|