xref: /llvm-project/bolt/include/bolt/Passes/Inliner.h (revision a5f3d1a803020167bd9d494a8a3921e7dcc1550a)
1 //===- bolt/Passes/Inliner.h - Inlining infra for BOLT ----------*- C++ -*-===//
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 // The set of optimization/analysis passes that run on BinaryFunctions.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef BOLT_PASSES_INLINER_H
14 #define BOLT_PASSES_INLINER_H
15 
16 #include "bolt/Passes/BinaryPasses.h"
17 
18 namespace llvm {
19 namespace bolt {
20 
21 enum InliningType : char {
22   INL_NONE = 0, /// Cannot inline
23   INL_TAILCALL, /// Can inline at tail call site
24   INL_ANY       /// Can inline at any call site
25 };
26 
27 struct InliningInfo {
28   InliningType Type{INL_NONE};
29   uint64_t SizeAfterInlining{0};
30   uint64_t SizeAfterTailCallInlining{0};
31 
TypeInliningInfo32   InliningInfo(InliningType Type = INL_NONE) : Type(Type) {}
33 };
34 
35 /// Check if the inliner can handle inlining of \p BF.
36 InliningInfo getInliningInfo(const BinaryFunction &BF);
37 
38 class Inliner : public BinaryFunctionPass {
39   std::unordered_map<const BinaryFunction *, InliningInfo> InliningCandidates;
40 
41   /// Count total amount of bytes inlined for all instances of Inliner.
42   /// Note that this number could be negative indicating that the inliner
43   /// reduced the size.
44   int64_t TotalInlinedBytes{0};
45 
46   /// Dynamic count of calls eliminated.
47   uint64_t NumInlinedDynamicCalls{0};
48 
49   /// Number of call sites that were inlined.
50   uint64_t NumInlinedCallSites{0};
51 
52   /// Size in bytes of a regular call instruction.
53   static uint64_t SizeOfCallInst;
54 
55   /// Size in bytes of a tail call instruction.
56   static uint64_t SizeOfTailCallInst;
57 
58   /// Set of functions modified by inlining (used for printing).
59   std::unordered_set<const BinaryFunction *> Modified;
60 
61   /// Return the size in bytes of a regular call instruction.
62   uint64_t getSizeOfCallInst(const BinaryContext &BC);
63 
64   /// Return the size in bytes of a tail call instruction.
65   uint64_t getSizeOfTailCallInst(const BinaryContext &BC);
66 
67   void findInliningCandidates(BinaryContext &BC);
68 
69   bool inlineCallsInFunction(BinaryFunction &Function);
70 
71   /// Inline a function call \p CallInst to function \p Callee.
72   ///
73   /// Return the location (basic block and instruction iterator) where the code
74   /// of the caller function continues after the inlined code.
75   std::pair<BinaryBasicBlock *, BinaryBasicBlock::iterator>
76   inlineCall(BinaryBasicBlock &CallerBB, BinaryBasicBlock::iterator CallInst,
77              const BinaryFunction &Callee);
78 
79 public:
Inliner(const cl::opt<bool> & PrintPass)80   explicit Inliner(const cl::opt<bool> &PrintPass)
81       : BinaryFunctionPass(PrintPass) {}
82 
getName()83   const char *getName() const override { return "inlining"; }
84 
shouldPrint(const BinaryFunction & BF)85   bool shouldPrint(const BinaryFunction &BF) const override {
86     return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0;
87   }
88 
89   Error runOnFunctions(BinaryContext &BC) override;
90 };
91 
92 } // namespace bolt
93 } // namespace llvm
94 
95 #endif
96