1 //===- InlineSimple.cpp - Code to perform simple function inlining --------===// 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 bottom-up inlining of functions into callees. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/Analysis/AssumptionCache.h" 14 #include "llvm/Analysis/InlineCost.h" 15 #include "llvm/Analysis/ProfileSummaryInfo.h" 16 #include "llvm/Analysis/TargetLibraryInfo.h" 17 #include "llvm/Analysis/TargetTransformInfo.h" 18 #include "llvm/IR/CallSite.h" 19 #include "llvm/IR/CallingConv.h" 20 #include "llvm/IR/DataLayout.h" 21 #include "llvm/IR/Instructions.h" 22 #include "llvm/IR/Module.h" 23 #include "llvm/IR/Type.h" 24 #include "llvm/InitializePasses.h" 25 #include "llvm/Transforms/IPO.h" 26 #include "llvm/Transforms/IPO/Inliner.h" 27 28 using namespace llvm; 29 30 #define DEBUG_TYPE "inline" 31 32 namespace { 33 34 /// Actual inliner pass implementation. 35 /// 36 /// The common implementation of the inlining logic is shared between this 37 /// inliner pass and the always inliner pass. The two passes use different cost 38 /// analyses to determine when to inline. 39 class SimpleInliner : public LegacyInlinerBase { 40 41 InlineParams Params; 42 43 public: 44 SimpleInliner() : LegacyInlinerBase(ID), Params(llvm::getInlineParams()) { 45 initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); 46 } 47 48 explicit SimpleInliner(InlineParams Params) 49 : LegacyInlinerBase(ID), Params(std::move(Params)) { 50 initializeSimpleInlinerPass(*PassRegistry::getPassRegistry()); 51 } 52 53 static char ID; // Pass identification, replacement for typeid 54 55 InlineCost getInlineCost(CallSite CS) override { 56 Function *Callee = CS.getCalledFunction(); 57 TargetTransformInfo &TTI = TTIWP->getTTI(*Callee); 58 59 bool RemarksEnabled = false; 60 const auto &BBs = CS.getCaller()->getBasicBlockList(); 61 if (!BBs.empty()) { 62 auto DI = OptimizationRemark(DEBUG_TYPE, "", DebugLoc(), &BBs.front()); 63 if (DI.isEnabled()) 64 RemarksEnabled = true; 65 } 66 OptimizationRemarkEmitter ORE(CS.getCaller()); 67 68 std::function<AssumptionCache &(Function &)> GetAssumptionCache = 69 [&](Function &F) -> AssumptionCache & { 70 return ACT->getAssumptionCache(F); 71 }; 72 return llvm::getInlineCost( 73 cast<CallBase>(*CS.getInstruction()), Params, TTI, GetAssumptionCache, 74 /*GetBFI=*/None, PSI, RemarksEnabled ? &ORE : nullptr); 75 } 76 77 bool runOnSCC(CallGraphSCC &SCC) override; 78 void getAnalysisUsage(AnalysisUsage &AU) const override; 79 80 private: 81 TargetTransformInfoWrapperPass *TTIWP; 82 83 }; 84 85 } // end anonymous namespace 86 87 char SimpleInliner::ID = 0; 88 INITIALIZE_PASS_BEGIN(SimpleInliner, "inline", "Function Integration/Inlining", 89 false, false) 90 INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) 91 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) 92 INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass) 93 INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) 94 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) 95 INITIALIZE_PASS_END(SimpleInliner, "inline", "Function Integration/Inlining", 96 false, false) 97 98 Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); } 99 100 Pass *llvm::createFunctionInliningPass(int Threshold) { 101 return new SimpleInliner(llvm::getInlineParams(Threshold)); 102 } 103 104 Pass *llvm::createFunctionInliningPass(unsigned OptLevel, 105 unsigned SizeOptLevel, 106 bool DisableInlineHotCallSite) { 107 auto Param = llvm::getInlineParams(OptLevel, SizeOptLevel); 108 if (DisableInlineHotCallSite) 109 Param.HotCallSiteThreshold = 0; 110 return new SimpleInliner(Param); 111 } 112 113 Pass *llvm::createFunctionInliningPass(InlineParams &Params) { 114 return new SimpleInliner(Params); 115 } 116 117 bool SimpleInliner::runOnSCC(CallGraphSCC &SCC) { 118 TTIWP = &getAnalysis<TargetTransformInfoWrapperPass>(); 119 return LegacyInlinerBase::runOnSCC(SCC); 120 } 121 122 void SimpleInliner::getAnalysisUsage(AnalysisUsage &AU) const { 123 AU.addRequired<TargetTransformInfoWrapperPass>(); 124 LegacyInlinerBase::getAnalysisUsage(AU); 125 } 126