diff options
Diffstat (limited to 'llvm/include')
-rw-r--r-- | llvm/include/llvm/CGData/CodeGenData.h | 11 | ||||
-rw-r--r-- | llvm/include/llvm/CGData/StableFunctionMap.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/CGData/StableFunctionMapRecord.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/CodeGen/GlobalMergeFunctions.h | 85 | ||||
-rw-r--r-- | llvm/include/llvm/CodeGen/Passes.h | 3 | ||||
-rw-r--r-- | llvm/include/llvm/InitializePasses.h | 1 | ||||
-rw-r--r-- | llvm/include/llvm/LinkAllPasses.h | 1 | ||||
-rw-r--r-- | llvm/include/llvm/Passes/CodeGenPassBuilder.h | 4 | ||||
-rw-r--r-- | llvm/include/llvm/Passes/MachinePassRegistry.def | 1 | ||||
-rw-r--r-- | llvm/include/llvm/Target/CGPassBuilderOption.h | 1 |
10 files changed, 109 insertions, 2 deletions
diff --git a/llvm/include/llvm/CGData/CodeGenData.h b/llvm/include/llvm/CGData/CodeGenData.h index 5d7c747..da0e412 100644 --- a/llvm/include/llvm/CGData/CodeGenData.h +++ b/llvm/include/llvm/CGData/CodeGenData.h @@ -145,6 +145,9 @@ public: const OutlinedHashTree *getOutlinedHashTree() { return PublishedHashTree.get(); } + const StableFunctionMap *getStableFunctionMap() { + return PublishedStableFunctionMap.get(); + } /// Returns true if we should write codegen data. bool emitCGData() { return EmitCGData; } @@ -169,10 +172,18 @@ inline bool hasOutlinedHashTree() { return CodeGenData::getInstance().hasOutlinedHashTree(); } +inline bool hasStableFunctionMap() { + return CodeGenData::getInstance().hasStableFunctionMap(); +} + inline const OutlinedHashTree *getOutlinedHashTree() { return CodeGenData::getInstance().getOutlinedHashTree(); } +inline const StableFunctionMap *getStableFunctionMap() { + return CodeGenData::getInstance().getStableFunctionMap(); +} + inline bool emitCGData() { return CodeGenData::getInstance().emitCGData(); } inline void diff --git a/llvm/include/llvm/CGData/StableFunctionMap.h b/llvm/include/llvm/CGData/StableFunctionMap.h index a2e1abb..8881adf 100644 --- a/llvm/include/llvm/CGData/StableFunctionMap.h +++ b/llvm/include/llvm/CGData/StableFunctionMap.h @@ -110,7 +110,7 @@ struct StableFunctionMap { size_t size(SizeType Type = UniqueHashCount) const; /// Finalize the stable function map by trimming content. - void finalize(); + void finalize(bool SkipTrim = false); private: /// Insert a `StableFunctionEntry` into the function map directly. This diff --git a/llvm/include/llvm/CGData/StableFunctionMapRecord.h b/llvm/include/llvm/CGData/StableFunctionMapRecord.h index 0517f2c..f9b3ed7 100644 --- a/llvm/include/llvm/CGData/StableFunctionMapRecord.h +++ b/llvm/include/llvm/CGData/StableFunctionMapRecord.h @@ -49,7 +49,7 @@ struct StableFunctionMapRecord { void deserializeYAML(yaml::Input &YIS); /// Finalize the stable function map by trimming content. - void finalize() { FunctionMap->finalize(); } + void finalize(bool SkipTrim = false) { FunctionMap->finalize(SkipTrim); } /// Merge the stable function map into this one. void merge(const StableFunctionMapRecord &Other) { diff --git a/llvm/include/llvm/CodeGen/GlobalMergeFunctions.h b/llvm/include/llvm/CodeGen/GlobalMergeFunctions.h new file mode 100644 index 0000000..82239e0 --- /dev/null +++ b/llvm/include/llvm/CodeGen/GlobalMergeFunctions.h @@ -0,0 +1,85 @@ +//===------ GlobalMergeFunctions.h - Global merge functions -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This pass defines the implementation of a function merging mechanism +// that utilizes a stable function hash to track differences in constants and +// identify potential merge candidates. The process involves two rounds: +// 1. The first round collects stable function hashes and identifies merge +// candidates with matching hashes. It also computes the set of parameters +// that point to different constants during the stable function merge. +// 2. The second round leverages this collected global function information to +// optimistically create a merged function in each module context, ensuring +// correct transformation. +// Similar to the global outliner, this approach uses the linker's deduplication +// (ICF) to fold identical merged functions, thereby reducing the final binary +// size. The work is inspired by the concepts discussed in the following paper: +// https://dl.acm.org/doi/pdf/10.1145/3652032.3657575. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_GLOBALMERGEFUNCTIONS_H +#define LLVM_CODEGEN_GLOBALMERGEFUNCTIONS_H + +#include "llvm/CGData/StableFunctionMap.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Pass.h" + +enum class HashFunctionMode { + Local, + BuildingHashFuncion, + UsingHashFunction, +}; + +namespace llvm { + +// A vector of locations (the pair of (instruction, operand) indices) reachable +// from a parameter. +using ParamLocs = SmallVector<IndexPair, 4>; +// A vector of parameters +using ParamLocsVecTy = SmallVector<ParamLocs, 8>; + +/// GlobalMergeFunc is a ModulePass that implements a function merging mechanism +/// using stable function hashes. It identifies and merges functions with +/// matching hashes across modules to optimize binary size. +class GlobalMergeFunc { + HashFunctionMode MergerMode = HashFunctionMode::Local; + + std::unique_ptr<StableFunctionMap> LocalFunctionMap; + + const ModuleSummaryIndex *Index; + +public: + /// The suffix used to identify the merged function that parameterizes + /// the constant values. Note that the original function, without this suffix, + /// becomes a thunk supplying contexts to the merged function via parameters. + static constexpr const char MergingInstanceSuffix[] = ".Tgm"; + + GlobalMergeFunc(const ModuleSummaryIndex *Index) : Index(Index) {}; + + void initializeMergerMode(const Module &M); + + bool run(Module &M); + + /// Analyze module to create stable function into LocalFunctionMap. + void analyze(Module &M); + + /// Emit LocalFunctionMap into __llvm_merge section. + void emitFunctionMap(Module &M); + + /// Merge functions in the module using the given function map. + bool merge(Module &M, const StableFunctionMap *FunctionMap); +}; + +/// Global function merging pass for new pass manager. +struct GlobalMergeFuncPass : public PassInfoMixin<GlobalMergeFuncPass> { + PreservedAnalyses run(Module &M, AnalysisManager<Module> &); +}; + +} // end namespace llvm +#endif // LLVM_CODEGEN_GLOBALMERGEFUNCTIONS_H diff --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h index 72054ab..708ff46 100644 --- a/llvm/include/llvm/CodeGen/Passes.h +++ b/llvm/include/llvm/CodeGen/Passes.h @@ -507,6 +507,9 @@ namespace llvm { /// This pass frees the memory occupied by the MachineFunction. FunctionPass *createFreeMachineFunctionPass(); + /// This pass performs merging similar functions globally. + ModulePass *createGlobalMergeFuncPass(); + /// This pass performs outlining on machine instructions directly before /// printing assembly. ModulePass *createMachineOutlinerPass(bool RunOnAllFunctions = true); diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index bf934de..0e16627 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -123,6 +123,7 @@ void initializeGCEmptyBasicBlocksPass(PassRegistry &); void initializeGCMachineCodeAnalysisPass(PassRegistry &); void initializeGCModuleInfoPass(PassRegistry &); void initializeGVNLegacyPassPass(PassRegistry &); +void initializeGlobalMergeFuncPassWrapperPass(PassRegistry &); void initializeGlobalMergePass(PassRegistry &); void initializeGlobalsAAWrapperPassPass(PassRegistry &); void initializeHardwareLoopsLegacyPass(PassRegistry &); diff --git a/llvm/include/llvm/LinkAllPasses.h b/llvm/include/llvm/LinkAllPasses.h index 8d89cc8..54245ca 100644 --- a/llvm/include/llvm/LinkAllPasses.h +++ b/llvm/include/llvm/LinkAllPasses.h @@ -79,6 +79,7 @@ struct ForcePassLinking { (void)llvm::createDomOnlyViewerWrapperPassPass(); (void)llvm::createDomViewerWrapperPassPass(); (void)llvm::createAlwaysInlinerLegacyPass(); + (void)llvm::createGlobalMergeFuncPass(); (void)llvm::createGlobalsAAWrapperPass(); (void)llvm::createInstSimplifyLegacyPass(); (void)llvm::createInstructionCombiningPass(); diff --git a/llvm/include/llvm/Passes/CodeGenPassBuilder.h b/llvm/include/llvm/Passes/CodeGenPassBuilder.h index 9e95625..3f7d226 100644 --- a/llvm/include/llvm/Passes/CodeGenPassBuilder.h +++ b/llvm/include/llvm/Passes/CodeGenPassBuilder.h @@ -35,6 +35,7 @@ #include "llvm/CodeGen/FinalizeISel.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GlobalMerge.h" +#include "llvm/CodeGen/GlobalMergeFunctions.h" #include "llvm/CodeGen/IndirectBrExpand.h" #include "llvm/CodeGen/InterleavedAccess.h" #include "llvm/CodeGen/InterleavedLoadCombine.h" @@ -713,6 +714,9 @@ void CodeGenPassBuilder<Derived, TargetMachineT>::addIRPasses( // Convert conditional moves to conditional jumps when profitable. if (getOptLevel() != CodeGenOptLevel::None && !Opt.DisableSelectOptimize) addPass(SelectOptimizePass(&TM)); + + if (Opt.EnableGlobalMergeFunc) + addPass(GlobalMergeFuncPass()); } /// Turn exception handling constructs into something the code generators can diff --git a/llvm/include/llvm/Passes/MachinePassRegistry.def b/llvm/include/llvm/Passes/MachinePassRegistry.def index 9d12a12..3ceb5ca 100644 --- a/llvm/include/llvm/Passes/MachinePassRegistry.def +++ b/llvm/include/llvm/Passes/MachinePassRegistry.def @@ -29,6 +29,7 @@ MODULE_PASS("jmc-instrumenter", JMCInstrumenterPass()) MODULE_PASS("lower-emutls", LowerEmuTLSPass()) MODULE_PASS("pre-isel-intrinsic-lowering", PreISelIntrinsicLoweringPass()) MODULE_PASS("shadow-stack-gc-lowering", ShadowStackGCLoweringPass()) +MODULE_PASS("global-merge-func", GlobalMergeFuncPass()) #undef MODULE_PASS #ifndef FUNCTION_ANALYSIS diff --git a/llvm/include/llvm/Target/CGPassBuilderOption.h b/llvm/include/llvm/Target/CGPassBuilderOption.h index 8ab6d63..29bdb9c 100644 --- a/llvm/include/llvm/Target/CGPassBuilderOption.h +++ b/llvm/include/llvm/Target/CGPassBuilderOption.h @@ -31,6 +31,7 @@ struct CGPassBuilderOption { bool DisableVerify = false; bool EnableImplicitNullChecks = false; bool EnableBlockPlacementStats = false; + bool EnableGlobalMergeFunc = false; bool EnableMachineFunctionSplitter = false; bool MISchedPostRA = false; bool EarlyLiveIntervals = false; |