xref: /llvm-project/bolt/include/bolt/Passes/SplitFunctions.h (revision a5f3d1a803020167bd9d494a8a3921e7dcc1550a)
1 //===- bolt/Passes/SplitFunctions.h - Split function code -------*- 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 #ifndef BOLT_PASSES_SPLIT_FUNCTIONS_H
10 #define BOLT_PASSES_SPLIT_FUNCTIONS_H
11 
12 #include "bolt/Core/FunctionLayout.h"
13 #include "bolt/Passes/BinaryPasses.h"
14 #include "llvm/ADT/Hashing.h"
15 #include "llvm/Support/CommandLine.h"
16 #include <atomic>
17 
18 namespace llvm {
19 namespace bolt {
20 
21 /// Strategy used to partition blocks into fragments.
22 enum SplitFunctionsStrategy : char {
23   /// Split each function into a hot and cold fragment using profiling
24   /// information.
25   Profile2 = 0,
26   /// Split each function into a hot, warm, and cold fragment using
27   /// profiling information.
28   CDSplit,
29   /// Split each function into a hot and cold fragment at a randomly chosen
30   /// split point (ignoring any available profiling information).
31   Random2,
32   /// Split each function into N fragments at a randomly chosen split points
33   /// (ignoring any available profiling information).
34   RandomN,
35   /// Split all basic blocks of each function into fragments such that each
36   /// fragment contains exactly a single basic block.
37   All
38 };
39 
40 class SplitStrategy {
41 public:
42   using BlockIt = BinaryFunction::BasicBlockOrderType::iterator;
43 
44   virtual ~SplitStrategy() = default;
45   virtual bool canSplit(const BinaryFunction &BF) = 0;
46   virtual bool compactFragments() = 0;
47   virtual void fragment(const BlockIt Start, const BlockIt End) = 0;
48 };
49 
50 /// Split function code in multiple parts.
51 class SplitFunctions : public BinaryFunctionPass {
52 private:
53   /// Split function body into fragments.
54   void splitFunction(BinaryFunction &Function, SplitStrategy &Strategy);
55 
56   struct TrampolineKey {
57     FragmentNum SourceFN = FragmentNum::main();
58     const MCSymbol *Target = nullptr;
59 
60     TrampolineKey() = default;
TrampolineKeyTrampolineKey61     TrampolineKey(const FragmentNum SourceFN, const MCSymbol *const Target)
62         : SourceFN(SourceFN), Target(Target) {}
63 
getEmptyKeyTrampolineKey64     static inline TrampolineKey getEmptyKey() { return TrampolineKey(); };
getTombstoneKeyTrampolineKey65     static inline TrampolineKey getTombstoneKey() {
66       return TrampolineKey(FragmentNum(UINT_MAX), nullptr);
67     };
getHashValueTrampolineKey68     static unsigned getHashValue(const TrampolineKey &Val) {
69       return llvm::hash_combine(Val.SourceFN.get(), Val.Target);
70     }
isEqualTrampolineKey71     static bool isEqual(const TrampolineKey &LHS, const TrampolineKey &RHS) {
72       return LHS.SourceFN == RHS.SourceFN && LHS.Target == RHS.Target;
73     }
74   };
75 
76   /// Map basic block labels to their trampoline block labels.
77   using TrampolineSetType =
78       DenseMap<TrampolineKey, const MCSymbol *, TrampolineKey>;
79 
80   using BasicBlockOrderType = BinaryFunction::BasicBlockOrderType;
81 
82   /// Create trampoline landing pads for exception handling code to guarantee
83   /// that every landing pad is placed in the same function fragment as the
84   /// corresponding thrower block. The trampoline landing pad, when created,
85   /// will redirect the execution to the real landing pad in a different
86   /// fragment.
87   TrampolineSetType createEHTrampolines(BinaryFunction &Function) const;
88 
89   /// Merge trampolines into \p Layout without trampolines. The merge will place
90   /// a trampoline immediately before its destination. Used to revert the effect
91   /// of trampolines after createEHTrampolines().
92   BasicBlockOrderType
93   mergeEHTrampolines(BinaryFunction &BF, BasicBlockOrderType &Layout,
94                      const TrampolineSetType &Trampolines) const;
95 
96   std::atomic<uint64_t> SplitBytesHot{0ull};
97   std::atomic<uint64_t> SplitBytesCold{0ull};
98 
99 public:
SplitFunctions(const cl::opt<bool> & PrintPass)100   explicit SplitFunctions(const cl::opt<bool> &PrintPass)
101       : BinaryFunctionPass(PrintPass) {}
102 
103   bool shouldOptimize(const BinaryFunction &BF) const override;
104 
getName()105   const char *getName() const override { return "split-functions"; }
106 
107   Error runOnFunctions(BinaryContext &BC) override;
108 };
109 
110 } // namespace bolt
111 } // namespace llvm
112 
113 #endif
114