1 //===- bolt/Passes/IdenticalCodeFolding.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 #ifndef BOLT_PASSES_IDENTICAL_CODE_FOLDING_H 10 #define BOLT_PASSES_IDENTICAL_CODE_FOLDING_H 11 12 #include "bolt/Core/BinaryFunction.h" 13 #include "bolt/Passes/BinaryPasses.h" 14 #include "llvm/ADT/SparseBitVector.h" 15 16 namespace llvm { 17 namespace bolt { 18 19 /// An optimization that replaces references to identical functions with 20 /// references to a single one of them. 21 /// 22 class IdenticalCodeFolding : public BinaryFunctionPass { 23 protected: 24 /// Return true if the function is safe to fold. 25 bool shouldOptimize(const BinaryFunction &BF) const override; 26 27 public: 28 enum class ICFLevel { 29 None, /// No ICF. (Default) 30 Safe, /// Safe ICF. 31 All, /// Aggressive ICF. 32 }; 33 explicit IdenticalCodeFolding(const cl::opt<bool> &PrintPass) 34 : BinaryFunctionPass(PrintPass) {} 35 36 const char *getName() const override { return "identical-code-folding"; } 37 Error runOnFunctions(BinaryContext &BC) override; 38 39 private: 40 /// Bit vector of memory addresses of vtables. 41 llvm::SparseBitVector<> VTableBitVector; 42 43 /// Return true if the memory address is in a vtable. 44 bool isAddressInVTable(uint64_t Address) const { 45 return VTableBitVector.test(Address / 8); 46 } 47 48 /// Mark memory address of a vtable as used. 49 void setAddressUsedInVTable(uint64_t Address) { 50 VTableBitVector.set(Address / 8); 51 } 52 53 /// Scan symbol table and mark memory addresses of 54 /// vtables. 55 void initVTableReferences(const BinaryContext &BC); 56 57 /// Analyze code section and relocations and mark functions that are not 58 /// safe to fold. 59 void markFunctionsUnsafeToFold(BinaryContext &BC); 60 61 /// Process static and dynamic relocations in the data sections to identify 62 /// function references, and mark them as unsafe to fold. It filters out 63 /// symbol references that are in vtables. 64 void analyzeDataRelocations(BinaryContext &BC); 65 66 /// Process functions that have been disassembled and mark functions that are 67 /// used in non-control flow instructions as unsafe to fold. 68 void analyzeFunctions(BinaryContext &BC); 69 }; 70 71 class DeprecatedICFNumericOptionParser 72 : public cl::parser<IdenticalCodeFolding::ICFLevel> { 73 public: 74 explicit DeprecatedICFNumericOptionParser(cl::Option &O) 75 : cl::parser<IdenticalCodeFolding::ICFLevel>(O) {} 76 77 bool parse(cl::Option &O, StringRef ArgName, StringRef Arg, 78 IdenticalCodeFolding::ICFLevel &Value) { 79 if (Arg == "0" || Arg == "1") { 80 Value = (Arg == "0") ? IdenticalCodeFolding::ICFLevel::None 81 : IdenticalCodeFolding::ICFLevel::All; 82 errs() << formatv("BOLT-WARNING: specifying numeric value \"{0}\" " 83 "for option -{1} is deprecated\n", 84 Arg, ArgName); 85 return false; 86 } 87 return cl::parser<IdenticalCodeFolding::ICFLevel>::parse(O, ArgName, Arg, 88 Value); 89 } 90 }; 91 92 } // namespace bolt 93 } // namespace llvm 94 95 #endif 96