mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
Revert "Enrich inline messages", tests fail
llvm-svn: 338496
This commit is contained in:
parent
bdae10300d
commit
28d06c0be1
@ -74,15 +74,8 @@ class InlineCost {
|
||||
/// The adjusted threshold against which this cost was computed.
|
||||
const int Threshold;
|
||||
|
||||
/// Must be set for Always and Never instances.
|
||||
const char *Reason = nullptr;
|
||||
|
||||
// Trivial constructor, interesting logic in the factory functions below.
|
||||
InlineCost(int Cost, int Threshold, const char *Reason = nullptr)
|
||||
: Cost(Cost), Threshold(Threshold), Reason(Reason) {
|
||||
assert((isVariable() || Reason) &&
|
||||
"Reason must be provided for Never or Always");
|
||||
}
|
||||
InlineCost(int Cost, int Threshold) : Cost(Cost), Threshold(Threshold) {}
|
||||
|
||||
public:
|
||||
static InlineCost get(int Cost, int Threshold) {
|
||||
@ -90,11 +83,11 @@ public:
|
||||
assert(Cost < NeverInlineCost && "Cost crosses sentinel value");
|
||||
return InlineCost(Cost, Threshold);
|
||||
}
|
||||
static InlineCost getAlways(const char *Reason) {
|
||||
return InlineCost(AlwaysInlineCost, 0, Reason);
|
||||
static InlineCost getAlways() {
|
||||
return InlineCost(AlwaysInlineCost, 0);
|
||||
}
|
||||
static InlineCost getNever(const char *Reason) {
|
||||
return InlineCost(NeverInlineCost, 0, Reason);
|
||||
static InlineCost getNever() {
|
||||
return InlineCost(NeverInlineCost, 0);
|
||||
}
|
||||
|
||||
/// Test whether the inline cost is low enough for inlining.
|
||||
@ -119,30 +112,12 @@ public:
|
||||
return Threshold;
|
||||
}
|
||||
|
||||
/// Get the reason of Always or Never.
|
||||
const char *getReason() const {
|
||||
assert((Reason || isVariable()) &&
|
||||
"InlineCost reason must be set for Always or Never");
|
||||
return Reason;
|
||||
}
|
||||
|
||||
/// Get the cost delta from the threshold for inlining.
|
||||
/// Only valid if the cost is of the variable kind. Returns a negative
|
||||
/// value if the cost is too high to inline.
|
||||
int getCostDelta() const { return Threshold - getCost(); }
|
||||
};
|
||||
|
||||
/// InlineResult is basically true or false. For false results the message
|
||||
/// describes a reason why it is decided not to inline.
|
||||
struct InlineResult {
|
||||
const char *message = nullptr;
|
||||
InlineResult(bool result, const char *message = nullptr)
|
||||
: message(result ? nullptr : (message ? message : "cost > threshold")) {}
|
||||
InlineResult(const char *message = nullptr) : message(message) {}
|
||||
operator bool() const { return !message; }
|
||||
operator const char *() const { return message; }
|
||||
};
|
||||
|
||||
/// Thresholds to tune inline cost analysis. The inline cost analysis decides
|
||||
/// the condition to apply a threshold and applies it. Otherwise,
|
||||
/// DefaultThreshold is used. If a threshold is Optional, it is applied only
|
||||
|
@ -414,7 +414,6 @@ public:
|
||||
Argument(StringRef Key, const Value *V);
|
||||
Argument(StringRef Key, const Type *T);
|
||||
Argument(StringRef Key, StringRef S);
|
||||
Argument(StringRef Key, const char *S) : Argument(Key, StringRef(S)) {};
|
||||
Argument(StringRef Key, int N);
|
||||
Argument(StringRef Key, float N);
|
||||
Argument(StringRef Key, long N);
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/InlineCost.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/ValueHandle.h"
|
||||
#include "llvm/Transforms/Utils/ValueMapper.h"
|
||||
@ -233,16 +232,13 @@ public:
|
||||
/// and all varargs at the callsite will be passed to any calls to
|
||||
/// ForwardVarArgsTo. The caller of InlineFunction has to make sure any varargs
|
||||
/// are only used by ForwardVarArgsTo.
|
||||
InlineResult InlineFunction(CallInst *C, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR = nullptr,
|
||||
bool InsertLifetime = true);
|
||||
InlineResult InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR = nullptr,
|
||||
bool InsertLifetime = true);
|
||||
InlineResult InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR = nullptr,
|
||||
bool InsertLifetime = true,
|
||||
Function *ForwardVarArgsTo = nullptr);
|
||||
bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR = nullptr, bool InsertLifetime = true);
|
||||
bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR = nullptr, bool InsertLifetime = true);
|
||||
bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR = nullptr, bool InsertLifetime = true,
|
||||
Function *ForwardVarArgsTo = nullptr);
|
||||
|
||||
/// Clones a loop \p OrigLoop. Returns the loop and the blocks in \p
|
||||
/// Blocks.
|
||||
|
@ -227,8 +227,7 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
|
||||
BlockFrequencyInfo *CallerBFI);
|
||||
|
||||
// Custom analysis routines.
|
||||
InlineResult analyzeBlock(BasicBlock *BB,
|
||||
SmallPtrSetImpl<const Value *> &EphValues);
|
||||
bool analyzeBlock(BasicBlock *BB, SmallPtrSetImpl<const Value *> &EphValues);
|
||||
|
||||
// Disable several entry points to the visitor so we don't accidentally use
|
||||
// them by declaring but not defining them here.
|
||||
@ -291,7 +290,7 @@ public:
|
||||
NumInstructionsSimplified(0), SROACostSavings(0),
|
||||
SROACostSavingsLost(0) {}
|
||||
|
||||
InlineResult analyzeCall(CallSite CS);
|
||||
bool analyzeCall(CallSite CS);
|
||||
|
||||
int getThreshold() { return Threshold; }
|
||||
int getCost() { return Cost; }
|
||||
@ -1542,9 +1541,8 @@ bool CallAnalyzer::visitInstruction(Instruction &I) {
|
||||
/// aborts early if the threshold has been exceeded or an impossible to inline
|
||||
/// construct has been detected. It returns false if inlining is no longer
|
||||
/// viable, and true if inlining remains viable.
|
||||
InlineResult
|
||||
CallAnalyzer::analyzeBlock(BasicBlock *BB,
|
||||
SmallPtrSetImpl<const Value *> &EphValues) {
|
||||
bool CallAnalyzer::analyzeBlock(BasicBlock *BB,
|
||||
SmallPtrSetImpl<const Value *> &EphValues) {
|
||||
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
|
||||
// FIXME: Currently, the number of instructions in a function regardless of
|
||||
// our ability to simplify them during inline to constants or dead code,
|
||||
@ -1576,29 +1574,16 @@ CallAnalyzer::analyzeBlock(BasicBlock *BB,
|
||||
|
||||
using namespace ore;
|
||||
// If the visit this instruction detected an uninlinable pattern, abort.
|
||||
InlineResult IR;
|
||||
if (IsRecursiveCall)
|
||||
IR = "recursive";
|
||||
else if (ExposesReturnsTwice)
|
||||
IR = "exposes returns twice";
|
||||
else if (HasDynamicAlloca)
|
||||
IR = "dynamic alloca";
|
||||
else if (HasIndirectBr)
|
||||
IR = "indirect branch";
|
||||
else if (HasUninlineableIntrinsic)
|
||||
IR = "uninlinable intrinsic";
|
||||
else if (UsesVarArgs)
|
||||
IR = "varargs";
|
||||
if (!IR) {
|
||||
if (IsRecursiveCall || ExposesReturnsTwice || HasDynamicAlloca ||
|
||||
HasIndirectBr || HasUninlineableIntrinsic || UsesVarArgs) {
|
||||
if (ORE)
|
||||
ORE->emit([&]() {
|
||||
return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline",
|
||||
CandidateCS.getInstruction())
|
||||
<< NV("Callee", &F) << " has uninlinable pattern ("
|
||||
<< NV("InlineResult", IR.message)
|
||||
<< ") and cost is not fully computed";
|
||||
<< NV("Callee", &F)
|
||||
<< " has uninlinable pattern and cost is not fully computed";
|
||||
});
|
||||
return IR;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the caller is a recursive function then we don't want to inline
|
||||
@ -1606,15 +1591,15 @@ CallAnalyzer::analyzeBlock(BasicBlock *BB,
|
||||
// the caller stack usage dramatically.
|
||||
if (IsCallerRecursive &&
|
||||
AllocatedSize > InlineConstants::TotalAllocaSizeRecursiveCaller) {
|
||||
InlineResult IR = "recursive and allocates too much stack space";
|
||||
if (ORE)
|
||||
ORE->emit([&]() {
|
||||
return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline",
|
||||
CandidateCS.getInstruction())
|
||||
<< NV("Callee", &F) << " is " << NV("InlineResult", IR.message)
|
||||
<< ". Cost is not fully computed";
|
||||
<< NV("Callee", &F)
|
||||
<< " is recursive and allocates too much stack space. Cost is "
|
||||
"not fully computed";
|
||||
});
|
||||
return IR;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we've past the maximum possible threshold so we don't spin in
|
||||
@ -1710,7 +1695,7 @@ void CallAnalyzer::findDeadBlocks(BasicBlock *CurrBB, BasicBlock *NextBB) {
|
||||
/// factors and heuristics. If this method returns false but the computed cost
|
||||
/// is below the computed threshold, then inlining was forcibly disabled by
|
||||
/// some artifact of the routine.
|
||||
InlineResult CallAnalyzer::analyzeCall(CallSite CS) {
|
||||
bool CallAnalyzer::analyzeCall(CallSite CS) {
|
||||
++NumCallsAnalyzed;
|
||||
|
||||
// Perform some tweaks to the cost and threshold based on the direct
|
||||
@ -1745,7 +1730,7 @@ InlineResult CallAnalyzer::analyzeCall(CallSite CS) {
|
||||
|
||||
// Check if we're done. This can happen due to bonuses and penalties.
|
||||
if (Cost >= Threshold && !ComputeFullInlineCost)
|
||||
return "high cost";
|
||||
return false;
|
||||
|
||||
if (F.empty())
|
||||
return true;
|
||||
@ -1824,13 +1809,12 @@ InlineResult CallAnalyzer::analyzeCall(CallSite CS) {
|
||||
// site. If the blockaddress escapes the function, e.g., via a global
|
||||
// variable, inlining may lead to an invalid cross-function reference.
|
||||
if (BB->hasAddressTaken())
|
||||
return "blockaddress";
|
||||
return false;
|
||||
|
||||
// Analyze the cost of this block. If we blow through the threshold, this
|
||||
// returns false, and we can bail on out.
|
||||
InlineResult IR = analyzeBlock(BB, EphValues);
|
||||
if (!IR)
|
||||
return IR;
|
||||
if (!analyzeBlock(BB, EphValues))
|
||||
return false;
|
||||
|
||||
TerminatorInst *TI = BB->getTerminator();
|
||||
|
||||
@ -1883,7 +1867,7 @@ InlineResult CallAnalyzer::analyzeCall(CallSite CS) {
|
||||
// inlining this would cause the removal of the caller (so the instruction
|
||||
// is not actually duplicated, just moved).
|
||||
if (!OnlyOneCallAndLocalLinkage && ContainsNoDuplicateCall)
|
||||
return "noduplicate";
|
||||
return false;
|
||||
|
||||
// We applied the maximum possible vector bonus at the beginning. Now,
|
||||
// subtract the excess bonus, if any, from the Threshold before
|
||||
@ -1977,7 +1961,7 @@ InlineCost llvm::getInlineCost(
|
||||
|
||||
// Cannot inline indirect calls.
|
||||
if (!Callee)
|
||||
return llvm::InlineCost::getNever("indirect call");
|
||||
return llvm::InlineCost::getNever();
|
||||
|
||||
// Never inline calls with byval arguments that does not have the alloca
|
||||
// address space. Since byval arguments can be replaced with a copy to an
|
||||
@ -1989,59 +1973,54 @@ InlineCost llvm::getInlineCost(
|
||||
if (CS.isByValArgument(I)) {
|
||||
PointerType *PTy = cast<PointerType>(CS.getArgument(I)->getType());
|
||||
if (PTy->getAddressSpace() != AllocaAS)
|
||||
return llvm::InlineCost::getNever("byval arguments without alloca"
|
||||
" address space");
|
||||
return llvm::InlineCost::getNever();
|
||||
}
|
||||
|
||||
// Calls to functions with always-inline attributes should be inlined
|
||||
// whenever possible.
|
||||
if (CS.hasFnAttr(Attribute::AlwaysInline)) {
|
||||
if (isInlineViable(*Callee))
|
||||
return llvm::InlineCost::getAlways("always inline attribute");
|
||||
return llvm::InlineCost::getNever("inapplicable always inline attribute");
|
||||
return llvm::InlineCost::getAlways();
|
||||
return llvm::InlineCost::getNever();
|
||||
}
|
||||
|
||||
// Never inline functions with conflicting attributes (unless callee has
|
||||
// always-inline attribute).
|
||||
Function *Caller = CS.getCaller();
|
||||
if (!functionsHaveCompatibleAttributes(Caller, Callee, CalleeTTI))
|
||||
return llvm::InlineCost::getNever("conflicting attributes");
|
||||
return llvm::InlineCost::getNever();
|
||||
|
||||
// Don't inline this call if the caller has the optnone attribute.
|
||||
if (Caller->hasFnAttribute(Attribute::OptimizeNone))
|
||||
return llvm::InlineCost::getNever("optnone attribute");
|
||||
return llvm::InlineCost::getNever();
|
||||
|
||||
// Don't inline a function that treats null pointer as valid into a caller
|
||||
// that does not have this attribute.
|
||||
if (!Caller->nullPointerIsDefined() && Callee->nullPointerIsDefined())
|
||||
return llvm::InlineCost::getNever("nullptr definitions incompatible");
|
||||
return llvm::InlineCost::getNever();
|
||||
|
||||
// Don't inline functions which can be interposed at link-time.
|
||||
if (Callee->isInterposable())
|
||||
return llvm::InlineCost::getNever("interposable");
|
||||
|
||||
// Don't inline functions marked noinline.
|
||||
if (Callee->hasFnAttribute(Attribute::NoInline))
|
||||
return llvm::InlineCost::getNever("noinline function attribute");
|
||||
|
||||
// Don't inline call sites marked noinline.
|
||||
if (CS.isNoInline())
|
||||
return llvm::InlineCost::getNever("noinline call site attribute");
|
||||
// Don't inline functions which can be interposed at link-time. Don't inline
|
||||
// functions marked noinline or call sites marked noinline.
|
||||
// Note: inlining non-exact non-interposable functions is fine, since we know
|
||||
// we have *a* correct implementation of the source level function.
|
||||
if (Callee->isInterposable() || Callee->hasFnAttribute(Attribute::NoInline) ||
|
||||
CS.isNoInline())
|
||||
return llvm::InlineCost::getNever();
|
||||
|
||||
LLVM_DEBUG(llvm::dbgs() << " Analyzing call of " << Callee->getName()
|
||||
<< "... (caller:" << Caller->getName() << ")\n");
|
||||
|
||||
CallAnalyzer CA(CalleeTTI, GetAssumptionCache, GetBFI, PSI, ORE, *Callee, CS,
|
||||
Params);
|
||||
InlineResult ShouldInline = CA.analyzeCall(CS);
|
||||
bool ShouldInline = CA.analyzeCall(CS);
|
||||
|
||||
LLVM_DEBUG(CA.dump());
|
||||
|
||||
// Check if there was a reason to force inlining or no inlining.
|
||||
if (!ShouldInline && CA.getCost() < CA.getThreshold())
|
||||
return InlineCost::getNever(ShouldInline.message);
|
||||
return InlineCost::getNever();
|
||||
if (ShouldInline && CA.getCost() >= CA.getThreshold())
|
||||
return InlineCost::getAlways("empty function");
|
||||
return InlineCost::getAlways();
|
||||
|
||||
return llvm::InlineCost::get(CA.getCost(), CA.getThreshold());
|
||||
}
|
||||
|
@ -174,23 +174,18 @@ InlineCost AMDGPUInliner::getInlineCost(CallSite CS) {
|
||||
Function *Caller = CS.getCaller();
|
||||
TargetTransformInfo &TTI = TTIWP->getTTI(*Callee);
|
||||
|
||||
if (!Callee || Callee->isDeclaration())
|
||||
return llvm::InlineCost::getNever("undefined callee");
|
||||
|
||||
if (CS.isNoInline())
|
||||
return llvm::InlineCost::getNever("noinline");
|
||||
|
||||
if (!TTI.areInlineCompatible(Caller, Callee))
|
||||
return llvm::InlineCost::getNever("incompatible");
|
||||
if (!Callee || Callee->isDeclaration() || CS.isNoInline() ||
|
||||
!TTI.areInlineCompatible(Caller, Callee))
|
||||
return llvm::InlineCost::getNever();
|
||||
|
||||
if (CS.hasFnAttr(Attribute::AlwaysInline)) {
|
||||
if (isInlineViable(*Callee))
|
||||
return llvm::InlineCost::getAlways("alwaysinline viable");
|
||||
return llvm::InlineCost::getNever("alwaysinline unviable");
|
||||
return llvm::InlineCost::getAlways();
|
||||
return llvm::InlineCost::getNever();
|
||||
}
|
||||
|
||||
if (isWrapperOnlyCall(CS))
|
||||
return llvm::InlineCost::getAlways("wrapper-only call");
|
||||
return llvm::InlineCost::getAlways();
|
||||
|
||||
InlineParams LocalParams = Params;
|
||||
LocalParams.DefaultThreshold = (int)getInlineThreshold(CS);
|
||||
|
@ -150,7 +150,7 @@ InlineCost AlwaysInlinerLegacyPass::getInlineCost(CallSite CS) {
|
||||
// declarations.
|
||||
if (Callee && !Callee->isDeclaration() &&
|
||||
CS.hasFnAttr(Attribute::AlwaysInline) && isInlineViable(*Callee))
|
||||
return InlineCost::getAlways("always inliner");
|
||||
return InlineCost::getAlways();
|
||||
|
||||
return InlineCost::getNever("always inliner");
|
||||
return InlineCost::getNever();
|
||||
}
|
||||
|
@ -64,7 +64,6 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@ -276,9 +275,8 @@ static bool InlineCallIfPossible(
|
||||
|
||||
// Try to inline the function. Get the list of static allocas that were
|
||||
// inlined.
|
||||
InlineResult IR = InlineFunction(CS, IFI, &AAR, InsertLifetime);
|
||||
if (!IR)
|
||||
return IR;
|
||||
if (!InlineFunction(CS, IFI, &AAR, InsertLifetime))
|
||||
return false;
|
||||
|
||||
if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No)
|
||||
ImportedFunctionsStats.recordInline(*Caller, *Callee);
|
||||
@ -288,7 +286,7 @@ static bool InlineCallIfPossible(
|
||||
if (!DisableInlinedAllocaMerging)
|
||||
mergeInlinedArrayAllocas(Caller, IFI, InlinedArrayAllocas, InlineHistory);
|
||||
|
||||
return IR; // success
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Return true if inlining of CS can block the caller from being
|
||||
@ -367,33 +365,6 @@ shouldBeDeferred(Function *Caller, CallSite CS, InlineCost IC,
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::basic_ostream<char> &operator<<(std::basic_ostream<char> &R,
|
||||
const ore::NV &Arg) {
|
||||
return R << Arg.Val;
|
||||
}
|
||||
|
||||
template <class RemarkT>
|
||||
RemarkT &operator<<(RemarkT &&R, const InlineCost &IC) {
|
||||
using namespace ore;
|
||||
if (IC.isAlways()) {
|
||||
R << "(cost=always)";
|
||||
} else if (IC.isNever()) {
|
||||
R << "(cost=never)";
|
||||
} else {
|
||||
R << "(cost=" << ore::NV("Cost", IC.getCost())
|
||||
<< ", threshold=" << ore::NV("Threshold", IC.getThreshold()) << ")";
|
||||
}
|
||||
if (const char *Reason = IC.getReason())
|
||||
R << ": " << ore::NV("Reason", Reason);
|
||||
return R;
|
||||
}
|
||||
|
||||
static std::string inlineCostStr(const InlineCost &IC) {
|
||||
std::stringstream Remark;
|
||||
Remark << IC;
|
||||
return Remark.str();
|
||||
}
|
||||
|
||||
/// Return the cost only if the inliner should attempt to inline at the given
|
||||
/// CallSite. If we return the cost, we will emit an optimisation remark later
|
||||
/// using that cost, so we won't do so from this function.
|
||||
@ -408,32 +379,35 @@ shouldInline(CallSite CS, function_ref<InlineCost(CallSite CS)> GetInlineCost,
|
||||
Function *Caller = CS.getCaller();
|
||||
|
||||
if (IC.isAlways()) {
|
||||
LLVM_DEBUG(dbgs() << " Inlining " << inlineCostStr(IC)
|
||||
LLVM_DEBUG(dbgs() << " Inlining: cost=always"
|
||||
<< ", Call: " << *CS.getInstruction() << "\n");
|
||||
return IC;
|
||||
}
|
||||
|
||||
if (IC.isNever()) {
|
||||
LLVM_DEBUG(dbgs() << " NOT Inlining " << inlineCostStr(IC)
|
||||
LLVM_DEBUG(dbgs() << " NOT Inlining: cost=never"
|
||||
<< ", Call: " << *CS.getInstruction() << "\n");
|
||||
ORE.emit([&]() {
|
||||
return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call)
|
||||
<< NV("Callee", Callee) << " not inlined into "
|
||||
<< NV("Caller", Caller) << " because it should never be inlined "
|
||||
<< IC;
|
||||
<< NV("Caller", Caller)
|
||||
<< " because it should never be inlined (cost=never)";
|
||||
});
|
||||
return IC;
|
||||
return None;
|
||||
}
|
||||
|
||||
if (!IC) {
|
||||
LLVM_DEBUG(dbgs() << " NOT Inlining " << inlineCostStr(IC)
|
||||
LLVM_DEBUG(dbgs() << " NOT Inlining: cost=" << IC.getCost()
|
||||
<< ", thres=" << IC.getThreshold()
|
||||
<< ", Call: " << *CS.getInstruction() << "\n");
|
||||
ORE.emit([&]() {
|
||||
return OptimizationRemarkMissed(DEBUG_TYPE, "TooCostly", Call)
|
||||
<< NV("Callee", Callee) << " not inlined into "
|
||||
<< NV("Caller", Caller) << " because too costly to inline " << IC;
|
||||
<< NV("Caller", Caller) << " because too costly to inline (cost="
|
||||
<< NV("Cost", IC.getCost())
|
||||
<< ", threshold=" << NV("Threshold", IC.getThreshold()) << ")";
|
||||
});
|
||||
return IC;
|
||||
return None;
|
||||
}
|
||||
|
||||
int TotalSecondaryCost = 0;
|
||||
@ -454,7 +428,8 @@ shouldInline(CallSite CS, function_ref<InlineCost(CallSite CS)> GetInlineCost,
|
||||
return None;
|
||||
}
|
||||
|
||||
LLVM_DEBUG(dbgs() << " Inlining " << inlineCostStr(IC)
|
||||
LLVM_DEBUG(dbgs() << " Inlining: cost=" << IC.getCost()
|
||||
<< ", thres=" << IC.getThreshold()
|
||||
<< ", Call: " << *CS.getInstruction() << '\n');
|
||||
return IC;
|
||||
}
|
||||
@ -486,18 +461,6 @@ bool LegacyInlinerBase::runOnSCC(CallGraphSCC &SCC) {
|
||||
return inlineCalls(SCC);
|
||||
}
|
||||
|
||||
static void emit_inlined_into(OptimizationRemarkEmitter &ORE, DebugLoc &DLoc,
|
||||
const BasicBlock *Block, const Function &Callee,
|
||||
const Function &Caller, const InlineCost &IC) {
|
||||
ORE.emit([&]() {
|
||||
bool AlwaysInline = IC.isAlways();
|
||||
StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined";
|
||||
return OptimizationRemark(DEBUG_TYPE, RemarkName, DLoc, Block)
|
||||
<< ore::NV("Callee", &Callee) << " inlined into "
|
||||
<< ore::NV("Caller", &Caller) << " with " << IC;
|
||||
});
|
||||
}
|
||||
|
||||
static bool
|
||||
inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
||||
std::function<AssumptionCache &(Function &)> GetAssumptionCache,
|
||||
@ -622,9 +585,8 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
||||
Optional<InlineCost> OIC = shouldInline(CS, GetInlineCost, ORE);
|
||||
// If the policy determines that we should inline this function,
|
||||
// delete the call instead.
|
||||
if (!OIC || !*OIC) {
|
||||
if (!OIC)
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this call site is dead and it is to a readonly function, we should
|
||||
// just delete the call instead of trying to inline it, regardless of
|
||||
@ -644,21 +606,34 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
|
||||
// Attempt to inline the function.
|
||||
using namespace ore;
|
||||
|
||||
InlineResult IR = InlineCallIfPossible(
|
||||
CS, InlineInfo, InlinedArrayAllocas, InlineHistoryID,
|
||||
InsertLifetime, AARGetter, ImportedFunctionsStats);
|
||||
if (!IR) {
|
||||
if (!InlineCallIfPossible(CS, InlineInfo, InlinedArrayAllocas,
|
||||
InlineHistoryID, InsertLifetime, AARGetter,
|
||||
ImportedFunctionsStats)) {
|
||||
ORE.emit([&]() {
|
||||
return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc,
|
||||
Block)
|
||||
<< NV("Callee", Callee) << " will not be inlined into "
|
||||
<< NV("Caller", Caller) << ": " << NV("Reason", IR.message);
|
||||
<< NV("Caller", Caller);
|
||||
});
|
||||
continue;
|
||||
}
|
||||
++NumInlined;
|
||||
|
||||
emit_inlined_into(ORE, DLoc, Block, *Callee, *Caller, *OIC);
|
||||
ORE.emit([&]() {
|
||||
bool AlwaysInline = OIC->isAlways();
|
||||
StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined";
|
||||
OptimizationRemark R(DEBUG_TYPE, RemarkName, DLoc, Block);
|
||||
R << NV("Callee", Callee) << " inlined into ";
|
||||
R << NV("Caller", Caller);
|
||||
if (AlwaysInline)
|
||||
R << " with cost=always";
|
||||
else {
|
||||
R << " with cost=" << NV("Cost", OIC->getCost());
|
||||
R << " (threshold=" << NV("Threshold", OIC->getThreshold());
|
||||
R << ")";
|
||||
}
|
||||
return R;
|
||||
});
|
||||
|
||||
// If inlining this function gave us any new call sites, throw them
|
||||
// onto our worklist to process. They are useful inline candidates.
|
||||
@ -996,7 +971,7 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
||||
|
||||
Optional<InlineCost> OIC = shouldInline(CS, GetInlineCost, ORE);
|
||||
// Check whether we want to inline this callsite.
|
||||
if (!OIC || !*OIC)
|
||||
if (!OIC)
|
||||
continue;
|
||||
|
||||
// Setup the data structure used to plumb customization into the
|
||||
@ -1012,19 +987,32 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
|
||||
|
||||
using namespace ore;
|
||||
|
||||
InlineResult IR = InlineFunction(CS, IFI);
|
||||
if (!IR) {
|
||||
if (!InlineFunction(CS, IFI)) {
|
||||
ORE.emit([&]() {
|
||||
return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block)
|
||||
<< NV("Callee", &Callee) << " will not be inlined into "
|
||||
<< NV("Caller", &F) << ": " << NV("Reason", IR.message);
|
||||
<< NV("Caller", &F);
|
||||
});
|
||||
continue;
|
||||
}
|
||||
DidInline = true;
|
||||
InlinedCallees.insert(&Callee);
|
||||
|
||||
emit_inlined_into(ORE, DLoc, Block, Callee, F, *OIC);
|
||||
ORE.emit([&]() {
|
||||
bool AlwaysInline = OIC->isAlways();
|
||||
StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined";
|
||||
OptimizationRemark R(DEBUG_TYPE, RemarkName, DLoc, Block);
|
||||
R << NV("Callee", &Callee) << " inlined into ";
|
||||
R << NV("Caller", &F);
|
||||
if (AlwaysInline)
|
||||
R << " with cost=always";
|
||||
else {
|
||||
R << " with cost=" << NV("Cost", OIC->getCost());
|
||||
R << " (threshold=" << NV("Threshold", OIC->getThreshold());
|
||||
R << ")";
|
||||
}
|
||||
return R;
|
||||
});
|
||||
|
||||
// Add any new callsites to defined functions to the worklist.
|
||||
if (!IFI.InlinedCallSites.empty()) {
|
||||
|
@ -84,15 +84,13 @@ PreserveAlignmentAssumptions("preserve-alignment-assumptions-during-inlining",
|
||||
cl::init(true), cl::Hidden,
|
||||
cl::desc("Convert align attributes to assumptions during inlining."));
|
||||
|
||||
llvm::InlineResult llvm::InlineFunction(CallInst *CI, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR,
|
||||
bool InsertLifetime) {
|
||||
bool llvm::InlineFunction(CallInst *CI, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR, bool InsertLifetime) {
|
||||
return InlineFunction(CallSite(CI), IFI, CalleeAAR, InsertLifetime);
|
||||
}
|
||||
|
||||
llvm::InlineResult llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR,
|
||||
bool InsertLifetime) {
|
||||
bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR, bool InsertLifetime) {
|
||||
return InlineFunction(CallSite(II), IFI, CalleeAAR, InsertLifetime);
|
||||
}
|
||||
|
||||
@ -1493,10 +1491,9 @@ static void updateCalleeCount(BlockFrequencyInfo *CallerBFI, BasicBlock *CallBB,
|
||||
/// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now
|
||||
/// exists in the instruction stream. Similarly this will inline a recursive
|
||||
/// function by one level.
|
||||
llvm::InlineResult llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR,
|
||||
bool InsertLifetime,
|
||||
Function *ForwardVarArgsTo) {
|
||||
bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
AAResults *CalleeAAR, bool InsertLifetime,
|
||||
Function *ForwardVarArgsTo) {
|
||||
Instruction *TheCall = CS.getInstruction();
|
||||
assert(TheCall->getParent() && TheCall->getFunction()
|
||||
&& "Instruction not in function!");
|
||||
@ -1507,7 +1504,7 @@ llvm::InlineResult llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
Function *CalledFunc = CS.getCalledFunction();
|
||||
if (!CalledFunc || // Can't inline external function or indirect
|
||||
CalledFunc->isDeclaration()) // call!
|
||||
return "external or indirect";
|
||||
return false;
|
||||
|
||||
// The inliner does not know how to inline through calls with operand bundles
|
||||
// in general ...
|
||||
@ -1521,7 +1518,7 @@ llvm::InlineResult llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
if (Tag == LLVMContext::OB_funclet)
|
||||
continue;
|
||||
|
||||
return "unsupported operand bundle";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1540,7 +1537,7 @@ llvm::InlineResult llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
if (!Caller->hasGC())
|
||||
Caller->setGC(CalledFunc->getGC());
|
||||
else if (CalledFunc->getGC() != Caller->getGC())
|
||||
return "incompatible GC";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the personality function from the callee if it contains a landing pad.
|
||||
@ -1564,7 +1561,7 @@ llvm::InlineResult llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
// TODO: This isn't 100% true. Some personality functions are proper
|
||||
// supersets of others and can be used in place of the other.
|
||||
else if (CalledPersonality != CallerPersonality)
|
||||
return "incompatible personality";
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need to figure out which funclet the callsite was in so that we may
|
||||
@ -1589,7 +1586,7 @@ llvm::InlineResult llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
// for catchpads.
|
||||
for (const BasicBlock &CalledBB : *CalledFunc) {
|
||||
if (isa<CatchSwitchInst>(CalledBB.getFirstNonPHI()))
|
||||
return "catch in cleanup funclet";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (isAsynchronousEHPersonality(Personality)) {
|
||||
@ -1597,7 +1594,7 @@ llvm::InlineResult llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
// funclet in the callee.
|
||||
for (const BasicBlock &CalledBB : *CalledFunc) {
|
||||
if (CalledBB.isEHPad())
|
||||
return "SEH in cleanup funclet";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,15 +25,14 @@
|
||||
; YAML-NEXT: - Callee: tinkywinky
|
||||
; YAML-NEXT: - String: ' inlined into '
|
||||
; YAML-NEXT: - Caller: main
|
||||
; YAML-NEXT: - String: ' with '
|
||||
; YAML-NEXT: - String: '(cost='
|
||||
; YAML-NEXT: - String: ' with cost='
|
||||
; YAML-NEXT: - Cost: '-15000'
|
||||
; YAML-NEXT: - String: ', threshold='
|
||||
; YAML-NEXT: - String: ' (threshold='
|
||||
; YAML-NEXT: - Threshold: '337'
|
||||
; YAML-NEXT: - String: ')'
|
||||
; YAML-NEXT: ...
|
||||
|
||||
; CHECK: tinkywinky inlined into main with (cost=-15000, threshold=337) (hotness: 300)
|
||||
; CHECK: tinkywinky inlined into main with cost=-15000 (threshold=337) (hotness: 300)
|
||||
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-scei-ps4"
|
||||
|
@ -26,10 +26,9 @@
|
||||
; YAML-NEXT: - Callee: tinkywinky
|
||||
; YAML-NEXT: - String: ' inlined into '
|
||||
; YAML-NEXT: - Caller: main
|
||||
; YAML-NEXT: - String: ' with '
|
||||
; YAML-NEXT: - String: '(cost='
|
||||
; YAML-NEXT: - String: ' with cost='
|
||||
; YAML-NEXT: - Cost: '-15000'
|
||||
; YAML-NEXT: - String: ', threshold='
|
||||
; YAML-NEXT: - String: ' (threshold='
|
||||
; YAML-NEXT: - Threshold: '337'
|
||||
; YAML-NEXT: - String: ')'
|
||||
; YAML-NEXT: ...
|
||||
|
@ -17,10 +17,9 @@
|
||||
; YAML-NEXT: - Callee: foo
|
||||
; YAML-NEXT: - String: ' inlined into '
|
||||
; YAML-NEXT: - Caller: main
|
||||
; YAML-NEXT: - String: ' with '
|
||||
; YAML-NEXT: - String: '(cost='
|
||||
; YAML-NEXT: - String: ' with cost='
|
||||
; YAML-NEXT: - Cost: '-15000'
|
||||
; YAML-NEXT: - String: ', threshold='
|
||||
; YAML-NEXT: - String: ' (threshold='
|
||||
; YAML-NEXT: - Threshold: '337'
|
||||
; YAML-NEXT: - String: ')'
|
||||
; YAML-NEXT: ...
|
||||
|
@ -53,10 +53,9 @@
|
||||
; YAML-NEXT: - Callee: foo
|
||||
; YAML-NEXT: - String: ' inlined into '
|
||||
; YAML-NEXT: - Caller: main
|
||||
; YAML-NEXT: - String: ' with '
|
||||
; YAML-NEXT: - String: '(cost='
|
||||
; YAML-NEXT: - String: ' with cost='
|
||||
; YAML-NEXT: - Cost: '-15000'
|
||||
; YAML-NEXT: - String: ', threshold='
|
||||
; YAML-NEXT: - String: ' (threshold='
|
||||
; YAML-NEXT: - Threshold: '337'
|
||||
; YAML-NEXT: - String: ')'
|
||||
; YAML-NEXT: ...
|
||||
|
@ -25,10 +25,9 @@
|
||||
; YAML1-NEXT: - Callee: foo
|
||||
; YAML1-NEXT: - String: ' inlined into '
|
||||
; YAML1-NEXT: - Caller: main
|
||||
; YAML1-NEXT: - String: ' with '
|
||||
; YAML1-NEXT: - String: '(cost='
|
||||
; YAML1-NEXT: - String: ' with cost='
|
||||
; YAML1-NEXT: - Cost: '-30'
|
||||
; YAML1-NEXT: - String: ', threshold='
|
||||
; YAML1-NEXT: - String: ' (threshold='
|
||||
; YAML1-NEXT: - Threshold: '337'
|
||||
; YAML1-NEXT: - String: ')'
|
||||
; YAML1-NEXT: ...
|
||||
@ -44,10 +43,9 @@
|
||||
; YAML2-NEXT: - Callee: bar
|
||||
; YAML2-NEXT: - String: ' inlined into '
|
||||
; YAML2-NEXT: - Caller: foo
|
||||
; YAML2-NEXT: - String: ' with '
|
||||
; YAML2-NEXT: - String: '(cost='
|
||||
; YAML2-NEXT: - String: ' with cost='
|
||||
; YAML2-NEXT: - Cost: '-30'
|
||||
; YAML2-NEXT: - String: ', threshold='
|
||||
; YAML2-NEXT: - String: ' (threshold='
|
||||
; YAML2-NEXT: - Threshold: '337'
|
||||
; YAML2-NEXT: - String: ')'
|
||||
; YAML2-NEXT: ...
|
||||
|
@ -22,10 +22,9 @@
|
||||
; YAML1-NEXT: - Callee: foo
|
||||
; YAML1-NEXT: - String: ' inlined into '
|
||||
; YAML1-NEXT: - Caller: main
|
||||
; YAML1-NEXT: - String: ' with '
|
||||
; YAML1-NEXT: - String: '(cost='
|
||||
; YAML1-NEXT: - String: ' with cost='
|
||||
; YAML1-NEXT: - Cost: '-30'
|
||||
; YAML1-NEXT: - String: ', threshold='
|
||||
; YAML1-NEXT: - String: ' (threshold='
|
||||
; YAML1-NEXT: - Threshold: '337'
|
||||
; YAML1-NEXT: - String: ')'
|
||||
; YAML1-NEXT: ...
|
||||
@ -41,10 +40,9 @@
|
||||
; YAML2-NEXT: - Callee: bar
|
||||
; YAML2-NEXT: - String: ' inlined into '
|
||||
; YAML2-NEXT: - Caller: foo
|
||||
; YAML2-NEXT: - String: ' with '
|
||||
; YAML2-NEXT: - String: '(cost='
|
||||
; YAML2-NEXT: - String: ' with cost='
|
||||
; YAML2-NEXT: - Cost: '-30'
|
||||
; YAML2-NEXT: - String: ', threshold='
|
||||
; YAML2-NEXT: - String: ' (threshold='
|
||||
; YAML2-NEXT: - Threshold: '337'
|
||||
; YAML2-NEXT: - String: ')'
|
||||
; YAML2-NEXT: ...
|
||||
|
@ -6,26 +6,26 @@
|
||||
|
||||
; NOFP-DAG: single not inlined into test_single because too costly to inline (cost=125, threshold=75)
|
||||
; NOFP-DAG: single not inlined into test_single because too costly to inline (cost=125, threshold=75)
|
||||
; NOFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15, threshold=75)
|
||||
; NOFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15015, threshold=75)
|
||||
; NOFP-DAG: single_cheap inlined into test_single_cheap with cost=-15 (threshold=75)
|
||||
; NOFP-DAG: single_cheap inlined into test_single_cheap with cost=-15015 (threshold=75)
|
||||
; NOFP-DAG: double not inlined into test_double because too costly to inline (cost=125, threshold=75)
|
||||
; NOFP-DAG: double not inlined into test_double because too costly to inline (cost=125, threshold=75)
|
||||
; NOFP-DAG: single_force_soft not inlined into test_single_force_soft because too costly to inline (cost=125, threshold=75)
|
||||
; NOFP-DAG: single_force_soft not inlined into test_single_force_soft because too costly to inline (cost=125, threshold=75)
|
||||
|
||||
; FULLFP-DAG: single inlined into test_single with (cost=0, threshold=75)
|
||||
; FULLFP-DAG: single inlined into test_single with (cost=-15000, threshold=75)
|
||||
; FULLFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15, threshold=75)
|
||||
; FULLFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15015, threshold=75)
|
||||
; FULLFP-DAG: double inlined into test_double with (cost=0, threshold=75)
|
||||
; FULLFP-DAG: double inlined into test_double with (cost=-15000, threshold=75)
|
||||
; FULLFP-DAG: single inlined into test_single with cost=0 (threshold=75)
|
||||
; FULLFP-DAG: single inlined into test_single with cost=-15000 (threshold=75)
|
||||
; FULLFP-DAG: single_cheap inlined into test_single_cheap with cost=-15 (threshold=75)
|
||||
; FULLFP-DAG: single_cheap inlined into test_single_cheap with cost=-15015 (threshold=75)
|
||||
; FULLFP-DAG: double inlined into test_double with cost=0 (threshold=75)
|
||||
; FULLFP-DAG: double inlined into test_double with cost=-15000 (threshold=75)
|
||||
; FULLFP-DAG: single_force_soft not inlined into test_single_force_soft because too costly to inline (cost=125, threshold=75)
|
||||
; FULLFP-DAG: single_force_soft not inlined into test_single_force_soft because too costly to inline (cost=125, threshold=75)
|
||||
|
||||
; SINGLEFP-DAG: single inlined into test_single with (cost=0, threshold=75)
|
||||
; SINGLEFP-DAG: single inlined into test_single with (cost=-15000, threshold=75)
|
||||
; SINGLEFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15, threshold=75)
|
||||
; SINGLEFP-DAG: single_cheap inlined into test_single_cheap with (cost=-15015, threshold=75)
|
||||
; SINGLEFP-DAG: single inlined into test_single with cost=0 (threshold=75)
|
||||
; SINGLEFP-DAG: single inlined into test_single with cost=-15000 (threshold=75)
|
||||
; SINGLEFP-DAG: single_cheap inlined into test_single_cheap with cost=-15 (threshold=75)
|
||||
; SINGLEFP-DAG: single_cheap inlined into test_single_cheap with cost=-15015 (threshold=75)
|
||||
; SINGLEFP-DAG: double not inlined into test_double because too costly to inline (cost=125, threshold=75)
|
||||
; SINGLEFP-DAG: double not inlined into test_double because too costly to inline (cost=125, threshold=75)
|
||||
; SINGLEFP-DAG: single_force_soft not inlined into test_single_force_soft because too costly to inline (cost=125, threshold=75)
|
||||
|
@ -14,7 +14,7 @@
|
||||
; 4 return foo();
|
||||
; 5 }
|
||||
|
||||
; CHECK: remark: /tmp/s.c:4:10: foo inlined into bar with (cost={{[0-9\-]+}}, threshold={{[0-9]+}})
|
||||
; CHECK: remark: /tmp/s.c:4:10: foo inlined into bar with cost={{[0-9\-]+}} (threshold={{[0-9]+}})
|
||||
; THRESHOLD-NOT: remark
|
||||
|
||||
; ModuleID = '/tmp/s.c'
|
||||
|
@ -17,7 +17,7 @@
|
||||
; 4 return foo();
|
||||
; 5 }
|
||||
|
||||
; CHECK: remark: /tmp/s.c:4:10: foo inlined into bar with (cost={{[0-9\-]+}}, threshold={{[0-9]+}}) (hotness: 30)
|
||||
; CHECK: remark: /tmp/s.c:4:10: foo inlined into bar with cost={{[0-9\-]+}} (threshold={{[0-9]+}}) (hotness: 30)
|
||||
|
||||
; YAML: --- !Passed
|
||||
; YAML-NEXT: Pass: inline
|
||||
@ -31,10 +31,9 @@
|
||||
; YAML-NEXT: - String: ' inlined into '
|
||||
; YAML-NEXT: - Caller: bar
|
||||
; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 3, Column: 0 }
|
||||
; YAML-NEXT: - String: ' with '
|
||||
; YAML-NEXT: - String: '(cost='
|
||||
; YAML-NEXT: - String: ' with cost='
|
||||
; YAML-NEXT: - Cost: '{{[0-9\-]+}}'
|
||||
; YAML-NEXT: - String: ', threshold='
|
||||
; YAML-NEXT: - String: ' (threshold='
|
||||
; YAML-NEXT: - Threshold: '{{[0-9]+}}'
|
||||
; YAML-NEXT: - String: ')'
|
||||
; YAML-NEXT: ...
|
||||
|
@ -5,8 +5,8 @@
|
||||
; RUN: -pass-remarks-analysis=inline -pass-remarks-with-hotness -S 2>&1 \
|
||||
; RUN: | FileCheck %s
|
||||
|
||||
; CHECK: foo inlined into bar with (cost=always): always inline attribute (hotness: 30)
|
||||
; CHECK: foz not inlined into bar because it should never be inlined (cost=never): noinline function attribute (hotness: 30)
|
||||
; CHECK: foo inlined into bar with cost=always (hotness: 30)
|
||||
; CHECK: foz not inlined into bar because it should never be inlined (cost=never) (hotness: 30)
|
||||
|
||||
; Function Attrs: alwaysinline nounwind uwtable
|
||||
define i32 @foo() #0 !prof !1 {
|
||||
|
@ -14,8 +14,8 @@
|
||||
|
||||
; HOTNESS: fox will not be inlined into bar because its definition is unavailable
|
||||
; NO_HOTNESS-NOT: fox will not be inlined into bar because its definition is unavailable
|
||||
; CHECK: foo inlined into bar with (cost=always): always inline attribute
|
||||
; CHECK: foz not inlined into bar because it should never be inlined (cost=never): noinline function attribute
|
||||
; CHECK: foo inlined into bar with cost=always
|
||||
; CHECK: foz not inlined into bar because it should never be inlined (cost=never)
|
||||
|
||||
; Function Attrs: alwaysinline nounwind uwtable
|
||||
define i32 @foo(i32 %x, i32 %y) #0 !prof !1 {
|
||||
|
@ -34,8 +34,7 @@
|
||||
; YAML-NEXT: - Callee: f
|
||||
; YAML-NEXT: - String: ' inlined into '
|
||||
; YAML-NEXT: - Caller: _start
|
||||
; YAML-NEXT: - String: ' with '
|
||||
; YAML-NEXT: - String: 'cost='
|
||||
; YAML-NEXT: - String: ' with cost='
|
||||
; YAML-NEXT: - Cost: '0'
|
||||
; YAML-NEXT: - String: ' (threshold='
|
||||
; YAML-NEXT: - Threshold: '337'
|
||||
@ -52,8 +51,7 @@
|
||||
; YAML-HOT-NEXT: - Callee: f
|
||||
; YAML-HOT-NEXT: - String: ' inlined into '
|
||||
; YAML-HOT-NEXT: - Caller: _start
|
||||
; YAML-HOT-NEXT: - String: ' with'
|
||||
; YAML-HOT-NEXT: - String: 'cost='
|
||||
; YAML-HOT-NEXT: - String: ' with cost='
|
||||
; YAML-HOT-NEXT: - Cost: '0'
|
||||
; YAML-HOT-NEXT: - String: ' (threshold='
|
||||
; YAML-HOT-NEXT: - Threshold: '337'
|
||||
|
Loading…
x
Reference in New Issue
Block a user