summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Analysis/InlineCost.h35
-rw-r--r--include/llvm/IR/DiagnosticInfo.h1
-rw-r--r--include/llvm/Transforms/Utils/Cloning.h18
-rw-r--r--lib/Analysis/InlineCost.cpp93
-rw-r--r--lib/Target/AMDGPU/AMDGPUInline.cpp17
-rw-r--r--lib/Transforms/IPO/AlwaysInliner.cpp4
-rw-r--r--lib/Transforms/IPO/Inliner.cpp120
-rw-r--r--lib/Transforms/Utils/InlineFunction.cpp29
-rw-r--r--test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll7
-rw-r--r--test/LTO/Resolution/X86/diagnostic-handler-remarks.ll5
-rw-r--r--test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll5
-rw-r--r--test/LTO/X86/diagnostic-handler-remarks.ll5
-rw-r--r--test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll10
-rw-r--r--test/ThinLTO/X86/diagnostic-handler-remarks.ll10
-rw-r--r--test/Transforms/Inline/ARM/inline-fp.ll24
-rw-r--r--test/Transforms/Inline/optimization-remarks-hotness-threshold.ll2
-rw-r--r--test/Transforms/Inline/optimization-remarks-passed-yaml.ll7
-rw-r--r--test/Transforms/Inline/optimization-remarks-with-hotness.ll4
-rw-r--r--test/Transforms/Inline/optimization-remarks.ll4
-rw-r--r--test/tools/gold/X86/opt-remarks.ll6
20 files changed, 244 insertions, 162 deletions
diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h
index 8c412057fb8..529fb75bec9 100644
--- a/include/llvm/Analysis/InlineCost.h
+++ b/include/llvm/Analysis/InlineCost.h
@@ -74,8 +74,15 @@ 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) : Cost(Cost), Threshold(Threshold) {}
+ 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");
+ }
public:
static InlineCost get(int Cost, int Threshold) {
@@ -83,11 +90,11 @@ public:
assert(Cost < NeverInlineCost && "Cost crosses sentinel value");
return InlineCost(Cost, Threshold);
}
- static InlineCost getAlways() {
- return InlineCost(AlwaysInlineCost, 0);
+ static InlineCost getAlways(const char *Reason) {
+ return InlineCost(AlwaysInlineCost, 0, Reason);
}
- static InlineCost getNever() {
- return InlineCost(NeverInlineCost, 0);
+ static InlineCost getNever(const char *Reason) {
+ return InlineCost(NeverInlineCost, 0, Reason);
}
/// Test whether the inline cost is low enough for inlining.
@@ -112,12 +119,30 @@ 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
diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h
index 81d4ae84bf0..b8fdae2fcad 100644
--- a/include/llvm/IR/DiagnosticInfo.h
+++ b/include/llvm/IR/DiagnosticInfo.h
@@ -414,6 +414,7 @@ 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);
diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h
index 7531fb2d69b..e4d6053b70b 100644
--- a/include/llvm/Transforms/Utils/Cloning.h
+++ b/include/llvm/Transforms/Utils/Cloning.h
@@ -22,6 +22,7 @@
#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"
@@ -232,13 +233,16 @@ 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.
-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);
+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);
/// Clones a loop \p OrigLoop. Returns the loop and the blocks in \p
/// Blocks.
diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp
index a6cccc3b591..1d879f8aee9 100644
--- a/lib/Analysis/InlineCost.cpp
+++ b/lib/Analysis/InlineCost.cpp
@@ -227,7 +227,8 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
BlockFrequencyInfo *CallerBFI);
// Custom analysis routines.
- bool analyzeBlock(BasicBlock *BB, SmallPtrSetImpl<const Value *> &EphValues);
+ InlineResult 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.
@@ -290,7 +291,7 @@ public:
NumInstructionsSimplified(0), SROACostSavings(0),
SROACostSavingsLost(0) {}
- bool analyzeCall(CallSite CS);
+ InlineResult analyzeCall(CallSite CS);
int getThreshold() { return Threshold; }
int getCost() { return Cost; }
@@ -1541,8 +1542,9 @@ 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.
-bool CallAnalyzer::analyzeBlock(BasicBlock *BB,
- SmallPtrSetImpl<const Value *> &EphValues) {
+InlineResult
+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,
@@ -1574,16 +1576,29 @@ bool CallAnalyzer::analyzeBlock(BasicBlock *BB,
using namespace ore;
// If the visit this instruction detected an uninlinable pattern, abort.
- if (IsRecursiveCall || ExposesReturnsTwice || HasDynamicAlloca ||
- HasIndirectBr || HasUninlineableIntrinsic || UsesVarArgs) {
+ 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 (ORE)
ORE->emit([&]() {
return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline",
CandidateCS.getInstruction())
- << NV("Callee", &F)
- << " has uninlinable pattern and cost is not fully computed";
+ << NV("Callee", &F) << " has uninlinable pattern ("
+ << NV("InlineResult", IR.message)
+ << ") and cost is not fully computed";
});
- return false;
+ return IR;
}
// If the caller is a recursive function then we don't want to inline
@@ -1591,15 +1606,15 @@ bool 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 recursive and allocates too much stack space. Cost is "
- "not fully computed";
+ << NV("Callee", &F) << " is " << NV("InlineResult", IR.message)
+ << ". Cost is not fully computed";
});
- return false;
+ return IR;
}
// Check if we've past the maximum possible threshold so we don't spin in
@@ -1695,7 +1710,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.
-bool CallAnalyzer::analyzeCall(CallSite CS) {
+InlineResult CallAnalyzer::analyzeCall(CallSite CS) {
++NumCallsAnalyzed;
// Perform some tweaks to the cost and threshold based on the direct
@@ -1730,7 +1745,7 @@ bool CallAnalyzer::analyzeCall(CallSite CS) {
// Check if we're done. This can happen due to bonuses and penalties.
if (Cost >= Threshold && !ComputeFullInlineCost)
- return false;
+ return "high cost";
if (F.empty())
return true;
@@ -1809,12 +1824,13 @@ bool 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 false;
+ return "blockaddress";
// Analyze the cost of this block. If we blow through the threshold, this
// returns false, and we can bail on out.
- if (!analyzeBlock(BB, EphValues))
- return false;
+ InlineResult IR = analyzeBlock(BB, EphValues);
+ if (!IR)
+ return IR;
TerminatorInst *TI = BB->getTerminator();
@@ -1867,7 +1883,7 @@ bool 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 false;
+ return "noduplicate";
// We applied the maximum possible vector bonus at the beginning. Now,
// subtract the excess bonus, if any, from the Threshold before
@@ -1961,7 +1977,7 @@ InlineCost llvm::getInlineCost(
// Cannot inline indirect calls.
if (!Callee)
- return llvm::InlineCost::getNever();
+ return llvm::InlineCost::getNever("indirect call");
// 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
@@ -1973,54 +1989,59 @@ InlineCost llvm::getInlineCost(
if (CS.isByValArgument(I)) {
PointerType *PTy = cast<PointerType>(CS.getArgument(I)->getType());
if (PTy->getAddressSpace() != AllocaAS)
- return llvm::InlineCost::getNever();
+ return llvm::InlineCost::getNever("byval arguments without alloca"
+ " address space");
}
// Calls to functions with always-inline attributes should be inlined
// whenever possible.
if (CS.hasFnAttr(Attribute::AlwaysInline)) {
if (isInlineViable(*Callee))
- return llvm::InlineCost::getAlways();
- return llvm::InlineCost::getNever();
+ return llvm::InlineCost::getAlways("always inline attribute");
+ return llvm::InlineCost::getNever("inapplicable always inline attribute");
}
// 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();
+ return llvm::InlineCost::getNever("conflicting attributes");
// Don't inline this call if the caller has the optnone attribute.
if (Caller->hasFnAttribute(Attribute::OptimizeNone))
- return llvm::InlineCost::getNever();
+ return llvm::InlineCost::getNever("optnone attribute");
// 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();
+ return llvm::InlineCost::getNever("nullptr definitions incompatible");
+
+ // 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 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();
+ // Don't inline call sites marked noinline.
+ if (CS.isNoInline())
+ return llvm::InlineCost::getNever("noinline call site attribute");
LLVM_DEBUG(llvm::dbgs() << " Analyzing call of " << Callee->getName()
<< "... (caller:" << Caller->getName() << ")\n");
CallAnalyzer CA(CalleeTTI, GetAssumptionCache, GetBFI, PSI, ORE, *Callee, CS,
Params);
- bool ShouldInline = CA.analyzeCall(CS);
+ InlineResult 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();
+ return InlineCost::getNever(ShouldInline.message);
if (ShouldInline && CA.getCost() >= CA.getThreshold())
- return InlineCost::getAlways();
+ return InlineCost::getAlways("empty function");
return llvm::InlineCost::get(CA.getCost(), CA.getThreshold());
}
diff --git a/lib/Target/AMDGPU/AMDGPUInline.cpp b/lib/Target/AMDGPU/AMDGPUInline.cpp
index 35dd9eb0a47..7060ff353f4 100644
--- a/lib/Target/AMDGPU/AMDGPUInline.cpp
+++ b/lib/Target/AMDGPU/AMDGPUInline.cpp
@@ -174,18 +174,23 @@ InlineCost AMDGPUInliner::getInlineCost(CallSite CS) {
Function *Caller = CS.getCaller();
TargetTransformInfo &TTI = TTIWP->getTTI(*Callee);
- if (!Callee || Callee->isDeclaration() || CS.isNoInline() ||
- !TTI.areInlineCompatible(Caller, Callee))
- return llvm::InlineCost::getNever();
+ 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 (CS.hasFnAttr(Attribute::AlwaysInline)) {
if (isInlineViable(*Callee))
- return llvm::InlineCost::getAlways();
- return llvm::InlineCost::getNever();
+ return llvm::InlineCost::getAlways("alwaysinline viable");
+ return llvm::InlineCost::getNever("alwaysinline unviable");
}
if (isWrapperOnlyCall(CS))
- return llvm::InlineCost::getAlways();
+ return llvm::InlineCost::getAlways("wrapper-only call");
InlineParams LocalParams = Params;
LocalParams.DefaultThreshold = (int)getInlineThreshold(CS);
diff --git a/lib/Transforms/IPO/AlwaysInliner.cpp b/lib/Transforms/IPO/AlwaysInliner.cpp
index 3b735ddd192..07138718ce2 100644
--- a/lib/Transforms/IPO/AlwaysInliner.cpp
+++ b/lib/Transforms/IPO/AlwaysInliner.cpp
@@ -150,7 +150,7 @@ InlineCost AlwaysInlinerLegacyPass::getInlineCost(CallSite CS) {
// declarations.
if (Callee && !Callee->isDeclaration() &&
CS.hasFnAttr(Attribute::AlwaysInline) && isInlineViable(*Callee))
- return InlineCost::getAlways();
+ return InlineCost::getAlways("always inliner");
- return InlineCost::getNever();
+ return InlineCost::getNever("always inliner");
}
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp
index 3da0c2e83eb..fdf47b7bd62 100644
--- a/lib/Transforms/IPO/Inliner.cpp
+++ b/lib/Transforms/IPO/Inliner.cpp
@@ -64,6 +64,7 @@
#include <algorithm>
#include <cassert>
#include <functional>
+#include <sstream>
#include <tuple>
#include <utility>
#include <vector>
@@ -275,8 +276,9 @@ static bool InlineCallIfPossible(
// Try to inline the function. Get the list of static allocas that were
// inlined.
- if (!InlineFunction(CS, IFI, &AAR, InsertLifetime))
- return false;
+ InlineResult IR = InlineFunction(CS, IFI, &AAR, InsertLifetime);
+ if (!IR)
+ return IR;
if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No)
ImportedFunctionsStats.recordInline(*Caller, *Callee);
@@ -286,7 +288,7 @@ static bool InlineCallIfPossible(
if (!DisableInlinedAllocaMerging)
mergeInlinedArrayAllocas(Caller, IFI, InlinedArrayAllocas, InlineHistory);
- return true;
+ return IR; // success
}
/// Return true if inlining of CS can block the caller from being
@@ -365,6 +367,33 @@ 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.
@@ -379,35 +408,32 @@ shouldInline(CallSite CS, function_ref<InlineCost(CallSite CS)> GetInlineCost,
Function *Caller = CS.getCaller();
if (IC.isAlways()) {
- LLVM_DEBUG(dbgs() << " Inlining: cost=always"
+ LLVM_DEBUG(dbgs() << " Inlining " << inlineCostStr(IC)
<< ", Call: " << *CS.getInstruction() << "\n");
return IC;
}
if (IC.isNever()) {
- LLVM_DEBUG(dbgs() << " NOT Inlining: cost=never"
+ LLVM_DEBUG(dbgs() << " NOT Inlining " << inlineCostStr(IC)
<< ", 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 (cost=never)";
+ << NV("Caller", Caller) << " because it should never be inlined "
+ << IC;
});
- return None;
+ return IC;
}
if (!IC) {
- LLVM_DEBUG(dbgs() << " NOT Inlining: cost=" << IC.getCost()
- << ", thres=" << IC.getThreshold()
+ LLVM_DEBUG(dbgs() << " NOT Inlining " << inlineCostStr(IC)
<< ", 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 (cost="
- << NV("Cost", IC.getCost())
- << ", threshold=" << NV("Threshold", IC.getThreshold()) << ")";
+ << NV("Caller", Caller) << " because too costly to inline " << IC;
});
- return None;
+ return IC;
}
int TotalSecondaryCost = 0;
@@ -428,8 +454,7 @@ shouldInline(CallSite CS, function_ref<InlineCost(CallSite CS)> GetInlineCost,
return None;
}
- LLVM_DEBUG(dbgs() << " Inlining: cost=" << IC.getCost()
- << ", thres=" << IC.getThreshold()
+ LLVM_DEBUG(dbgs() << " Inlining " << inlineCostStr(IC)
<< ", Call: " << *CS.getInstruction() << '\n');
return IC;
}
@@ -461,6 +486,18 @@ 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,
@@ -585,8 +622,9 @@ 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)
+ if (!OIC || !*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
@@ -606,34 +644,21 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
// Attempt to inline the function.
using namespace ore;
- if (!InlineCallIfPossible(CS, InlineInfo, InlinedArrayAllocas,
- InlineHistoryID, InsertLifetime, AARGetter,
- ImportedFunctionsStats)) {
+ InlineResult IR = InlineCallIfPossible(
+ CS, InlineInfo, InlinedArrayAllocas, InlineHistoryID,
+ InsertLifetime, AARGetter, ImportedFunctionsStats);
+ if (!IR) {
ORE.emit([&]() {
return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc,
Block)
<< NV("Callee", Callee) << " will not be inlined into "
- << NV("Caller", Caller);
+ << NV("Caller", Caller) << ": " << NV("Reason", IR.message);
});
continue;
}
++NumInlined;
- 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;
- });
+ emit_inlined_into(ORE, DLoc, Block, *Callee, *Caller, *OIC);
// If inlining this function gave us any new call sites, throw them
// onto our worklist to process. They are useful inline candidates.
@@ -971,7 +996,7 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
Optional<InlineCost> OIC = shouldInline(CS, GetInlineCost, ORE);
// Check whether we want to inline this callsite.
- if (!OIC)
+ if (!OIC || !*OIC)
continue;
// Setup the data structure used to plumb customization into the
@@ -987,32 +1012,19 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
using namespace ore;
- if (!InlineFunction(CS, IFI)) {
+ InlineResult IR = InlineFunction(CS, IFI);
+ if (!IR) {
ORE.emit([&]() {
return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block)
<< NV("Callee", &Callee) << " will not be inlined into "
- << NV("Caller", &F);
+ << NV("Caller", &F) << ": " << NV("Reason", IR.message);
});
continue;
}
DidInline = true;
InlinedCallees.insert(&Callee);
- 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;
- });
+ emit_inlined_into(ORE, DLoc, Block, Callee, F, *OIC);
// Add any new callsites to defined functions to the worklist.
if (!IFI.InlinedCallSites.empty()) {
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index ddc6e07e2f5..f8226f529ee 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -84,13 +84,15 @@ PreserveAlignmentAssumptions("preserve-alignment-assumptions-during-inlining",
cl::init(true), cl::Hidden,
cl::desc("Convert align attributes to assumptions during inlining."));
-bool llvm::InlineFunction(CallInst *CI, InlineFunctionInfo &IFI,
- AAResults *CalleeAAR, bool InsertLifetime) {
+llvm::InlineResult llvm::InlineFunction(CallInst *CI, InlineFunctionInfo &IFI,
+ AAResults *CalleeAAR,
+ bool InsertLifetime) {
return InlineFunction(CallSite(CI), IFI, CalleeAAR, InsertLifetime);
}
-bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
- AAResults *CalleeAAR, bool InsertLifetime) {
+llvm::InlineResult llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
+ AAResults *CalleeAAR,
+ bool InsertLifetime) {
return InlineFunction(CallSite(II), IFI, CalleeAAR, InsertLifetime);
}
@@ -1491,9 +1493,10 @@ 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.
-bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
- AAResults *CalleeAAR, bool InsertLifetime,
- Function *ForwardVarArgsTo) {
+llvm::InlineResult 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!");
@@ -1504,7 +1507,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
Function *CalledFunc = CS.getCalledFunction();
if (!CalledFunc || // Can't inline external function or indirect
CalledFunc->isDeclaration()) // call!
- return false;
+ return "external or indirect";
// The inliner does not know how to inline through calls with operand bundles
// in general ...
@@ -1518,7 +1521,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
if (Tag == LLVMContext::OB_funclet)
continue;
- return false;
+ return "unsupported operand bundle";
}
}
@@ -1537,7 +1540,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
if (!Caller->hasGC())
Caller->setGC(CalledFunc->getGC());
else if (CalledFunc->getGC() != Caller->getGC())
- return false;
+ return "incompatible GC";
}
// Get the personality function from the callee if it contains a landing pad.
@@ -1561,7 +1564,7 @@ bool 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 false;
+ return "incompatible personality";
}
// We need to figure out which funclet the callsite was in so that we may
@@ -1586,7 +1589,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
// for catchpads.
for (const BasicBlock &CalledBB : *CalledFunc) {
if (isa<CatchSwitchInst>(CalledBB.getFirstNonPHI()))
- return false;
+ return "catch in cleanup funclet";
}
}
} else if (isAsynchronousEHPersonality(Personality)) {
@@ -1594,7 +1597,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
// funclet in the callee.
for (const BasicBlock &CalledBB : *CalledFunc) {
if (CalledBB.isEHPad())
- return false;
+ return "SEH in cleanup funclet";
}
}
}
diff --git a/test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll b/test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll
index c45dd4bcd0e..9932f527dc6 100644
--- a/test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll
+++ b/test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll
@@ -25,14 +25,15 @@
; YAML-NEXT: - Callee: tinkywinky
; YAML-NEXT: - String: ' inlined into '
; YAML-NEXT: - Caller: main
-; YAML-NEXT: - String: ' with cost='
+; YAML-NEXT: - String: ' with '
+; YAML-NEXT: - String: '(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"
diff --git a/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll b/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll
index 8a3c97a8438..03db4a722b5 100644
--- a/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll
+++ b/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll
@@ -26,9 +26,10 @@
; YAML-NEXT: - Callee: tinkywinky
; YAML-NEXT: - String: ' inlined into '
; YAML-NEXT: - Caller: main
-; YAML-NEXT: - String: ' with cost='
+; YAML-NEXT: - String: ' with '
+; YAML-NEXT: - String: '(cost='
; YAML-NEXT: - Cost: '-15000'
-; YAML-NEXT: - String: ' (threshold='
+; YAML-NEXT: - String: ', threshold='
; YAML-NEXT: - Threshold: '337'
; YAML-NEXT: - String: ')'
; YAML-NEXT: ...
diff --git a/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll b/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll
index 81116996ae2..d1dddf1a71f 100644
--- a/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll
+++ b/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll
@@ -17,9 +17,10 @@
; YAML-NEXT: - Callee: foo
; YAML-NEXT: - String: ' inlined into '
; YAML-NEXT: - Caller: main
-; YAML-NEXT: - String: ' with cost='
+; YAML-NEXT: - String: ' with '
+; YAML-NEXT: - String: '(cost='
; YAML-NEXT: - Cost: '-15000'
-; YAML-NEXT: - String: ' (threshold='
+; YAML-NEXT: - String: ', threshold='
; YAML-NEXT: - Threshold: '337'
; YAML-NEXT: - String: ')'
; YAML-NEXT: ...
diff --git a/test/LTO/X86/diagnostic-handler-remarks.ll b/test/LTO/X86/diagnostic-handler-remarks.ll
index b6d02675bf1..94f88ec43c5 100644
--- a/test/LTO/X86/diagnostic-handler-remarks.ll
+++ b/test/LTO/X86/diagnostic-handler-remarks.ll
@@ -53,9 +53,10 @@
; YAML-NEXT: - Callee: foo
; YAML-NEXT: - String: ' inlined into '
; YAML-NEXT: - Caller: main
-; YAML-NEXT: - String: ' with cost='
+; YAML-NEXT: - String: ' with '
+; YAML-NEXT: - String: '(cost='
; YAML-NEXT: - Cost: '-15000'
-; YAML-NEXT: - String: ' (threshold='
+; YAML-NEXT: - String: ', threshold='
; YAML-NEXT: - Threshold: '337'
; YAML-NEXT: - String: ')'
; YAML-NEXT: ...
diff --git a/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll b/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll
index 0f0e26e53ca..239e6efe3a1 100644
--- a/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll
+++ b/test/ThinLTO/X86/diagnostic-handler-remarks-with-hotness.ll
@@ -25,9 +25,10 @@
; YAML1-NEXT: - Callee: foo
; YAML1-NEXT: - String: ' inlined into '
; YAML1-NEXT: - Caller: main
-; YAML1-NEXT: - String: ' with cost='
+; YAML1-NEXT: - String: ' with '
+; YAML1-NEXT: - String: '(cost='
; YAML1-NEXT: - Cost: '-30'
-; YAML1-NEXT: - String: ' (threshold='
+; YAML1-NEXT: - String: ', threshold='
; YAML1-NEXT: - Threshold: '337'
; YAML1-NEXT: - String: ')'
; YAML1-NEXT: ...
@@ -43,9 +44,10 @@
; YAML2-NEXT: - Callee: bar
; YAML2-NEXT: - String: ' inlined into '
; YAML2-NEXT: - Caller: foo
-; YAML2-NEXT: - String: ' with cost='
+; YAML2-NEXT: - String: ' with '
+; YAML2-NEXT: - String: '(cost='
; YAML2-NEXT: - Cost: '-30'
-; YAML2-NEXT: - String: ' (threshold='
+; YAML2-NEXT: - String: ', threshold='
; YAML2-NEXT: - Threshold: '337'
; YAML2-NEXT: - String: ')'
; YAML2-NEXT: ...
diff --git a/test/ThinLTO/X86/diagnostic-handler-remarks.ll b/test/ThinLTO/X86/diagnostic-handler-remarks.ll
index 2fd2cf8102b..d4606ba999d 100644
--- a/test/ThinLTO/X86/diagnostic-handler-remarks.ll
+++ b/test/ThinLTO/X86/diagnostic-handler-remarks.ll
@@ -22,9 +22,10 @@
; YAML1-NEXT: - Callee: foo
; YAML1-NEXT: - String: ' inlined into '
; YAML1-NEXT: - Caller: main
-; YAML1-NEXT: - String: ' with cost='
+; YAML1-NEXT: - String: ' with '
+; YAML1-NEXT: - String: '(cost='
; YAML1-NEXT: - Cost: '-30'
-; YAML1-NEXT: - String: ' (threshold='
+; YAML1-NEXT: - String: ', threshold='
; YAML1-NEXT: - Threshold: '337'
; YAML1-NEXT: - String: ')'
; YAML1-NEXT: ...
@@ -40,9 +41,10 @@
; YAML2-NEXT: - Callee: bar
; YAML2-NEXT: - String: ' inlined into '
; YAML2-NEXT: - Caller: foo
-; YAML2-NEXT: - String: ' with cost='
+; YAML2-NEXT: - String: ' with '
+; YAML2-NEXT: - String: '(cost='
; YAML2-NEXT: - Cost: '-30'
-; YAML2-NEXT: - String: ' (threshold='
+; YAML2-NEXT: - String: ', threshold='
; YAML2-NEXT: - Threshold: '337'
; YAML2-NEXT: - String: ')'
; YAML2-NEXT: ...
diff --git a/test/Transforms/Inline/ARM/inline-fp.ll b/test/Transforms/Inline/ARM/inline-fp.ll
index b4e76dfc7d2..be3dd2a93fd 100644
--- a/test/Transforms/Inline/ARM/inline-fp.ll
+++ b/test/Transforms/Inline/ARM/inline-fp.ll
@@ -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)
diff --git a/test/Transforms/Inline/optimization-remarks-hotness-threshold.ll b/test/Transforms/Inline/optimization-remarks-hotness-threshold.ll
index 6ae9543754b..16d7db33412 100644
--- a/test/Transforms/Inline/optimization-remarks-hotness-threshold.ll
+++ b/test/Transforms/Inline/optimization-remarks-hotness-threshold.ll
@@ -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'
diff --git a/test/Transforms/Inline/optimization-remarks-passed-yaml.ll b/test/Transforms/Inline/optimization-remarks-passed-yaml.ll
index e0ba213b6de..0ac76354a2b 100644
--- a/test/Transforms/Inline/optimization-remarks-passed-yaml.ll
+++ b/test/Transforms/Inline/optimization-remarks-passed-yaml.ll
@@ -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,9 +31,10 @@
; YAML-NEXT: - String: ' inlined into '
; YAML-NEXT: - Caller: bar
; YAML-NEXT: DebugLoc: { File: /tmp/s.c, Line: 3, Column: 0 }
-; YAML-NEXT: - String: ' with cost='
+; YAML-NEXT: - String: ' with '
+; YAML-NEXT: - String: '(cost='
; YAML-NEXT: - Cost: '{{[0-9\-]+}}'
-; YAML-NEXT: - String: ' (threshold='
+; YAML-NEXT: - String: ', threshold='
; YAML-NEXT: - Threshold: '{{[0-9]+}}'
; YAML-NEXT: - String: ')'
; YAML-NEXT: ...
diff --git a/test/Transforms/Inline/optimization-remarks-with-hotness.ll b/test/Transforms/Inline/optimization-remarks-with-hotness.ll
index 3614c3b5230..1a1c0f4bac1 100644
--- a/test/Transforms/Inline/optimization-remarks-with-hotness.ll
+++ b/test/Transforms/Inline/optimization-remarks-with-hotness.ll
@@ -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 (hotness: 30)
-; CHECK: foz not inlined into bar because it should never be inlined (cost=never) (hotness: 30)
+; 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)
; Function Attrs: alwaysinline nounwind uwtable
define i32 @foo() #0 !prof !1 {
diff --git a/test/Transforms/Inline/optimization-remarks.ll b/test/Transforms/Inline/optimization-remarks.ll
index 16f782682e1..72e90aefa61 100644
--- a/test/Transforms/Inline/optimization-remarks.ll
+++ b/test/Transforms/Inline/optimization-remarks.ll
@@ -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
-; CHECK: foz not inlined into bar because it should never be inlined (cost=never)
+; 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
; Function Attrs: alwaysinline nounwind uwtable
define i32 @foo(i32 %x, i32 %y) #0 !prof !1 {
diff --git a/test/tools/gold/X86/opt-remarks.ll b/test/tools/gold/X86/opt-remarks.ll
index 2cca9bf5d2f..7a83df4af53 100644
--- a/test/tools/gold/X86/opt-remarks.ll
+++ b/test/tools/gold/X86/opt-remarks.ll
@@ -34,7 +34,8 @@
; YAML-NEXT: - Callee: f
; YAML-NEXT: - String: ' inlined into '
; YAML-NEXT: - Caller: _start
-; YAML-NEXT: - String: ' with cost='
+; YAML-NEXT: - String: ' with '
+; YAML-NEXT: - String: 'cost='
; YAML-NEXT: - Cost: '0'
; YAML-NEXT: - String: ' (threshold='
; YAML-NEXT: - Threshold: '337'
@@ -51,7 +52,8 @@
; YAML-HOT-NEXT: - Callee: f
; YAML-HOT-NEXT: - String: ' inlined into '
; YAML-HOT-NEXT: - Caller: _start
-; YAML-HOT-NEXT: - String: ' with cost='
+; YAML-HOT-NEXT: - String: ' with'
+; YAML-HOT-NEXT: - String: 'cost='
; YAML-HOT-NEXT: - Cost: '0'
; YAML-HOT-NEXT: - String: ' (threshold='
; YAML-HOT-NEXT: - Threshold: '337'