xref: /freebsd/contrib/llvm-project/llvm/include/llvm/CodeGen/GlobalMergeFunctions.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===------ GlobalMergeFunctions.h - Global merge functions -----*- 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 // This pass defines the implementation of a function merging mechanism
10 // that utilizes a stable function hash to track differences in constants and
11 // identify potential merge candidates. The process involves two rounds:
12 // 1. The first round collects stable function hashes and identifies merge
13 //    candidates with matching hashes. It also computes the set of parameters
14 //    that point to different constants during the stable function merge.
15 // 2. The second round leverages this collected global function information to
16 //    optimistically create a merged function in each module context, ensuring
17 //    correct transformation.
18 // Similar to the global outliner, this approach uses the linker's deduplication
19 // (ICF) to fold identical merged functions, thereby reducing the final binary
20 // size. The work is inspired by the concepts discussed in the following paper:
21 // https://dl.acm.org/doi/pdf/10.1145/3652032.3657575.
22 //
23 //===----------------------------------------------------------------------===//
24 
25 #ifndef LLVM_CODEGEN_GLOBALMERGEFUNCTIONS_H
26 #define LLVM_CODEGEN_GLOBALMERGEFUNCTIONS_H
27 
28 #include "llvm/CGData/StableFunctionMap.h"
29 #include "llvm/IR/Module.h"
30 #include "llvm/IR/PassManager.h"
31 #include "llvm/Pass.h"
32 
33 enum class HashFunctionMode {
34   Local,
35   BuildingHashFuncion,
36   UsingHashFunction,
37 };
38 
39 namespace llvm {
40 
41 // A vector of locations (the pair of (instruction, operand) indices) reachable
42 // from a parameter.
43 using ParamLocs = SmallVector<IndexPair, 4>;
44 // A vector of parameters
45 using ParamLocsVecTy = SmallVector<ParamLocs, 8>;
46 
47 /// GlobalMergeFunc is a ModulePass that implements a function merging mechanism
48 /// using stable function hashes. It identifies and merges functions with
49 /// matching hashes across modules to optimize binary size.
50 class GlobalMergeFunc {
51   HashFunctionMode MergerMode = HashFunctionMode::Local;
52 
53   std::unique_ptr<StableFunctionMap> LocalFunctionMap;
54 
55   const ModuleSummaryIndex *Index;
56 
57 public:
58   /// The suffix used to identify the merged function that parameterizes
59   /// the constant values. Note that the original function, without this suffix,
60   /// becomes a thunk supplying contexts to the merged function via parameters.
61   static constexpr const char MergingInstanceSuffix[] = ".Tgm";
62 
GlobalMergeFunc(const ModuleSummaryIndex * Index)63   GlobalMergeFunc(const ModuleSummaryIndex *Index) : Index(Index) {};
64 
65   void initializeMergerMode(const Module &M);
66 
67   bool run(Module &M);
68 
69   /// Analyze module to create stable function into LocalFunctionMap.
70   void analyze(Module &M);
71 
72   /// Emit LocalFunctionMap into __llvm_merge section.
73   void emitFunctionMap(Module &M);
74 
75   /// Merge functions in the module using the given function map.
76   bool merge(Module &M, const StableFunctionMap *FunctionMap);
77 };
78 
79 /// Global function merging pass for new pass manager.
80 struct GlobalMergeFuncPass : public PassInfoMixin<GlobalMergeFuncPass> {
81   const ModuleSummaryIndex *ImportSummary = nullptr;
82   GlobalMergeFuncPass() = default;
GlobalMergeFuncPassGlobalMergeFuncPass83   GlobalMergeFuncPass(const ModuleSummaryIndex *ImportSummary)
84       : ImportSummary(ImportSummary) {}
85   PreservedAnalyses run(Module &M, AnalysisManager<Module> &);
86 };
87 
88 } // end namespace llvm
89 #endif // LLVM_CODEGEN_GLOBALMERGEFUNCTIONS_H
90