aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/InlineCost.cpp
diff options
context:
space:
mode:
authorTeresa Johnson <tejohnson@google.com>2020-02-06 13:28:41 -0800
committerTeresa Johnson <tejohnson@google.com>2020-02-28 07:34:14 -0800
commitf9ca75f19bab639988ebbe68c81d07babd952afb (patch)
treeba86feae04f86ea3ccf09470636f69fda9b3398d /llvm/lib/Analysis/InlineCost.cpp
parentb6e80864b6da7937504dcf5698ea49801d1f7be2 (diff)
downloadllvm-f9ca75f19bab639988ebbe68c81d07babd952afb.zip
llvm-f9ca75f19bab639988ebbe68c81d07babd952afb.tar.gz
llvm-f9ca75f19bab639988ebbe68c81d07babd952afb.tar.bz2
[Inliner] Inlining should honor nobuiltin attributes
Summary: Final patch in series to fix inlining between functions with different nobuiltin attributes/options, which was specifically an issue in LTO. See discussion on D61634 for background. The prior patch in this series (D67923) enabled per-Function TLI construction that identified the nobuiltin attributes. Here I have allowed inlining to proceed if the callee's nobuiltins are a subset of the caller's nobuiltins, but not in the reverse case, which should be conservatively correct. This is controlled by a new option, -inline-caller-superset-nobuiltin, which is enabled by default. Reviewers: hfinkel, gchatelet, chandlerc, davidxl Subscribers: arsenm, jvesely, nhaehnle, mehdi_amini, eraman, hiraditya, haicheng, dexonsmith, kerbowa, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D74162
Diffstat (limited to 'llvm/lib/Analysis/InlineCost.cpp')
-rw-r--r--llvm/lib/Analysis/InlineCost.cpp26
1 files changed, 21 insertions, 5 deletions
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index 4182452..b4aa2fb 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -24,6 +24,7 @@
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Config/llvm-config.h"
@@ -103,6 +104,12 @@ static cl::opt<bool> OptComputeFullInlineCost(
cl::desc("Compute the full inline cost of a call site even when the cost "
"exceeds the threshold."));
+static cl::opt<bool> InlineCallerSupersetNoBuiltin(
+ "inline-caller-superset-nobuiltin", cl::Hidden, cl::init(true),
+ cl::ZeroOrMore,
+ cl::desc("Allow inlining when caller has a superset of callee's nobuiltin "
+ "attributes."));
+
namespace {
class InlineCostCallAnalyzer;
@@ -2146,10 +2153,17 @@ LLVM_DUMP_METHOD void InlineCostCallAnalyzer::dump() {
/// Test that there are no attribute conflicts between Caller and Callee
/// that prevent inlining.
-static bool functionsHaveCompatibleAttributes(Function *Caller,
- Function *Callee,
- TargetTransformInfo &TTI) {
+static bool functionsHaveCompatibleAttributes(
+ Function *Caller, Function *Callee, TargetTransformInfo &TTI,
+ function_ref<const TargetLibraryInfo &(Function &)> &GetTLI) {
+ // Note that CalleeTLI must be a copy not a reference. The legacy pass manager
+ // caches the most recently created TLI in the TargetLibraryInfoWrapperPass
+ // object, and always returns the same object (which is overwritten on each
+ // GetTLI call). Therefore we copy the first result.
+ auto CalleeTLI = GetTLI(*Callee);
return TTI.areInlineCompatible(Caller, Callee) &&
+ GetTLI(*Caller).areInlineCompatible(CalleeTLI,
+ InlineCallerSupersetNoBuiltin) &&
AttributeFuncs::areInlineCompatible(*Caller, *Callee);
}
@@ -2190,9 +2204,10 @@ InlineCost llvm::getInlineCost(
CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI,
std::function<AssumptionCache &(Function &)> &GetAssumptionCache,
Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI,
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
return getInlineCost(Call, Call.getCalledFunction(), Params, CalleeTTI,
- GetAssumptionCache, GetBFI, PSI, ORE);
+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE);
}
InlineCost llvm::getInlineCost(
@@ -2200,6 +2215,7 @@ InlineCost llvm::getInlineCost(
TargetTransformInfo &CalleeTTI,
std::function<AssumptionCache &(Function &)> &GetAssumptionCache,
Optional<function_ref<BlockFrequencyInfo &(Function &)>> GetBFI,
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
// Cannot inline indirect calls.
@@ -2232,7 +2248,7 @@ InlineCost llvm::getInlineCost(
// Never inline functions with conflicting attributes (unless callee has
// always-inline attribute).
Function *Caller = Call.getCaller();
- if (!functionsHaveCompatibleAttributes(Caller, Callee, CalleeTTI))
+ if (!functionsHaveCompatibleAttributes(Caller, Callee, CalleeTTI, GetTLI))
return llvm::InlineCost::getNever("conflicting attributes");
// Don't inline this call if the caller has the optnone attribute.