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