Home | History | Annotate | Line # | Download | only in Analysis
      1 //===- InlineAdvisor.cpp - analysis pass implementation -------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file implements InlineAdvisorAnalysis and DefaultInlineAdvisor, and
     10 // related types.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "llvm/Analysis/InlineAdvisor.h"
     15 #include "llvm/ADT/Statistic.h"
     16 #include "llvm/Analysis/InlineCost.h"
     17 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
     18 #include "llvm/Analysis/ProfileSummaryInfo.h"
     19 #include "llvm/Analysis/ReplayInlineAdvisor.h"
     20 #include "llvm/Analysis/TargetLibraryInfo.h"
     21 #include "llvm/Analysis/TargetTransformInfo.h"
     22 #include "llvm/IR/DebugInfoMetadata.h"
     23 #include "llvm/IR/Instructions.h"
     24 #include "llvm/Support/CommandLine.h"
     25 #include "llvm/Support/raw_ostream.h"
     26 
     27 using namespace llvm;
     28 #define DEBUG_TYPE "inline"
     29 
     30 // This weirdly named statistic tracks the number of times that, when attempting
     31 // to inline a function A into B, we analyze the callers of B in order to see
     32 // if those would be more profitable and blocked inline steps.
     33 STATISTIC(NumCallerCallersAnalyzed, "Number of caller-callers analyzed");
     34 
     35 /// Flag to add inline messages as callsite attributes 'inline-remark'.
     36 static cl::opt<bool>
     37     InlineRemarkAttribute("inline-remark-attribute", cl::init(false),
     38                           cl::Hidden,
     39                           cl::desc("Enable adding inline-remark attribute to"
     40                                    " callsites processed by inliner but decided"
     41                                    " to be not inlined"));
     42 
     43 // An integer used to limit the cost of inline deferral.  The default negative
     44 // number tells shouldBeDeferred to only take the secondary cost into account.
     45 static cl::opt<int>
     46     InlineDeferralScale("inline-deferral-scale",
     47                         cl::desc("Scale to limit the cost of inline deferral"),
     48                         cl::init(2), cl::Hidden);
     49 
     50 extern cl::opt<InlinerFunctionImportStatsOpts> InlinerFunctionImportStats;
     51 
     52 void DefaultInlineAdvice::recordUnsuccessfulInliningImpl(
     53     const InlineResult &Result) {
     54   using namespace ore;
     55   llvm::setInlineRemark(*OriginalCB, std::string(Result.getFailureReason()) +
     56                                          "; " + inlineCostStr(*OIC));
     57   ORE.emit([&]() {
     58     return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block)
     59            << NV("Callee", Callee) << " will not be inlined into "
     60            << NV("Caller", Caller) << ": "
     61            << NV("Reason", Result.getFailureReason());
     62   });
     63 }
     64 
     65 void DefaultInlineAdvice::recordInliningWithCalleeDeletedImpl() {
     66   if (EmitRemarks)
     67     emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, *OIC);
     68 }
     69 
     70 void DefaultInlineAdvice::recordInliningImpl() {
     71   if (EmitRemarks)
     72     emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, *OIC);
     73 }
     74 
     75 llvm::Optional<llvm::InlineCost> static getDefaultInlineAdvice(
     76     CallBase &CB, FunctionAnalysisManager &FAM, const InlineParams &Params) {
     77   Function &Caller = *CB.getCaller();
     78   ProfileSummaryInfo *PSI =
     79       FAM.getResult<ModuleAnalysisManagerFunctionProxy>(Caller)
     80           .getCachedResult<ProfileSummaryAnalysis>(
     81               *CB.getParent()->getParent()->getParent());
     82 
     83   auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(Caller);
     84   auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
     85     return FAM.getResult<AssumptionAnalysis>(F);
     86   };
     87   auto GetBFI = [&](Function &F) -> BlockFrequencyInfo & {
     88     return FAM.getResult<BlockFrequencyAnalysis>(F);
     89   };
     90   auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & {
     91     return FAM.getResult<TargetLibraryAnalysis>(F);
     92   };
     93 
     94   auto GetInlineCost = [&](CallBase &CB) {
     95     Function &Callee = *CB.getCalledFunction();
     96     auto &CalleeTTI = FAM.getResult<TargetIRAnalysis>(Callee);
     97     bool RemarksEnabled =
     98         Callee.getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(
     99             DEBUG_TYPE);
    100     return getInlineCost(CB, Params, CalleeTTI, GetAssumptionCache, GetTLI,
    101                          GetBFI, PSI, RemarksEnabled ? &ORE : nullptr);
    102   };
    103   return llvm::shouldInline(CB, GetInlineCost, ORE,
    104                             Params.EnableDeferral.getValueOr(false));
    105 }
    106 
    107 std::unique_ptr<InlineAdvice>
    108 DefaultInlineAdvisor::getAdviceImpl(CallBase &CB) {
    109   auto OIC = getDefaultInlineAdvice(CB, FAM, Params);
    110   return std::make_unique<DefaultInlineAdvice>(
    111       this, CB, OIC,
    112       FAM.getResult<OptimizationRemarkEmitterAnalysis>(*CB.getCaller()));
    113 }
    114 
    115 InlineAdvice::InlineAdvice(InlineAdvisor *Advisor, CallBase &CB,
    116                            OptimizationRemarkEmitter &ORE,
    117                            bool IsInliningRecommended)
    118     : Advisor(Advisor), Caller(CB.getCaller()), Callee(CB.getCalledFunction()),
    119       DLoc(CB.getDebugLoc()), Block(CB.getParent()), ORE(ORE),
    120       IsInliningRecommended(IsInliningRecommended) {}
    121 
    122 void InlineAdvisor::markFunctionAsDeleted(Function *F) {
    123   assert((!DeletedFunctions.count(F)) &&
    124          "Cannot put cause a function to become dead twice!");
    125   DeletedFunctions.insert(F);
    126 }
    127 
    128 void InlineAdvisor::freeDeletedFunctions() {
    129   for (auto *F : DeletedFunctions)
    130     delete F;
    131   DeletedFunctions.clear();
    132 }
    133 
    134 void InlineAdvice::recordInlineStatsIfNeeded() {
    135   if (Advisor->ImportedFunctionsStats)
    136     Advisor->ImportedFunctionsStats->recordInline(*Caller, *Callee);
    137 }
    138 
    139 void InlineAdvice::recordInlining() {
    140   markRecorded();
    141   recordInlineStatsIfNeeded();
    142   recordInliningImpl();
    143 }
    144 
    145 void InlineAdvice::recordInliningWithCalleeDeleted() {
    146   markRecorded();
    147   recordInlineStatsIfNeeded();
    148   Advisor->markFunctionAsDeleted(Callee);
    149   recordInliningWithCalleeDeletedImpl();
    150 }
    151 
    152 AnalysisKey InlineAdvisorAnalysis::Key;
    153 
    154 bool InlineAdvisorAnalysis::Result::tryCreate(InlineParams Params,
    155                                               InliningAdvisorMode Mode,
    156                                               StringRef ReplayFile) {
    157   auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
    158   switch (Mode) {
    159   case InliningAdvisorMode::Default:
    160     Advisor.reset(new DefaultInlineAdvisor(M, FAM, Params));
    161     // Restrict replay to default advisor, ML advisors are stateful so
    162     // replay will need augmentations to interleave with them correctly.
    163     if (!ReplayFile.empty()) {
    164       Advisor = std::make_unique<ReplayInlineAdvisor>(
    165           M, FAM, M.getContext(), std::move(Advisor), ReplayFile,
    166           /* EmitRemarks =*/true);
    167     }
    168     break;
    169   case InliningAdvisorMode::Development:
    170 #ifdef LLVM_HAVE_TF_API
    171     Advisor =
    172         llvm::getDevelopmentModeAdvisor(M, MAM, [&FAM, Params](CallBase &CB) {
    173           auto OIC = getDefaultInlineAdvice(CB, FAM, Params);
    174           return OIC.hasValue();
    175         });
    176 #endif
    177     break;
    178   case InliningAdvisorMode::Release:
    179 #ifdef LLVM_HAVE_TF_AOT
    180     Advisor = llvm::getReleaseModeAdvisor(M, MAM);
    181 #endif
    182     break;
    183   }
    184 
    185   return !!Advisor;
    186 }
    187 
    188 /// Return true if inlining of CB can block the caller from being
    189 /// inlined which is proved to be more beneficial. \p IC is the
    190 /// estimated inline cost associated with callsite \p CB.
    191 /// \p TotalSecondaryCost will be set to the estimated cost of inlining the
    192 /// caller if \p CB is suppressed for inlining.
    193 static bool
    194 shouldBeDeferred(Function *Caller, InlineCost IC, int &TotalSecondaryCost,
    195                  function_ref<InlineCost(CallBase &CB)> GetInlineCost) {
    196   // For now we only handle local or inline functions.
    197   if (!Caller->hasLocalLinkage() && !Caller->hasLinkOnceODRLinkage())
    198     return false;
    199   // If the cost of inlining CB is non-positive, it is not going to prevent the
    200   // caller from being inlined into its callers and hence we don't need to
    201   // defer.
    202   if (IC.getCost() <= 0)
    203     return false;
    204   // Try to detect the case where the current inlining candidate caller (call
    205   // it B) is a static or linkonce-ODR function and is an inlining candidate
    206   // elsewhere, and the current candidate callee (call it C) is large enough
    207   // that inlining it into B would make B too big to inline later. In these
    208   // circumstances it may be best not to inline C into B, but to inline B into
    209   // its callers.
    210   //
    211   // This only applies to static and linkonce-ODR functions because those are
    212   // expected to be available for inlining in the translation units where they
    213   // are used. Thus we will always have the opportunity to make local inlining
    214   // decisions. Importantly the linkonce-ODR linkage covers inline functions
    215   // and templates in C++.
    216   //
    217   // FIXME: All of this logic should be sunk into getInlineCost. It relies on
    218   // the internal implementation of the inline cost metrics rather than
    219   // treating them as truly abstract units etc.
    220   TotalSecondaryCost = 0;
    221   // The candidate cost to be imposed upon the current function.
    222   int CandidateCost = IC.getCost() - 1;
    223   // If the caller has local linkage and can be inlined to all its callers, we
    224   // can apply a huge negative bonus to TotalSecondaryCost.
    225   bool ApplyLastCallBonus = Caller->hasLocalLinkage() && !Caller->hasOneUse();
    226   // This bool tracks what happens if we DO inline C into B.
    227   bool InliningPreventsSomeOuterInline = false;
    228   unsigned NumCallerUsers = 0;
    229   for (User *U : Caller->users()) {
    230     CallBase *CS2 = dyn_cast<CallBase>(U);
    231 
    232     // If this isn't a call to Caller (it could be some other sort
    233     // of reference) skip it.  Such references will prevent the caller
    234     // from being removed.
    235     if (!CS2 || CS2->getCalledFunction() != Caller) {
    236       ApplyLastCallBonus = false;
    237       continue;
    238     }
    239 
    240     InlineCost IC2 = GetInlineCost(*CS2);
    241     ++NumCallerCallersAnalyzed;
    242     if (!IC2) {
    243       ApplyLastCallBonus = false;
    244       continue;
    245     }
    246     if (IC2.isAlways())
    247       continue;
    248 
    249     // See if inlining of the original callsite would erase the cost delta of
    250     // this callsite. We subtract off the penalty for the call instruction,
    251     // which we would be deleting.
    252     if (IC2.getCostDelta() <= CandidateCost) {
    253       InliningPreventsSomeOuterInline = true;
    254       TotalSecondaryCost += IC2.getCost();
    255       NumCallerUsers++;
    256     }
    257   }
    258 
    259   if (!InliningPreventsSomeOuterInline)
    260     return false;
    261 
    262   // If all outer calls to Caller would get inlined, the cost for the last
    263   // one is set very low by getInlineCost, in anticipation that Caller will
    264   // be removed entirely.  We did not account for this above unless there
    265   // is only one caller of Caller.
    266   if (ApplyLastCallBonus)
    267     TotalSecondaryCost -= InlineConstants::LastCallToStaticBonus;
    268 
    269   // If InlineDeferralScale is negative, then ignore the cost of primary
    270   // inlining -- IC.getCost() multiplied by the number of callers to Caller.
    271   if (InlineDeferralScale < 0)
    272     return TotalSecondaryCost < IC.getCost();
    273 
    274   int TotalCost = TotalSecondaryCost + IC.getCost() * NumCallerUsers;
    275   int Allowance = IC.getCost() * InlineDeferralScale;
    276   return TotalCost < Allowance;
    277 }
    278 
    279 namespace llvm {
    280 static raw_ostream &operator<<(raw_ostream &R, const ore::NV &Arg) {
    281   return R << Arg.Val;
    282 }
    283 
    284 template <class RemarkT>
    285 RemarkT &operator<<(RemarkT &&R, const InlineCost &IC) {
    286   using namespace ore;
    287   if (IC.isAlways()) {
    288     R << "(cost=always)";
    289   } else if (IC.isNever()) {
    290     R << "(cost=never)";
    291   } else {
    292     R << "(cost=" << ore::NV("Cost", IC.getCost())
    293       << ", threshold=" << ore::NV("Threshold", IC.getThreshold()) << ")";
    294   }
    295   if (const char *Reason = IC.getReason())
    296     R << ": " << ore::NV("Reason", Reason);
    297   return R;
    298 }
    299 } // namespace llvm
    300 
    301 std::string llvm::inlineCostStr(const InlineCost &IC) {
    302   std::string Buffer;
    303   raw_string_ostream Remark(Buffer);
    304   Remark << IC;
    305   return Remark.str();
    306 }
    307 
    308 void llvm::setInlineRemark(CallBase &CB, StringRef Message) {
    309   if (!InlineRemarkAttribute)
    310     return;
    311 
    312   Attribute Attr = Attribute::get(CB.getContext(), "inline-remark", Message);
    313   CB.addAttribute(AttributeList::FunctionIndex, Attr);
    314 }
    315 
    316 /// Return the cost only if the inliner should attempt to inline at the given
    317 /// CallSite. If we return the cost, we will emit an optimisation remark later
    318 /// using that cost, so we won't do so from this function. Return None if
    319 /// inlining should not be attempted.
    320 Optional<InlineCost>
    321 llvm::shouldInline(CallBase &CB,
    322                    function_ref<InlineCost(CallBase &CB)> GetInlineCost,
    323                    OptimizationRemarkEmitter &ORE, bool EnableDeferral) {
    324   using namespace ore;
    325 
    326   InlineCost IC = GetInlineCost(CB);
    327   Instruction *Call = &CB;
    328   Function *Callee = CB.getCalledFunction();
    329   Function *Caller = CB.getCaller();
    330 
    331   if (IC.isAlways()) {
    332     LLVM_DEBUG(dbgs() << "    Inlining " << inlineCostStr(IC)
    333                       << ", Call: " << CB << "\n");
    334     return IC;
    335   }
    336 
    337   if (!IC) {
    338     LLVM_DEBUG(dbgs() << "    NOT Inlining " << inlineCostStr(IC)
    339                       << ", Call: " << CB << "\n");
    340     if (IC.isNever()) {
    341       ORE.emit([&]() {
    342         return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call)
    343                << NV("Callee", Callee) << " not inlined into "
    344                << NV("Caller", Caller) << " because it should never be inlined "
    345                << IC;
    346       });
    347     } else {
    348       ORE.emit([&]() {
    349         return OptimizationRemarkMissed(DEBUG_TYPE, "TooCostly", Call)
    350                << NV("Callee", Callee) << " not inlined into "
    351                << NV("Caller", Caller) << " because too costly to inline "
    352                << IC;
    353       });
    354     }
    355     setInlineRemark(CB, inlineCostStr(IC));
    356     return None;
    357   }
    358 
    359   int TotalSecondaryCost = 0;
    360   if (EnableDeferral &&
    361       shouldBeDeferred(Caller, IC, TotalSecondaryCost, GetInlineCost)) {
    362     LLVM_DEBUG(dbgs() << "    NOT Inlining: " << CB
    363                       << " Cost = " << IC.getCost()
    364                       << ", outer Cost = " << TotalSecondaryCost << '\n');
    365     ORE.emit([&]() {
    366       return OptimizationRemarkMissed(DEBUG_TYPE, "IncreaseCostInOtherContexts",
    367                                       Call)
    368              << "Not inlining. Cost of inlining " << NV("Callee", Callee)
    369              << " increases the cost of inlining " << NV("Caller", Caller)
    370              << " in other contexts";
    371     });
    372     setInlineRemark(CB, "deferred");
    373     // IC does not bool() to false, so get an InlineCost that will.
    374     // This will not be inspected to make an error message.
    375     return None;
    376   }
    377 
    378   LLVM_DEBUG(dbgs() << "    Inlining " << inlineCostStr(IC) << ", Call: " << CB
    379                     << '\n');
    380   return IC;
    381 }
    382 
    383 std::string llvm::getCallSiteLocation(DebugLoc DLoc) {
    384   std::string Buffer;
    385   raw_string_ostream CallSiteLoc(Buffer);
    386   bool First = true;
    387   for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) {
    388     if (!First)
    389       CallSiteLoc << " @ ";
    390     // Note that negative line offset is actually possible, but we use
    391     // unsigned int to match line offset representation in remarks so
    392     // it's directly consumable by relay advisor.
    393     uint32_t Offset =
    394         DIL->getLine() - DIL->getScope()->getSubprogram()->getLine();
    395     uint32_t Discriminator = DIL->getBaseDiscriminator();
    396     StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
    397     if (Name.empty())
    398       Name = DIL->getScope()->getSubprogram()->getName();
    399     CallSiteLoc << Name.str() << ":" << llvm::utostr(Offset) << ":"
    400                 << llvm::utostr(DIL->getColumn());
    401     if (Discriminator)
    402       CallSiteLoc << "." << llvm::utostr(Discriminator);
    403     First = false;
    404   }
    405 
    406   return CallSiteLoc.str();
    407 }
    408 
    409 void llvm::addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc) {
    410   if (!DLoc.get()) {
    411     return;
    412   }
    413 
    414   bool First = true;
    415   Remark << " at callsite ";
    416   for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) {
    417     if (!First)
    418       Remark << " @ ";
    419     unsigned int Offset = DIL->getLine();
    420     Offset -= DIL->getScope()->getSubprogram()->getLine();
    421     unsigned int Discriminator = DIL->getBaseDiscriminator();
    422     StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
    423     if (Name.empty())
    424       Name = DIL->getScope()->getSubprogram()->getName();
    425     Remark << Name << ":" << ore::NV("Line", Offset) << ":"
    426            << ore::NV("Column", DIL->getColumn());
    427     if (Discriminator)
    428       Remark << "." << ore::NV("Disc", Discriminator);
    429     First = false;
    430   }
    431 
    432   Remark << ";";
    433 }
    434 
    435 void llvm::emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
    436                            const BasicBlock *Block, const Function &Callee,
    437                            const Function &Caller, const InlineCost &IC,
    438                            bool ForProfileContext, const char *PassName) {
    439   ORE.emit([&]() {
    440     bool AlwaysInline = IC.isAlways();
    441     StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined";
    442     OptimizationRemark Remark(PassName ? PassName : DEBUG_TYPE, RemarkName,
    443                               DLoc, Block);
    444     Remark << ore::NV("Callee", &Callee) << " inlined into ";
    445     Remark << ore::NV("Caller", &Caller);
    446     if (ForProfileContext)
    447       Remark << " to match profiling context";
    448     Remark << " with " << IC;
    449     addLocationToRemarks(Remark, DLoc);
    450     return Remark;
    451   });
    452 }
    453 
    454 InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM)
    455     : M(M), FAM(FAM) {
    456   if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) {
    457     ImportedFunctionsStats =
    458         std::make_unique<ImportedFunctionsInliningStatistics>();
    459     ImportedFunctionsStats->setModuleInfo(M);
    460   }
    461 }
    462 
    463 InlineAdvisor::~InlineAdvisor() {
    464   if (ImportedFunctionsStats) {
    465     assert(InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No);
    466     ImportedFunctionsStats->dump(InlinerFunctionImportStats ==
    467                                  InlinerFunctionImportStatsOpts::Verbose);
    468   }
    469 
    470   freeDeletedFunctions();
    471 }
    472 
    473 std::unique_ptr<InlineAdvice> InlineAdvisor::getMandatoryAdvice(CallBase &CB,
    474                                                                 bool Advice) {
    475   return std::make_unique<InlineAdvice>(this, CB, getCallerORE(CB), Advice);
    476 }
    477 
    478 InlineAdvisor::MandatoryInliningKind
    479 InlineAdvisor::getMandatoryKind(CallBase &CB, FunctionAnalysisManager &FAM,
    480                                 OptimizationRemarkEmitter &ORE) {
    481   auto &Callee = *CB.getCalledFunction();
    482 
    483   auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & {
    484     return FAM.getResult<TargetLibraryAnalysis>(F);
    485   };
    486 
    487   auto &TIR = FAM.getResult<TargetIRAnalysis>(Callee);
    488 
    489   auto TrivialDecision =
    490       llvm::getAttributeBasedInliningDecision(CB, &Callee, TIR, GetTLI);
    491 
    492   if (TrivialDecision.hasValue()) {
    493     if (TrivialDecision->isSuccess())
    494       return MandatoryInliningKind::Always;
    495     else
    496       return MandatoryInliningKind::Never;
    497   }
    498   return MandatoryInliningKind::NotMandatory;
    499 }
    500 
    501 std::unique_ptr<InlineAdvice> InlineAdvisor::getAdvice(CallBase &CB,
    502                                                        bool MandatoryOnly) {
    503   if (!MandatoryOnly)
    504     return getAdviceImpl(CB);
    505   bool Advice = CB.getCaller() != CB.getCalledFunction() &&
    506                 MandatoryInliningKind::Always ==
    507                     getMandatoryKind(CB, FAM, getCallerORE(CB));
    508   return getMandatoryAdvice(CB, Advice);
    509 }
    510 
    511 OptimizationRemarkEmitter &InlineAdvisor::getCallerORE(CallBase &CB) {
    512   return FAM.getResult<OptimizationRemarkEmitterAnalysis>(*CB.getCaller());
    513 }
    514