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