1f22ef01cSRoman Divacky //===- InlineSimple.cpp - Code to perform simple function inlining --------===//
2f22ef01cSRoman Divacky //
3f22ef01cSRoman Divacky //                     The LLVM Compiler Infrastructure
4f22ef01cSRoman Divacky //
5f22ef01cSRoman Divacky // This file is distributed under the University of Illinois Open Source
6f22ef01cSRoman Divacky // License. See LICENSE.TXT for details.
7f22ef01cSRoman Divacky //
8f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
9f22ef01cSRoman Divacky //
10f22ef01cSRoman Divacky // This file implements bottom-up inlining of functions into callees.
11f22ef01cSRoman Divacky //
12f22ef01cSRoman Divacky //===----------------------------------------------------------------------===//
13f22ef01cSRoman Divacky 
1439d628a0SDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
15f22ef01cSRoman Divacky #include "llvm/Analysis/InlineCost.h"
163ca95b02SDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h"
177d523365SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
187d523365SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h"
1991bc56edSDimitry Andric #include "llvm/IR/CallSite.h"
20139f7f9bSDimitry Andric #include "llvm/IR/CallingConv.h"
21139f7f9bSDimitry Andric #include "llvm/IR/DataLayout.h"
22139f7f9bSDimitry Andric #include "llvm/IR/Instructions.h"
23139f7f9bSDimitry Andric #include "llvm/IR/Module.h"
24139f7f9bSDimitry Andric #include "llvm/IR/Type.h"
257d523365SDimitry Andric #include "llvm/Transforms/IPO.h"
26d88c1a5aSDimitry Andric #include "llvm/Transforms/IPO/Inliner.h"
27f22ef01cSRoman Divacky 
28f22ef01cSRoman Divacky using namespace llvm;
29f22ef01cSRoman Divacky 
3091bc56edSDimitry Andric #define DEBUG_TYPE "inline"
3191bc56edSDimitry Andric 
32f22ef01cSRoman Divacky namespace {
33f22ef01cSRoman Divacky 
34*4ba319b5SDimitry Andric /// Actual inliner pass implementation.
35139f7f9bSDimitry Andric ///
36139f7f9bSDimitry Andric /// The common implementation of the inlining logic is shared between this
37139f7f9bSDimitry Andric /// inliner pass and the always inliner pass. The two passes use different cost
38139f7f9bSDimitry Andric /// analyses to determine when to inline.
39d88c1a5aSDimitry Andric class SimpleInliner : public LegacyInlinerBase {
40d88c1a5aSDimitry Andric 
41d88c1a5aSDimitry Andric   InlineParams Params;
42139f7f9bSDimitry Andric 
43f22ef01cSRoman Divacky public:
SimpleInliner()44d88c1a5aSDimitry Andric   SimpleInliner() : LegacyInlinerBase(ID), Params(llvm::getInlineParams()) {
452754fe60SDimitry Andric     initializeSimpleInlinerPass(*PassRegistry::getPassRegistry());
462754fe60SDimitry Andric   }
47139f7f9bSDimitry Andric 
SimpleInliner(InlineParams Params)48d88c1a5aSDimitry Andric   explicit SimpleInliner(InlineParams Params)
497a7e6055SDimitry Andric       : LegacyInlinerBase(ID), Params(std::move(Params)) {
502754fe60SDimitry Andric     initializeSimpleInlinerPass(*PassRegistry::getPassRegistry());
512754fe60SDimitry Andric   }
52139f7f9bSDimitry Andric 
53f22ef01cSRoman Divacky   static char ID; // Pass identification, replacement for typeid
54139f7f9bSDimitry Andric 
getInlineCost(CallSite CS)5591bc56edSDimitry Andric   InlineCost getInlineCost(CallSite CS) override {
567d523365SDimitry Andric     Function *Callee = CS.getCalledFunction();
577d523365SDimitry Andric     TargetTransformInfo &TTI = TTIWP->getTTI(*Callee);
582cab237bSDimitry Andric 
592cab237bSDimitry Andric     bool RemarksEnabled = false;
602cab237bSDimitry Andric     const auto &BBs = CS.getCaller()->getBasicBlockList();
612cab237bSDimitry Andric     if (!BBs.empty()) {
622cab237bSDimitry Andric       auto DI = OptimizationRemark(DEBUG_TYPE, "", DebugLoc(), &BBs.front());
632cab237bSDimitry Andric       if (DI.isEnabled())
642cab237bSDimitry Andric         RemarksEnabled = true;
652cab237bSDimitry Andric     }
662cab237bSDimitry Andric     OptimizationRemarkEmitter ORE(CS.getCaller());
672cab237bSDimitry Andric 
68d88c1a5aSDimitry Andric     std::function<AssumptionCache &(Function &)> GetAssumptionCache =
69d88c1a5aSDimitry Andric         [&](Function &F) -> AssumptionCache & {
70d88c1a5aSDimitry Andric       return ACT->getAssumptionCache(F);
71d88c1a5aSDimitry Andric     };
727a7e6055SDimitry Andric     return llvm::getInlineCost(CS, Params, TTI, GetAssumptionCache,
732cab237bSDimitry Andric                                /*GetBFI=*/None, PSI,
742cab237bSDimitry Andric                                RemarksEnabled ? &ORE : nullptr);
75f22ef01cSRoman Divacky   }
76139f7f9bSDimitry Andric 
7791bc56edSDimitry Andric   bool runOnSCC(CallGraphSCC &SCC) override;
7891bc56edSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
797d523365SDimitry Andric 
807d523365SDimitry Andric private:
817d523365SDimitry Andric   TargetTransformInfoWrapperPass *TTIWP;
82d88c1a5aSDimitry Andric 
83f22ef01cSRoman Divacky };
84139f7f9bSDimitry Andric 
85139f7f9bSDimitry Andric } // end anonymous namespace
86f22ef01cSRoman Divacky 
87f22ef01cSRoman Divacky char SimpleInliner::ID = 0;
88d88c1a5aSDimitry Andric INITIALIZE_PASS_BEGIN(SimpleInliner, "inline", "Function Integration/Inlining",
89d88c1a5aSDimitry Andric                       false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)9039d628a0SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
9191bc56edSDimitry Andric INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
923ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
937d523365SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
947d523365SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
95d88c1a5aSDimitry Andric INITIALIZE_PASS_END(SimpleInliner, "inline", "Function Integration/Inlining",
96d88c1a5aSDimitry Andric                     false, false)
97f22ef01cSRoman Divacky 
98f22ef01cSRoman Divacky Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); }
99f22ef01cSRoman Divacky 
createFunctionInliningPass(int Threshold)100f22ef01cSRoman Divacky Pass *llvm::createFunctionInliningPass(int Threshold) {
101d88c1a5aSDimitry Andric   return new SimpleInliner(llvm::getInlineParams(Threshold));
102f22ef01cSRoman Divacky }
103f22ef01cSRoman Divacky 
createFunctionInliningPass(unsigned OptLevel,unsigned SizeOptLevel,bool DisableInlineHotCallSite)10491bc56edSDimitry Andric Pass *llvm::createFunctionInliningPass(unsigned OptLevel,
1057a7e6055SDimitry Andric                                        unsigned SizeOptLevel,
1067a7e6055SDimitry Andric                                        bool DisableInlineHotCallSite) {
1077a7e6055SDimitry Andric   auto Param = llvm::getInlineParams(OptLevel, SizeOptLevel);
1087a7e6055SDimitry Andric   if (DisableInlineHotCallSite)
1097a7e6055SDimitry Andric     Param.HotCallSiteThreshold = 0;
1107a7e6055SDimitry Andric   return new SimpleInliner(Param);
111d88c1a5aSDimitry Andric }
112d88c1a5aSDimitry Andric 
createFunctionInliningPass(InlineParams & Params)113d88c1a5aSDimitry Andric Pass *llvm::createFunctionInliningPass(InlineParams &Params) {
114d88c1a5aSDimitry Andric   return new SimpleInliner(Params);
11591bc56edSDimitry Andric }
11691bc56edSDimitry Andric 
runOnSCC(CallGraphSCC & SCC)117139f7f9bSDimitry Andric bool SimpleInliner::runOnSCC(CallGraphSCC &SCC) {
1187d523365SDimitry Andric   TTIWP = &getAnalysis<TargetTransformInfoWrapperPass>();
119d88c1a5aSDimitry Andric   return LegacyInlinerBase::runOnSCC(SCC);
120f22ef01cSRoman Divacky }
121f22ef01cSRoman Divacky 
getAnalysisUsage(AnalysisUsage & AU) const122139f7f9bSDimitry Andric void SimpleInliner::getAnalysisUsage(AnalysisUsage &AU) const {
1237d523365SDimitry Andric   AU.addRequired<TargetTransformInfoWrapperPass>();
124d88c1a5aSDimitry Andric   LegacyInlinerBase::getAnalysisUsage(AU);
125139f7f9bSDimitry Andric }
126