Files
swift-mirror/include/swift/SILPasses/Utils/SILInliner.h
Mark Lacey 1859b476d4 Further integration of inlining, devirtualization, and specialization.
This updates the performance inliner to iterate on inlining in cases
where devirtualization or specialization after the first pass of
inlining expose new opportunities for inlining. Similarly, in some cases
inlining exposes new opportunities for devirtualization, e.g. when we
inline an initializer and can now see an alloc_ref that allows us to
devirtualize some class_methods.

The implementation currently has some inefficiencies which increase the
swift compilation time for the stdlib by around 3% (this is swift-time
only, no LLVM time, so overall time does not grow by this much).

Unfortunately the (unchanged) current implementation of the core
inlining trades off improved estimates of code growth for increased
compile time, and that plays a part in why compile time increases as
much as it does. Despite this, I have some ideas on how to win some of
that time back in future patches.

Performance differences are mixed, and this will likely require some
further inliner tuning to reduce or remove some of the losses seen here
at -O. I will open radars for the losses.

Wins:
DeltaBlue                        10.2%
EditDistance                     13.8%
SwiftStructuresInsertionSort     32.6%
SwiftStructuresStack             34.9%

Losses:
PopFrontArrayGeneric            -12.7%
PrimeNum                        -19.0%
RC4                             -30.7%
Sim2DArray                      -14.6%

There were a handful of wins and losses at Onone and Ounchecked as
well. I'll review the perf testing output and open radars accordingly.

The new test case shows an example of the power of the closer
integration here. We are able to completely devirtualize and inline a
series of class_method applies (10 deep in this case, but in theory
substantially deeper) in a single pass of the inliner, whereas before we
could only do a single level per pass of inlining & devirtualization.

Swift SVN r27561
2015-04-22 04:48:13 +00:00

123 lines
4.4 KiB
C++

//===--- SILInliner.h - Inlines SIL functions --------------------*- C++ -*-==//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 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
//
//===----------------------------------------------------------------------===//
//
// This file defines the SILInliner class, used for inlining SIL functions into
// function application sites
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SIL_SILINLINER_H
#define SWIFT_SIL_SILINLINER_H
#include "llvm/ADT/DenseMap.h"
#include "swift/SIL/TypeSubstCloner.h"
#include <functional>
namespace swift {
// For now Free is 0 and Expensive is 1. This can be changed in the future by
// adding more categories.
enum class InlineCost : unsigned {
Free = 0,
Expensive = 1
};
/// Return the 'cost' of one instruction. Instructions that are expected to
/// disappear at the LLVM IR level are assigned a cost of 'Free'.
InlineCost instructionInlineCost(SILInstruction &I);
class SILInliner : public TypeSubstCloner<SILInliner> {
public:
friend class SILVisitor<SILInliner>;
friend class SILCloner<SILInliner>;
enum class InlineKind {
MandatoryInline,
PerformanceInline
};
SILInliner(SILFunction &To, SILFunction &From, InlineKind IKind,
TypeSubstitutionMap &ContextSubs, ArrayRef<Substitution> ApplySubs,
FullApplyCollector::CallbackType Callback =nullptr)
: TypeSubstCloner<SILInliner>(To, From, ContextSubs, ApplySubs, true),
IKind(IKind), CalleeEntryBB(nullptr), CallSiteScope(nullptr),
Callback(Callback) {
}
/// inlineFunction - This method inlines a callee function, assuming that it
/// is called with the given arguments, into the caller at a given instruction
/// (as specified by a basic block iterator), assuming that the instruction
/// corresponds semantically to an application of the function. It only
/// performs one step of inlining: it does not recursively inline functions
/// called by the callee.
///
/// Returns true on success or false if it is unable to inline the function
/// (for any reason). If successful, I now points to the first inlined
/// instruction, or the next instruction after the removed instruction in the
/// original function, in case the inlined function is completely trivial
bool inlineFunction(FullApplySite AI, ArrayRef<SILValue> Args);
private:
void visitDebugValueInst(DebugValueInst *Inst);
void visitDebugValueAddrInst(DebugValueAddrInst *Inst);
SILDebugScope *getOrCreateInlineScope(SILInstruction *Orig);
void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
if (IKind == InlineKind::MandatoryInline)
// Transparent functions are inheriting the location of the call
// site. No soup, err, debugging for you!
Cloned->setDebugScope(CallSiteScope);
else
// Create an inlined version of the scope.
Cloned->setDebugScope(getOrCreateInlineScope(Orig));
// Call client-supplied callback function.
if (Callback)
Callback(Orig, Cloned);
// We intentionally do not call
// SILClonerWithScopes<SILInliner>::postProcess() here as it does
// the wrong thing for inlined functions.
SILCloner<SILInliner>::postProcess(Orig, Cloned);
}
SILLocation remapLocation(SILLocation InLoc) {
// For performance inlining return the original location.
if (IKind == InlineKind::PerformanceInline)
return InLoc;
// Inlined location wraps the call site that is being inlined, regardless
// of the input location.
return Loc.hasValue() ? Loc.getValue() :
MandatoryInlinedLocation::getMandatoryInlinedLocation((Decl*)nullptr);
}
InlineKind IKind;
SILBasicBlock *CalleeEntryBB;
/// \brief The location representing the inlined instructions.
///
/// This location wraps the call site AST node that is being inlined.
/// Alternatively, it can be the SIL file location of the call site (in case
/// of SIL-to-SIL transformations).
Optional<SILLocation> Loc;
SILDebugScope *CallSiteScope;
SILFunction *CalleeFunction;
llvm::SmallDenseMap<SILDebugScope *, SILDebugScope *> InlinedScopeCache;
FullApplyCollector::CallbackType Callback;
};
} // end namespace swift
#endif