Skip to content
Closed
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 44 additions & 26 deletions llvm/lib/Transforms/IPO/AlwaysInliner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,47 @@ using namespace llvm;

namespace {

/// Sanity check for a call site's inlinability based on inline attributes.
static bool canInlineCallBase(CallBase *CB) {
return CB->hasFnAttr(Attribute::AlwaysInline) &&
!CB->getAttributes().hasFnAttr(Attribute::NoInline);
}

/// Attempt to inline a call site \p CB into its caller.
/// Returns true if the inlining was successful, false otherwise.
static bool attemptInlineFunction(
Function &F, CallBase *CB, bool InsertLifetime,
function_ref<AAResults &(Function &)> &GetAAR,
function_ref<AssumptionCache &(Function &)> &GetAssumptionCache,
ProfileSummaryInfo &PSI) {
Function *Caller = CB->getCaller();
OptimizationRemarkEmitter ORE(Caller);
DebugLoc DLoc = CB->getDebugLoc();
BasicBlock *Block = CB->getParent();

InlineFunctionInfo IFI(GetAssumptionCache, &PSI, nullptr, nullptr);
InlineResult Res = InlineFunction(*CB, IFI, /*MergeAttributes=*/true,
&GetAAR(F), InsertLifetime);
if (!Res.isSuccess()) {
ORE.emit([&]() {
return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block)
<< "'" << ore::NV("Callee", &F) << "' is not inlined into '"
<< ore::NV("Caller", Caller)
<< "': " << ore::NV("Reason", Res.getFailureReason());
});
return false;
}

emitInlinedIntoBasedOnCost(ORE, DLoc, Block, F, *Caller,
InlineCost::getAlways("always inline attribute"),
/*ForProfileContext=*/false, DEBUG_TYPE);

return true;
}

/// This function inlines all functions that are marked with the always_inline
/// attribute. It also removes the inlined functions if they are dead after the
/// inlining process.
bool AlwaysInlineImpl(
Module &M, bool InsertLifetime, ProfileSummaryInfo &PSI,
FunctionAnalysisManager *FAM,
Expand All @@ -50,36 +91,13 @@ bool AlwaysInlineImpl(

for (User *U : F.users())
if (auto *CB = dyn_cast<CallBase>(U))
if (CB->getCalledFunction() == &F &&
CB->hasFnAttr(Attribute::AlwaysInline) &&
!CB->getAttributes().hasFnAttr(Attribute::NoInline))
if (CB->getCalledFunction() == &F && canInlineCallBase(CB))
Calls.insert(CB);

for (CallBase *CB : Calls) {
Function *Caller = CB->getCaller();
OptimizationRemarkEmitter ORE(Caller);
DebugLoc DLoc = CB->getDebugLoc();
BasicBlock *Block = CB->getParent();

InlineFunctionInfo IFI(GetAssumptionCache, &PSI, nullptr, nullptr);
InlineResult Res = InlineFunction(*CB, IFI, /*MergeAttributes=*/true,
&GetAAR(F), InsertLifetime);
if (!Res.isSuccess()) {
ORE.emit([&]() {
return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block)
<< "'" << ore::NV("Callee", &F) << "' is not inlined into '"
<< ore::NV("Caller", Caller)
<< "': " << ore::NV("Reason", Res.getFailureReason());
});
continue;
}

emitInlinedIntoBasedOnCost(
ORE, DLoc, Block, F, *Caller,
InlineCost::getAlways("always inline attribute"),
/*ForProfileContext=*/false, DEBUG_TYPE);

Changed = true;
Changed |= attemptInlineFunction(F, CB, InsertLifetime, GetAAR,
GetAssumptionCache, PSI);
if (FAM)
FAM->invalidate(*Caller, PreservedAnalyses::none());
}
Expand Down