| //===--- 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; |
| } |
| |