aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/InlineCost.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/InlineCost.cpp')
-rw-r--r--llvm/lib/Analysis/InlineCost.cpp439
1 files changed, 340 insertions, 99 deletions
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index a35f5e11f0e0..4c2413e14435 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -113,6 +113,10 @@ static cl::opt<int> HotCallSiteRelFreq(
"entry frequency, for a callsite to be hot in the absence of "
"profile information."));
+static cl::opt<int> CallPenalty(
+ "inline-call-penalty", cl::Hidden, cl::init(25),
+ cl::desc("Call penalty that is applied per callsite when inlining"));
+
static cl::opt<bool> OptComputeFullInlineCost(
"inline-cost-full", cl::Hidden, cl::init(false), cl::ZeroOrMore,
cl::desc("Compute the full inline cost of a call site even when the cost "
@@ -390,7 +394,6 @@ protected:
bool visitPtrToInt(PtrToIntInst &I);
bool visitIntToPtr(IntToPtrInst &I);
bool visitCastInst(CastInst &I);
- bool visitUnaryInstruction(UnaryInstruction &I);
bool visitCmpInst(CmpInst &I);
bool visitSub(BinaryOperator &I);
bool visitBinaryOperator(BinaryOperator &I);
@@ -411,19 +414,18 @@ protected:
bool visitUnreachableInst(UnreachableInst &I);
public:
- CallAnalyzer(
- Function &Callee, CallBase &Call, const TargetTransformInfo &TTI,
- function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
- function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
- ProfileSummaryInfo *PSI = nullptr,
- OptimizationRemarkEmitter *ORE = nullptr)
+ CallAnalyzer(Function &Callee, CallBase &Call, const TargetTransformInfo &TTI,
+ function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
+ function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
+ ProfileSummaryInfo *PSI = nullptr,
+ OptimizationRemarkEmitter *ORE = nullptr)
: TTI(TTI), GetAssumptionCache(GetAssumptionCache), GetBFI(GetBFI),
PSI(PSI), F(Callee), DL(F.getParent()->getDataLayout()), ORE(ORE),
CandidateCall(Call), EnableLoadElimination(true) {}
InlineResult analyze();
- Optional<Constant*> getSimplifiedValue(Instruction *I) {
+ Optional<Constant *> getSimplifiedValue(Instruction *I) {
if (SimplifiedValues.find(I) != SimplifiedValues.end())
return SimplifiedValues[I];
return None;
@@ -441,6 +443,25 @@ public:
void dump();
};
+// Considering forming a binary search, we should find the number of nodes
+// which is same as the number of comparisons when lowered. For a given
+// number of clusters, n, we can define a recursive function, f(n), to find
+// the number of nodes in the tree. The recursion is :
+// f(n) = 1 + f(n/2) + f (n - n/2), when n > 3,
+// and f(n) = n, when n <= 3.
+// This will lead a binary tree where the leaf should be either f(2) or f(3)
+// when n > 3. So, the number of comparisons from leaves should be n, while
+// the number of non-leaf should be :
+// 2^(log2(n) - 1) - 1
+// = 2^log2(n) * 2^-1 - 1
+// = n / 2 - 1.
+// Considering comparisons from leaf and non-leaf nodes, we can estimate the
+// number of comparisons in a simple closed form :
+// n + n / 2 - 1 = n * 3 / 2 - 1
+int64_t getExpectedNumberOfCompare(int NumCaseCluster) {
+ return 3 * static_cast<int64_t>(NumCaseCluster) / 2 - 1;
+}
+
/// FIXME: if it is necessary to derive from InlineCostCallAnalyzer, note
/// the FIXME in onLoweredCall, when instantiating an InlineCostCallAnalyzer
class InlineCostCallAnalyzer final : public CallAnalyzer {
@@ -489,6 +510,12 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
// sense that it's not weighted by profile counts at all.
int ColdSize = 0;
+ // Whether inlining is decided by cost-benefit analysis.
+ bool DecidedByCostBenefit = false;
+
+ // The cost-benefit pair computed by cost-benefit analysis.
+ Optional<CostBenefitPair> CostBenefit = None;
+
bool SingleBB = true;
unsigned SROACostSavings = 0;
@@ -514,7 +541,7 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
/// Handle a capped 'int' increment for Cost.
void addCost(int64_t Inc, int64_t UpperBound = INT_MAX) {
assert(UpperBound > 0 && UpperBound <= INT_MAX && "invalid upper bound");
- Cost = (int)std::min(UpperBound, Cost + Inc);
+ Cost = std::min<int>(UpperBound, Cost + Inc);
}
void onDisableSROA(AllocaInst *Arg) override {
@@ -531,7 +558,7 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
addCost(LoadEliminationCost);
LoadEliminationCost = 0;
}
- void onCallPenalty() override { addCost(InlineConstants::CallPenalty); }
+ void onCallPenalty() override { addCost(CallPenalty); }
void onCallArgumentSetup(const CallBase &Call) override {
// Pay the price of the argument setup. We account for the average 1
// instruction per call argument setup here.
@@ -566,7 +593,7 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
}
} else
// Otherwise simply add the cost for merely making the call.
- addCost(InlineConstants::CallPenalty);
+ addCost(CallPenalty);
}
void onFinalizeSwitch(unsigned JumpTableSize,
@@ -575,38 +602,26 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
// branch to destination.
// Maximum valid cost increased in this function.
if (JumpTableSize) {
- int64_t JTCost = (int64_t)JumpTableSize * InlineConstants::InstrCost +
- 4 * InlineConstants::InstrCost;
+ int64_t JTCost =
+ static_cast<int64_t>(JumpTableSize) * InlineConstants::InstrCost +
+ 4 * InlineConstants::InstrCost;
- addCost(JTCost, (int64_t)CostUpperBound);
+ addCost(JTCost, static_cast<int64_t>(CostUpperBound));
return;
}
- // Considering forming a binary search, we should find the number of nodes
- // which is same as the number of comparisons when lowered. For a given
- // number of clusters, n, we can define a recursive function, f(n), to find
- // the number of nodes in the tree. The recursion is :
- // f(n) = 1 + f(n/2) + f (n - n/2), when n > 3,
- // and f(n) = n, when n <= 3.
- // This will lead a binary tree where the leaf should be either f(2) or f(3)
- // when n > 3. So, the number of comparisons from leaves should be n, while
- // the number of non-leaf should be :
- // 2^(log2(n) - 1) - 1
- // = 2^log2(n) * 2^-1 - 1
- // = n / 2 - 1.
- // Considering comparisons from leaf and non-leaf nodes, we can estimate the
- // number of comparisons in a simple closed form :
- // n + n / 2 - 1 = n * 3 / 2 - 1
+
if (NumCaseCluster <= 3) {
// Suppose a comparison includes one compare and one conditional branch.
addCost(NumCaseCluster * 2 * InlineConstants::InstrCost);
return;
}
- int64_t ExpectedNumberOfCompare = 3 * (int64_t)NumCaseCluster / 2 - 1;
+ int64_t ExpectedNumberOfCompare =
+ getExpectedNumberOfCompare(NumCaseCluster);
int64_t SwitchCost =
ExpectedNumberOfCompare * 2 * InlineConstants::InstrCost;
- addCost(SwitchCost, (int64_t)CostUpperBound);
+ addCost(SwitchCost, static_cast<int64_t>(CostUpperBound));
}
void onMissedSimplification() override {
addCost(InlineConstants::InstrCost);
@@ -672,15 +687,22 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
}
bool isCostBenefitAnalysisEnabled() {
- if (!InlineEnableCostBenefitAnalysis)
- return false;
-
if (!PSI || !PSI->hasProfileSummary())
return false;
if (!GetBFI)
return false;
+ if (InlineEnableCostBenefitAnalysis.getNumOccurrences()) {
+ // Honor the explicit request from the user.
+ if (!InlineEnableCostBenefitAnalysis)
+ return false;
+ } else {
+ // Otherwise, require instrumentation profile.
+ if (!PSI->hasInstrumentationProfile())
+ return false;
+ }
+
auto *Caller = CandidateCall.getParent()->getParent();
if (!Caller->getEntryCount())
return false;
@@ -693,7 +715,9 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
if (!PSI->isHotCallSite(CandidateCall, CallerBFI))
return false;
- if (!F.getEntryCount())
+ // Make sure we have a nonzero entry count.
+ auto EntryCount = F.getEntryCount();
+ if (!EntryCount || !EntryCount.getCount())
return false;
BlockFrequencyInfo *CalleeBFI = &(GetBFI(F));
@@ -749,9 +773,6 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
CurrentSavings += InlineConstants::InstrCost;
}
}
- // TODO: Consider other forms of savings like switch statements,
- // indirect calls becoming direct, SROACostSavings, LoadEliminationCost,
- // etc.
}
auto ProfileCount = CalleeBFI->getBlockProfileCount(&BB);
@@ -762,7 +783,7 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
// Compute the cycle savings per call.
auto EntryProfileCount = F.getEntryCount();
- assert(EntryProfileCount.hasValue());
+ assert(EntryProfileCount.hasValue() && EntryProfileCount.getCount());
auto EntryCount = EntryProfileCount.getCount();
CycleSavings += EntryCount / 2;
CycleSavings = CycleSavings.udiv(EntryCount);
@@ -780,6 +801,8 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
// savings threshold.
Size = Size > InlineSizeAllowance ? Size - InlineSizeAllowance : 1;
+ CostBenefit.emplace(APInt(128, Size), CycleSavings);
+
// Return true if the savings justify the cost of inlining. Specifically,
// we evaluate the following inequality:
//
@@ -813,7 +836,7 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
continue;
NumLoops++;
}
- addCost(NumLoops * InlineConstants::CallPenalty);
+ addCost(NumLoops * InlineConstants::LoopPenalty);
}
// We applied the maximum possible vector bonus at the beginning. Now,
@@ -825,6 +848,7 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
Threshold -= VectorBonus / 2;
if (auto Result = costBenefitAnalysis()) {
+ DecidedByCostBenefit = true;
if (Result.getValue())
return InlineResult::success();
else
@@ -924,9 +948,213 @@ public:
}
virtual ~InlineCostCallAnalyzer() {}
- int getThreshold() { return Threshold; }
- int getCost() { return Cost; }
+ int getThreshold() const { return Threshold; }
+ int getCost() const { return Cost; }
+ Optional<CostBenefitPair> getCostBenefitPair() { return CostBenefit; }
+ bool wasDecidedByCostBenefit() const { return DecidedByCostBenefit; }
+};
+
+class InlineCostFeaturesAnalyzer final : public CallAnalyzer {
+private:
+ InlineCostFeatures Cost = {};
+
+ // FIXME: These constants are taken from the heuristic-based cost visitor.
+ // These should be removed entirely in a later revision to avoid reliance on
+ // heuristics in the ML inliner.
+ static constexpr int JTCostMultiplier = 4;
+ static constexpr int CaseClusterCostMultiplier = 2;
+ static constexpr int SwitchCostMultiplier = 2;
+
+ // FIXME: These are taken from the heuristic-based cost visitor: we should
+ // eventually abstract these to the CallAnalyzer to avoid duplication.
+ unsigned SROACostSavingOpportunities = 0;
+ int VectorBonus = 0;
+ int SingleBBBonus = 0;
+ int Threshold = 5;
+
+ DenseMap<AllocaInst *, unsigned> SROACosts;
+
+ void increment(InlineCostFeatureIndex Feature, int64_t Delta = 1) {
+ Cost[static_cast<size_t>(Feature)] += Delta;
+ }
+
+ void set(InlineCostFeatureIndex Feature, int64_t Value) {
+ Cost[static_cast<size_t>(Feature)] = Value;
+ }
+
+ void onDisableSROA(AllocaInst *Arg) override {
+ auto CostIt = SROACosts.find(Arg);
+ if (CostIt == SROACosts.end())
+ return;
+
+ increment(InlineCostFeatureIndex::SROALosses, CostIt->second);
+ SROACostSavingOpportunities -= CostIt->second;
+ SROACosts.erase(CostIt);
+ }
+
+ void onDisableLoadElimination() override {
+ set(InlineCostFeatureIndex::LoadElimination, 1);
+ }
+
+ void onCallPenalty() override {
+ increment(InlineCostFeatureIndex::CallPenalty, CallPenalty);
+ }
+
+ void onCallArgumentSetup(const CallBase &Call) override {
+ increment(InlineCostFeatureIndex::CallArgumentSetup,
+ Call.arg_size() * InlineConstants::InstrCost);
+ }
+
+ void onLoadRelativeIntrinsic() override {
+ increment(InlineCostFeatureIndex::LoadRelativeIntrinsic,
+ 3 * InlineConstants::InstrCost);
+ }
+
+ void onLoweredCall(Function *F, CallBase &Call,
+ bool IsIndirectCall) override {
+ increment(InlineCostFeatureIndex::LoweredCallArgSetup,
+ Call.arg_size() * InlineConstants::InstrCost);
+
+ if (IsIndirectCall) {
+ InlineParams IndirectCallParams = {/* DefaultThreshold*/ 0,
+ /*HintThreshold*/ {},
+ /*ColdThreshold*/ {},
+ /*OptSizeThreshold*/ {},
+ /*OptMinSizeThreshold*/ {},
+ /*HotCallSiteThreshold*/ {},
+ /*LocallyHotCallSiteThreshold*/ {},
+ /*ColdCallSiteThreshold*/ {},
+ /*ComputeFullInlineCost*/ true,
+ /*EnableDeferral*/ true};
+ IndirectCallParams.DefaultThreshold =
+ InlineConstants::IndirectCallThreshold;
+
+ InlineCostCallAnalyzer CA(*F, Call, IndirectCallParams, TTI,
+ GetAssumptionCache, GetBFI, PSI, ORE, false,
+ true);
+ if (CA.analyze().isSuccess()) {
+ increment(InlineCostFeatureIndex::NestedInlineCostEstimate,
+ CA.getCost());
+ increment(InlineCostFeatureIndex::NestedInlines, 1);
+ }
+ } else {
+ onCallPenalty();
+ }
+ }
+
+ void onFinalizeSwitch(unsigned JumpTableSize,
+ unsigned NumCaseCluster) override {
+
+ if (JumpTableSize) {
+ int64_t JTCost =
+ static_cast<int64_t>(JumpTableSize) * InlineConstants::InstrCost +
+ JTCostMultiplier * InlineConstants::InstrCost;
+ increment(InlineCostFeatureIndex::JumpTablePenalty, JTCost);
+ return;
+ }
+
+ if (NumCaseCluster <= 3) {
+ increment(InlineCostFeatureIndex::CaseClusterPenalty,
+ NumCaseCluster * CaseClusterCostMultiplier *
+ InlineConstants::InstrCost);
+ return;
+ }
+
+ int64_t ExpectedNumberOfCompare =
+ getExpectedNumberOfCompare(NumCaseCluster);
+
+ int64_t SwitchCost = ExpectedNumberOfCompare * SwitchCostMultiplier *
+ InlineConstants::InstrCost;
+ increment(InlineCostFeatureIndex::SwitchPenalty, SwitchCost);
+ }
+
+ void onMissedSimplification() override {
+ increment(InlineCostFeatureIndex::UnsimplifiedCommonInstructions,
+ InlineConstants::InstrCost);
+ }
+
+ void onInitializeSROAArg(AllocaInst *Arg) override { SROACosts[Arg] = 0; }
+ void onAggregateSROAUse(AllocaInst *Arg) override {
+ SROACosts.find(Arg)->second += InlineConstants::InstrCost;
+ SROACostSavingOpportunities += InlineConstants::InstrCost;
+ }
+
+ void onBlockAnalyzed(const BasicBlock *BB) override {
+ if (BB->getTerminator()->getNumSuccessors() > 1)
+ set(InlineCostFeatureIndex::IsMultipleBlocks, 1);
+ Threshold -= SingleBBBonus;
+ }
+
+ InlineResult finalizeAnalysis() override {
+ auto *Caller = CandidateCall.getFunction();
+ if (Caller->hasMinSize()) {
+ DominatorTree DT(F);
+ LoopInfo LI(DT);
+ for (Loop *L : LI) {
+ // Ignore loops that will not be executed
+ if (DeadBlocks.count(L->getHeader()))
+ continue;
+ increment(InlineCostFeatureIndex::NumLoops,
+ InlineConstants::LoopPenalty);
+ }
+ }
+ set(InlineCostFeatureIndex::DeadBlocks, DeadBlocks.size());
+ set(InlineCostFeatureIndex::SimplifiedInstructions,
+ NumInstructionsSimplified);
+ set(InlineCostFeatureIndex::ConstantArgs, NumConstantArgs);
+ set(InlineCostFeatureIndex::ConstantOffsetPtrArgs,
+ NumConstantOffsetPtrArgs);
+ set(InlineCostFeatureIndex::SROASavings, SROACostSavingOpportunities);
+
+ if (NumVectorInstructions <= NumInstructions / 10)
+ Threshold -= VectorBonus;
+ else if (NumVectorInstructions <= NumInstructions / 2)
+ Threshold -= VectorBonus / 2;
+
+ set(InlineCostFeatureIndex::Threshold, Threshold);
+
+ return InlineResult::success();
+ }
+
+ bool shouldStop() override { return false; }
+
+ void onLoadEliminationOpportunity() override {
+ increment(InlineCostFeatureIndex::LoadElimination, 1);
+ }
+
+ InlineResult onAnalysisStart() override {
+ increment(InlineCostFeatureIndex::CallSiteCost,
+ -1 * getCallsiteCost(this->CandidateCall, DL));
+
+ set(InlineCostFeatureIndex::ColdCcPenalty,
+ (F.getCallingConv() == CallingConv::Cold));
+
+ // FIXME: we shouldn't repeat this logic in both the Features and Cost
+ // analyzer - instead, we should abstract it to a common method in the
+ // CallAnalyzer
+ int SingleBBBonusPercent = 50;
+ int VectorBonusPercent = TTI.getInlinerVectorBonusPercent();
+ Threshold += TTI.adjustInliningThreshold(&CandidateCall);
+ Threshold *= TTI.getInliningThresholdMultiplier();
+ SingleBBBonus = Threshold * SingleBBBonusPercent / 100;
+ VectorBonus = Threshold * VectorBonusPercent / 100;
+ Threshold += (SingleBBBonus + VectorBonus);
+
+ return InlineResult::success();
+ }
+
+public:
+ InlineCostFeaturesAnalyzer(
+ const TargetTransformInfo &TTI,
+ function_ref<AssumptionCache &(Function &)> &GetAssumptionCache,
+ function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
+ ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE, Function &Callee,
+ CallBase &Call)
+ : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, PSI) {}
+
+ const InlineCostFeatures &features() const { return Cost; }
};
+
} // namespace
/// Test whether the given value is an Alloca-derived function argument.
@@ -940,8 +1168,8 @@ void CallAnalyzer::disableSROAForArg(AllocaInst *SROAArg) {
disableLoadElimination();
}
-void InlineCostAnnotationWriter::emitInstructionAnnot(const Instruction *I,
- formatted_raw_ostream &OS) {
+void InlineCostAnnotationWriter::emitInstructionAnnot(
+ const Instruction *I, formatted_raw_ostream &OS) {
// The cost of inlining of the given instruction is printed always.
// The threshold delta is printed only when it is non-zero. It happens
// when we decided to give a bonus at a particular instruction.
@@ -1023,12 +1251,14 @@ bool CallAnalyzer::isGEPFree(GetElementPtrInst &GEP) {
Operands.push_back(SimpleOp);
else
Operands.push_back(Op);
- return TargetTransformInfo::TCC_Free ==
- TTI.getUserCost(&GEP, Operands,
- TargetTransformInfo::TCK_SizeAndLatency);
+ return TTI.getUserCost(&GEP, Operands,
+ TargetTransformInfo::TCK_SizeAndLatency) ==
+ TargetTransformInfo::TCC_Free;
}
bool CallAnalyzer::visitAlloca(AllocaInst &I) {
+ disableSROA(I.getOperand(0));
+
// Check whether inlining will turn a dynamic alloca into a static
// alloca and handle that case.
if (I.isArrayAllocation()) {
@@ -1044,13 +1274,11 @@ bool CallAnalyzer::visitAlloca(AllocaInst &I) {
// is needed to track stack usage during inlining.
Type *Ty = I.getAllocatedType();
AllocatedSize = SaturatingMultiplyAdd(
- AllocSize->getLimitedValue(), DL.getTypeAllocSize(Ty).getKnownMinSize(),
- AllocatedSize);
- if (AllocatedSize > InlineConstants::MaxSimplifiedDynamicAllocaToInline) {
+ AllocSize->getLimitedValue(),
+ DL.getTypeAllocSize(Ty).getKnownMinSize(), AllocatedSize);
+ if (AllocatedSize > InlineConstants::MaxSimplifiedDynamicAllocaToInline)
HasDynamicAlloca = true;
- return false;
- }
- return Base::visitAlloca(I);
+ return false;
}
}
@@ -1061,15 +1289,13 @@ bool CallAnalyzer::visitAlloca(AllocaInst &I) {
SaturatingAdd(DL.getTypeAllocSize(Ty).getKnownMinSize(), AllocatedSize);
}
- // We will happily inline static alloca instructions.
- if (I.isStaticAlloca())
- return Base::visitAlloca(I);
-
// FIXME: This is overly conservative. Dynamic allocas are inefficient for
// a variety of reasons, and so we would like to not inline them into
// functions which don't currently have a dynamic alloca. This simply
// disables inlining altogether in the presence of a dynamic alloca.
- HasDynamicAlloca = true;
+ if (!I.isStaticAlloca())
+ HasDynamicAlloca = true;
+
return false;
}
@@ -1202,11 +1428,11 @@ bool CallAnalyzer::visitGetElementPtr(GetElementPtrInst &I) {
if (!DisableGEPConstOperand)
if (simplifyInstruction(I, [&](SmallVectorImpl<Constant *> &COps) {
- SmallVector<Constant *, 2> Indices;
- for (unsigned int Index = 1 ; Index < COps.size() ; ++Index)
+ SmallVector<Constant *, 2> Indices;
+ for (unsigned int Index = 1; Index < COps.size(); ++Index)
Indices.push_back(COps[Index]);
- return ConstantExpr::getGetElementPtr(I.getSourceElementType(), COps[0],
- Indices, I.isInBounds());
+ return ConstantExpr::getGetElementPtr(
+ I.getSourceElementType(), COps[0], Indices, I.isInBounds());
}))
return true;
@@ -1295,8 +1521,8 @@ bool CallAnalyzer::visitPtrToInt(PtrToIntInst &I) {
if (auto *SROAArg = getSROAArgForValueOrNull(I.getOperand(0)))
SROAArgValues[&I] = SROAArg;
- return TargetTransformInfo::TCC_Free ==
- TTI.getUserCost(&I, TargetTransformInfo::TCK_SizeAndLatency);
+ return TTI.getUserCost(&I, TargetTransformInfo::TCK_SizeAndLatency) ==
+ TargetTransformInfo::TCC_Free;
}
bool CallAnalyzer::visitIntToPtr(IntToPtrInst &I) {
@@ -1320,8 +1546,8 @@ bool CallAnalyzer::visitIntToPtr(IntToPtrInst &I) {
if (auto *SROAArg = getSROAArgForValueOrNull(Op))
SROAArgValues[&I] = SROAArg;
- return TargetTransformInfo::TCC_Free ==
- TTI.getUserCost(&I, TargetTransformInfo::TCK_SizeAndLatency);
+ return TTI.getUserCost(&I, TargetTransformInfo::TCK_SizeAndLatency) ==
+ TargetTransformInfo::TCC_Free;
}
bool CallAnalyzer::visitCastInst(CastInst &I) {
@@ -1352,21 +1578,8 @@ bool CallAnalyzer::visitCastInst(CastInst &I) {
break;
}
- return TargetTransformInfo::TCC_Free ==
- TTI.getUserCost(&I, TargetTransformInfo::TCK_SizeAndLatency);
-}
-
-bool CallAnalyzer::visitUnaryInstruction(UnaryInstruction &I) {
- Value *Operand = I.getOperand(0);
- if (simplifyInstruction(I, [&](SmallVectorImpl<Constant *> &COps) {
- return ConstantFoldInstOperands(&I, COps[0], DL);
- }))
- return true;
-
- // Disable any SROA on the argument to arbitrary unary instructions.
- disableSROA(Operand);
-
- return false;
+ return TTI.getUserCost(&I, TargetTransformInfo::TCK_SizeAndLatency) ==
+ TargetTransformInfo::TCC_Free;
}
bool CallAnalyzer::paramHasAttr(Argument *A, Attribute::AttrKind Attr) {
@@ -1577,10 +1790,11 @@ void InlineCostCallAnalyzer::updateThreshold(CallBase &Call, Function &Callee) {
}
}
+ Threshold += TTI.adjustInliningThreshold(&Call);
+
// Finally, take the target-specific inlining threshold multiplier into
// account.
Threshold *= TTI.getInliningThresholdMultiplier();
- Threshold += TTI.adjustInliningThreshold(&Call);
SingleBBBonus = Threshold * SingleBBBonusPercent / 100;
VectorBonus = Threshold * VectorBonusPercent / 100;
@@ -1763,8 +1977,8 @@ bool CallAnalyzer::visitExtractValue(ExtractValueInst &I) {
}))
return true;
- // SROA can look through these but give them a cost.
- return false;
+ // SROA can't look through these, but they may be free.
+ return Base::visitExtractValue(I);
}
bool CallAnalyzer::visitInsertValue(InsertValueInst &I) {
@@ -1776,8 +1990,8 @@ bool CallAnalyzer::visitInsertValue(InsertValueInst &I) {
}))
return true;
- // SROA can look through these but give them a cost.
- return false;
+ // SROA can't look through these, but they may be free.
+ return Base::visitInsertValue(I);
}
/// Try to simplify a call site.
@@ -1872,6 +2086,11 @@ bool CallAnalyzer::visitCallBase(CallBase &Call) {
case Intrinsic::vastart:
InitsVargArgs = true;
return false;
+ case Intrinsic::launder_invariant_group:
+ case Intrinsic::strip_invariant_group:
+ if (auto *SROAArg = getSROAArgForValueOrNull(II->getOperand(0)))
+ SROAArgValues[II] = SROAArg;
+ return true;
}
}
@@ -1948,9 +2167,9 @@ bool CallAnalyzer::visitSelectInst(SelectInst &SI) {
}
// Select condition is a constant.
- Value *SelectedV = CondC->isAllOnesValue()
- ? TrueVal
- : (CondC->isNullValue()) ? FalseVal : nullptr;
+ Value *SelectedV = CondC->isAllOnesValue() ? TrueVal
+ : (CondC->isNullValue()) ? FalseVal
+ : nullptr;
if (!SelectedV) {
// Condition is a vector constant that is not all 1s or all 0s. If all
// operands are constants, ConstantExpr::getSelect() can handle the cases
@@ -2002,7 +2221,7 @@ bool CallAnalyzer::visitSwitchInst(SwitchInst &SI) {
// proportional to the size of the tree or the size of jump table range.
//
// NB: We convert large switches which are just used to initialize large phi
- // nodes to lookup tables instead in simplify-cfg, so this shouldn't prevent
+ // nodes to lookup tables instead in simplifycfg, so this shouldn't prevent
// inlining those. It will prevent inlining in cases where the optimization
// does not (yet) fire.
@@ -2056,8 +2275,8 @@ bool CallAnalyzer::visitUnreachableInst(UnreachableInst &I) {
bool CallAnalyzer::visitInstruction(Instruction &I) {
// Some instructions are free. All of the free intrinsics can also be
// handled by SROA, etc.
- if (TargetTransformInfo::TCC_Free ==
- TTI.getUserCost(&I, TargetTransformInfo::TCK_SizeAndLatency))
+ if (TTI.getUserCost(&I, TargetTransformInfo::TCK_SizeAndLatency) ==
+ TargetTransformInfo::TCC_Free)
return true;
// We found something we don't understand or can't handle. Mark any SROA-able
@@ -2415,9 +2634,7 @@ void InlineCostCallAnalyzer::print() {
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// Dump stats about this call's analysis.
-LLVM_DUMP_METHOD void InlineCostCallAnalyzer::dump() {
- print();
-}
+LLVM_DUMP_METHOD void InlineCostCallAnalyzer::dump() { print(); }
#endif
/// Test that there are no attribute conflicts between Caller and Callee
@@ -2443,7 +2660,7 @@ int llvm::getCallsiteCost(CallBase &Call, const DataLayout &DL) {
// We approximate the number of loads and stores needed by dividing the
// size of the byval type by the target's pointer size.
PointerType *PTy = cast<PointerType>(Call.getArgOperand(I)->getType());
- unsigned TypeSize = DL.getTypeSizeInBits(PTy->getElementType());
+ unsigned TypeSize = DL.getTypeSizeInBits(Call.getParamByValType(I));
unsigned AS = PTy->getAddressSpace();
unsigned PointerSize = DL.getPointerSizeInBits(AS);
// Ceiling division.
@@ -2465,7 +2682,7 @@ int llvm::getCallsiteCost(CallBase &Call, const DataLayout &DL) {
}
}
// The call instruction also disappears after inlining.
- Cost += InlineConstants::InstrCost + InlineConstants::CallPenalty;
+ Cost += InlineConstants::InstrCost + CallPenalty;
return Cost;
}
@@ -2504,6 +2721,19 @@ Optional<int> llvm::getInliningCostEstimate(
return CA.getCost();
}
+Optional<InlineCostFeatures> llvm::getInliningCostFeatures(
+ CallBase &Call, TargetTransformInfo &CalleeTTI,
+ function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
+ function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
+ ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
+ InlineCostFeaturesAnalyzer CFA(CalleeTTI, GetAssumptionCache, GetBFI, PSI,
+ ORE, *Call.getCalledFunction(), Call);
+ auto R = CFA.analyze();
+ if (!R.isSuccess())
+ return None;
+ return CFA.features();
+}
+
Optional<InlineResult> llvm::getAttributeBasedInliningDecision(
CallBase &Call, Function *Callee, TargetTransformInfo &CalleeTTI,
function_ref<const TargetLibraryInfo &(Function &)> GetTLI) {
@@ -2608,6 +2838,17 @@ InlineCost llvm::getInlineCost(
LLVM_DEBUG(CA.dump());
+ // Always make cost benefit based decision explicit.
+ // We use always/never here since threshold is not meaningful,
+ // as it's not what drives cost-benefit analysis.
+ if (CA.wasDecidedByCostBenefit()) {
+ if (ShouldInline.isSuccess())
+ return InlineCost::getAlways("benefit over cost",
+ CA.getCostBenefitPair());
+ else
+ return InlineCost::getNever("cost over benefit", CA.getCostBenefitPair());
+ }
+
// Check if there was a reason to force inlining or no inlining.
if (!ShouldInline.isSuccess() && CA.getCost() < CA.getThreshold())
return InlineCost::getNever(ShouldInline.getFailureReason());
@@ -2761,8 +3002,8 @@ PreservedAnalyses
InlineCostAnnotationPrinterPass::run(Function &F,
FunctionAnalysisManager &FAM) {
PrintInstructionComments = true;
- std::function<AssumptionCache &(Function &)> GetAssumptionCache = [&](
- Function &F) -> AssumptionCache & {
+ std::function<AssumptionCache &(Function &)> GetAssumptionCache =
+ [&](Function &F) -> AssumptionCache & {
return FAM.getResult<AssumptionAnalysis>(F);
};
Module *M = F.getParent();