Skip to content

[CGData] Global Merge Functions #112671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions llvm/include/llvm/CGData/CodeGenData.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ class CodeGenData {
const OutlinedHashTree *getOutlinedHashTree() {
return PublishedHashTree.get();
}
const StableFunctionMap *getStableFunctionMap() {
return PublishedStableFunctionMap.get();
}

/// Returns true if we should write codegen data.
bool emitCGData() { return EmitCGData; }
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/InitializePasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ void initializeGCEmptyBasicBlocksPass(PassRegistry &);
void initializeGCMachineCodeAnalysisPass(PassRegistry &);
void initializeGCModuleInfoPass(PassRegistry &);
void initializeGVNLegacyPassPass(PassRegistry &);
void initializeGlobalMergeFuncPass(PassRegistry &);
void initializeGlobalMergePass(PassRegistry &);
void initializeGlobalsAAWrapperPassPass(PassRegistry &);
void initializeHardwareLoopsLegacyPass(PassRegistry &);
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/LinkAllPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/Transforms/IPO.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ enum class PassSummaryAction {
Export, ///< Export information to summary.
};

/// createGlobalMergeFuncPass - This pass generates merged instances by
/// parameterizing distinct constants across similar functions, utilizing stable
/// function hash information.
Pass *createGlobalMergeFuncPass();

} // End llvm namespace

#endif
78 changes: 78 additions & 0 deletions llvm/include/llvm/Transforms/IPO/GlobalMergeFunctions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//===------ 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_TRANSFORMS_IPO_GLOBALMERGEFUNCTIONS_H
#define LLVM_TRANSFORMS_IPO_GLOBALMERGEFUNCTIONS_H

#include "llvm/CGData/StableFunctionMap.h"
#include "llvm/IR/Module.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 : public ModulePass {
HashFunctionMode MergerMode = HashFunctionMode::Local;

std::unique_ptr<StableFunctionMap> LocalFunctionMap;

public:
static char ID;

GlobalMergeFunc();

StringRef getPassName() const override;

void getAnalysisUsage(AnalysisUsage &AU) const override;

void initializeMergerMode(const Module &M);

bool runOnModule(Module &M) override;

/// 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);
};

} // end namespace llvm
#endif // LLVM_TRANSFORMS_IPO_GLOBALMERGEFUNCTIONS_H
3 changes: 3 additions & 0 deletions llvm/lib/CodeGen/TargetPassConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ static cl::opt<RunOutliner> EnableMachineOutliner(
"Disable all outlining"),
// Sentinel value for unspecified option.
clEnumValN(RunOutliner::AlwaysOutline, "", "")));
cl::opt<bool> EnableGlobalMergeFunc(
"enable-global-merge-func", cl::Hidden,
cl::desc("Enable global merge functions that are based on hash function"));
// Disable the pass to fix unwind information. Whether the pass is included in
// the pipeline is controlled via the target options, this option serves as
// manual override.
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/LTO/LTO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/IPO/GlobalMergeFunctions.h"
#include "llvm/Transforms/IPO/MemProfContextDisambiguation.h"
#include "llvm/Transforms/IPO/WholeProgramDevirt.h"
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Transforms/IPO/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ add_llvm_component_library(LLVMipo
GlobalDCE.cpp
GlobalOpt.cpp
GlobalSplit.cpp
GlobalMergeFunctions.cpp
HotColdSplitting.cpp
IPO.cpp
IROutliner.cpp
Expand Down Expand Up @@ -60,6 +61,7 @@ add_llvm_component_library(LLVMipo
Analysis
BitReader
BitWriter
CGData
Core
FrontendOpenMP
InstCombine
Expand Down
Loading
Loading