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