mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-08 03:30:22 +00:00
f91f5af802
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
102 lines
3.6 KiB
C++
102 lines
3.6 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/Target/TargetData.h"
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
// AlwaysInliner only inlines functions that are mark as "always inline".
|
|
class AlwaysInliner : public Inliner {
|
|
InlineCostAnalyzer CA;
|
|
public:
|
|
// Use extremely low threshold.
|
|
AlwaysInliner() : Inliner(ID, -2000000000, /*InsertLifetime*/true) {
|
|
initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
AlwaysInliner(bool InsertLifetime) : Inliner(ID, -2000000000,
|
|
InsertLifetime) {
|
|
initializeAlwaysInlinerPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
static char ID; // Pass identification, replacement for typeid
|
|
InlineCost getInlineCost(CallSite CS) {
|
|
Function *Callee = CS.getCalledFunction();
|
|
// We assume indirect calls aren't calling an always-inline function.
|
|
if (!Callee) return InlineCost::getNever();
|
|
|
|
// We can't inline calls to external functions.
|
|
// FIXME: We shouldn't even get here.
|
|
if (Callee->isDeclaration()) return InlineCost::getNever();
|
|
|
|
// Return never for anything not marked as always inline.
|
|
if (!Callee->hasFnAttr(Attribute::AlwaysInline))
|
|
return InlineCost::getNever();
|
|
|
|
// We still have to check the inline cost in case there are reasons to
|
|
// not inline which trump the always-inline attribute such as setjmp and
|
|
// indirectbr.
|
|
return CA.getInlineCost(CS);
|
|
}
|
|
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, /*AlwaysInlineOnly=*/true);
|
|
}
|
|
virtual bool doInitialization(CallGraph &CG);
|
|
void releaseMemory() {
|
|
CA.clear();
|
|
}
|
|
};
|
|
}
|
|
|
|
char AlwaysInliner::ID = 0;
|
|
INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline",
|
|
"Inliner for always_inline functions", false, false)
|
|
INITIALIZE_AG_DEPENDENCY(CallGraph)
|
|
INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
|
|
"Inliner for always_inline functions", false, false)
|
|
|
|
Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); }
|
|
|
|
Pass *llvm::createAlwaysInlinerPass(bool InsertLifetime) {
|
|
return new AlwaysInliner(InsertLifetime);
|
|
}
|
|
|
|
// doInitialization - Initializes the vector of functions that have not
|
|
// been annotated with the "always inline" attribute.
|
|
bool AlwaysInliner::doInitialization(CallGraph &CG) {
|
|
CA.setTargetData(getAnalysisIfAvailable<TargetData>());
|
|
return false;
|
|
}
|