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