mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-21 03:53:04 +02:00
[Inliner] clang-format various parts of the inliner prior to changes
here. NFC. llvm-svn: 277557
This commit is contained in:
parent
2b69153c7d
commit
dc1947bc2e
@ -12,7 +12,6 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Transforms/IPO.h"
|
|
||||||
#include "llvm/ADT/SmallPtrSet.h"
|
#include "llvm/ADT/SmallPtrSet.h"
|
||||||
#include "llvm/Analysis/AssumptionCache.h"
|
#include "llvm/Analysis/AssumptionCache.h"
|
||||||
#include "llvm/Analysis/CallGraph.h"
|
#include "llvm/Analysis/CallGraph.h"
|
||||||
@ -26,6 +25,7 @@
|
|||||||
#include "llvm/IR/IntrinsicInst.h"
|
#include "llvm/IR/IntrinsicInst.h"
|
||||||
#include "llvm/IR/Module.h"
|
#include "llvm/IR/Module.h"
|
||||||
#include "llvm/IR/Type.h"
|
#include "llvm/IR/Type.h"
|
||||||
|
#include "llvm/Transforms/IPO.h"
|
||||||
#include "llvm/Transforms/IPO/InlinerPass.h"
|
#include "llvm/Transforms/IPO/InlinerPass.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -55,21 +55,20 @@ public:
|
|||||||
|
|
||||||
using llvm::Pass::doFinalization;
|
using llvm::Pass::doFinalization;
|
||||||
bool doFinalization(CallGraph &CG) override {
|
bool doFinalization(CallGraph &CG) override {
|
||||||
return removeDeadFunctions(CG, /*AlwaysInlineOnly=*/ true);
|
return removeDeadFunctions(CG, /*AlwaysInlineOnly=*/true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char AlwaysInliner::ID = 0;
|
char AlwaysInliner::ID = 0;
|
||||||
INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline",
|
INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline",
|
||||||
"Inliner for always_inline functions", false, false)
|
"Inliner for always_inline functions", false, false)
|
||||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||||
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||||
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
|
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
|
||||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||||
INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
|
INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
|
||||||
"Inliner for always_inline functions", false, false)
|
"Inliner for always_inline functions", false, false)
|
||||||
|
|
||||||
Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); }
|
Pass *llvm::createAlwaysInlinerPass() { return new AlwaysInliner(); }
|
||||||
|
|
||||||
|
@ -61,8 +61,8 @@ public:
|
|||||||
InlineCost getInlineCost(CallSite CS) override {
|
InlineCost getInlineCost(CallSite CS) override {
|
||||||
Function *Callee = CS.getCalledFunction();
|
Function *Callee = CS.getCalledFunction();
|
||||||
TargetTransformInfo &TTI = TTIWP->getTTI(*Callee);
|
TargetTransformInfo &TTI = TTIWP->getTTI(*Callee);
|
||||||
std::function<AssumptionCache &(Function &)> GetAssumptionCache = [&](
|
std::function<AssumptionCache &(Function &)> GetAssumptionCache =
|
||||||
Function &F) -> AssumptionCache & {
|
[&](Function &F) -> AssumptionCache & {
|
||||||
return ACT->getAssumptionCache(F);
|
return ACT->getAssumptionCache(F);
|
||||||
};
|
};
|
||||||
return llvm::getInlineCost(CS, DefaultThreshold, TTI, GetAssumptionCache,
|
return llvm::getInlineCost(CS, DefaultThreshold, TTI, GetAssumptionCache,
|
||||||
@ -79,15 +79,15 @@ private:
|
|||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
char SimpleInliner::ID = 0;
|
char SimpleInliner::ID = 0;
|
||||||
INITIALIZE_PASS_BEGIN(SimpleInliner, "inline",
|
INITIALIZE_PASS_BEGIN(SimpleInliner, "inline", "Function Integration/Inlining",
|
||||||
"Function Integration/Inlining", false, false)
|
false, false)
|
||||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||||
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||||
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
|
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
|
||||||
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
|
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
|
||||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||||
INITIALIZE_PASS_END(SimpleInliner, "inline",
|
INITIALIZE_PASS_END(SimpleInliner, "inline", "Function Integration/Inlining",
|
||||||
"Function Integration/Inlining", false, false)
|
false, false)
|
||||||
|
|
||||||
Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); }
|
Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); }
|
||||||
|
|
||||||
|
@ -81,9 +81,7 @@ void Inliner::getAnalysisUsage(AnalysisUsage &AU) const {
|
|||||||
CallGraphSCCPass::getAnalysisUsage(AU);
|
CallGraphSCCPass::getAnalysisUsage(AU);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef DenseMap<ArrayType *, std::vector<AllocaInst *>> InlinedArrayAllocasTy;
|
||||||
typedef DenseMap<ArrayType*, std::vector<AllocaInst*> >
|
|
||||||
InlinedArrayAllocasTy;
|
|
||||||
|
|
||||||
/// If it is possible to inline the specified call site,
|
/// If it is possible to inline the specified call site,
|
||||||
/// do so and update the CallGraph for this operation.
|
/// do so and update the CallGraph for this operation.
|
||||||
@ -134,8 +132,8 @@ static bool InlineCallIfPossible(
|
|||||||
//
|
//
|
||||||
// Because we don't have this information, we do this simple and useful hack.
|
// Because we don't have this information, we do this simple and useful hack.
|
||||||
//
|
//
|
||||||
SmallPtrSet<AllocaInst*, 16> UsedAllocas;
|
SmallPtrSet<AllocaInst *, 16> UsedAllocas;
|
||||||
|
|
||||||
// When processing our SCC, check to see if CS was inlined from some other
|
// 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:
|
// call site. For example, if we're processing "A" in this code:
|
||||||
// A() { B() }
|
// A() { B() }
|
||||||
@ -148,25 +146,25 @@ static bool InlineCallIfPossible(
|
|||||||
// because their scopes are not disjoint. We could make this smarter by
|
// because their scopes are not disjoint. We could make this smarter by
|
||||||
// keeping track of the inline history for each alloca in the
|
// keeping track of the inline history for each alloca in the
|
||||||
// InlinedArrayAllocas but this isn't likely to be a significant win.
|
// InlinedArrayAllocas but this isn't likely to be a significant win.
|
||||||
if (InlineHistory != -1) // Only do merging for top-level call sites in SCC.
|
if (InlineHistory != -1) // Only do merging for top-level call sites in SCC.
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Loop over all the allocas we have so far and see if they can be merged with
|
// 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.
|
// a previously inlined alloca. If not, remember that we had it.
|
||||||
for (unsigned AllocaNo = 0, e = IFI.StaticAllocas.size();
|
for (unsigned AllocaNo = 0, e = IFI.StaticAllocas.size(); AllocaNo != e;
|
||||||
AllocaNo != e; ++AllocaNo) {
|
++AllocaNo) {
|
||||||
AllocaInst *AI = IFI.StaticAllocas[AllocaNo];
|
AllocaInst *AI = IFI.StaticAllocas[AllocaNo];
|
||||||
|
|
||||||
// Don't bother trying to merge array allocations (they will usually be
|
// Don't bother trying to merge array allocations (they will usually be
|
||||||
// canonicalized to be an allocation *of* an array), or allocations whose
|
// canonicalized to be an allocation *of* an array), or allocations whose
|
||||||
// type is not itself an array (because we're afraid of pessimizing SRoA).
|
// type is not itself an array (because we're afraid of pessimizing SRoA).
|
||||||
ArrayType *ATy = dyn_cast<ArrayType>(AI->getAllocatedType());
|
ArrayType *ATy = dyn_cast<ArrayType>(AI->getAllocatedType());
|
||||||
if (!ATy || AI->isArrayAllocation())
|
if (!ATy || AI->isArrayAllocation())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Get the list of all available allocas for this array type.
|
// Get the list of all available allocas for this array type.
|
||||||
std::vector<AllocaInst*> &AllocasForType = InlinedArrayAllocas[ATy];
|
std::vector<AllocaInst *> &AllocasForType = InlinedArrayAllocas[ATy];
|
||||||
|
|
||||||
// Loop over the allocas in AllocasForType to see if we can reuse one. Note
|
// 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
|
// 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'
|
// multiple different allocas that we just inlined, we use the 'UsedAllocas'
|
||||||
@ -177,22 +175,22 @@ static bool InlineCallIfPossible(
|
|||||||
|
|
||||||
unsigned Align1 = AI->getAlignment(),
|
unsigned Align1 = AI->getAlignment(),
|
||||||
Align2 = AvailableAlloca->getAlignment();
|
Align2 = AvailableAlloca->getAlignment();
|
||||||
|
|
||||||
// The available alloca has to be in the right function, not in some other
|
// The available alloca has to be in the right function, not in some other
|
||||||
// function in this SCC.
|
// function in this SCC.
|
||||||
if (AvailableAlloca->getParent() != AI->getParent())
|
if (AvailableAlloca->getParent() != AI->getParent())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If the inlined function already uses this alloca then we can't reuse
|
// If the inlined function already uses this alloca then we can't reuse
|
||||||
// it.
|
// it.
|
||||||
if (!UsedAllocas.insert(AvailableAlloca).second)
|
if (!UsedAllocas.insert(AvailableAlloca).second)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Otherwise, we *can* reuse it, RAUW AI into AvailableAlloca and declare
|
// Otherwise, we *can* reuse it, RAUW AI into AvailableAlloca and declare
|
||||||
// success!
|
// success!
|
||||||
DEBUG(dbgs() << " ***MERGED ALLOCA: " << *AI << "\n\t\tINTO: "
|
DEBUG(dbgs() << " ***MERGED ALLOCA: " << *AI
|
||||||
<< *AvailableAlloca << '\n');
|
<< "\n\t\tINTO: " << *AvailableAlloca << '\n');
|
||||||
|
|
||||||
// Move affected dbg.declare calls immediately after the new alloca to
|
// Move affected dbg.declare calls immediately after the new alloca to
|
||||||
// avoid the situation when a dbg.declare preceeds its alloca.
|
// avoid the situation when a dbg.declare preceeds its alloca.
|
||||||
if (auto *L = LocalAsMetadata::getIfExists(AI))
|
if (auto *L = LocalAsMetadata::getIfExists(AI))
|
||||||
@ -226,7 +224,7 @@ static bool InlineCallIfPossible(
|
|||||||
// If we already nuked the alloca, we're done with it.
|
// If we already nuked the alloca, we're done with it.
|
||||||
if (MergedAwayAlloca)
|
if (MergedAwayAlloca)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If we were unable to merge away the alloca either because there are no
|
// 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
|
// allocas of the right type available or because we reused them all
|
||||||
// already, remember that this alloca came from an inlined function and mark
|
// already, remember that this alloca came from an inlined function and mark
|
||||||
@ -235,7 +233,7 @@ static bool InlineCallIfPossible(
|
|||||||
AllocasForType.push_back(AI);
|
AllocasForType.push_back(AI);
|
||||||
UsedAllocas.insert(AI);
|
UsedAllocas.insert(AI);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,28 +325,28 @@ shouldBeDeferred(Function *Caller, CallSite CS, InlineCost IC,
|
|||||||
static bool shouldInline(CallSite CS,
|
static bool shouldInline(CallSite CS,
|
||||||
std::function<InlineCost(CallSite CS)> GetInlineCost) {
|
std::function<InlineCost(CallSite CS)> GetInlineCost) {
|
||||||
InlineCost IC = GetInlineCost(CS);
|
InlineCost IC = GetInlineCost(CS);
|
||||||
|
|
||||||
if (IC.isAlways()) {
|
if (IC.isAlways()) {
|
||||||
DEBUG(dbgs() << " Inlining: cost=always"
|
DEBUG(dbgs() << " Inlining: cost=always"
|
||||||
<< ", Call: " << *CS.getInstruction() << "\n");
|
<< ", Call: " << *CS.getInstruction() << "\n");
|
||||||
emitAnalysis(CS, Twine(CS.getCalledFunction()->getName()) +
|
emitAnalysis(CS, Twine(CS.getCalledFunction()->getName()) +
|
||||||
" should always be inlined (cost=always)");
|
" should always be inlined (cost=always)");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IC.isNever()) {
|
if (IC.isNever()) {
|
||||||
DEBUG(dbgs() << " NOT Inlining: cost=never"
|
DEBUG(dbgs() << " NOT Inlining: cost=never"
|
||||||
<< ", Call: " << *CS.getInstruction() << "\n");
|
<< ", Call: " << *CS.getInstruction() << "\n");
|
||||||
emitAnalysis(CS, Twine(CS.getCalledFunction()->getName() +
|
emitAnalysis(CS, Twine(CS.getCalledFunction()->getName() +
|
||||||
" should never be inlined (cost=never)"));
|
" should never be inlined (cost=never)"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Function *Caller = CS.getCaller();
|
Function *Caller = CS.getCaller();
|
||||||
if (!IC) {
|
if (!IC) {
|
||||||
DEBUG(dbgs() << " NOT Inlining: cost=" << IC.getCost()
|
DEBUG(dbgs() << " NOT Inlining: cost=" << IC.getCost()
|
||||||
<< ", thres=" << (IC.getCostDelta() + IC.getCost())
|
<< ", thres=" << (IC.getCostDelta() + IC.getCost())
|
||||||
<< ", Call: " << *CS.getInstruction() << "\n");
|
<< ", Call: " << *CS.getInstruction() << "\n");
|
||||||
emitAnalysis(CS, Twine(CS.getCalledFunction()->getName() +
|
emitAnalysis(CS, Twine(CS.getCalledFunction()->getName() +
|
||||||
" too costly to inline (cost=") +
|
" too costly to inline (cost=") +
|
||||||
Twine(IC.getCost()) + ", threshold=" +
|
Twine(IC.getCost()) + ", threshold=" +
|
||||||
@ -359,8 +357,8 @@ static bool shouldInline(CallSite CS,
|
|||||||
int TotalSecondaryCost = 0;
|
int TotalSecondaryCost = 0;
|
||||||
if (shouldBeDeferred(Caller, CS, IC, TotalSecondaryCost, GetInlineCost)) {
|
if (shouldBeDeferred(Caller, CS, IC, TotalSecondaryCost, GetInlineCost)) {
|
||||||
DEBUG(dbgs() << " NOT Inlining: " << *CS.getInstruction()
|
DEBUG(dbgs() << " NOT Inlining: " << *CS.getInstruction()
|
||||||
<< " Cost = " << IC.getCost()
|
<< " Cost = " << IC.getCost()
|
||||||
<< ", outer Cost = " << TotalSecondaryCost << '\n');
|
<< ", outer Cost = " << TotalSecondaryCost << '\n');
|
||||||
emitAnalysis(CS, Twine("Not inlining. Cost of inlining " +
|
emitAnalysis(CS, Twine("Not inlining. Cost of inlining " +
|
||||||
CS.getCalledFunction()->getName() +
|
CS.getCalledFunction()->getName() +
|
||||||
" increases the cost of inlining " +
|
" increases the cost of inlining " +
|
||||||
@ -369,8 +367,8 @@ static bool shouldInline(CallSite CS,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(dbgs() << " Inlining: cost=" << IC.getCost()
|
DEBUG(dbgs() << " Inlining: cost=" << IC.getCost()
|
||||||
<< ", thres=" << (IC.getCostDelta() + IC.getCost())
|
<< ", thres=" << (IC.getCostDelta() + IC.getCost())
|
||||||
<< ", Call: " << *CS.getInstruction() << '\n');
|
<< ", Call: " << *CS.getInstruction() << '\n');
|
||||||
emitAnalysis(
|
emitAnalysis(
|
||||||
CS, CS.getCalledFunction()->getName() + Twine(" can be inlined into ") +
|
CS, CS.getCalledFunction()->getName() + Twine(" can be inlined into ") +
|
||||||
CS.getCaller()->getName() + " with cost=" + Twine(IC.getCost()) +
|
CS.getCaller()->getName() + " with cost=" + Twine(IC.getCost()) +
|
||||||
@ -380,8 +378,9 @@ static bool shouldInline(CallSite CS,
|
|||||||
|
|
||||||
/// Return true if the specified inline history ID
|
/// Return true if the specified inline history ID
|
||||||
/// indicates an inline history that includes the specified function.
|
/// indicates an inline history that includes the specified function.
|
||||||
static bool InlineHistoryIncludes(Function *F, int InlineHistoryID,
|
static bool InlineHistoryIncludes(
|
||||||
const SmallVectorImpl<std::pair<Function*, int> > &InlineHistory) {
|
Function *F, int InlineHistoryID,
|
||||||
|
const SmallVectorImpl<std::pair<Function *, int>> &InlineHistory) {
|
||||||
while (InlineHistoryID != -1) {
|
while (InlineHistoryID != -1) {
|
||||||
assert(unsigned(InlineHistoryID) < InlineHistory.size() &&
|
assert(unsigned(InlineHistoryID) < InlineHistory.size() &&
|
||||||
"Invalid inline history ID");
|
"Invalid inline history ID");
|
||||||
@ -412,11 +411,12 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
|||||||
std::function<InlineCost(CallSite CS)> GetInlineCost,
|
std::function<InlineCost(CallSite CS)> GetInlineCost,
|
||||||
std::function<AAResults &(Function &)> AARGetter,
|
std::function<AAResults &(Function &)> AARGetter,
|
||||||
ImportedFunctionsInliningStatistics &ImportedFunctionsStats) {
|
ImportedFunctionsInliningStatistics &ImportedFunctionsStats) {
|
||||||
SmallPtrSet<Function*, 8> SCCFunctions;
|
SmallPtrSet<Function *, 8> SCCFunctions;
|
||||||
DEBUG(dbgs() << "Inliner visiting SCC:");
|
DEBUG(dbgs() << "Inliner visiting SCC:");
|
||||||
for (CallGraphNode *Node : SCC) {
|
for (CallGraphNode *Node : SCC) {
|
||||||
Function *F = Node->getFunction();
|
Function *F = Node->getFunction();
|
||||||
if (F) SCCFunctions.insert(F);
|
if (F)
|
||||||
|
SCCFunctions.insert(F);
|
||||||
DEBUG(dbgs() << " " << (F ? F->getName() : "INDIRECTNODE"));
|
DEBUG(dbgs() << " " << (F ? F->getName() : "INDIRECTNODE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,17 +424,18 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
|||||||
// inline call sites in the original functions, not call sites that result
|
// inline call sites in the original functions, not call sites that result
|
||||||
// from inlining other functions.
|
// from inlining other functions.
|
||||||
SmallVector<std::pair<CallSite, int>, 16> CallSites;
|
SmallVector<std::pair<CallSite, int>, 16> CallSites;
|
||||||
|
|
||||||
// When inlining a callee produces new call sites, we want to keep track of
|
// 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
|
// 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
|
// infinite inlining in some obscure cases. To represent this, we use an
|
||||||
// index into the InlineHistory vector.
|
// index into the InlineHistory vector.
|
||||||
SmallVector<std::pair<Function*, int>, 8> InlineHistory;
|
SmallVector<std::pair<Function *, int>, 8> InlineHistory;
|
||||||
|
|
||||||
for (CallGraphNode *Node : SCC) {
|
for (CallGraphNode *Node : SCC) {
|
||||||
Function *F = Node->getFunction();
|
Function *F = Node->getFunction();
|
||||||
if (!F) continue;
|
if (!F)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (BasicBlock &BB : *F)
|
for (BasicBlock &BB : *F)
|
||||||
for (Instruction &I : BB) {
|
for (Instruction &I : BB) {
|
||||||
CallSite CS(cast<Value>(&I));
|
CallSite CS(cast<Value>(&I));
|
||||||
@ -442,14 +443,14 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
|||||||
// never be inlined.
|
// never be inlined.
|
||||||
if (!CS || isa<IntrinsicInst>(I))
|
if (!CS || isa<IntrinsicInst>(I))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If this is a direct call to an external function, we can never inline
|
// 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
|
// it. If it is an indirect call, inlining may resolve it to be a
|
||||||
// direct call, so we keep it.
|
// direct call, so we keep it.
|
||||||
if (Function *Callee = CS.getCalledFunction())
|
if (Function *Callee = CS.getCalledFunction())
|
||||||
if (Callee->isDeclaration())
|
if (Callee->isDeclaration())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CallSites.push_back(std::make_pair(CS, -1));
|
CallSites.push_back(std::make_pair(CS, -1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -468,7 +469,6 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
|||||||
if (SCCFunctions.count(F))
|
if (SCCFunctions.count(F))
|
||||||
std::swap(CallSites[i--], CallSites[--FirstCallInSCC]);
|
std::swap(CallSites[i--], CallSites[--FirstCallInSCC]);
|
||||||
|
|
||||||
|
|
||||||
InlinedArrayAllocasTy InlinedArrayAllocas;
|
InlinedArrayAllocasTy InlinedArrayAllocas;
|
||||||
InlineFunctionInfo InlineInfo(&CG, &GetAssumptionCache);
|
InlineFunctionInfo InlineInfo(&CG, &GetAssumptionCache);
|
||||||
|
|
||||||
@ -483,7 +483,7 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
|||||||
// CallSites may be modified inside so ranged for loop can not be used.
|
// CallSites may be modified inside so ranged for loop can not be used.
|
||||||
for (unsigned CSi = 0; CSi != CallSites.size(); ++CSi) {
|
for (unsigned CSi = 0; CSi != CallSites.size(); ++CSi) {
|
||||||
CallSite CS = CallSites[CSi].first;
|
CallSite CS = CallSites[CSi].first;
|
||||||
|
|
||||||
Function *Caller = CS.getCaller();
|
Function *Caller = CS.getCaller();
|
||||||
Function *Callee = CS.getCalledFunction();
|
Function *Callee = CS.getCalledFunction();
|
||||||
|
|
||||||
@ -492,16 +492,17 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
|||||||
// size. This happens because IPSCCP propagates the result out of the
|
// size. This happens because IPSCCP propagates the result out of the
|
||||||
// call and then we're left with the dead call.
|
// call and then we're left with the dead call.
|
||||||
if (isInstructionTriviallyDead(CS.getInstruction(), &TLI)) {
|
if (isInstructionTriviallyDead(CS.getInstruction(), &TLI)) {
|
||||||
DEBUG(dbgs() << " -> Deleting dead call: "
|
DEBUG(dbgs() << " -> Deleting dead call: " << *CS.getInstruction()
|
||||||
<< *CS.getInstruction() << "\n");
|
<< "\n");
|
||||||
// Update the call graph by deleting the edge from Callee to Caller.
|
// Update the call graph by deleting the edge from Callee to Caller.
|
||||||
CG[Caller]->removeCallEdgeFor(CS);
|
CG[Caller]->removeCallEdgeFor(CS);
|
||||||
CS.getInstruction()->eraseFromParent();
|
CS.getInstruction()->eraseFromParent();
|
||||||
++NumCallsDeleted;
|
++NumCallsDeleted;
|
||||||
} else {
|
} else {
|
||||||
// We can only inline direct calls to non-declarations.
|
// We can only inline direct calls to non-declarations.
|
||||||
if (!Callee || Callee->isDeclaration()) continue;
|
if (!Callee || Callee->isDeclaration())
|
||||||
|
continue;
|
||||||
|
|
||||||
// If this call site was obtained by inlining another function, verify
|
// If this call site was obtained by inlining another function, verify
|
||||||
// that the include path for the function did not include the callee
|
// that the include path for the function did not include the callee
|
||||||
// itself. If so, we'd be recursively inlining the same function,
|
// itself. If so, we'd be recursively inlining the same function,
|
||||||
@ -511,7 +512,7 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
|||||||
if (InlineHistoryID != -1 &&
|
if (InlineHistoryID != -1 &&
|
||||||
InlineHistoryIncludes(Callee, InlineHistoryID, InlineHistory))
|
InlineHistoryIncludes(Callee, InlineHistoryID, InlineHistory))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LLVMContext &CallerCtx = Caller->getContext();
|
LLVMContext &CallerCtx = Caller->getContext();
|
||||||
|
|
||||||
// Get DebugLoc to report. CS will be invalid after Inliner.
|
// Get DebugLoc to report. CS will be invalid after Inliner.
|
||||||
@ -556,30 +557,30 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
|||||||
CallSites.push_back(std::make_pair(CallSite(Ptr), NewHistoryID));
|
CallSites.push_back(std::make_pair(CallSite(Ptr), NewHistoryID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we inlined or deleted the last possible call site to the function,
|
// If we inlined or deleted the last possible call site to the function,
|
||||||
// delete the function body now.
|
// delete the function body now.
|
||||||
if (Callee && Callee->use_empty() && Callee->hasLocalLinkage() &&
|
if (Callee && Callee->use_empty() && Callee->hasLocalLinkage() &&
|
||||||
// TODO: Can remove if in SCC now.
|
// TODO: Can remove if in SCC now.
|
||||||
!SCCFunctions.count(Callee) &&
|
!SCCFunctions.count(Callee) &&
|
||||||
|
|
||||||
// The function may be apparently dead, but if there are indirect
|
// The function may be apparently dead, but if there are indirect
|
||||||
// callgraph references to the node, we cannot delete it yet, this
|
// callgraph references to the node, we cannot delete it yet, this
|
||||||
// could invalidate the CGSCC iterator.
|
// could invalidate the CGSCC iterator.
|
||||||
CG[Callee]->getNumReferences() == 0) {
|
CG[Callee]->getNumReferences() == 0) {
|
||||||
DEBUG(dbgs() << " -> Deleting dead function: "
|
DEBUG(dbgs() << " -> Deleting dead function: " << Callee->getName()
|
||||||
<< Callee->getName() << "\n");
|
<< "\n");
|
||||||
CallGraphNode *CalleeNode = CG[Callee];
|
CallGraphNode *CalleeNode = CG[Callee];
|
||||||
|
|
||||||
// Remove any call graph edges from the callee to its callees.
|
// Remove any call graph edges from the callee to its callees.
|
||||||
CalleeNode->removeAllCalledFunctions();
|
CalleeNode->removeAllCalledFunctions();
|
||||||
|
|
||||||
// Removing the node for callee from the call graph and delete it.
|
// Removing the node for callee from the call graph and delete it.
|
||||||
delete CG.removeFunctionFromModule(CalleeNode);
|
delete CG.removeFunctionFromModule(CalleeNode);
|
||||||
++NumDeleted;
|
++NumDeleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove this call site from the list. If possible, use
|
// Remove this call site from the list. If possible, use
|
||||||
// swap/pop_back for efficiency, but do not use it if doing so would
|
// 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
|
// move a call site to a function in this SCC before the
|
||||||
// 'FirstCallInSCC' barrier.
|
// 'FirstCallInSCC' barrier.
|
||||||
@ -587,7 +588,7 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
|||||||
CallSites[CSi] = CallSites.back();
|
CallSites[CSi] = CallSites.back();
|
||||||
CallSites.pop_back();
|
CallSites.pop_back();
|
||||||
} else {
|
} else {
|
||||||
CallSites.erase(CallSites.begin()+CSi);
|
CallSites.erase(CallSites.begin() + CSi);
|
||||||
}
|
}
|
||||||
--CSi;
|
--CSi;
|
||||||
|
|
||||||
@ -633,7 +634,7 @@ bool Inliner::doFinalization(CallGraph &CG) {
|
|||||||
|
|
||||||
/// Remove dead functions that are not included in DNR (Do Not Remove) list.
|
/// Remove dead functions that are not included in DNR (Do Not Remove) list.
|
||||||
bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) {
|
bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) {
|
||||||
SmallVector<CallGraphNode*, 16> FunctionsToRemove;
|
SmallVector<CallGraphNode *, 16> FunctionsToRemove;
|
||||||
SmallVector<CallGraphNode *, 16> DeadFunctionsInComdats;
|
SmallVector<CallGraphNode *, 16> DeadFunctionsInComdats;
|
||||||
SmallDenseMap<const Comdat *, int, 16> ComdatEntriesAlive;
|
SmallDenseMap<const Comdat *, int, 16> ComdatEntriesAlive;
|
||||||
|
|
||||||
@ -725,9 +726,9 @@ bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) {
|
|||||||
// here to do this, it doesn't matter which order the functions are deleted
|
// here to do this, it doesn't matter which order the functions are deleted
|
||||||
// in.
|
// in.
|
||||||
array_pod_sort(FunctionsToRemove.begin(), FunctionsToRemove.end());
|
array_pod_sort(FunctionsToRemove.begin(), FunctionsToRemove.end());
|
||||||
FunctionsToRemove.erase(std::unique(FunctionsToRemove.begin(),
|
FunctionsToRemove.erase(
|
||||||
FunctionsToRemove.end()),
|
std::unique(FunctionsToRemove.begin(), FunctionsToRemove.end()),
|
||||||
FunctionsToRemove.end());
|
FunctionsToRemove.end());
|
||||||
for (CallGraphNode *CGN : FunctionsToRemove) {
|
for (CallGraphNode *CGN : FunctionsToRemove) {
|
||||||
delete CG.removeFunctionFromModule(CGN);
|
delete CG.removeFunctionFromModule(CGN);
|
||||||
++NumDeleted;
|
++NumDeleted;
|
||||||
|
Loading…
Reference in New Issue
Block a user