| //===- InlineAlways.cpp - Code to inline always_inline functions ----------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file implements a custom inliner that handles only functions that | |
| // are marked as "always inline". | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/Transforms/IPO/AlwaysInliner.h" | |
| #include "llvm/ADT/SetVector.h" | |
| #include "llvm/Analysis/AssumptionCache.h" | |
| #include "llvm/Analysis/InlineCost.h" | |
| #include "llvm/Analysis/TargetLibraryInfo.h" | |
| #include "llvm/IR/CallSite.h" | |
| #include "llvm/IR/CallingConv.h" | |
| #include "llvm/IR/DataLayout.h" | |
| #include "llvm/IR/Instructions.h" | |
| #include "llvm/IR/Module.h" | |
| #include "llvm/IR/Type.h" | |
| #include "llvm/InitializePasses.h" | |
| #include "llvm/Transforms/IPO.h" | |
| #include "llvm/Transforms/IPO/Inliner.h" | |
| #include "llvm/Transforms/Utils/Cloning.h" | |
| #include "llvm/Transforms/Utils/ModuleUtils.h" | |
| using namespace llvm; | |
| #define DEBUG_TYPE "inline" | |
| PreservedAnalyses AlwaysInlinerPass::run(Module &M, | |
| ModuleAnalysisManager &MAM) { | |
| // Add inline assumptions during code generation. | |
| FunctionAnalysisManager &FAM = | |
| MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); | |
| std::function<AssumptionCache &(Function &)> GetAssumptionCache = | |
| [&](Function &F) -> AssumptionCache & { | |
| return FAM.getResult<AssumptionAnalysis>(F); | |
| }; | |
| InlineFunctionInfo IFI(/*cg=*/nullptr, &GetAssumptionCache); | |
| SmallSetVector<CallSite, 16> Calls; | |
| bool Changed = false; | |
| SmallVector<Function *, 16> InlinedFunctions; | |
| for (Function &F : M) | |
| if (!F.isDeclaration() && F.hasFnAttribute(Attribute::AlwaysInline) && | |
| isInlineViable(F)) { | |
| Calls.clear(); | |
| for (User *U : F.users()) | |
| if (auto CS = CallSite(U)) | |
| if (CS.getCalledFunction() == &F) | |
| Calls.insert(CS); | |
| for (CallSite CS : Calls) | |
| // FIXME: We really shouldn't be able to fail to inline at this point! | |
| // We should do something to log or check the inline failures here. | |
| Changed |= | |
| InlineFunction(CS, IFI, /*CalleeAAR=*/nullptr, InsertLifetime); | |
| // Remember to try and delete this function afterward. This both avoids | |
| // re-walking the rest of the module and avoids dealing with any iterator | |
| // invalidation issues while deleting functions. | |
| InlinedFunctions.push_back(&F); | |
| } | |
| // Remove any live functions. | |
| erase_if(InlinedFunctions, [&](Function *F) { | |
| F->removeDeadConstantUsers(); | |
| return !F->isDefTriviallyDead(); | |
| }); | |
| // Delete the non-comdat ones from the module and also from our vector. | |
| auto NonComdatBegin = partition( | |
| InlinedFunctions, [&](Function *F) { return F->hasComdat(); }); | |
| for (Function *F : make_range(NonComdatBegin, InlinedFunctions.end())) | |
| M.getFunctionList().erase(F); | |
| InlinedFunctions.erase(NonComdatBegin, InlinedFunctions.end()); | |
| if (!InlinedFunctions.empty()) { | |
| // Now we just have the comdat functions. Filter out the ones whose comdats | |
| // are not actually dead. | |
| filterDeadComdatFunctions(M, InlinedFunctions); | |
| // The remaining functions are actually dead. | |
| for (Function *F : InlinedFunctions) | |
| M.getFunctionList().erase(F); | |
| } | |
| return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); | |
| } | |
| namespace { | |
| /// Inliner pass which only handles "always inline" functions. | |
| /// | |
| /// Unlike the \c AlwaysInlinerPass, this uses the more heavyweight \c Inliner | |
| /// base class to provide several facilities such as array alloca merging. | |
| class AlwaysInlinerLegacyPass : public LegacyInlinerBase { | |
| public: | |
| AlwaysInlinerLegacyPass() : LegacyInlinerBase(ID, /*InsertLifetime*/ true) { | |
| initializeAlwaysInlinerLegacyPassPass(*PassRegistry::getPassRegistry()); | |
| } | |
| AlwaysInlinerLegacyPass(bool InsertLifetime) | |
| : LegacyInlinerBase(ID, InsertLifetime) { | |
| initializeAlwaysInlinerLegacyPassPass(*PassRegistry::getPassRegistry()); | |
| } | |
| /// Main run interface method. We override here to avoid calling skipSCC(). | |
| bool runOnSCC(CallGraphSCC &SCC) override { return inlineCalls(SCC); } | |
| static char ID; // Pass identification, replacement for typeid | |
| InlineCost getInlineCost(CallSite CS) override; | |
| using llvm::Pass::doFinalization; | |
| bool doFinalization(CallGraph &CG) override { | |
| return removeDeadFunctions(CG, /*AlwaysInlineOnly=*/true); | |
| } | |
| }; | |
| } | |
| char AlwaysInlinerLegacyPass::ID = 0; | |
| INITIALIZE_PASS_BEGIN(AlwaysInlinerLegacyPass, "always-inline", | |
| "Inliner for always_inline functions", false, false) | |
| INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) | |
| INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) | |
| INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass) | |
| INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) | |
| INITIALIZE_PASS_END(AlwaysInlinerLegacyPass, "always-inline", | |
| "Inliner for always_inline functions", false, false) | |
| Pass *llvm::createAlwaysInlinerLegacyPass(bool InsertLifetime) { | |
| return new AlwaysInlinerLegacyPass(InsertLifetime); | |
| } | |
| /// Get the inline cost for the always-inliner. | |
| /// | |
| /// The always inliner *only* handles functions which are marked with the | |
| /// attribute to force inlining. As such, it is dramatically simpler and avoids | |
| /// using the powerful (but expensive) inline cost analysis. Instead it uses | |
| /// a very simple and boring direct walk of the instructions looking for | |
| /// impossible-to-inline constructs. | |
| /// | |
| /// Note, it would be possible to go to some lengths to cache the information | |
| /// computed here, but as we only expect to do this for relatively few and | |
| /// small functions which have the explicit attribute to force inlining, it is | |
| /// likely not worth it in practice. | |
| InlineCost AlwaysInlinerLegacyPass::getInlineCost(CallSite CS) { | |
| Function *Callee = CS.getCalledFunction(); | |
| // Only inline direct calls to functions with always-inline attributes | |
| // that are viable for inlining. | |
| if (!Callee) | |
| return InlineCost::getNever("indirect call"); | |
| // FIXME: We shouldn't even get here for declarations. | |
| if (Callee->isDeclaration()) | |
| return InlineCost::getNever("no definition"); | |
| if (!CS.hasFnAttr(Attribute::AlwaysInline)) | |
| return InlineCost::getNever("no alwaysinline attribute"); | |
| auto IsViable = isInlineViable(*Callee); | |
| if (!IsViable) | |
| return InlineCost::getNever(IsViable.message); | |
| return InlineCost::getAlways("always inliner"); | |
| } |