mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-12 06:06:19 +00:00
Fix cases where we missed inlining some more obvious candidates because the
caller was in an SCC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13693 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
74c68ffd5f
commit
befa499d45
@ -7,8 +7,9 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
//
|
//
|
||||||
// This file implements the code shared between the LLVM inliners. This
|
// This file implements the mechanics required to implement inlining without
|
||||||
// implements all of the boring mechanics of the bottom-up inlining.
|
// missing any calls and updating the call graph. The decisions of which calls
|
||||||
|
// are profitable to inline are implemented elsewhere.
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
@ -23,6 +24,7 @@
|
|||||||
#include "Support/CommandLine.h"
|
#include "Support/CommandLine.h"
|
||||||
#include "Support/Debug.h"
|
#include "Support/Debug.h"
|
||||||
#include "Support/Statistic.h"
|
#include "Support/Statistic.h"
|
||||||
|
#include <set>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -35,8 +37,41 @@ namespace {
|
|||||||
|
|
||||||
Inliner::Inliner() : InlineThreshold(InlineLimit) {}
|
Inliner::Inliner() : InlineThreshold(InlineLimit) {}
|
||||||
|
|
||||||
int Inliner::getRecursiveInlineCost(CallSite CS) {
|
// InlineCallIfPossible - If it is possible to inline the specified call site,
|
||||||
return getInlineCost(CS);
|
// do so and update the CallGraph for this operation.
|
||||||
|
static bool InlineCallIfPossible(CallSite CS, CallGraph &CG,
|
||||||
|
const std::set<Function*> &SCCFunctions) {
|
||||||
|
Function *Caller = CS.getInstruction()->getParent()->getParent();
|
||||||
|
Function *Callee = CS.getCalledFunction();
|
||||||
|
if (!InlineFunction(CS)) return false;
|
||||||
|
|
||||||
|
// Update the call graph by deleting the edge from Callee to Caller
|
||||||
|
CallGraphNode *CalleeNode = CG[Callee];
|
||||||
|
CallGraphNode *CallerNode = CG[Caller];
|
||||||
|
CallerNode->removeCallEdgeTo(CalleeNode);
|
||||||
|
|
||||||
|
// Since we inlined all uninlined call sites in the callee into the caller,
|
||||||
|
// add edges from the caller to all of the callees of the callee.
|
||||||
|
for (CallGraphNode::iterator I = CalleeNode->begin(),
|
||||||
|
E = CalleeNode->end(); I != E; ++I)
|
||||||
|
CallerNode->addCalledFunction(*I);
|
||||||
|
|
||||||
|
// If we inlined the last possible call site to the function,
|
||||||
|
// delete the function body now.
|
||||||
|
if (Callee->use_empty() && Callee->hasInternalLinkage() &&
|
||||||
|
!SCCFunctions.count(Callee)) {
|
||||||
|
DEBUG(std::cerr << " -> Deleting dead function: "
|
||||||
|
<< Callee->getName() << "\n");
|
||||||
|
|
||||||
|
// Remove any call graph edges from the callee to its callees.
|
||||||
|
while (CalleeNode->begin() != CalleeNode->end())
|
||||||
|
CalleeNode->removeCallEdgeTo(*(CalleeNode->end()-1));
|
||||||
|
|
||||||
|
// Removing the node for callee from the call graph and delete it.
|
||||||
|
delete CG.removeFunctionFromModule(CalleeNode);
|
||||||
|
++NumDeleted;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
|
bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
|
||||||
@ -45,42 +80,59 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
|
|||||||
std::set<Function*> SCCFunctions;
|
std::set<Function*> SCCFunctions;
|
||||||
DEBUG(std::cerr << "Inliner visiting SCC:");
|
DEBUG(std::cerr << "Inliner visiting SCC:");
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
|
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
|
||||||
SCCFunctions.insert(SCC[i]->getFunction());
|
Function *F = SCC[i]->getFunction();
|
||||||
DEBUG(std::cerr << " " << (SCC[i]->getFunction() ?
|
if (F) SCCFunctions.insert(F);
|
||||||
SCC[i]->getFunction()->getName() : "INDIRECTNODE"));
|
DEBUG(std::cerr << " " << (F ? F->getName() : "INDIRECTNODE"));
|
||||||
}
|
}
|
||||||
DEBUG(std::cerr << "\n");
|
|
||||||
|
|
||||||
bool Changed = false;
|
|
||||||
for (std::set<Function*>::iterator SCCI = SCCFunctions.begin(),
|
|
||||||
E = SCCFunctions.end(); SCCI != E; ++SCCI) {
|
|
||||||
Function *F = *SCCI;
|
|
||||||
if (F == 0 || F->isExternal()) continue;
|
|
||||||
DEBUG(std::cerr << " Inspecting function: " << F->getName() << "\n");
|
|
||||||
|
|
||||||
// Scan through and identify all call sites ahead of time so that we only
|
// 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
|
// inline call sites in the original functions, not call sites that result
|
||||||
// in inlining other functions.
|
// from inlining other functions.
|
||||||
std::vector<CallSite> CallSites;
|
std::vector<CallSite> CallSites;
|
||||||
|
|
||||||
|
for (std::set<Function*>::iterator SCCI = SCCFunctions.begin(),
|
||||||
|
E = SCCFunctions.end(); SCCI != E; ++SCCI)
|
||||||
|
if (Function *F = *SCCI)
|
||||||
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
|
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
|
||||||
for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
|
for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
|
||||||
CallSite CS = CallSite::get(I);
|
CallSite CS = CallSite::get(I);
|
||||||
if (CS.getInstruction() && CS.getCalledFunction() &&
|
if (CS.getInstruction() && (!CS.getCalledFunction() ||
|
||||||
!CS.getCalledFunction()->isExternal())
|
!CS.getCalledFunction()->isExternal()))
|
||||||
CallSites.push_back(CS);
|
CallSites.push_back(CS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG(std::cerr << ": " << CallSites.size() << " call sites.\n");
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
if (Function *F = CallSites[i].getCalledFunction())
|
||||||
|
if (SCCFunctions.count(F))
|
||||||
|
std::swap(CallSites[i--], CallSites[--FirstCallInSCC]);
|
||||||
|
|
||||||
// Now that we have all of the call sites, loop over them and inline them if
|
// Now that we have all of the call sites, loop over them and inline them if
|
||||||
// it looks profitable to do so.
|
// it looks profitable to do so.
|
||||||
for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
|
bool Changed = false;
|
||||||
CallSite CS = CallSites[i];
|
bool LocalChange;
|
||||||
Function *Callee = CS.getCalledFunction();
|
do {
|
||||||
// Determine whether this is a function IN the SCC...
|
LocalChange = false;
|
||||||
bool inSCC = SCCFunctions.count(Callee);
|
// Iterate over the outer loop because inlining functions can cause indirect
|
||||||
|
// calls to become direct calls.
|
||||||
|
for (unsigned CSi = 0; CSi != CallSites.size(); ++CSi)
|
||||||
|
if (Function *Callee = CallSites[CSi].getCalledFunction()) {
|
||||||
|
// Calls to external functions are never inlinable.
|
||||||
|
if (Callee->isExternal() ||
|
||||||
|
CallSites[CSi].getInstruction()->getParent()->getParent() ==Callee){
|
||||||
|
std::swap(CallSites[CSi], CallSites.back());
|
||||||
|
--CSi;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// If the policy determines that we should inline this function,
|
// If the policy determines that we should inline this function,
|
||||||
// try to do so...
|
// try to do so.
|
||||||
int InlineCost = inSCC ? getRecursiveInlineCost(CS) : getInlineCost(CS);
|
CallSite CS = CallSites[CSi];
|
||||||
|
int InlineCost = getInlineCost(CS);
|
||||||
if (InlineCost >= (int)InlineThreshold) {
|
if (InlineCost >= (int)InlineThreshold) {
|
||||||
DEBUG(std::cerr << " NOT Inlining: cost=" << InlineCost
|
DEBUG(std::cerr << " NOT Inlining: cost=" << InlineCost
|
||||||
<< ", Call: " << *CS.getInstruction());
|
<< ", Call: " << *CS.getInstruction());
|
||||||
@ -91,42 +143,19 @@ bool Inliner::runOnSCC(const std::vector<CallGraphNode*> &SCC) {
|
|||||||
Function *Caller = CS.getInstruction()->getParent()->getParent();
|
Function *Caller = CS.getInstruction()->getParent()->getParent();
|
||||||
|
|
||||||
// Attempt to inline the function...
|
// Attempt to inline the function...
|
||||||
if (InlineFunction(CS)) {
|
if (InlineCallIfPossible(CS, CG, SCCFunctions)) {
|
||||||
|
// Remove this call site from the list.
|
||||||
|
std::swap(CallSites[CSi], CallSites.back());
|
||||||
|
CallSites.pop_back();
|
||||||
|
--CSi;
|
||||||
|
|
||||||
++NumInlined;
|
++NumInlined;
|
||||||
|
|
||||||
// Update the call graph by deleting the edge from Callee to Caller
|
|
||||||
CallGraphNode *CalleeNode = CG[Callee];
|
|
||||||
CallGraphNode *CallerNode = CG[Caller];
|
|
||||||
CallerNode->removeCallEdgeTo(CalleeNode);
|
|
||||||
|
|
||||||
// Since we inlined all uninlinable call sites in the callee into the
|
|
||||||
// caller, add edges from the caller to all of the callees of the
|
|
||||||
// callee.
|
|
||||||
for (CallGraphNode::iterator I = CalleeNode->begin(),
|
|
||||||
E = CalleeNode->end(); I != E; ++I)
|
|
||||||
CallerNode->addCalledFunction(*I);
|
|
||||||
|
|
||||||
// If we inlined the last possible call site to the function,
|
|
||||||
// delete the function body now.
|
|
||||||
if (Callee->use_empty() && Callee != Caller &&
|
|
||||||
Callee->hasInternalLinkage()) {
|
|
||||||
DEBUG(std::cerr << " -> Deleting dead function: "
|
|
||||||
<< Callee->getName() << "\n");
|
|
||||||
SCCFunctions.erase(Callee); // Remove function from this SCC.
|
|
||||||
|
|
||||||
// Remove any call graph edges from the callee to its callees.
|
|
||||||
while (CalleeNode->begin() != CalleeNode->end())
|
|
||||||
CalleeNode->removeCallEdgeTo(*(CalleeNode->end()-1));
|
|
||||||
|
|
||||||
// Removing the node for callee from the call graph and delete it.
|
|
||||||
delete CG.removeFunctionFromModule(CalleeNode);
|
|
||||||
++NumDeleted;
|
|
||||||
}
|
|
||||||
Changed = true;
|
Changed = true;
|
||||||
|
LocalChange = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} while (LocalChange);
|
||||||
|
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user