diff options
author | Teresa Johnson <tejohnson@google.com> | 2020-02-06 13:28:41 -0800 |
---|---|---|
committer | Teresa Johnson <tejohnson@google.com> | 2020-02-28 07:34:14 -0800 |
commit | f9ca75f19bab639988ebbe68c81d07babd952afb (patch) | |
tree | ba86feae04f86ea3ccf09470636f69fda9b3398d /llvm/lib/Analysis/InlineCost.cpp | |
parent | b6e80864b6da7937504dcf5698ea49801d1f7be2 (diff) | |
download | llvm-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.cpp | 26 |
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. |