xref: /llvm-project/bolt/include/bolt/Passes/IdenticalCodeFolding.h (revision 3c357a49d61e4c81a1ac016502ee504521bc8dda)
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