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