llvm-6502/lib/Transforms/IPO/InlineAlways.cpp
Jakob Stoklund Olesen f7477470d3 Try to keep the cached inliner costs around for a bit longer for big functions.
The Caller cost info would be reset everytime a callee was inlined. If the
caller has lots of calls and there is some mutual recursion going on, the
caller cost info could be calculated many times.

This patch reduces inliner runtime from 240s to 0.5s for a function with 20000
small function calls.

This is a more conservative version of r98089 that doesn't break the clang
test CodeGenCXX/temp-order.cpp. That test relies on rather extreme inlining
for constant folding.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98099 91177308-0d34-0410-b5e6-96231b3b80d8
2010-03-09 23:02:17 +00:00

78 lines
2.5 KiB
C++

//===- InlineAlways.cpp - Code to inline always_inline functions ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a custom inliner that handles only functions that
// are marked as "always inline".
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "inline"
#include "llvm/CallingConv.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Module.h"
#include "llvm/Type.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/InlineCost.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/InlinerPass.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;
namespace {
// AlwaysInliner only inlines functions that are mark as "always inline".
class AlwaysInliner : public Inliner {
// Functions that are never inlined
SmallPtrSet<const Function*, 16> NeverInline;
InlineCostAnalyzer CA;
public:
// Use extremely low threshold.
AlwaysInliner() : Inliner(&ID, -2000000000) {}
static char ID; // Pass identification, replacement for typeid
InlineCost getInlineCost(CallSite CS) {
return CA.getInlineCost(CS, NeverInline);
}
float getInlineFudgeFactor(CallSite CS) {
return CA.getInlineFudgeFactor(CS);
}
void resetCachedCostInfo(Function *Caller) {
CA.resetCachedCostInfo(Caller);
}
void growCachedCostInfo(Function* Caller, Function* Callee) {
CA.growCachedCostInfo(Caller, Callee);
}
virtual bool doFinalization(CallGraph &CG) {
return removeDeadFunctions(CG, &NeverInline);
}
virtual bool doInitialization(CallGraph &CG);
};
}
char AlwaysInliner::ID = 0;
static RegisterPass<AlwaysInliner>
X("always-inline", "Inliner for always_inline functions");
Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); }
// doInitialization - Initializes the vector of functions that have not
// been annotated with the "always inline" attribute.
bool AlwaysInliner::doInitialization(CallGraph &CG) {
Module &M = CG.getModule();
for (Module::iterator I = M.begin(), E = M.end();
I != E; ++I)
if (!I->isDeclaration() && !I->hasFnAttr(Attribute::AlwaysInline))
NeverInline.insert(I);
return false;
}