xref: /llvm-project/bolt/include/bolt/Passes/JTFootprintReduction.h (revision a5f3d1a803020167bd9d494a8a3921e7dcc1550a)
1 //===- bolt/Passes/JTFootprintReduction.h -----------------------*- 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 // Jump table footprint reduction pass
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef BOLT_PASSES_JT_FOOTPRINT_REDUCTION_H
14 #define BOLT_PASSES_JT_FOOTPRINT_REDUCTION_H
15 
16 #include "bolt/Passes/BinaryPasses.h"
17 
18 namespace llvm {
19 namespace bolt {
20 class DataflowInfoManager;
21 
22 /// This pass identify indirect jumps to jump tables and reduce their entries
23 /// size from 8 to 4 bytes. For PIC jump tables, it will remove the PIC code
24 /// (since BOLT only process static code and it makes no sense to use expensive
25 /// PIC-style jumps in static code).
26 class JTFootprintReduction : public BinaryFunctionPass {
27   uint64_t TotalJTScore{0};
28   uint64_t TotalJTs{0};
29   uint64_t TotalJTsDenied{0};
30   uint64_t OptimizedScore{0};
31   uint64_t IndJmps{0};
32   uint64_t IndJmpsDenied{0};
33   uint64_t NumJTsBadMatch{0};
34   uint64_t NumJTsNoReg{0};
35   uint64_t BytesSaved{0};
36   DenseSet<JumpTable *> BlacklistedJTs;
37   DenseSet<const BinaryFunction *> Modified;
38 
39   /// Check if \p Function presents jump tables where all jump locations can
40   /// be safely changed to use a different code sequence. If this is true, we
41   /// will be able to emit the whole table with a smaller entry size.
42   void checkOpportunities(BinaryFunction &Function, DataflowInfoManager &Info);
43 
44   /// The Non-PIC jump table optimization consists of reducing the jump table
45   /// entry size from 8 to 4 bytes. For that, we need to change the jump code
46   /// sequence from a single jmp * instruction to a pair of load32zext-jmp
47   /// instructions that depend on the availability of an extra register.
48   /// This saves dcache/dTLB at the expense of icache.
49   bool tryOptimizeNonPIC(BinaryContext &BC, BinaryBasicBlock &BB,
50                          BinaryBasicBlock::iterator Inst, uint64_t JTAddr,
51                          JumpTable *JumpTable, DataflowInfoManager &Info);
52 
53   /// The PIC jump table optimization consists of "de-pic-ifying" it, since the
54   /// PIC jump sequence is larger than its non-PIC counterpart, saving icache.
55   bool tryOptimizePIC(BinaryContext &BC, BinaryBasicBlock &BB,
56                       BinaryBasicBlock::iterator Inst, uint64_t JTAddr,
57                       JumpTable *JumpTable, DataflowInfoManager &Info);
58 
59   /// Run a pass for \p Function
60   void optimizeFunction(BinaryFunction &Function, DataflowInfoManager &Info);
61 
62 public:
JTFootprintReduction(const cl::opt<bool> & PrintPass)63   explicit JTFootprintReduction(const cl::opt<bool> &PrintPass)
64       : BinaryFunctionPass(PrintPass) {}
65 
66   /// BinaryPass interface functions
getName()67   const char *getName() const override { return "jt-footprint-reduction"; }
shouldPrint(const BinaryFunction & BF)68   bool shouldPrint(const BinaryFunction &BF) const override {
69     return BinaryFunctionPass::shouldPrint(BF) && Modified.count(&BF) > 0;
70   }
71   Error runOnFunctions(BinaryContext &BC) override;
72 };
73 
74 } // namespace bolt
75 } // namespace llvm
76 
77 #endif
78