Skip to content

Commit

Permalink
Avoid using a raw AssumptionCacheTracker in various inliner functions.
Browse files Browse the repository at this point in the history
This unblocks the new PM part of River's patch in
https://reviews.llvm.org/D22706

Conveniently, this same change was needed for D21921 and so these
changes are just spun out from there.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@276515 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
chisophugis committed Jul 23, 2016
1 parent e48bbc4 commit 9486968
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 82 deletions.
16 changes: 10 additions & 6 deletions include/llvm/Analysis/InlineCost.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define LLVM_ANALYSIS_INLINECOST_H

#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/AssumptionCache.h"
#include <cassert>
#include <climits>

Expand Down Expand Up @@ -110,18 +111,21 @@ class InlineCost {
///
/// Also note that calling this function *dynamically* computes the cost of
/// inlining the callsite. It is an expensive, heavyweight call.
InlineCost getInlineCost(CallSite CS, int DefaultThreshold,
TargetTransformInfo &CalleeTTI,
AssumptionCacheTracker *ACT, ProfileSummaryInfo *PSI);
InlineCost
getInlineCost(CallSite CS, int DefaultThreshold, TargetTransformInfo &CalleeTTI,
std::function<AssumptionCache &(Function &)> &GetAssumptionCache,
ProfileSummaryInfo *PSI);

/// \brief Get an InlineCost with the callee explicitly specified.
/// This allows you to calculate the cost of inlining a function via a
/// pointer. This behaves exactly as the version with no explicit callee
/// parameter in all other respects.
//
InlineCost getInlineCost(CallSite CS, Function *Callee, int DefaultThreshold,
TargetTransformInfo &CalleeTTI,
AssumptionCacheTracker *ACT, ProfileSummaryInfo *PSI);
InlineCost
getInlineCost(CallSite CS, Function *Callee, int DefaultThreshold,
TargetTransformInfo &CalleeTTI,
std::function<AssumptionCache &(Function &)> &GetAssumptionCache,
ProfileSummaryInfo *PSI);

int computeThresholdFromOptLevels(unsigned OptLevel, unsigned SizeOptLevel);

Expand Down
13 changes: 2 additions & 11 deletions include/llvm/Transforms/IPO/InlinerPass.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#define LLVM_TRANSFORMS_IPO_INLINERPASS_H

#include "llvm/Analysis/CallGraphSCCPass.h"
#include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/TargetTransformInfo.h"

namespace llvm {
class AssumptionCacheTracker;
Expand Down Expand Up @@ -73,17 +75,6 @@ struct Inliner : public CallGraphSCCPass {
// InsertLifetime - Insert @llvm.lifetime intrinsics.
bool InsertLifetime;

/// shouldInline - Return true if the inliner should attempt to
/// inline at the given CallSite.
bool shouldInline(CallSite CS);
/// Return true if inlining of CS can block the caller from being
/// inlined which is proved to be more beneficial. \p IC is the
/// estimated inline cost associated with callsite \p CS.
/// \p TotalAltCost will be set to the estimated cost of inlining the caller
/// if \p CS is suppressed for inlining.
bool shouldBeDeferred(Function *Caller, CallSite CS, InlineCost IC,
int &TotalAltCost);

protected:
AssumptionCacheTracker *ACT;
ProfileSummaryInfo *PSI;
Expand Down
8 changes: 5 additions & 3 deletions include/llvm/Transforms/Utils/Cloning.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/IR/ValueMap.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
Expand Down Expand Up @@ -176,13 +177,14 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
class InlineFunctionInfo {
public:
explicit InlineFunctionInfo(CallGraph *cg = nullptr,
AssumptionCacheTracker *ACT = nullptr)
: CG(cg), ACT(ACT) {}
std::function<AssumptionCache &(Function &)>
*GetAssumptionCache = nullptr)
: CG(cg), GetAssumptionCache(GetAssumptionCache) {}

/// CG - If non-null, InlineFunction will update the callgraph to reflect the
/// changes it makes.
CallGraph *CG;
AssumptionCacheTracker *ACT;
std::function<AssumptionCache &(Function &)> *GetAssumptionCache;

/// StaticAllocas - InlineFunction fills this in with all static allocas that
/// get copied into the caller.
Expand Down
58 changes: 29 additions & 29 deletions lib/Analysis/InlineCost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
/// The TargetTransformInfo available for this compilation.
const TargetTransformInfo &TTI;

/// The cache of @llvm.assume intrinsics.
AssumptionCacheTracker *ACT;
/// Getter for the cache of @llvm.assume intrinsics.
std::function<AssumptionCache &(Function &)> &GetAssumptionCache;

/// Profile summary information.
ProfileSummaryInfo *PSI;
Expand Down Expand Up @@ -203,20 +203,21 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
bool visitUnreachableInst(UnreachableInst &I);

public:
CallAnalyzer(const TargetTransformInfo &TTI, AssumptionCacheTracker *ACT,
CallAnalyzer(const TargetTransformInfo &TTI,
std::function<AssumptionCache &(Function &)> &GetAssumptionCache,
ProfileSummaryInfo *PSI, Function &Callee, int Threshold,
CallSite CSArg)
: TTI(TTI), ACT(ACT), PSI(PSI), F(Callee), CandidateCS(CSArg),
Threshold(Threshold), Cost(0), IsCallerRecursive(false),
IsRecursiveCall(false), ExposesReturnsTwice(false),
HasDynamicAlloca(false), ContainsNoDuplicateCall(false),
HasReturn(false), HasIndirectBr(false), HasFrameEscape(false),
AllocatedSize(0), NumInstructions(0), NumVectorInstructions(0),
FiftyPercentVectorBonus(0), TenPercentVectorBonus(0), VectorBonus(0),
NumConstantArgs(0), NumConstantOffsetPtrArgs(0), NumAllocaArgs(0),
NumConstantPtrCmps(0), NumConstantPtrDiffs(0),
NumInstructionsSimplified(0), SROACostSavings(0),
SROACostSavingsLost(0) {}
: TTI(TTI), GetAssumptionCache(GetAssumptionCache), PSI(PSI), F(Callee),
CandidateCS(CSArg), Threshold(Threshold), Cost(0),
IsCallerRecursive(false), IsRecursiveCall(false),
ExposesReturnsTwice(false), HasDynamicAlloca(false),
ContainsNoDuplicateCall(false), HasReturn(false), HasIndirectBr(false),
HasFrameEscape(false), AllocatedSize(0), NumInstructions(0),
NumVectorInstructions(0), FiftyPercentVectorBonus(0),
TenPercentVectorBonus(0), VectorBonus(0), NumConstantArgs(0),
NumConstantOffsetPtrArgs(0), NumAllocaArgs(0), NumConstantPtrCmps(0),
NumConstantPtrDiffs(0), NumInstructionsSimplified(0),
SROACostSavings(0), SROACostSavingsLost(0) {}

bool analyzeCall(CallSite CS);

Expand Down Expand Up @@ -957,8 +958,8 @@ bool CallAnalyzer::visitCallSite(CallSite CS) {
// during devirtualization and so we want to give it a hefty bonus for
// inlining, but cap that bonus in the event that inlining wouldn't pan
// out. Pretend to inline the function, with a custom threshold.
CallAnalyzer CA(TTI, ACT, PSI, *F, InlineConstants::IndirectCallThreshold,
CS);
CallAnalyzer CA(TTI, GetAssumptionCache, PSI, *F,
InlineConstants::IndirectCallThreshold, CS);
if (CA.analyzeCall(CS)) {
// We were able to inline the indirect call! Subtract the cost from the
// threshold to get the bonus we want to apply, but don't go below zero.
Expand Down Expand Up @@ -1312,8 +1313,7 @@ bool CallAnalyzer::analyzeCall(CallSite CS) {
// the ephemeral values multiple times (and they're completely determined by
// the callee, so this is purely duplicate work).
SmallPtrSet<const Value *, 32> EphValues;
CodeMetrics::collectEphemeralValues(&F, &ACT->getAssumptionCache(F),
EphValues);
CodeMetrics::collectEphemeralValues(&F, &GetAssumptionCache(F), EphValues);

// The worklist of live basic blocks in the callee *after* inlining. We avoid
// adding basic blocks of the callee which can be proven to be dead for this
Expand Down Expand Up @@ -1444,12 +1444,12 @@ static bool functionsHaveCompatibleAttributes(Function *Caller,
AttributeFuncs::areInlineCompatible(*Caller, *Callee);
}

InlineCost llvm::getInlineCost(CallSite CS, int DefaultThreshold,
TargetTransformInfo &CalleeTTI,
AssumptionCacheTracker *ACT,
ProfileSummaryInfo *PSI) {
InlineCost llvm::getInlineCost(
CallSite CS, int DefaultThreshold, TargetTransformInfo &CalleeTTI,
std::function<AssumptionCache &(Function &)> &GetAssumptionCache,
ProfileSummaryInfo *PSI) {
return getInlineCost(CS, CS.getCalledFunction(), DefaultThreshold, CalleeTTI,
ACT, PSI);
GetAssumptionCache, PSI);
}

int llvm::computeThresholdFromOptLevels(unsigned OptLevel,
Expand All @@ -1465,11 +1465,11 @@ int llvm::computeThresholdFromOptLevels(unsigned OptLevel,

int llvm::getDefaultInlineThreshold() { return DefaultInlineThreshold; }

InlineCost llvm::getInlineCost(CallSite CS, Function *Callee,
int DefaultThreshold,
TargetTransformInfo &CalleeTTI,
AssumptionCacheTracker *ACT,
ProfileSummaryInfo *PSI) {
InlineCost llvm::getInlineCost(
CallSite CS, Function *Callee, int DefaultThreshold,
TargetTransformInfo &CalleeTTI,
std::function<AssumptionCache &(Function &)> &GetAssumptionCache,
ProfileSummaryInfo *PSI) {

// Cannot inline indirect calls.
if (!Callee)
Expand Down Expand Up @@ -1503,7 +1503,7 @@ InlineCost llvm::getInlineCost(CallSite CS, Function *Callee,
DEBUG(llvm::dbgs() << " Analyzing call of " << Callee->getName()
<< "...\n");

CallAnalyzer CA(CalleeTTI, ACT, PSI, *Callee, DefaultThreshold, CS);
CallAnalyzer CA(CalleeTTI, GetAssumptionCache, PSI, *Callee, DefaultThreshold, CS);
bool ShouldInline = CA.analyzeCall(CS);

DEBUG(CA.dump());
Expand Down
7 changes: 6 additions & 1 deletion lib/Transforms/IPO/InlineSimple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ class SimpleInliner : public Inliner {
InlineCost getInlineCost(CallSite CS) override {
Function *Callee = CS.getCalledFunction();
TargetTransformInfo &TTI = TTIWP->getTTI(*Callee);
return llvm::getInlineCost(CS, DefaultThreshold, TTI, ACT, PSI);
std::function<AssumptionCache &(Function &)> GetAssumptionCache = [&](
Function &F) -> AssumptionCache & {
return ACT->getAssumptionCache(F);
};
return llvm::getInlineCost(CS, DefaultThreshold, TTI, GetAssumptionCache,
PSI);
}

bool runOnSCC(CallGraphSCC &SCC) override;
Expand Down
81 changes: 55 additions & 26 deletions lib/Transforms/IPO/Inliner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,15 @@ InlinedArrayAllocasTy;
/// 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.
static bool InlineCallIfPossible(Pass &P, CallSite CS, InlineFunctionInfo &IFI,
InlinedArrayAllocasTy &InlinedArrayAllocas,
int InlineHistory, bool InsertLifetime) {
static bool
InlineCallIfPossible(CallSite CS, InlineFunctionInfo &IFI,
InlinedArrayAllocasTy &InlinedArrayAllocas,
int InlineHistory, bool InsertLifetime,
std::function<AAResults &(Function &)> &AARGetter) {
Function *Callee = CS.getCalledFunction();
Function *Caller = CS.getCaller();

// We need to manually construct BasicAA directly in order to disable
// its use of other function analyses.
BasicAAResult BAR(createLegacyPMBasicAAResult(P, *Callee));

// Construct our own AA results for this function. We do this manually to
// work around the limitations of the legacy pass manager.
AAResults AAR(createLegacyPMAAResults(P, *Callee, BAR));
AAResults &AAR = AARGetter(*Callee);

// Try to inline the function. Get the list of static allocas that were
// inlined.
Expand Down Expand Up @@ -229,8 +225,15 @@ static void emitAnalysis(CallSite CS, const Twine &Msg) {
emitOptimizationRemarkAnalysis(Ctx, DEBUG_TYPE, *Caller, DLoc, Msg);
}

bool Inliner::shouldBeDeferred(Function *Caller, CallSite CS, InlineCost IC,
int &TotalSecondaryCost) {
/// Return true if inlining of CS can block the caller from being
/// inlined which is proved to be more beneficial. \p IC is the
/// estimated inline cost associated with callsite \p CS.
/// \p TotalAltCost will be set to the estimated cost of inlining the caller
/// if \p CS is suppressed for inlining.
static bool
shouldBeDeferred(Function *Caller, CallSite CS, InlineCost IC,
int &TotalSecondaryCost,
std::function<InlineCost(CallSite CS)> &GetInlineCost) {

// For now we only handle local or inline functions.
if (!Caller->hasLocalLinkage() && !Caller->hasLinkOnceODRLinkage())
Expand Down Expand Up @@ -269,7 +272,7 @@ bool Inliner::shouldBeDeferred(Function *Caller, CallSite CS, InlineCost IC,
continue;
}

InlineCost IC2 = getInlineCost(CS2);
InlineCost IC2 = GetInlineCost(CS2);
++NumCallerCallersAnalyzed;
if (!IC2) {
callerWillBeRemoved = false;
Expand Down Expand Up @@ -300,8 +303,9 @@ bool Inliner::shouldBeDeferred(Function *Caller, CallSite CS, InlineCost IC,
}

/// Return true if the inliner should attempt to inline at the given CallSite.
bool Inliner::shouldInline(CallSite CS) {
InlineCost IC = getInlineCost(CS);
static bool shouldInline(CallSite CS,
std::function<InlineCost(CallSite CS)> GetInlineCost) {
InlineCost IC = GetInlineCost(CS);

if (IC.isAlways()) {
DEBUG(dbgs() << " Inlining: cost=always"
Expand Down Expand Up @@ -332,7 +336,7 @@ bool Inliner::shouldInline(CallSite CS) {
}

int TotalSecondaryCost = 0;
if (shouldBeDeferred(Caller, CS, IC, TotalSecondaryCost)) {
if (shouldBeDeferred(Caller, CS, IC, TotalSecondaryCost, GetInlineCost)) {
DEBUG(dbgs() << " NOT Inlining: " << *CS.getInstruction()
<< " Cost = " << IC.getCost()
<< ", outer Cost = " << TotalSecondaryCost << '\n');
Expand Down Expand Up @@ -370,15 +374,17 @@ static bool InlineHistoryIncludes(Function *F, int InlineHistoryID,
bool Inliner::runOnSCC(CallGraphSCC &SCC) {
if (skipSCC(SCC))
return false;

return inlineCalls(SCC);
}

bool Inliner::inlineCalls(CallGraphSCC &SCC) {
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
ACT = &getAnalysis<AssumptionCacheTracker>();
PSI = getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI(CG.getModule());
auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();

static bool
inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
std::function<AssumptionCache &(Function &)> GetAssumptionCache,
ProfileSummaryInfo *PSI, TargetLibraryInfo &TLI,
bool InsertLifetime,
std::function<InlineCost(CallSite CS)> GetInlineCost,
std::function<AAResults &(Function &)> AARGetter) {
SmallPtrSet<Function*, 8> SCCFunctions;
DEBUG(dbgs() << "Inliner visiting SCC:");
for (CallGraphNode *Node : SCC) {
Expand Down Expand Up @@ -437,7 +443,7 @@ bool Inliner::inlineCalls(CallGraphSCC &SCC) {


InlinedArrayAllocasTy InlinedArrayAllocas;
InlineFunctionInfo InlineInfo(&CG, ACT);
InlineFunctionInfo InlineInfo(&CG, &GetAssumptionCache);

// Now that we have all of the call sites, loop over them and inline them if
// it looks profitable to do so.
Expand Down Expand Up @@ -486,7 +492,7 @@ bool Inliner::inlineCalls(CallGraphSCC &SCC) {

// If the policy determines that we should inline this function,
// try to do so.
if (!shouldInline(CS)) {
if (!shouldInline(CS, GetInlineCost)) {
emitOptimizationRemarkMissed(CallerCtx, DEBUG_TYPE, *Caller, DLoc,
Twine(Callee->getName() +
" will not be inlined into " +
Expand All @@ -495,8 +501,8 @@ bool Inliner::inlineCalls(CallGraphSCC &SCC) {
}

// Attempt to inline the function.
if (!InlineCallIfPossible(*this, CS, InlineInfo, InlinedArrayAllocas,
InlineHistoryID, InsertLifetime)) {
if (!InlineCallIfPossible(CS, InlineInfo, InlinedArrayAllocas,
InlineHistoryID, InsertLifetime, AARGetter)) {
emitOptimizationRemarkMissed(CallerCtx, DEBUG_TYPE, *Caller, DLoc,
Twine(Callee->getName() +
" will not be inlined into " +
Expand Down Expand Up @@ -565,6 +571,29 @@ bool Inliner::inlineCalls(CallGraphSCC &SCC) {
return Changed;
}

bool Inliner::inlineCalls(CallGraphSCC &SCC) {
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
ACT = &getAnalysis<AssumptionCacheTracker>();
PSI = getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI(CG.getModule());
auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
// We compute dedicated AA results for each function in the SCC as needed. We
// use a lambda referencing external objects so that they live long enough to
// be queried, but we re-use them each time.
Optional<BasicAAResult> BAR;
Optional<AAResults> AAR;
auto AARGetter = [&](Function &F) -> AAResults & {
BAR.emplace(createLegacyPMBasicAAResult(*this, F));
AAR.emplace(createLegacyPMAAResults(*this, F, *BAR));
return *AAR;
};
auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
return ACT->getAssumptionCache(F);
};
return inlineCallsImpl(SCC, CG, GetAssumptionCache, PSI, TLI, InsertLifetime,
[this](CallSite CS) { return getInlineCost(CS); },
AARGetter);
}

/// Remove now-dead linkonce functions at the end of
/// processing to avoid breaking the SCC traversal.
bool Inliner::doFinalization(CallGraph &CG) {
Expand Down
4 changes: 3 additions & 1 deletion lib/Transforms/IPO/SampleProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,8 @@ SampleProfileLoader::findFunctionSamples(const Instruction &Inst) const {
bool SampleProfileLoader::inlineHotFunctions(Function &F) {
bool Changed = false;
LLVMContext &Ctx = F.getContext();
std::function<AssumptionCache &(Function &)> GetAssumptionCache = [&](
Function &F) -> AssumptionCache & { return ACT->getAssumptionCache(F); };
while (true) {
bool LocalChanged = false;
SmallVector<CallInst *, 10> CIS;
Expand All @@ -638,7 +640,7 @@ bool SampleProfileLoader::inlineHotFunctions(Function &F) {
}
}
for (auto CI : CIS) {
InlineFunctionInfo IFI(nullptr, ACT);
InlineFunctionInfo IFI(nullptr, ACT ? &GetAssumptionCache : nullptr);
Function *CalledFunction = CI->getCalledFunction();
DebugLoc DLoc = CI->getDebugLoc();
uint64_t NumSamples = findCalleeFunctionSamples(*CI)->getTotalSamples();
Expand Down
Loading

0 comments on commit 9486968

Please sign in to comment.