2004-06-20 04:11:48 +00:00
|
|
|
//===- Inliner.cpp - Code common to all inliners --------------------------===//
|
2005-04-21 23:48:37 +00:00
|
|
|
//
|
2003-10-20 19:43:21 +00:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 20:36:04 +00:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-21 23:48:37 +00:00
|
|
|
//
|
2003-10-20 19:43:21 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
2003-08-31 19:10:30 +00:00
|
|
|
//
|
2004-05-23 21:22:17 +00:00
|
|
|
// This file implements the mechanics required to implement inlining without
|
|
|
|
// missing any calls and updating the call graph. The decisions of which calls
|
|
|
|
// are profitable to inline are implemented elsewhere.
|
2003-08-31 19:10:30 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2006-12-19 22:09:18 +00:00
|
|
|
#define DEBUG_TYPE "inline"
|
2003-08-31 19:10:30 +00:00
|
|
|
#include "llvm/Module.h"
|
2004-07-29 17:30:56 +00:00
|
|
|
#include "llvm/Instructions.h"
|
2009-03-19 18:03:56 +00:00
|
|
|
#include "llvm/IntrinsicInst.h"
|
2003-08-31 19:10:30 +00:00
|
|
|
#include "llvm/Analysis/CallGraph.h"
|
2009-10-13 18:30:07 +00:00
|
|
|
#include "llvm/Analysis/InlineCost.h"
|
2007-01-30 23:28:39 +00:00
|
|
|
#include "llvm/Target/TargetData.h"
|
2007-06-19 22:29:50 +00:00
|
|
|
#include "llvm/Transforms/IPO/InlinerPass.h"
|
2003-08-31 19:10:30 +00:00
|
|
|
#include "llvm/Transforms/Utils/Cloning.h"
|
2009-11-12 21:58:18 +00:00
|
|
|
#include "llvm/Transforms/Utils/Local.h"
|
|
|
|
#include "llvm/Support/CallSite.h"
|
2004-09-01 22:55:40 +00:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
2009-07-25 00:23:56 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2009-08-27 04:32:07 +00:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2004-09-01 22:55:40 +00:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2003-11-21 21:45:31 +00:00
|
|
|
using namespace llvm;
|
2003-11-11 22:41:34 +00:00
|
|
|
|
2006-12-19 22:09:18 +00:00
|
|
|
STATISTIC(NumInlined, "Number of functions inlined");
|
2010-05-01 17:19:38 +00:00
|
|
|
STATISTIC(NumCallsDeleted, "Number of call sites deleted, not inlined");
|
2006-12-19 22:09:18 +00:00
|
|
|
STATISTIC(NumDeleted, "Number of functions deleted because all callers found");
|
2009-08-27 06:29:33 +00:00
|
|
|
STATISTIC(NumMergedAllocas, "Number of allocas merged together");
|
2006-12-19 22:09:18 +00:00
|
|
|
|
2008-05-13 00:00:25 +00:00
|
|
|
static cl::opt<int>
|
2010-02-04 18:48:20 +00:00
|
|
|
InlineLimit("inline-threshold", cl::Hidden, cl::init(225), cl::ZeroOrMore,
|
|
|
|
cl::desc("Control the amount of inlining to perform (default = 225)"));
|
2003-08-31 19:10:30 +00:00
|
|
|
|
2010-02-13 01:51:53 +00:00
|
|
|
static cl::opt<int>
|
|
|
|
HintThreshold("inlinehint-threshold", cl::Hidden, cl::init(325),
|
|
|
|
cl::desc("Threshold for inlining functions with inline hint"));
|
2010-02-06 01:16:28 +00:00
|
|
|
|
|
|
|
// Threshold to use when optsize is specified (and there is no -inline-limit).
|
|
|
|
const int OptSizeThreshold = 75;
|
|
|
|
|
2010-08-06 18:33:48 +00:00
|
|
|
Inliner::Inliner(char &ID)
|
2012-02-25 02:56:01 +00:00
|
|
|
: CallGraphSCCPass(ID), InlineThreshold(InlineLimit), InsertLifetime(true) {}
|
2003-08-31 19:10:30 +00:00
|
|
|
|
2012-02-25 02:56:01 +00:00
|
|
|
Inliner::Inliner(char &ID, int Threshold, bool InsertLifetime)
|
2010-11-02 23:40:26 +00:00
|
|
|
: CallGraphSCCPass(ID), InlineThreshold(InlineLimit.getNumOccurrences() > 0 ?
|
2012-02-25 02:56:01 +00:00
|
|
|
InlineLimit : Threshold),
|
|
|
|
InsertLifetime(InsertLifetime) {}
|
2008-01-12 06:49:13 +00:00
|
|
|
|
2007-01-30 23:28:39 +00:00
|
|
|
/// getAnalysisUsage - For this class, we declare that we require and preserve
|
|
|
|
/// the call graph. If the derived class implements this method, it should
|
|
|
|
/// always explicitly call the implementation here.
|
|
|
|
void Inliner::getAnalysisUsage(AnalysisUsage &Info) const {
|
|
|
|
CallGraphSCCPass::getAnalysisUsage(Info);
|
|
|
|
}
|
|
|
|
|
2009-08-27 06:29:33 +00:00
|
|
|
|
2011-07-18 04:54:35 +00:00
|
|
|
typedef DenseMap<ArrayType*, std::vector<AllocaInst*> >
|
2009-08-27 06:29:33 +00:00
|
|
|
InlinedArrayAllocasTy;
|
|
|
|
|
|
|
|
/// InlineCallIfPossible - If it is possible to inline the specified call site,
|
|
|
|
/// do so and update the CallGraph for this operation.
|
|
|
|
///
|
|
|
|
/// This function also does some basic book-keeping to update the IR. The
|
2009-08-28 04:48:54 +00:00
|
|
|
/// InlinedArrayAllocas map keeps track of any allocas that are already
|
|
|
|
/// available from other functions inlined into the caller. If we are able to
|
|
|
|
/// inline this call site we attempt to reuse already available allocas or add
|
|
|
|
/// any new allocas to the set if not possible.
|
2010-04-22 23:07:58 +00:00
|
|
|
static bool InlineCallIfPossible(CallSite CS, InlineFunctionInfo &IFI,
|
Fix PR8735, a really terrible problem in the inliner's "alloca merging"
optimization.
Consider:
static void foo() {
A = alloca
...
}
static void bar() {
B = alloca
...
call foo();
}
void main() {
bar()
}
The inliner proceeds bottom up, but lets pretend it decides not to inline foo
into bar. When it gets to main, it inlines bar into main(), and says "hey, I
just inlined an alloca "B" into main, lets remember that. Then it keeps going
and finds that it now contains a call to foo. It decides to inline foo into
main, and says "hey, foo has an alloca A, and I have an alloca B from another
inlined call site, lets reuse it". The problem with this of course, is that
the lifetime of A and B are nested, not disjoint.
Unfortunately I can't create a reasonable testcase for this: the one in the
PR is both huge and extremely sensitive, because you minor tweaks end up
causing foo to get inlined into bar too early. We already have tests for the
basic alloca merging optimization and this does not break them.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120995 91177308-0d34-0410-b5e6-96231b3b80d8
2010-12-06 07:52:42 +00:00
|
|
|
InlinedArrayAllocasTy &InlinedArrayAllocas,
|
2012-02-25 02:56:01 +00:00
|
|
|
int InlineHistory, bool InsertLifetime) {
|
2004-05-23 21:22:17 +00:00
|
|
|
Function *Callee = CS.getCalledFunction();
|
2008-11-21 00:09:21 +00:00
|
|
|
Function *Caller = CS.getCaller();
|
|
|
|
|
2009-08-27 06:29:33 +00:00
|
|
|
// Try to inline the function. Get the list of static allocas that were
|
|
|
|
// inlined.
|
2012-02-25 02:56:01 +00:00
|
|
|
if (!InlineFunction(CS, IFI, InsertLifetime))
|
2009-08-27 04:32:07 +00:00
|
|
|
return false;
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2008-11-21 00:06:32 +00:00
|
|
|
// If the inlined function had a higher stack protection level than the
|
|
|
|
// calling function, then bump up the caller's stack protection level.
|
|
|
|
if (Callee->hasFnAttr(Attribute::StackProtectReq))
|
|
|
|
Caller->addFnAttr(Attribute::StackProtectReq);
|
|
|
|
else if (Callee->hasFnAttr(Attribute::StackProtect) &&
|
|
|
|
!Caller->hasFnAttr(Attribute::StackProtectReq))
|
|
|
|
Caller->addFnAttr(Attribute::StackProtect);
|
|
|
|
|
2009-08-27 06:29:33 +00:00
|
|
|
// Look at all of the allocas that we inlined through this call site. If we
|
|
|
|
// have already inlined other allocas through other calls into this function,
|
|
|
|
// then we know that they have disjoint lifetimes and that we can merge them.
|
|
|
|
//
|
|
|
|
// There are many heuristics possible for merging these allocas, and the
|
|
|
|
// different options have different tradeoffs. One thing that we *really*
|
|
|
|
// don't want to hurt is SRoA: once inlining happens, often allocas are no
|
|
|
|
// longer address taken and so they can be promoted.
|
|
|
|
//
|
|
|
|
// Our "solution" for that is to only merge allocas whose outermost type is an
|
|
|
|
// array type. These are usually not promoted because someone is using a
|
|
|
|
// variable index into them. These are also often the most important ones to
|
|
|
|
// merge.
|
|
|
|
//
|
|
|
|
// A better solution would be to have real memory lifetime markers in the IR
|
|
|
|
// and not have the inliner do any merging of allocas at all. This would
|
|
|
|
// allow the backend to do proper stack slot coloring of all allocas that
|
|
|
|
// *actually make it to the backend*, which is really what we want.
|
|
|
|
//
|
|
|
|
// Because we don't have this information, we do this simple and useful hack.
|
|
|
|
//
|
|
|
|
SmallPtrSet<AllocaInst*, 16> UsedAllocas;
|
|
|
|
|
Fix PR8735, a really terrible problem in the inliner's "alloca merging"
optimization.
Consider:
static void foo() {
A = alloca
...
}
static void bar() {
B = alloca
...
call foo();
}
void main() {
bar()
}
The inliner proceeds bottom up, but lets pretend it decides not to inline foo
into bar. When it gets to main, it inlines bar into main(), and says "hey, I
just inlined an alloca "B" into main, lets remember that. Then it keeps going
and finds that it now contains a call to foo. It decides to inline foo into
main, and says "hey, foo has an alloca A, and I have an alloca B from another
inlined call site, lets reuse it". The problem with this of course, is that
the lifetime of A and B are nested, not disjoint.
Unfortunately I can't create a reasonable testcase for this: the one in the
PR is both huge and extremely sensitive, because you minor tweaks end up
causing foo to get inlined into bar too early. We already have tests for the
basic alloca merging optimization and this does not break them.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120995 91177308-0d34-0410-b5e6-96231b3b80d8
2010-12-06 07:52:42 +00:00
|
|
|
// When processing our SCC, check to see if CS was inlined from some other
|
|
|
|
// call site. For example, if we're processing "A" in this code:
|
|
|
|
// A() { B() }
|
|
|
|
// B() { x = alloca ... C() }
|
|
|
|
// C() { y = alloca ... }
|
|
|
|
// Assume that C was not inlined into B initially, and so we're processing A
|
|
|
|
// and decide to inline B into A. Doing this makes an alloca available for
|
|
|
|
// reuse and makes a callsite (C) available for inlining. When we process
|
|
|
|
// the C call site we don't want to do any alloca merging between X and Y
|
|
|
|
// because their scopes are not disjoint. We could make this smarter by
|
|
|
|
// keeping track of the inline history for each alloca in the
|
|
|
|
// InlinedArrayAllocas but this isn't likely to be a significant win.
|
|
|
|
if (InlineHistory != -1) // Only do merging for top-level call sites in SCC.
|
|
|
|
return true;
|
|
|
|
|
2009-08-27 06:29:33 +00:00
|
|
|
// Loop over all the allocas we have so far and see if they can be merged with
|
|
|
|
// a previously inlined alloca. If not, remember that we had it.
|
2010-04-22 23:07:58 +00:00
|
|
|
for (unsigned AllocaNo = 0, e = IFI.StaticAllocas.size();
|
2009-08-27 06:29:33 +00:00
|
|
|
AllocaNo != e; ++AllocaNo) {
|
2010-04-22 23:07:58 +00:00
|
|
|
AllocaInst *AI = IFI.StaticAllocas[AllocaNo];
|
2009-08-27 06:29:33 +00:00
|
|
|
|
|
|
|
// Don't bother trying to merge array allocations (they will usually be
|
|
|
|
// canonicalized to be an allocation *of* an array), or allocations whose
|
|
|
|
// type is not itself an array (because we're afraid of pessimizing SRoA).
|
2011-07-18 04:54:35 +00:00
|
|
|
ArrayType *ATy = dyn_cast<ArrayType>(AI->getAllocatedType());
|
2009-08-27 06:29:33 +00:00
|
|
|
if (ATy == 0 || AI->isArrayAllocation())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Get the list of all available allocas for this array type.
|
|
|
|
std::vector<AllocaInst*> &AllocasForType = InlinedArrayAllocas[ATy];
|
|
|
|
|
|
|
|
// Loop over the allocas in AllocasForType to see if we can reuse one. Note
|
|
|
|
// that we have to be careful not to reuse the same "available" alloca for
|
|
|
|
// multiple different allocas that we just inlined, we use the 'UsedAllocas'
|
|
|
|
// set to keep track of which "available" allocas are being used by this
|
|
|
|
// function. Also, AllocasForType can be empty of course!
|
|
|
|
bool MergedAwayAlloca = false;
|
|
|
|
for (unsigned i = 0, e = AllocasForType.size(); i != e; ++i) {
|
|
|
|
AllocaInst *AvailableAlloca = AllocasForType[i];
|
|
|
|
|
|
|
|
// The available alloca has to be in the right function, not in some other
|
|
|
|
// function in this SCC.
|
|
|
|
if (AvailableAlloca->getParent() != AI->getParent())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// If the inlined function already uses this alloca then we can't reuse
|
|
|
|
// it.
|
|
|
|
if (!UsedAllocas.insert(AvailableAlloca))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Otherwise, we *can* reuse it, RAUW AI into AvailableAlloca and declare
|
|
|
|
// success!
|
2010-12-06 07:38:40 +00:00
|
|
|
DEBUG(dbgs() << " ***MERGED ALLOCA: " << *AI << "\n\t\tINTO: "
|
|
|
|
<< *AvailableAlloca << '\n');
|
2009-08-27 06:29:33 +00:00
|
|
|
|
|
|
|
AI->replaceAllUsesWith(AvailableAlloca);
|
|
|
|
AI->eraseFromParent();
|
|
|
|
MergedAwayAlloca = true;
|
|
|
|
++NumMergedAllocas;
|
2010-12-06 07:38:40 +00:00
|
|
|
IFI.StaticAllocas[AllocaNo] = 0;
|
2009-08-27 06:29:33 +00:00
|
|
|
break;
|
|
|
|
}
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2009-08-27 06:29:33 +00:00
|
|
|
// If we already nuked the alloca, we're done with it.
|
|
|
|
if (MergedAwayAlloca)
|
|
|
|
continue;
|
2010-12-06 07:38:40 +00:00
|
|
|
|
2009-08-27 06:29:33 +00:00
|
|
|
// If we were unable to merge away the alloca either because there are no
|
|
|
|
// allocas of the right type available or because we reused them all
|
|
|
|
// already, remember that this alloca came from an inlined function and mark
|
|
|
|
// it used so we don't reuse it for other allocas from this inline
|
|
|
|
// operation.
|
|
|
|
AllocasForType.push_back(AI);
|
|
|
|
UsedAllocas.insert(AI);
|
2004-05-23 21:22:17 +00:00
|
|
|
}
|
2009-08-27 06:29:33 +00:00
|
|
|
|
2004-05-23 21:22:17 +00:00
|
|
|
return true;
|
2003-08-31 19:10:30 +00:00
|
|
|
}
|
2010-01-20 17:51:28 +00:00
|
|
|
|
2010-02-06 01:16:28 +00:00
|
|
|
unsigned Inliner::getInlineThreshold(CallSite CS) const {
|
2010-02-13 01:51:53 +00:00
|
|
|
int thres = InlineThreshold;
|
2010-02-06 01:16:28 +00:00
|
|
|
|
|
|
|
// Listen to optsize when -inline-limit is not given.
|
|
|
|
Function *Caller = CS.getCaller();
|
2010-01-20 17:51:28 +00:00
|
|
|
if (Caller && !Caller->isDeclaration() &&
|
|
|
|
Caller->hasFnAttr(Attribute::OptimizeForSize) &&
|
|
|
|
InlineLimit.getNumOccurrences() == 0)
|
2010-02-13 01:51:53 +00:00
|
|
|
thres = OptSizeThreshold;
|
|
|
|
|
|
|
|
// Listen to inlinehint when it would increase the threshold.
|
|
|
|
Function *Callee = CS.getCalledFunction();
|
|
|
|
if (HintThreshold > thres && Callee && !Callee->isDeclaration() &&
|
|
|
|
Callee->hasFnAttr(Attribute::InlineHint))
|
|
|
|
thres = HintThreshold;
|
2010-02-06 01:16:28 +00:00
|
|
|
|
2010-02-13 01:51:53 +00:00
|
|
|
return thres;
|
2010-01-20 17:51:28 +00:00
|
|
|
}
|
|
|
|
|
2008-10-29 01:02:02 +00:00
|
|
|
/// shouldInline - Return true if the inliner should attempt to inline
|
|
|
|
/// at the given CallSite.
|
|
|
|
bool Inliner::shouldInline(CallSite CS) {
|
2008-10-30 19:26:59 +00:00
|
|
|
InlineCost IC = getInlineCost(CS);
|
2008-10-29 01:02:02 +00:00
|
|
|
|
2008-10-30 19:26:59 +00:00
|
|
|
if (IC.isAlways()) {
|
2010-01-05 01:27:51 +00:00
|
|
|
DEBUG(dbgs() << " Inlining: cost=always"
|
2009-07-31 19:52:24 +00:00
|
|
|
<< ", Call: " << *CS.getInstruction() << "\n");
|
2008-10-30 19:26:59 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IC.isNever()) {
|
2010-01-05 01:27:51 +00:00
|
|
|
DEBUG(dbgs() << " NOT Inlining: cost=never"
|
2009-07-31 19:52:24 +00:00
|
|
|
<< ", Call: " << *CS.getInstruction() << "\n");
|
2008-10-30 19:26:59 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-10-09 00:11:32 +00:00
|
|
|
Function *Caller = CS.getCaller();
|
Initial commit for the rewrite of the inline cost analysis to operate
on a per-callsite walk of the called function's instructions, in
breadth-first order over the potentially reachable set of basic blocks.
This is a major shift in how inline cost analysis works to improve the
accuracy and rationality of inlining decisions. A brief outline of the
algorithm this moves to:
- Build a simplification mapping based on the callsite arguments to the
function arguments.
- Push the entry block onto a worklist of potentially-live basic blocks.
- Pop the first block off of the *front* of the worklist (for
breadth-first ordering) and walk its instructions using a custom
InstVisitor.
- For each instruction's operands, re-map them based on the
simplification mappings available for the given callsite.
- Compute any simplification possible of the instruction after
re-mapping, and store that back int othe simplification mapping.
- Compute any bonuses, costs, or other impacts of the instruction on the
cost metric.
- When the terminator is reached, replace any conditional value in the
terminator with any simplifications from the mapping we have, and add
any successors which are not proven to be dead from these
simplifications to the worklist.
- Pop the next block off of the front of the worklist, and repeat.
- As soon as the cost of inlining exceeds the threshold for the
callsite, stop analyzing the function in order to bound cost.
The primary goal of this algorithm is to perfectly handle dead code
paths. We do not want any code in trivially dead code paths to impact
inlining decisions. The previous metric was *extremely* flawed here, and
would always subtract the average cost of two successors of
a conditional branch when it was proven to become an unconditional
branch at the callsite. There was no handling of wildly different costs
between the two successors, which would cause inlining when the path
actually taken was too large, and no inlining when the path actually
taken was trivially simple. There was also no handling of the code
*path*, only the immediate successors. These problems vanish completely
now. See the added regression tests for the shiny new features -- we
skip recursive function calls, SROA-killing instructions, and high cost
complex CFG structures when dead at the callsite being analyzed.
Switching to this algorithm required refactoring the inline cost
interface to accept the actual threshold rather than simply returning
a single cost. The resulting interface is pretty bad, and I'm planning
to do lots of interface cleanup after this patch.
Several other refactorings fell out of this, but I've tried to minimize
them for this patch. =/ There is still more cleanup that can be done
here. Please point out anything that you see in review.
I've worked really hard to try to mirror at least the spirit of all of
the previous heuristics in the new model. It's not clear that they are
all correct any more, but I wanted to minimize the change in this single
patch, it's already a bit ridiculous. One heuristic that is *not* yet
mirrored is to allow inlining of functions with a dynamic alloca *if*
the caller has a dynamic alloca. I will add this back, but I think the
most reasonable way requires changes to the inliner itself rather than
just the cost metric, and so I've deferred this for a subsequent patch.
The test case is XFAIL-ed until then.
As mentioned in the review mail, this seems to make Clang run about 1%
to 2% faster in -O0, but makes its binary size grow by just under 4%.
I've looked into the 4% growth, and it can be fixed, but requires
changes to other parts of the inliner.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153812 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-31 12:42:41 +00:00
|
|
|
if (!IC) {
|
|
|
|
DEBUG(dbgs() << " NOT Inlining: cost=" << IC.getCost()
|
|
|
|
<< ", thres=" << (IC.getCostDelta() + IC.getCost())
|
2009-07-31 19:52:24 +00:00
|
|
|
<< ", Call: " << *CS.getInstruction() << "\n");
|
2008-10-29 01:02:02 +00:00
|
|
|
return false;
|
|
|
|
}
|
2009-08-27 03:51:50 +00:00
|
|
|
|
2012-03-14 20:16:41 +00:00
|
|
|
// Try to detect the case where the current inlining candidate caller (call
|
|
|
|
// it B) is a static or linkonce-ODR function and is an inlining candidate
|
|
|
|
// elsewhere, and the current candidate callee (call it C) is large enough
|
|
|
|
// that inlining it into B would make B too big to inline later. In these
|
|
|
|
// circumstances it may be best not to inline C into B, but to inline B into
|
|
|
|
// its callers.
|
|
|
|
//
|
|
|
|
// This only applies to static and linkonce-ODR functions because those are
|
|
|
|
// expected to be available for inlining in the translation units where they
|
|
|
|
// are used. Thus we will always have the opportunity to make local inlining
|
|
|
|
// decisions. Importantly the linkonce-ODR linkage covers inline functions
|
|
|
|
// and templates in C++.
|
Initial commit for the rewrite of the inline cost analysis to operate
on a per-callsite walk of the called function's instructions, in
breadth-first order over the potentially reachable set of basic blocks.
This is a major shift in how inline cost analysis works to improve the
accuracy and rationality of inlining decisions. A brief outline of the
algorithm this moves to:
- Build a simplification mapping based on the callsite arguments to the
function arguments.
- Push the entry block onto a worklist of potentially-live basic blocks.
- Pop the first block off of the *front* of the worklist (for
breadth-first ordering) and walk its instructions using a custom
InstVisitor.
- For each instruction's operands, re-map them based on the
simplification mappings available for the given callsite.
- Compute any simplification possible of the instruction after
re-mapping, and store that back int othe simplification mapping.
- Compute any bonuses, costs, or other impacts of the instruction on the
cost metric.
- When the terminator is reached, replace any conditional value in the
terminator with any simplifications from the mapping we have, and add
any successors which are not proven to be dead from these
simplifications to the worklist.
- Pop the next block off of the front of the worklist, and repeat.
- As soon as the cost of inlining exceeds the threshold for the
callsite, stop analyzing the function in order to bound cost.
The primary goal of this algorithm is to perfectly handle dead code
paths. We do not want any code in trivially dead code paths to impact
inlining decisions. The previous metric was *extremely* flawed here, and
would always subtract the average cost of two successors of
a conditional branch when it was proven to become an unconditional
branch at the callsite. There was no handling of wildly different costs
between the two successors, which would cause inlining when the path
actually taken was too large, and no inlining when the path actually
taken was trivially simple. There was also no handling of the code
*path*, only the immediate successors. These problems vanish completely
now. See the added regression tests for the shiny new features -- we
skip recursive function calls, SROA-killing instructions, and high cost
complex CFG structures when dead at the callsite being analyzed.
Switching to this algorithm required refactoring the inline cost
interface to accept the actual threshold rather than simply returning
a single cost. The resulting interface is pretty bad, and I'm planning
to do lots of interface cleanup after this patch.
Several other refactorings fell out of this, but I've tried to minimize
them for this patch. =/ There is still more cleanup that can be done
here. Please point out anything that you see in review.
I've worked really hard to try to mirror at least the spirit of all of
the previous heuristics in the new model. It's not clear that they are
all correct any more, but I wanted to minimize the change in this single
patch, it's already a bit ridiculous. One heuristic that is *not* yet
mirrored is to allow inlining of functions with a dynamic alloca *if*
the caller has a dynamic alloca. I will add this back, but I think the
most reasonable way requires changes to the inliner itself rather than
just the cost metric, and so I've deferred this for a subsequent patch.
The test case is XFAIL-ed until then.
As mentioned in the review mail, this seems to make Clang run about 1%
to 2% faster in -O0, but makes its binary size grow by just under 4%.
I've looked into the 4% growth, and it can be fixed, but requires
changes to other parts of the inliner.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153812 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-31 12:42:41 +00:00
|
|
|
//
|
|
|
|
// FIXME: All of this logic should be sunk into getInlineCost. It relies on
|
|
|
|
// the internal implementation of the inline cost metrics rather than
|
|
|
|
// treating them as truly abstract units etc.
|
2012-03-14 20:16:41 +00:00
|
|
|
if (Caller->hasLocalLinkage() ||
|
|
|
|
Caller->getLinkage() == GlobalValue::LinkOnceODRLinkage) {
|
2009-10-09 00:11:32 +00:00
|
|
|
int TotalSecondaryCost = 0;
|
Initial commit for the rewrite of the inline cost analysis to operate
on a per-callsite walk of the called function's instructions, in
breadth-first order over the potentially reachable set of basic blocks.
This is a major shift in how inline cost analysis works to improve the
accuracy and rationality of inlining decisions. A brief outline of the
algorithm this moves to:
- Build a simplification mapping based on the callsite arguments to the
function arguments.
- Push the entry block onto a worklist of potentially-live basic blocks.
- Pop the first block off of the *front* of the worklist (for
breadth-first ordering) and walk its instructions using a custom
InstVisitor.
- For each instruction's operands, re-map them based on the
simplification mappings available for the given callsite.
- Compute any simplification possible of the instruction after
re-mapping, and store that back int othe simplification mapping.
- Compute any bonuses, costs, or other impacts of the instruction on the
cost metric.
- When the terminator is reached, replace any conditional value in the
terminator with any simplifications from the mapping we have, and add
any successors which are not proven to be dead from these
simplifications to the worklist.
- Pop the next block off of the front of the worklist, and repeat.
- As soon as the cost of inlining exceeds the threshold for the
callsite, stop analyzing the function in order to bound cost.
The primary goal of this algorithm is to perfectly handle dead code
paths. We do not want any code in trivially dead code paths to impact
inlining decisions. The previous metric was *extremely* flawed here, and
would always subtract the average cost of two successors of
a conditional branch when it was proven to become an unconditional
branch at the callsite. There was no handling of wildly different costs
between the two successors, which would cause inlining when the path
actually taken was too large, and no inlining when the path actually
taken was trivially simple. There was also no handling of the code
*path*, only the immediate successors. These problems vanish completely
now. See the added regression tests for the shiny new features -- we
skip recursive function calls, SROA-killing instructions, and high cost
complex CFG structures when dead at the callsite being analyzed.
Switching to this algorithm required refactoring the inline cost
interface to accept the actual threshold rather than simply returning
a single cost. The resulting interface is pretty bad, and I'm planning
to do lots of interface cleanup after this patch.
Several other refactorings fell out of this, but I've tried to minimize
them for this patch. =/ There is still more cleanup that can be done
here. Please point out anything that you see in review.
I've worked really hard to try to mirror at least the spirit of all of
the previous heuristics in the new model. It's not clear that they are
all correct any more, but I wanted to minimize the change in this single
patch, it's already a bit ridiculous. One heuristic that is *not* yet
mirrored is to allow inlining of functions with a dynamic alloca *if*
the caller has a dynamic alloca. I will add this back, but I think the
most reasonable way requires changes to the inliner itself rather than
just the cost metric, and so I've deferred this for a subsequent patch.
The test case is XFAIL-ed until then.
As mentioned in the review mail, this seems to make Clang run about 1%
to 2% faster in -O0, but makes its binary size grow by just under 4%.
I've looked into the 4% growth, and it can be fixed, but requires
changes to other parts of the inliner.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153812 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-31 12:42:41 +00:00
|
|
|
// The candidate cost to be imposed upon the current function.
|
|
|
|
int CandidateCost = IC.getCost() - (InlineConstants::CallPenalty + 1);
|
2011-01-04 19:01:54 +00:00
|
|
|
// This bool tracks what happens if we do NOT inline C into B.
|
Make a seemingly tiny change to the inliner and fix the generated code
size bloat. Unfortunately, I expect this to disable the majority of the
benefit from r152737. I'm hopeful at least that it will fix PR12345. To
explain this requires... quite a bit of backstory I'm afraid.
TL;DR: The change in r152737 actually did The Wrong Thing for
linkonce-odr functions. This change makes it do the right thing. The
benefits we saw were simple luck, not any actual strategy. Benchmark
numbers after a mini-blog-post so that I've written down my thoughts on
why all of this works and doesn't work...
To understand what's going on here, you have to understand how the
"bottom-up" inliner actually works. There are two fundamental modes to
the inliner:
1) Standard fixed-cost bottom-up inlining. This is the mode we usually
think about. It walks from the bottom of the CFG up to the top,
looking at callsites, taking information about the callsite and the
called function and computing th expected cost of inlining into that
callsite. If the cost is under a fixed threshold, it inlines. It's
a touch more complicated than that due to all the bonuses, weights,
etc. Inlining the last callsite to an internal function gets higher
weighth, etc. But essentially, this is the mode of operation.
2) Deferred bottom-up inlining (a term I just made up). This is the
interesting mode for this patch an r152737. Initially, this works
just like mode #1, but once we have the cost of inlining into the
callsite, we don't just compare it with a fixed threshold. First, we
check something else. Let's give some names to the entities at this
point, or we'll end up hopelessly confused. We're considering
inlining a function 'A' into its callsite within a function 'B'. We
want to check whether 'B' has any callers, and whether it might be
inlined into those callers. If so, we also check whether inlining 'A'
into 'B' would block any of the opportunities for inlining 'B' into
its callers. We take the sum of the costs of inlining 'B' into its
callers where that inlining would be blocked by inlining 'A' into
'B', and if that cost is less than the cost of inlining 'A' into 'B',
then we skip inlining 'A' into 'B'.
Now, in order for #2 to make sense, we have to have some confidence that
we will actually have the opportunity to inline 'B' into its callers
when cheaper, *and* that we'll be able to revisit the decision and
inline 'A' into 'B' if that ever becomes the correct tradeoff. This
often isn't true for external functions -- we can see very few of their
callers, and we won't be able to re-consider inlining 'A' into 'B' if
'B' is external when we finally see more callers of 'B'. There are two
cases where we believe this to be true for C/C++ code: functions local
to a translation unit, and functions with an inline definition in every
translation unit which uses them. These are represented as internal
linkage and linkonce-odr (resp.) in LLVM. I enabled this logic for
linkonce-odr in r152737.
Unfortunately, when I did that, I also introduced a subtle bug. There
was an implicit assumption that the last caller of the function within
the TU was the last caller of the function in the program. We want to
bonus the last caller of the function in the program by a huge amount
for inlining because inlining that callsite has very little cost.
Unfortunately, the last caller in the TU of a linkonce-odr function is
*not* the last caller in the program, and so we don't want to apply this
bonus. If we do, we can apply it to one callsite *per-TU*. Because of
the way deferred inlining works, when it sees this bonus applied to one
callsite in the TU for 'B', it decides that inlining 'B' is of the
*utmost* importance just so we can get that final bonus. It then
proceeds to essentially force deferred inlining regardless of the actual
cost tradeoff.
The result? PR12345: code bloat, code bloat, code bloat. Another result
is getting *damn* lucky on a few benchmarks, and the over-inlining
exposing critically important optimizations. I would very much like
a list of benchmarks that regress after this change goes in, with
bitcode before and after. This will help me greatly understand what
opportunities the current cost analysis is missing.
Initial benchmark numbers look very good. WebKit files that exhibited
the worst of PR12345 went from growing to shrinking compared to Clang
with r152737 reverted.
- Bootstrapped Clang is 3% smaller with this change.
- Bootstrapped Clang -O0 over a single-source-file of lib/Lex is 4%
faster with this change.
Please let me know about any other performance impact you see. Thanks to
Nico for reporting and urging me to actually fix, Richard Smith, Duncan
Sands, Manuel Klimek, and Benjamin Kramer for talking through the issues
today.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153506 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-27 10:48:28 +00:00
|
|
|
bool callerWillBeRemoved = Caller->hasLocalLinkage();
|
2011-01-04 19:01:54 +00:00
|
|
|
// This bool tracks what happens if we DO inline C into B.
|
|
|
|
bool inliningPreventsSomeOuterInline = false;
|
2009-10-09 00:11:32 +00:00
|
|
|
for (Value::use_iterator I = Caller->use_begin(), E =Caller->use_end();
|
|
|
|
I != E; ++I) {
|
2010-07-28 22:50:26 +00:00
|
|
|
CallSite CS2(*I);
|
2009-10-09 00:11:32 +00:00
|
|
|
|
|
|
|
// If this isn't a call to Caller (it could be some other sort
|
2011-01-04 19:01:54 +00:00
|
|
|
// of reference) skip it. Such references will prevent the caller
|
|
|
|
// from being removed.
|
|
|
|
if (!CS2 || CS2.getCalledFunction() != Caller) {
|
|
|
|
callerWillBeRemoved = false;
|
2009-10-09 00:11:32 +00:00
|
|
|
continue;
|
2011-01-04 19:01:54 +00:00
|
|
|
}
|
2009-10-09 00:11:32 +00:00
|
|
|
|
|
|
|
InlineCost IC2 = getInlineCost(CS2);
|
Initial commit for the rewrite of the inline cost analysis to operate
on a per-callsite walk of the called function's instructions, in
breadth-first order over the potentially reachable set of basic blocks.
This is a major shift in how inline cost analysis works to improve the
accuracy and rationality of inlining decisions. A brief outline of the
algorithm this moves to:
- Build a simplification mapping based on the callsite arguments to the
function arguments.
- Push the entry block onto a worklist of potentially-live basic blocks.
- Pop the first block off of the *front* of the worklist (for
breadth-first ordering) and walk its instructions using a custom
InstVisitor.
- For each instruction's operands, re-map them based on the
simplification mappings available for the given callsite.
- Compute any simplification possible of the instruction after
re-mapping, and store that back int othe simplification mapping.
- Compute any bonuses, costs, or other impacts of the instruction on the
cost metric.
- When the terminator is reached, replace any conditional value in the
terminator with any simplifications from the mapping we have, and add
any successors which are not proven to be dead from these
simplifications to the worklist.
- Pop the next block off of the front of the worklist, and repeat.
- As soon as the cost of inlining exceeds the threshold for the
callsite, stop analyzing the function in order to bound cost.
The primary goal of this algorithm is to perfectly handle dead code
paths. We do not want any code in trivially dead code paths to impact
inlining decisions. The previous metric was *extremely* flawed here, and
would always subtract the average cost of two successors of
a conditional branch when it was proven to become an unconditional
branch at the callsite. There was no handling of wildly different costs
between the two successors, which would cause inlining when the path
actually taken was too large, and no inlining when the path actually
taken was trivially simple. There was also no handling of the code
*path*, only the immediate successors. These problems vanish completely
now. See the added regression tests for the shiny new features -- we
skip recursive function calls, SROA-killing instructions, and high cost
complex CFG structures when dead at the callsite being analyzed.
Switching to this algorithm required refactoring the inline cost
interface to accept the actual threshold rather than simply returning
a single cost. The resulting interface is pretty bad, and I'm planning
to do lots of interface cleanup after this patch.
Several other refactorings fell out of this, but I've tried to minimize
them for this patch. =/ There is still more cleanup that can be done
here. Please point out anything that you see in review.
I've worked really hard to try to mirror at least the spirit of all of
the previous heuristics in the new model. It's not clear that they are
all correct any more, but I wanted to minimize the change in this single
patch, it's already a bit ridiculous. One heuristic that is *not* yet
mirrored is to allow inlining of functions with a dynamic alloca *if*
the caller has a dynamic alloca. I will add this back, but I think the
most reasonable way requires changes to the inliner itself rather than
just the cost metric, and so I've deferred this for a subsequent patch.
The test case is XFAIL-ed until then.
As mentioned in the review mail, this seems to make Clang run about 1%
to 2% faster in -O0, but makes its binary size grow by just under 4%.
I've looked into the 4% growth, and it can be fixed, but requires
changes to other parts of the inliner.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153812 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-31 12:42:41 +00:00
|
|
|
if (!IC2) {
|
2011-01-04 19:01:54 +00:00
|
|
|
callerWillBeRemoved = false;
|
Initial commit for the rewrite of the inline cost analysis to operate
on a per-callsite walk of the called function's instructions, in
breadth-first order over the potentially reachable set of basic blocks.
This is a major shift in how inline cost analysis works to improve the
accuracy and rationality of inlining decisions. A brief outline of the
algorithm this moves to:
- Build a simplification mapping based on the callsite arguments to the
function arguments.
- Push the entry block onto a worklist of potentially-live basic blocks.
- Pop the first block off of the *front* of the worklist (for
breadth-first ordering) and walk its instructions using a custom
InstVisitor.
- For each instruction's operands, re-map them based on the
simplification mappings available for the given callsite.
- Compute any simplification possible of the instruction after
re-mapping, and store that back int othe simplification mapping.
- Compute any bonuses, costs, or other impacts of the instruction on the
cost metric.
- When the terminator is reached, replace any conditional value in the
terminator with any simplifications from the mapping we have, and add
any successors which are not proven to be dead from these
simplifications to the worklist.
- Pop the next block off of the front of the worklist, and repeat.
- As soon as the cost of inlining exceeds the threshold for the
callsite, stop analyzing the function in order to bound cost.
The primary goal of this algorithm is to perfectly handle dead code
paths. We do not want any code in trivially dead code paths to impact
inlining decisions. The previous metric was *extremely* flawed here, and
would always subtract the average cost of two successors of
a conditional branch when it was proven to become an unconditional
branch at the callsite. There was no handling of wildly different costs
between the two successors, which would cause inlining when the path
actually taken was too large, and no inlining when the path actually
taken was trivially simple. There was also no handling of the code
*path*, only the immediate successors. These problems vanish completely
now. See the added regression tests for the shiny new features -- we
skip recursive function calls, SROA-killing instructions, and high cost
complex CFG structures when dead at the callsite being analyzed.
Switching to this algorithm required refactoring the inline cost
interface to accept the actual threshold rather than simply returning
a single cost. The resulting interface is pretty bad, and I'm planning
to do lots of interface cleanup after this patch.
Several other refactorings fell out of this, but I've tried to minimize
them for this patch. =/ There is still more cleanup that can be done
here. Please point out anything that you see in review.
I've worked really hard to try to mirror at least the spirit of all of
the previous heuristics in the new model. It's not clear that they are
all correct any more, but I wanted to minimize the change in this single
patch, it's already a bit ridiculous. One heuristic that is *not* yet
mirrored is to allow inlining of functions with a dynamic alloca *if*
the caller has a dynamic alloca. I will add this back, but I think the
most reasonable way requires changes to the inliner itself rather than
just the cost metric, and so I've deferred this for a subsequent patch.
The test case is XFAIL-ed until then.
As mentioned in the review mail, this seems to make Clang run about 1%
to 2% faster in -O0, but makes its binary size grow by just under 4%.
I've looked into the 4% growth, and it can be fixed, but requires
changes to other parts of the inliner.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153812 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-31 12:42:41 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (IC2.isAlways())
|
2009-10-09 00:11:32 +00:00
|
|
|
continue;
|
|
|
|
|
Initial commit for the rewrite of the inline cost analysis to operate
on a per-callsite walk of the called function's instructions, in
breadth-first order over the potentially reachable set of basic blocks.
This is a major shift in how inline cost analysis works to improve the
accuracy and rationality of inlining decisions. A brief outline of the
algorithm this moves to:
- Build a simplification mapping based on the callsite arguments to the
function arguments.
- Push the entry block onto a worklist of potentially-live basic blocks.
- Pop the first block off of the *front* of the worklist (for
breadth-first ordering) and walk its instructions using a custom
InstVisitor.
- For each instruction's operands, re-map them based on the
simplification mappings available for the given callsite.
- Compute any simplification possible of the instruction after
re-mapping, and store that back int othe simplification mapping.
- Compute any bonuses, costs, or other impacts of the instruction on the
cost metric.
- When the terminator is reached, replace any conditional value in the
terminator with any simplifications from the mapping we have, and add
any successors which are not proven to be dead from these
simplifications to the worklist.
- Pop the next block off of the front of the worklist, and repeat.
- As soon as the cost of inlining exceeds the threshold for the
callsite, stop analyzing the function in order to bound cost.
The primary goal of this algorithm is to perfectly handle dead code
paths. We do not want any code in trivially dead code paths to impact
inlining decisions. The previous metric was *extremely* flawed here, and
would always subtract the average cost of two successors of
a conditional branch when it was proven to become an unconditional
branch at the callsite. There was no handling of wildly different costs
between the two successors, which would cause inlining when the path
actually taken was too large, and no inlining when the path actually
taken was trivially simple. There was also no handling of the code
*path*, only the immediate successors. These problems vanish completely
now. See the added regression tests for the shiny new features -- we
skip recursive function calls, SROA-killing instructions, and high cost
complex CFG structures when dead at the callsite being analyzed.
Switching to this algorithm required refactoring the inline cost
interface to accept the actual threshold rather than simply returning
a single cost. The resulting interface is pretty bad, and I'm planning
to do lots of interface cleanup after this patch.
Several other refactorings fell out of this, but I've tried to minimize
them for this patch. =/ There is still more cleanup that can be done
here. Please point out anything that you see in review.
I've worked really hard to try to mirror at least the spirit of all of
the previous heuristics in the new model. It's not clear that they are
all correct any more, but I wanted to minimize the change in this single
patch, it's already a bit ridiculous. One heuristic that is *not* yet
mirrored is to allow inlining of functions with a dynamic alloca *if*
the caller has a dynamic alloca. I will add this back, but I think the
most reasonable way requires changes to the inliner itself rather than
just the cost metric, and so I've deferred this for a subsequent patch.
The test case is XFAIL-ed until then.
As mentioned in the review mail, this seems to make Clang run about 1%
to 2% faster in -O0, but makes its binary size grow by just under 4%.
I've looked into the 4% growth, and it can be fixed, but requires
changes to other parts of the inliner.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153812 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-31 12:42:41 +00:00
|
|
|
// See if inlining or original callsite would erase the cost delta of
|
|
|
|
// this callsite. We subtract off the penalty for the call instruction,
|
|
|
|
// which we would be deleting.
|
|
|
|
if (IC2.getCostDelta() <= CandidateCost) {
|
2011-01-04 19:01:54 +00:00
|
|
|
inliningPreventsSomeOuterInline = true;
|
Initial commit for the rewrite of the inline cost analysis to operate
on a per-callsite walk of the called function's instructions, in
breadth-first order over the potentially reachable set of basic blocks.
This is a major shift in how inline cost analysis works to improve the
accuracy and rationality of inlining decisions. A brief outline of the
algorithm this moves to:
- Build a simplification mapping based on the callsite arguments to the
function arguments.
- Push the entry block onto a worklist of potentially-live basic blocks.
- Pop the first block off of the *front* of the worklist (for
breadth-first ordering) and walk its instructions using a custom
InstVisitor.
- For each instruction's operands, re-map them based on the
simplification mappings available for the given callsite.
- Compute any simplification possible of the instruction after
re-mapping, and store that back int othe simplification mapping.
- Compute any bonuses, costs, or other impacts of the instruction on the
cost metric.
- When the terminator is reached, replace any conditional value in the
terminator with any simplifications from the mapping we have, and add
any successors which are not proven to be dead from these
simplifications to the worklist.
- Pop the next block off of the front of the worklist, and repeat.
- As soon as the cost of inlining exceeds the threshold for the
callsite, stop analyzing the function in order to bound cost.
The primary goal of this algorithm is to perfectly handle dead code
paths. We do not want any code in trivially dead code paths to impact
inlining decisions. The previous metric was *extremely* flawed here, and
would always subtract the average cost of two successors of
a conditional branch when it was proven to become an unconditional
branch at the callsite. There was no handling of wildly different costs
between the two successors, which would cause inlining when the path
actually taken was too large, and no inlining when the path actually
taken was trivially simple. There was also no handling of the code
*path*, only the immediate successors. These problems vanish completely
now. See the added regression tests for the shiny new features -- we
skip recursive function calls, SROA-killing instructions, and high cost
complex CFG structures when dead at the callsite being analyzed.
Switching to this algorithm required refactoring the inline cost
interface to accept the actual threshold rather than simply returning
a single cost. The resulting interface is pretty bad, and I'm planning
to do lots of interface cleanup after this patch.
Several other refactorings fell out of this, but I've tried to minimize
them for this patch. =/ There is still more cleanup that can be done
here. Please point out anything that you see in review.
I've worked really hard to try to mirror at least the spirit of all of
the previous heuristics in the new model. It's not clear that they are
all correct any more, but I wanted to minimize the change in this single
patch, it's already a bit ridiculous. One heuristic that is *not* yet
mirrored is to allow inlining of functions with a dynamic alloca *if*
the caller has a dynamic alloca. I will add this back, but I think the
most reasonable way requires changes to the inliner itself rather than
just the cost metric, and so I've deferred this for a subsequent patch.
The test case is XFAIL-ed until then.
As mentioned in the review mail, this seems to make Clang run about 1%
to 2% faster in -O0, but makes its binary size grow by just under 4%.
I've looked into the 4% growth, and it can be fixed, but requires
changes to other parts of the inliner.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153812 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-31 12:42:41 +00:00
|
|
|
TotalSecondaryCost += IC2.getCost();
|
2009-10-09 00:11:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// If all outer calls to Caller would get inlined, the cost for the last
|
|
|
|
// one is set very low by getInlineCost, in anticipation that Caller will
|
|
|
|
// be removed entirely. We did not account for this above unless there
|
|
|
|
// is only one caller of Caller.
|
2011-01-04 19:01:54 +00:00
|
|
|
if (callerWillBeRemoved && Caller->use_begin() != Caller->use_end())
|
2009-10-09 21:42:02 +00:00
|
|
|
TotalSecondaryCost += InlineConstants::LastCallToStaticBonus;
|
2009-10-09 00:11:32 +00:00
|
|
|
|
Initial commit for the rewrite of the inline cost analysis to operate
on a per-callsite walk of the called function's instructions, in
breadth-first order over the potentially reachable set of basic blocks.
This is a major shift in how inline cost analysis works to improve the
accuracy and rationality of inlining decisions. A brief outline of the
algorithm this moves to:
- Build a simplification mapping based on the callsite arguments to the
function arguments.
- Push the entry block onto a worklist of potentially-live basic blocks.
- Pop the first block off of the *front* of the worklist (for
breadth-first ordering) and walk its instructions using a custom
InstVisitor.
- For each instruction's operands, re-map them based on the
simplification mappings available for the given callsite.
- Compute any simplification possible of the instruction after
re-mapping, and store that back int othe simplification mapping.
- Compute any bonuses, costs, or other impacts of the instruction on the
cost metric.
- When the terminator is reached, replace any conditional value in the
terminator with any simplifications from the mapping we have, and add
any successors which are not proven to be dead from these
simplifications to the worklist.
- Pop the next block off of the front of the worklist, and repeat.
- As soon as the cost of inlining exceeds the threshold for the
callsite, stop analyzing the function in order to bound cost.
The primary goal of this algorithm is to perfectly handle dead code
paths. We do not want any code in trivially dead code paths to impact
inlining decisions. The previous metric was *extremely* flawed here, and
would always subtract the average cost of two successors of
a conditional branch when it was proven to become an unconditional
branch at the callsite. There was no handling of wildly different costs
between the two successors, which would cause inlining when the path
actually taken was too large, and no inlining when the path actually
taken was trivially simple. There was also no handling of the code
*path*, only the immediate successors. These problems vanish completely
now. See the added regression tests for the shiny new features -- we
skip recursive function calls, SROA-killing instructions, and high cost
complex CFG structures when dead at the callsite being analyzed.
Switching to this algorithm required refactoring the inline cost
interface to accept the actual threshold rather than simply returning
a single cost. The resulting interface is pretty bad, and I'm planning
to do lots of interface cleanup after this patch.
Several other refactorings fell out of this, but I've tried to minimize
them for this patch. =/ There is still more cleanup that can be done
here. Please point out anything that you see in review.
I've worked really hard to try to mirror at least the spirit of all of
the previous heuristics in the new model. It's not clear that they are
all correct any more, but I wanted to minimize the change in this single
patch, it's already a bit ridiculous. One heuristic that is *not* yet
mirrored is to allow inlining of functions with a dynamic alloca *if*
the caller has a dynamic alloca. I will add this back, but I think the
most reasonable way requires changes to the inliner itself rather than
just the cost metric, and so I've deferred this for a subsequent patch.
The test case is XFAIL-ed until then.
As mentioned in the review mail, this seems to make Clang run about 1%
to 2% faster in -O0, but makes its binary size grow by just under 4%.
I've looked into the 4% growth, and it can be fixed, but requires
changes to other parts of the inliner.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153812 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-31 12:42:41 +00:00
|
|
|
if (inliningPreventsSomeOuterInline && TotalSecondaryCost < IC.getCost()) {
|
|
|
|
DEBUG(dbgs() << " NOT Inlining: " << *CS.getInstruction() <<
|
|
|
|
" Cost = " << IC.getCost() <<
|
2009-10-09 00:11:32 +00:00
|
|
|
", outer Cost = " << TotalSecondaryCost << '\n');
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Initial commit for the rewrite of the inline cost analysis to operate
on a per-callsite walk of the called function's instructions, in
breadth-first order over the potentially reachable set of basic blocks.
This is a major shift in how inline cost analysis works to improve the
accuracy and rationality of inlining decisions. A brief outline of the
algorithm this moves to:
- Build a simplification mapping based on the callsite arguments to the
function arguments.
- Push the entry block onto a worklist of potentially-live basic blocks.
- Pop the first block off of the *front* of the worklist (for
breadth-first ordering) and walk its instructions using a custom
InstVisitor.
- For each instruction's operands, re-map them based on the
simplification mappings available for the given callsite.
- Compute any simplification possible of the instruction after
re-mapping, and store that back int othe simplification mapping.
- Compute any bonuses, costs, or other impacts of the instruction on the
cost metric.
- When the terminator is reached, replace any conditional value in the
terminator with any simplifications from the mapping we have, and add
any successors which are not proven to be dead from these
simplifications to the worklist.
- Pop the next block off of the front of the worklist, and repeat.
- As soon as the cost of inlining exceeds the threshold for the
callsite, stop analyzing the function in order to bound cost.
The primary goal of this algorithm is to perfectly handle dead code
paths. We do not want any code in trivially dead code paths to impact
inlining decisions. The previous metric was *extremely* flawed here, and
would always subtract the average cost of two successors of
a conditional branch when it was proven to become an unconditional
branch at the callsite. There was no handling of wildly different costs
between the two successors, which would cause inlining when the path
actually taken was too large, and no inlining when the path actually
taken was trivially simple. There was also no handling of the code
*path*, only the immediate successors. These problems vanish completely
now. See the added regression tests for the shiny new features -- we
skip recursive function calls, SROA-killing instructions, and high cost
complex CFG structures when dead at the callsite being analyzed.
Switching to this algorithm required refactoring the inline cost
interface to accept the actual threshold rather than simply returning
a single cost. The resulting interface is pretty bad, and I'm planning
to do lots of interface cleanup after this patch.
Several other refactorings fell out of this, but I've tried to minimize
them for this patch. =/ There is still more cleanup that can be done
here. Please point out anything that you see in review.
I've worked really hard to try to mirror at least the spirit of all of
the previous heuristics in the new model. It's not clear that they are
all correct any more, but I wanted to minimize the change in this single
patch, it's already a bit ridiculous. One heuristic that is *not* yet
mirrored is to allow inlining of functions with a dynamic alloca *if*
the caller has a dynamic alloca. I will add this back, but I think the
most reasonable way requires changes to the inliner itself rather than
just the cost metric, and so I've deferred this for a subsequent patch.
The test case is XFAIL-ed until then.
As mentioned in the review mail, this seems to make Clang run about 1%
to 2% faster in -O0, but makes its binary size grow by just under 4%.
I've looked into the 4% growth, and it can be fixed, but requires
changes to other parts of the inliner.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153812 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-31 12:42:41 +00:00
|
|
|
DEBUG(dbgs() << " Inlining: cost=" << IC.getCost()
|
|
|
|
<< ", thres=" << (IC.getCostDelta() + IC.getCost())
|
2009-10-09 00:11:32 +00:00
|
|
|
<< ", Call: " << *CS.getInstruction() << '\n');
|
2009-08-27 03:51:50 +00:00
|
|
|
return true;
|
2008-10-29 01:02:02 +00:00
|
|
|
}
|
2003-08-31 19:10:30 +00:00
|
|
|
|
2010-05-01 01:05:10 +00:00
|
|
|
/// InlineHistoryIncludes - Return true if the specified inline history ID
|
|
|
|
/// indicates an inline history that includes the specified function.
|
|
|
|
static bool InlineHistoryIncludes(Function *F, int InlineHistoryID,
|
|
|
|
const SmallVectorImpl<std::pair<Function*, int> > &InlineHistory) {
|
|
|
|
while (InlineHistoryID != -1) {
|
|
|
|
assert(unsigned(InlineHistoryID) < InlineHistory.size() &&
|
|
|
|
"Invalid inline history ID");
|
|
|
|
if (InlineHistory[InlineHistoryID].first == F)
|
|
|
|
return true;
|
|
|
|
InlineHistoryID = InlineHistory[InlineHistoryID].second;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-04-16 22:42:17 +00:00
|
|
|
bool Inliner::runOnSCC(CallGraphSCC &SCC) {
|
2003-08-31 19:10:30 +00:00
|
|
|
CallGraph &CG = getAnalysis<CallGraph>();
|
2009-07-24 18:13:53 +00:00
|
|
|
const TargetData *TD = getAnalysisIfAvailable<TargetData>();
|
2003-08-31 19:10:30 +00:00
|
|
|
|
2009-03-23 23:39:20 +00:00
|
|
|
SmallPtrSet<Function*, 8> SCCFunctions;
|
2010-01-05 01:27:51 +00:00
|
|
|
DEBUG(dbgs() << "Inliner visiting SCC:");
|
2010-04-16 22:42:17 +00:00
|
|
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
|
|
|
|
Function *F = (*I)->getFunction();
|
2004-05-23 21:22:17 +00:00
|
|
|
if (F) SCCFunctions.insert(F);
|
2010-01-05 01:27:51 +00:00
|
|
|
DEBUG(dbgs() << " " << (F ? F->getName() : "INDIRECTNODE"));
|
2003-08-31 19:10:30 +00:00
|
|
|
}
|
|
|
|
|
2004-05-23 21:22:17 +00:00
|
|
|
// Scan through and identify all call sites ahead of time so that we only
|
|
|
|
// inline call sites in the original functions, not call sites that result
|
|
|
|
// from inlining other functions.
|
2010-05-01 01:05:10 +00:00
|
|
|
SmallVector<std::pair<CallSite, int>, 16> CallSites;
|
|
|
|
|
|
|
|
// When inlining a callee produces new call sites, we want to keep track of
|
|
|
|
// the fact that they were inlined from the callee. This allows us to avoid
|
|
|
|
// infinite inlining in some obscure cases. To represent this, we use an
|
|
|
|
// index into the InlineHistory vector.
|
|
|
|
SmallVector<std::pair<Function*, int>, 8> InlineHistory;
|
2004-05-23 21:22:17 +00:00
|
|
|
|
2010-04-16 22:42:17 +00:00
|
|
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
|
|
|
|
Function *F = (*I)->getFunction();
|
2009-08-27 03:51:50 +00:00
|
|
|
if (!F) continue;
|
|
|
|
|
|
|
|
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
|
|
|
|
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
|
2010-07-28 22:50:26 +00:00
|
|
|
CallSite CS(cast<Value>(I));
|
2009-10-09 00:11:32 +00:00
|
|
|
// If this isn't a call, or it is a call to an intrinsic, it can
|
2009-08-31 05:34:32 +00:00
|
|
|
// never be inlined.
|
2010-07-28 22:50:26 +00:00
|
|
|
if (!CS || isa<IntrinsicInst>(I))
|
2009-08-27 03:51:50 +00:00
|
|
|
continue;
|
|
|
|
|
2009-08-31 05:34:32 +00:00
|
|
|
// If this is a direct call to an external function, we can never inline
|
|
|
|
// it. If it is an indirect call, inlining may resolve it to be a
|
|
|
|
// direct call, so we keep it.
|
|
|
|
if (CS.getCalledFunction() && CS.getCalledFunction()->isDeclaration())
|
|
|
|
continue;
|
|
|
|
|
2010-05-01 01:05:10 +00:00
|
|
|
CallSites.push_back(std::make_pair(CS, -1));
|
2009-08-27 03:51:50 +00:00
|
|
|
}
|
|
|
|
}
|
2003-08-31 19:10:30 +00:00
|
|
|
|
2010-01-05 01:27:51 +00:00
|
|
|
DEBUG(dbgs() << ": " << CallSites.size() << " call sites.\n");
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2010-04-20 00:47:08 +00:00
|
|
|
// If there are no calls in this function, exit early.
|
|
|
|
if (CallSites.empty())
|
|
|
|
return false;
|
|
|
|
|
2004-05-23 21:22:17 +00:00
|
|
|
// Now that we have all of the call sites, move the ones to functions in the
|
|
|
|
// current SCC to the end of the list.
|
|
|
|
unsigned FirstCallInSCC = CallSites.size();
|
|
|
|
for (unsigned i = 0; i < FirstCallInSCC; ++i)
|
2010-05-01 01:05:10 +00:00
|
|
|
if (Function *F = CallSites[i].first.getCalledFunction())
|
2004-05-23 21:22:17 +00:00
|
|
|
if (SCCFunctions.count(F))
|
|
|
|
std::swap(CallSites[i--], CallSites[--FirstCallInSCC]);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2009-08-27 06:29:33 +00:00
|
|
|
|
|
|
|
InlinedArrayAllocasTy InlinedArrayAllocas;
|
2010-04-22 23:07:58 +00:00
|
|
|
InlineFunctionInfo InlineInfo(&CG, TD);
|
2009-08-27 06:29:33 +00:00
|
|
|
|
2004-05-23 21:22:17 +00:00
|
|
|
// Now that we have all of the call sites, loop over them and inline them if
|
|
|
|
// it looks profitable to do so.
|
|
|
|
bool Changed = false;
|
|
|
|
bool LocalChange;
|
|
|
|
do {
|
|
|
|
LocalChange = false;
|
|
|
|
// Iterate over the outer loop because inlining functions can cause indirect
|
|
|
|
// calls to become direct calls.
|
2009-08-27 03:51:50 +00:00
|
|
|
for (unsigned CSi = 0; CSi != CallSites.size(); ++CSi) {
|
2010-05-01 01:05:10 +00:00
|
|
|
CallSite CS = CallSites[CSi].first;
|
2009-08-27 06:29:33 +00:00
|
|
|
|
2009-11-12 07:56:08 +00:00
|
|
|
Function *Caller = CS.getCaller();
|
2009-08-27 06:29:33 +00:00
|
|
|
Function *Callee = CS.getCalledFunction();
|
2009-11-12 07:56:08 +00:00
|
|
|
|
|
|
|
// If this call site is dead and it is to a readonly function, we should
|
|
|
|
// just delete the call instead of trying to inline it, regardless of
|
|
|
|
// size. This happens because IPSCCP propagates the result out of the
|
|
|
|
// call and then we're left with the dead call.
|
2009-11-12 21:58:18 +00:00
|
|
|
if (isInstructionTriviallyDead(CS.getInstruction())) {
|
2010-01-05 01:27:51 +00:00
|
|
|
DEBUG(dbgs() << " -> Deleting dead call: "
|
2009-11-12 07:56:08 +00:00
|
|
|
<< *CS.getInstruction() << "\n");
|
|
|
|
// Update the call graph by deleting the edge from Callee to Caller.
|
|
|
|
CG[Caller]->removeCallEdgeFor(CS);
|
|
|
|
CS.getInstruction()->eraseFromParent();
|
|
|
|
++NumCallsDeleted;
|
2010-03-09 23:02:17 +00:00
|
|
|
// Update the cached cost info with the missing call
|
|
|
|
growCachedCostInfo(Caller, NULL);
|
2009-11-12 07:56:08 +00:00
|
|
|
} else {
|
|
|
|
// We can only inline direct calls to non-declarations.
|
|
|
|
if (Callee == 0 || Callee->isDeclaration()) continue;
|
2009-08-27 03:51:50 +00:00
|
|
|
|
2010-07-13 18:27:13 +00:00
|
|
|
// If this call site was obtained by inlining another function, verify
|
2010-05-01 01:05:10 +00:00
|
|
|
// that the include path for the function did not include the callee
|
2010-12-06 07:38:40 +00:00
|
|
|
// itself. If so, we'd be recursively inlining the same function,
|
2010-05-01 01:05:10 +00:00
|
|
|
// which would provide the same callsites, which would cause us to
|
|
|
|
// infinitely inline.
|
|
|
|
int InlineHistoryID = CallSites[CSi].second;
|
|
|
|
if (InlineHistoryID != -1 &&
|
|
|
|
InlineHistoryIncludes(Callee, InlineHistoryID, InlineHistory))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
2009-11-12 07:56:08 +00:00
|
|
|
// If the policy determines that we should inline this function,
|
|
|
|
// try to do so.
|
|
|
|
if (!shouldInline(CS))
|
|
|
|
continue;
|
2009-10-09 00:11:32 +00:00
|
|
|
|
2010-04-22 23:37:35 +00:00
|
|
|
// Attempt to inline the function.
|
Fix PR8735, a really terrible problem in the inliner's "alloca merging"
optimization.
Consider:
static void foo() {
A = alloca
...
}
static void bar() {
B = alloca
...
call foo();
}
void main() {
bar()
}
The inliner proceeds bottom up, but lets pretend it decides not to inline foo
into bar. When it gets to main, it inlines bar into main(), and says "hey, I
just inlined an alloca "B" into main, lets remember that. Then it keeps going
and finds that it now contains a call to foo. It decides to inline foo into
main, and says "hey, foo has an alloca A, and I have an alloca B from another
inlined call site, lets reuse it". The problem with this of course, is that
the lifetime of A and B are nested, not disjoint.
Unfortunately I can't create a reasonable testcase for this: the one in the
PR is both huge and extremely sensitive, because you minor tweaks end up
causing foo to get inlined into bar too early. We already have tests for the
basic alloca merging optimization and this does not break them.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120995 91177308-0d34-0410-b5e6-96231b3b80d8
2010-12-06 07:52:42 +00:00
|
|
|
if (!InlineCallIfPossible(CS, InlineInfo, InlinedArrayAllocas,
|
2012-02-25 02:56:01 +00:00
|
|
|
InlineHistoryID, InsertLifetime))
|
2009-11-12 07:56:08 +00:00
|
|
|
continue;
|
|
|
|
++NumInlined;
|
2010-05-01 01:05:10 +00:00
|
|
|
|
2010-05-01 01:26:13 +00:00
|
|
|
// If inlining this function gave us any new call sites, throw them
|
2010-04-22 23:37:35 +00:00
|
|
|
// onto our worklist to process. They are useful inline candidates.
|
2010-05-01 01:26:13 +00:00
|
|
|
if (!InlineInfo.InlinedCalls.empty()) {
|
2010-05-01 01:05:10 +00:00
|
|
|
// Create a new inline history entry for this, so that we remember
|
|
|
|
// that these new callsites came about due to inlining Callee.
|
|
|
|
int NewHistoryID = InlineHistory.size();
|
|
|
|
InlineHistory.push_back(std::make_pair(Callee, InlineHistoryID));
|
|
|
|
|
2010-05-01 01:26:13 +00:00
|
|
|
for (unsigned i = 0, e = InlineInfo.InlinedCalls.size();
|
2010-05-01 01:05:10 +00:00
|
|
|
i != e; ++i) {
|
2010-05-01 01:26:13 +00:00
|
|
|
Value *Ptr = InlineInfo.InlinedCalls[i];
|
2012-03-25 04:03:40 +00:00
|
|
|
CallSites.push_back(std::make_pair(CallSite(Ptr), NewHistoryID));
|
2010-05-01 01:05:10 +00:00
|
|
|
}
|
2010-04-23 18:37:01 +00:00
|
|
|
}
|
2010-04-22 23:37:35 +00:00
|
|
|
|
2010-03-09 23:02:17 +00:00
|
|
|
// Update the cached cost info with the inlined call.
|
|
|
|
growCachedCostInfo(Caller, Callee);
|
2009-11-12 07:56:08 +00:00
|
|
|
}
|
2009-08-27 03:51:50 +00:00
|
|
|
|
2009-11-12 07:56:08 +00:00
|
|
|
// If we inlined or deleted the last possible call site to the function,
|
|
|
|
// delete the function body now.
|
|
|
|
if (Callee && Callee->use_empty() && Callee->hasLocalLinkage() &&
|
2009-08-31 05:34:32 +00:00
|
|
|
// TODO: Can remove if in SCC now.
|
2009-08-31 03:15:49 +00:00
|
|
|
!SCCFunctions.count(Callee) &&
|
2009-08-31 05:34:32 +00:00
|
|
|
|
2009-08-31 03:15:49 +00:00
|
|
|
// The function may be apparently dead, but if there are indirect
|
|
|
|
// callgraph references to the node, we cannot delete it yet, this
|
|
|
|
// could invalidate the CGSCC iterator.
|
|
|
|
CG[Callee]->getNumReferences() == 0) {
|
2010-01-05 01:27:51 +00:00
|
|
|
DEBUG(dbgs() << " -> Deleting dead function: "
|
2009-08-27 06:29:33 +00:00
|
|
|
<< Callee->getName() << "\n");
|
|
|
|
CallGraphNode *CalleeNode = CG[Callee];
|
|
|
|
|
|
|
|
// Remove any call graph edges from the callee to its callees.
|
|
|
|
CalleeNode->removeAllCalledFunctions();
|
|
|
|
|
|
|
|
resetCachedCostInfo(Callee);
|
|
|
|
|
|
|
|
// Removing the node for callee from the call graph and delete it.
|
|
|
|
delete CG.removeFunctionFromModule(CalleeNode);
|
|
|
|
++NumDeleted;
|
|
|
|
}
|
2009-08-27 03:51:50 +00:00
|
|
|
|
|
|
|
// Remove this call site from the list. If possible, use
|
|
|
|
// swap/pop_back for efficiency, but do not use it if doing so would
|
|
|
|
// move a call site to a function in this SCC before the
|
|
|
|
// 'FirstCallInSCC' barrier.
|
2010-04-16 22:42:17 +00:00
|
|
|
if (SCC.isSingular()) {
|
2010-05-31 12:50:41 +00:00
|
|
|
CallSites[CSi] = CallSites.back();
|
2009-08-27 03:51:50 +00:00
|
|
|
CallSites.pop_back();
|
|
|
|
} else {
|
|
|
|
CallSites.erase(CallSites.begin()+CSi);
|
2003-08-31 19:10:30 +00:00
|
|
|
}
|
2009-08-27 03:51:50 +00:00
|
|
|
--CSi;
|
|
|
|
|
|
|
|
Changed = true;
|
|
|
|
LocalChange = true;
|
|
|
|
}
|
2004-05-23 21:22:17 +00:00
|
|
|
} while (LocalChange);
|
2003-08-31 19:10:30 +00:00
|
|
|
|
2004-04-08 06:34:31 +00:00
|
|
|
return Changed;
|
2003-08-31 19:10:30 +00:00
|
|
|
}
|
2003-11-11 22:41:34 +00:00
|
|
|
|
2004-04-20 22:06:53 +00:00
|
|
|
// doFinalization - Remove now-dead linkonce functions at the end of
|
|
|
|
// processing to avoid breaking the SCC traversal.
|
|
|
|
bool Inliner::doFinalization(CallGraph &CG) {
|
2008-11-05 01:39:16 +00:00
|
|
|
return removeDeadFunctions(CG);
|
|
|
|
}
|
|
|
|
|
2009-08-27 03:51:50 +00:00
|
|
|
/// removeDeadFunctions - Remove dead functions that are not included in
|
|
|
|
/// DNR (Do Not Remove) list.
|
Start removing the use of an ad-hoc 'never inline' set and instead
directly query the function information which this set was representing.
This simplifies the interface of the inline cost analysis, and makes the
always-inline pass significantly more efficient.
Previously, always-inline would first make a single set of every
function in the module *except* those marked with the always-inline
attribute. It would then query this set at every call site to see if the
function was a member of the set, and if so, refuse to inline it. This
is quite wasteful. Instead, simply check the function attribute directly
when looking at the callsite.
The normal inliner also had similar redundancy. It added every function
in the module with the noinline attribute to its set to ignore, even
though inside the cost analysis function we *already tested* the
noinline attribute and produced the same result.
The only tricky part of removing this is that we have to be able to
correctly remove only the functions inlined by the always-inline pass
when finalizing, which requires a bit of a hack. Still, much less of
a hack than the set of all non-always-inline functions was. While I was
touching this function, I switched a heavy-weight set to a vector with
sort+unique. The algorithm already had a two-phase insert and removal
pattern, we were just needlessly paying the uniquing cost on every
insert.
This probably speeds up some compiles by a small amount (-O0 compiles
with lots of always-inline, so potentially heavy libc++ users), but I've
not tried to measure it.
I believe there is no functional change here, but yell if you spot one.
None are intended.
Finally, the direction this is going in is to greatly simplify the
inline cost query interface so that we can replace its implementation
with a much more clever one. Along the way, all the APIs get simplified,
so it seems incrementally good.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152903 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-16 06:10:13 +00:00
|
|
|
bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) {
|
|
|
|
SmallVector<CallGraphNode*, 16> FunctionsToRemove;
|
2004-04-21 20:44:33 +00:00
|
|
|
|
|
|
|
// Scan for all of the functions, looking for ones that should now be removed
|
|
|
|
// from the program. Insert the dead ones in the FunctionsToRemove set.
|
|
|
|
for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) {
|
|
|
|
CallGraphNode *CGN = I->second;
|
2009-08-27 03:51:50 +00:00
|
|
|
Function *F = CGN->getFunction();
|
Start removing the use of an ad-hoc 'never inline' set and instead
directly query the function information which this set was representing.
This simplifies the interface of the inline cost analysis, and makes the
always-inline pass significantly more efficient.
Previously, always-inline would first make a single set of every
function in the module *except* those marked with the always-inline
attribute. It would then query this set at every call site to see if the
function was a member of the set, and if so, refuse to inline it. This
is quite wasteful. Instead, simply check the function attribute directly
when looking at the callsite.
The normal inliner also had similar redundancy. It added every function
in the module with the noinline attribute to its set to ignore, even
though inside the cost analysis function we *already tested* the
noinline attribute and produced the same result.
The only tricky part of removing this is that we have to be able to
correctly remove only the functions inlined by the always-inline pass
when finalizing, which requires a bit of a hack. Still, much less of
a hack than the set of all non-always-inline functions was. While I was
touching this function, I switched a heavy-weight set to a vector with
sort+unique. The algorithm already had a two-phase insert and removal
pattern, we were just needlessly paying the uniquing cost on every
insert.
This probably speeds up some compiles by a small amount (-O0 compiles
with lots of always-inline, so potentially heavy libc++ users), but I've
not tried to measure it.
I believe there is no functional change here, but yell if you spot one.
None are intended.
Finally, the direction this is going in is to greatly simplify the
inline cost query interface so that we can replace its implementation
with a much more clever one. Along the way, all the APIs get simplified,
so it seems incrementally good.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152903 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-16 06:10:13 +00:00
|
|
|
if (!F || F->isDeclaration())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Handle the case when this function is called and we only want to care
|
|
|
|
// about always-inline functions. This is a bit of a hack to share code
|
|
|
|
// between here and the InlineAlways pass.
|
|
|
|
if (AlwaysInlineOnly && !F->hasFnAttr(Attribute::AlwaysInline))
|
|
|
|
continue;
|
|
|
|
|
2009-08-27 03:51:50 +00:00
|
|
|
// If the only remaining users of the function are dead constants, remove
|
|
|
|
// them.
|
|
|
|
F->removeDeadConstantUsers();
|
|
|
|
|
2011-10-20 05:23:42 +00:00
|
|
|
if (!F->isDefTriviallyDead())
|
2009-08-27 03:51:50 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Remove any call graph edges from the function to its callees.
|
|
|
|
CGN->removeAllCalledFunctions();
|
|
|
|
|
|
|
|
// Remove any edges from the external node to the function's call graph
|
|
|
|
// node. These edges might have been made irrelegant due to
|
|
|
|
// optimization of the program.
|
|
|
|
CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN);
|
2005-04-21 23:48:37 +00:00
|
|
|
|
2009-08-27 03:51:50 +00:00
|
|
|
// Removing the node for callee from the call graph and delete it.
|
Start removing the use of an ad-hoc 'never inline' set and instead
directly query the function information which this set was representing.
This simplifies the interface of the inline cost analysis, and makes the
always-inline pass significantly more efficient.
Previously, always-inline would first make a single set of every
function in the module *except* those marked with the always-inline
attribute. It would then query this set at every call site to see if the
function was a member of the set, and if so, refuse to inline it. This
is quite wasteful. Instead, simply check the function attribute directly
when looking at the callsite.
The normal inliner also had similar redundancy. It added every function
in the module with the noinline attribute to its set to ignore, even
though inside the cost analysis function we *already tested* the
noinline attribute and produced the same result.
The only tricky part of removing this is that we have to be able to
correctly remove only the functions inlined by the always-inline pass
when finalizing, which requires a bit of a hack. Still, much less of
a hack than the set of all non-always-inline functions was. While I was
touching this function, I switched a heavy-weight set to a vector with
sort+unique. The algorithm already had a two-phase insert and removal
pattern, we were just needlessly paying the uniquing cost on every
insert.
This probably speeds up some compiles by a small amount (-O0 compiles
with lots of always-inline, so potentially heavy libc++ users), but I've
not tried to measure it.
I believe there is no functional change here, but yell if you spot one.
None are intended.
Finally, the direction this is going in is to greatly simplify the
inline cost query interface so that we can replace its implementation
with a much more clever one. Along the way, all the APIs get simplified,
so it seems incrementally good.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152903 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-16 06:10:13 +00:00
|
|
|
FunctionsToRemove.push_back(CGN);
|
2004-04-20 22:06:53 +00:00
|
|
|
}
|
Start removing the use of an ad-hoc 'never inline' set and instead
directly query the function information which this set was representing.
This simplifies the interface of the inline cost analysis, and makes the
always-inline pass significantly more efficient.
Previously, always-inline would first make a single set of every
function in the module *except* those marked with the always-inline
attribute. It would then query this set at every call site to see if the
function was a member of the set, and if so, refuse to inline it. This
is quite wasteful. Instead, simply check the function attribute directly
when looking at the callsite.
The normal inliner also had similar redundancy. It added every function
in the module with the noinline attribute to its set to ignore, even
though inside the cost analysis function we *already tested* the
noinline attribute and produced the same result.
The only tricky part of removing this is that we have to be able to
correctly remove only the functions inlined by the always-inline pass
when finalizing, which requires a bit of a hack. Still, much less of
a hack than the set of all non-always-inline functions was. While I was
touching this function, I switched a heavy-weight set to a vector with
sort+unique. The algorithm already had a two-phase insert and removal
pattern, we were just needlessly paying the uniquing cost on every
insert.
This probably speeds up some compiles by a small amount (-O0 compiles
with lots of always-inline, so potentially heavy libc++ users), but I've
not tried to measure it.
I believe there is no functional change here, but yell if you spot one.
None are intended.
Finally, the direction this is going in is to greatly simplify the
inline cost query interface so that we can replace its implementation
with a much more clever one. Along the way, all the APIs get simplified,
so it seems incrementally good.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152903 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-16 06:10:13 +00:00
|
|
|
if (FunctionsToRemove.empty())
|
|
|
|
return false;
|
2004-04-21 20:44:33 +00:00
|
|
|
|
|
|
|
// Now that we know which functions to delete, do so. We didn't want to do
|
|
|
|
// this inline, because that would invalidate our CallGraph::iterator
|
|
|
|
// objects. :(
|
2009-08-27 03:51:50 +00:00
|
|
|
//
|
Start removing the use of an ad-hoc 'never inline' set and instead
directly query the function information which this set was representing.
This simplifies the interface of the inline cost analysis, and makes the
always-inline pass significantly more efficient.
Previously, always-inline would first make a single set of every
function in the module *except* those marked with the always-inline
attribute. It would then query this set at every call site to see if the
function was a member of the set, and if so, refuse to inline it. This
is quite wasteful. Instead, simply check the function attribute directly
when looking at the callsite.
The normal inliner also had similar redundancy. It added every function
in the module with the noinline attribute to its set to ignore, even
though inside the cost analysis function we *already tested* the
noinline attribute and produced the same result.
The only tricky part of removing this is that we have to be able to
correctly remove only the functions inlined by the always-inline pass
when finalizing, which requires a bit of a hack. Still, much less of
a hack than the set of all non-always-inline functions was. While I was
touching this function, I switched a heavy-weight set to a vector with
sort+unique. The algorithm already had a two-phase insert and removal
pattern, we were just needlessly paying the uniquing cost on every
insert.
This probably speeds up some compiles by a small amount (-O0 compiles
with lots of always-inline, so potentially heavy libc++ users), but I've
not tried to measure it.
I believe there is no functional change here, but yell if you spot one.
None are intended.
Finally, the direction this is going in is to greatly simplify the
inline cost query interface so that we can replace its implementation
with a much more clever one. Along the way, all the APIs get simplified,
so it seems incrementally good.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152903 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-16 06:10:13 +00:00
|
|
|
// Note that it doesn't matter that we are iterating over a non-stable order
|
2009-08-27 03:51:50 +00:00
|
|
|
// here to do this, it doesn't matter which order the functions are deleted
|
|
|
|
// in.
|
Start removing the use of an ad-hoc 'never inline' set and instead
directly query the function information which this set was representing.
This simplifies the interface of the inline cost analysis, and makes the
always-inline pass significantly more efficient.
Previously, always-inline would first make a single set of every
function in the module *except* those marked with the always-inline
attribute. It would then query this set at every call site to see if the
function was a member of the set, and if so, refuse to inline it. This
is quite wasteful. Instead, simply check the function attribute directly
when looking at the callsite.
The normal inliner also had similar redundancy. It added every function
in the module with the noinline attribute to its set to ignore, even
though inside the cost analysis function we *already tested* the
noinline attribute and produced the same result.
The only tricky part of removing this is that we have to be able to
correctly remove only the functions inlined by the always-inline pass
when finalizing, which requires a bit of a hack. Still, much less of
a hack than the set of all non-always-inline functions was. While I was
touching this function, I switched a heavy-weight set to a vector with
sort+unique. The algorithm already had a two-phase insert and removal
pattern, we were just needlessly paying the uniquing cost on every
insert.
This probably speeds up some compiles by a small amount (-O0 compiles
with lots of always-inline, so potentially heavy libc++ users), but I've
not tried to measure it.
I believe there is no functional change here, but yell if you spot one.
None are intended.
Finally, the direction this is going in is to greatly simplify the
inline cost query interface so that we can replace its implementation
with a much more clever one. Along the way, all the APIs get simplified,
so it seems incrementally good.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152903 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-16 06:10:13 +00:00
|
|
|
std::sort(FunctionsToRemove.begin(), FunctionsToRemove.end());
|
|
|
|
FunctionsToRemove.erase(std::unique(FunctionsToRemove.begin(),
|
|
|
|
FunctionsToRemove.end()),
|
|
|
|
FunctionsToRemove.end());
|
|
|
|
for (SmallVectorImpl<CallGraphNode *>::iterator I = FunctionsToRemove.begin(),
|
|
|
|
E = FunctionsToRemove.end();
|
|
|
|
I != E; ++I) {
|
2009-03-19 18:03:56 +00:00
|
|
|
resetCachedCostInfo((*I)->getFunction());
|
2004-04-21 20:44:33 +00:00
|
|
|
delete CG.removeFunctionFromModule(*I);
|
|
|
|
++NumDeleted;
|
|
|
|
}
|
Start removing the use of an ad-hoc 'never inline' set and instead
directly query the function information which this set was representing.
This simplifies the interface of the inline cost analysis, and makes the
always-inline pass significantly more efficient.
Previously, always-inline would first make a single set of every
function in the module *except* those marked with the always-inline
attribute. It would then query this set at every call site to see if the
function was a member of the set, and if so, refuse to inline it. This
is quite wasteful. Instead, simply check the function attribute directly
when looking at the callsite.
The normal inliner also had similar redundancy. It added every function
in the module with the noinline attribute to its set to ignore, even
though inside the cost analysis function we *already tested* the
noinline attribute and produced the same result.
The only tricky part of removing this is that we have to be able to
correctly remove only the functions inlined by the always-inline pass
when finalizing, which requires a bit of a hack. Still, much less of
a hack than the set of all non-always-inline functions was. While I was
touching this function, I switched a heavy-weight set to a vector with
sort+unique. The algorithm already had a two-phase insert and removal
pattern, we were just needlessly paying the uniquing cost on every
insert.
This probably speeds up some compiles by a small amount (-O0 compiles
with lots of always-inline, so potentially heavy libc++ users), but I've
not tried to measure it.
I believe there is no functional change here, but yell if you spot one.
None are intended.
Finally, the direction this is going in is to greatly simplify the
inline cost query interface so that we can replace its implementation
with a much more clever one. Along the way, all the APIs get simplified,
so it seems incrementally good.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@152903 91177308-0d34-0410-b5e6-96231b3b80d8
2012-03-16 06:10:13 +00:00
|
|
|
return true;
|
2004-04-20 22:06:53 +00:00
|
|
|
}
|