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
28using namespace llvm;
29
30#define DEBUG_TYPE "inline"
31
32namespace {
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.
39class SimpleInliner : public LegacyInlinerBase {
40
41  InlineParams Params;
42
43public:
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
80private:
81  TargetTransformInfoWrapperPass *TTIWP;
82
83};
84
85} // end anonymous namespace
86
87char SimpleInliner::ID = 0;
88INITIALIZE_PASS_BEGIN(SimpleInliner, "inline", "Function Integration/Inlining",
89                      false, false)
90INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
91INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
92INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
93INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
94INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
95INITIALIZE_PASS_END(SimpleInliner, "inline", "Function Integration/Inlining",
96                    false, false)
97
98Pass *llvm::createFunctionInliningPass() { return new SimpleInliner(); }
99
100Pass *llvm::createFunctionInliningPass(int Threshold) {
101  return new SimpleInliner(llvm::getInlineParams(Threshold));
102}
103
104Pass *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
113Pass *llvm::createFunctionInliningPass(InlineParams &Params) {
114  return new SimpleInliner(Params);
115}
116
117bool SimpleInliner::runOnSCC(CallGraphSCC &SCC) {
118  TTIWP = &getAnalysis<TargetTransformInfoWrapperPass>();
119  return LegacyInlinerBase::runOnSCC(SCC);
120}
121
122void SimpleInliner::getAnalysisUsage(AnalysisUsage &AU) const {
123  AU.addRequired<TargetTransformInfoWrapperPass>();
124  LegacyInlinerBase::getAnalysisUsage(AU);
125}
126