Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/IPO/ModuleInliner.cpp
35266 views
//===- ModuleInliner.cpp - Code related to module inliner -----------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the mechanics required to implement inlining without9// missing any calls in the module level. It doesn't need any infromation about10// SCC or call graph, which is different from the SCC inliner. The decisions of11// which calls are profitable to inline are implemented elsewhere.12//13//===----------------------------------------------------------------------===//1415#include "llvm/Transforms/IPO/ModuleInliner.h"16#include "llvm/ADT/ScopeExit.h"17#include "llvm/ADT/SmallVector.h"18#include "llvm/ADT/Statistic.h"19#include "llvm/Analysis/AliasAnalysis.h"20#include "llvm/Analysis/AssumptionCache.h"21#include "llvm/Analysis/BlockFrequencyInfo.h"22#include "llvm/Analysis/InlineAdvisor.h"23#include "llvm/Analysis/InlineCost.h"24#include "llvm/Analysis/InlineOrder.h"25#include "llvm/Analysis/OptimizationRemarkEmitter.h"26#include "llvm/Analysis/ProfileSummaryInfo.h"27#include "llvm/Analysis/ReplayInlineAdvisor.h"28#include "llvm/Analysis/TargetLibraryInfo.h"29#include "llvm/IR/DiagnosticInfo.h"30#include "llvm/IR/Function.h"31#include "llvm/IR/InstIterator.h"32#include "llvm/IR/Instruction.h"33#include "llvm/IR/IntrinsicInst.h"34#include "llvm/IR/Module.h"35#include "llvm/IR/PassManager.h"36#include "llvm/Support/CommandLine.h"37#include "llvm/Support/Debug.h"38#include "llvm/Support/raw_ostream.h"39#include "llvm/Transforms/Utils/CallPromotionUtils.h"40#include "llvm/Transforms/Utils/Cloning.h"41#include <cassert>4243using namespace llvm;4445#define DEBUG_TYPE "module-inline"4647STATISTIC(NumInlined, "Number of functions inlined");48STATISTIC(NumDeleted, "Number of functions deleted because all callers found");4950/// Return true if the specified inline history ID51/// indicates an inline history that includes the specified function.52static bool inlineHistoryIncludes(53Function *F, int InlineHistoryID,54const SmallVectorImpl<std::pair<Function *, int>> &InlineHistory) {55while (InlineHistoryID != -1) {56assert(unsigned(InlineHistoryID) < InlineHistory.size() &&57"Invalid inline history ID");58if (InlineHistory[InlineHistoryID].first == F)59return true;60InlineHistoryID = InlineHistory[InlineHistoryID].second;61}62return false;63}6465InlineAdvisor &ModuleInlinerPass::getAdvisor(const ModuleAnalysisManager &MAM,66FunctionAnalysisManager &FAM,67Module &M) {68if (OwnedAdvisor)69return *OwnedAdvisor;7071auto *IAA = MAM.getCachedResult<InlineAdvisorAnalysis>(M);72if (!IAA) {73// It should still be possible to run the inliner as a stand-alone module74// pass, for test scenarios. In that case, we default to the75// DefaultInlineAdvisor, which doesn't need to keep state between module76// pass runs. It also uses just the default InlineParams. In this case, we77// need to use the provided FAM, which is valid for the duration of the78// inliner pass, and thus the lifetime of the owned advisor. The one we79// would get from the MAM can be invalidated as a result of the inliner's80// activity.81OwnedAdvisor = std::make_unique<DefaultInlineAdvisor>(82M, FAM, Params, InlineContext{LTOPhase, InlinePass::ModuleInliner});8384return *OwnedAdvisor;85}86assert(IAA->getAdvisor() &&87"Expected a present InlineAdvisorAnalysis also have an "88"InlineAdvisor initialized");89return *IAA->getAdvisor();90}9192static bool isKnownLibFunction(Function &F, TargetLibraryInfo &TLI) {93LibFunc LF;9495// Either this is a normal library function or a "vectorizable"96// function. Not using the VFDatabase here because this query97// is related only to libraries handled via the TLI.98return TLI.getLibFunc(F, LF) ||99TLI.isKnownVectorFunctionInLibrary(F.getName());100}101102PreservedAnalyses ModuleInlinerPass::run(Module &M,103ModuleAnalysisManager &MAM) {104LLVM_DEBUG(dbgs() << "---- Module Inliner is Running ---- \n");105106auto &IAA = MAM.getResult<InlineAdvisorAnalysis>(M);107if (!IAA.tryCreate(Params, Mode, {},108InlineContext{LTOPhase, InlinePass::ModuleInliner})) {109M.getContext().emitError(110"Could not setup Inlining Advisor for the requested "111"mode and/or options");112return PreservedAnalyses::all();113}114115bool Changed = false;116117ProfileSummaryInfo *PSI = MAM.getCachedResult<ProfileSummaryAnalysis>(M);118119FunctionAnalysisManager &FAM =120MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();121122auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {123return FAM.getResult<TargetLibraryAnalysis>(F);124};125126InlineAdvisor &Advisor = getAdvisor(MAM, FAM, M);127Advisor.onPassEntry();128129auto AdvisorOnExit = make_scope_exit([&] { Advisor.onPassExit(); });130131// In the module inliner, a priority-based worklist is used for calls across132// the entire Module. With this module inliner, the inline order is not133// limited to bottom-up order. More globally scope inline order is enabled.134// Also, the inline deferral logic become unnecessary in this module inliner.135// It is possible to use other priority heuristics, e.g. profile-based136// heuristic.137//138// TODO: Here is a huge amount duplicate code between the module inliner and139// the SCC inliner, which need some refactoring.140auto Calls = getInlineOrder(FAM, Params, MAM, M);141assert(Calls != nullptr && "Expected an initialized InlineOrder");142143// Populate the initial list of calls in this module.144for (Function &F : M) {145auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);146for (Instruction &I : instructions(F))147if (auto *CB = dyn_cast<CallBase>(&I))148if (Function *Callee = CB->getCalledFunction()) {149if (!Callee->isDeclaration())150Calls->push({CB, -1});151else if (!isa<IntrinsicInst>(I)) {152using namespace ore;153setInlineRemark(*CB, "unavailable definition");154ORE.emit([&]() {155return OptimizationRemarkMissed(DEBUG_TYPE, "NoDefinition", &I)156<< NV("Callee", Callee) << " will not be inlined into "157<< NV("Caller", CB->getCaller())158<< " because its definition is unavailable"159<< setIsVerbose();160});161}162}163}164if (Calls->empty())165return PreservedAnalyses::all();166167// When inlining a callee produces new call sites, we want to keep track of168// the fact that they were inlined from the callee. This allows us to avoid169// infinite inlining in some obscure cases. To represent this, we use an170// index into the InlineHistory vector.171SmallVector<std::pair<Function *, int>, 16> InlineHistory;172173// Track the dead functions to delete once finished with inlining calls. We174// defer deleting these to make it easier to handle the call graph updates.175SmallVector<Function *, 4> DeadFunctions;176177// Loop forward over all of the calls.178while (!Calls->empty()) {179auto P = Calls->pop();180CallBase *CB = P.first;181const int InlineHistoryID = P.second;182Function &F = *CB->getCaller();183Function &Callee = *CB->getCalledFunction();184185LLVM_DEBUG(dbgs() << "Inlining calls in: " << F.getName() << "\n"186<< " Function size: " << F.getInstructionCount()187<< "\n");188(void)F;189190auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {191return FAM.getResult<AssumptionAnalysis>(F);192};193194if (InlineHistoryID != -1 &&195inlineHistoryIncludes(&Callee, InlineHistoryID, InlineHistory)) {196setInlineRemark(*CB, "recursive");197continue;198}199200auto Advice = Advisor.getAdvice(*CB, /*OnlyMandatory*/ false);201// Check whether we want to inline this callsite.202if (!Advice->isInliningRecommended()) {203Advice->recordUnattemptedInlining();204continue;205}206207// Setup the data structure used to plumb customization into the208// `InlineFunction` routine.209InlineFunctionInfo IFI(210GetAssumptionCache, PSI,211&FAM.getResult<BlockFrequencyAnalysis>(*(CB->getCaller())),212&FAM.getResult<BlockFrequencyAnalysis>(Callee));213214InlineResult IR =215InlineFunction(*CB, IFI, /*MergeAttributes=*/true,216&FAM.getResult<AAManager>(*CB->getCaller()));217if (!IR.isSuccess()) {218Advice->recordUnsuccessfulInlining(IR);219continue;220}221222Changed = true;223++NumInlined;224225LLVM_DEBUG(dbgs() << " Size after inlining: " << F.getInstructionCount()226<< "\n");227228// Add any new callsites to defined functions to the worklist.229if (!IFI.InlinedCallSites.empty()) {230int NewHistoryID = InlineHistory.size();231InlineHistory.push_back({&Callee, InlineHistoryID});232233for (CallBase *ICB : reverse(IFI.InlinedCallSites)) {234Function *NewCallee = ICB->getCalledFunction();235if (!NewCallee) {236// Try to promote an indirect (virtual) call without waiting for237// the post-inline cleanup and the next DevirtSCCRepeatedPass238// iteration because the next iteration may not happen and we may239// miss inlining it.240if (tryPromoteCall(*ICB))241NewCallee = ICB->getCalledFunction();242}243if (NewCallee)244if (!NewCallee->isDeclaration())245Calls->push({ICB, NewHistoryID});246}247}248249// For local functions, check whether this makes the callee trivially250// dead. In that case, we can drop the body of the function eagerly251// which may reduce the number of callers of other functions to one,252// changing inline cost thresholds.253bool CalleeWasDeleted = false;254if (Callee.hasLocalLinkage()) {255// To check this we also need to nuke any dead constant uses (perhaps256// made dead by this operation on other functions).257Callee.removeDeadConstantUsers();258// if (Callee.use_empty() && !CG.isLibFunction(Callee)) {259if (Callee.use_empty() && !isKnownLibFunction(Callee, GetTLI(Callee))) {260Calls->erase_if([&](const std::pair<CallBase *, int> &Call) {261return Call.first->getCaller() == &Callee;262});263// Clear the body and queue the function itself for deletion when we264// finish inlining.265// Note that after this point, it is an error to do anything other266// than use the callee's address or delete it.267Callee.dropAllReferences();268assert(!is_contained(DeadFunctions, &Callee) &&269"Cannot put cause a function to become dead twice!");270DeadFunctions.push_back(&Callee);271CalleeWasDeleted = true;272}273}274if (CalleeWasDeleted)275Advice->recordInliningWithCalleeDeleted();276else277Advice->recordInlining();278}279280// Now that we've finished inlining all of the calls across this module,281// delete all of the trivially dead functions.282//283// Note that this walks a pointer set which has non-deterministic order but284// that is OK as all we do is delete things and add pointers to unordered285// sets.286for (Function *DeadF : DeadFunctions) {287// Clear out any cached analyses.288FAM.clear(*DeadF, DeadF->getName());289290// And delete the actual function from the module.291M.getFunctionList().erase(DeadF);292293++NumDeleted;294}295296if (!Changed)297return PreservedAnalyses::all();298299return PreservedAnalyses::none();300}301302303