xref: /llvm-project/llvm/lib/CodeGen/GlobalMergeFunctions.cpp (revision 815343e7dd32cc4c5c903ac52daf87aaa4e4cd6e)
1d23c5c2dSKyungwoo Lee //===---- GlobalMergeFunctions.cpp - Global merge functions -------*- C++ -===//
2d23c5c2dSKyungwoo Lee //
3d23c5c2dSKyungwoo Lee // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4d23c5c2dSKyungwoo Lee // See https://llvm.org/LICENSE.txt for license information.
5d23c5c2dSKyungwoo Lee // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d23c5c2dSKyungwoo Lee //
7d23c5c2dSKyungwoo Lee //===----------------------------------------------------------------------===//
8d23c5c2dSKyungwoo Lee //
9d23c5c2dSKyungwoo Lee // This pass implements the global merge function pass.
10d23c5c2dSKyungwoo Lee //
11d23c5c2dSKyungwoo Lee //===----------------------------------------------------------------------===//
12d23c5c2dSKyungwoo Lee 
13d23c5c2dSKyungwoo Lee #include "llvm/CodeGen/GlobalMergeFunctions.h"
14d23c5c2dSKyungwoo Lee #include "llvm/ADT/Statistic.h"
15d23c5c2dSKyungwoo Lee #include "llvm/Analysis/ModuleSummaryAnalysis.h"
16d23c5c2dSKyungwoo Lee #include "llvm/CGData/CodeGenData.h"
17d23c5c2dSKyungwoo Lee #include "llvm/IR/IRBuilder.h"
18d23c5c2dSKyungwoo Lee #include "llvm/IR/StructuralHash.h"
19d23c5c2dSKyungwoo Lee #include "llvm/InitializePasses.h"
20d23c5c2dSKyungwoo Lee #include "llvm/Support/CommandLine.h"
21d23c5c2dSKyungwoo Lee #include "llvm/Transforms/Utils/ModuleUtils.h"
22d23c5c2dSKyungwoo Lee 
23d23c5c2dSKyungwoo Lee #define DEBUG_TYPE "global-merge-func"
24d23c5c2dSKyungwoo Lee 
25d23c5c2dSKyungwoo Lee using namespace llvm;
26d23c5c2dSKyungwoo Lee using namespace llvm::support;
27d23c5c2dSKyungwoo Lee 
28d23c5c2dSKyungwoo Lee static cl::opt<bool> DisableCGDataForMerging(
29d23c5c2dSKyungwoo Lee     "disable-cgdata-for-merging", cl::Hidden,
30d23c5c2dSKyungwoo Lee     cl::desc("Disable codegen data for function merging. Local "
31d23c5c2dSKyungwoo Lee              "merging is still enabled within a module."),
32d23c5c2dSKyungwoo Lee     cl::init(false));
33d23c5c2dSKyungwoo Lee 
34d23c5c2dSKyungwoo Lee STATISTIC(NumMergedFunctions,
35d23c5c2dSKyungwoo Lee           "Number of functions that are actually merged using function hash");
36d23c5c2dSKyungwoo Lee STATISTIC(NumAnalyzedModues, "Number of modules that are analyzed");
37d23c5c2dSKyungwoo Lee STATISTIC(NumAnalyzedFunctions, "Number of functions that are analyzed");
38d23c5c2dSKyungwoo Lee STATISTIC(NumEligibleFunctions, "Number of functions that are eligible");
39d23c5c2dSKyungwoo Lee 
40d23c5c2dSKyungwoo Lee /// Returns true if the \OpIdx operand of \p CI is the callee operand.
41d23c5c2dSKyungwoo Lee static bool isCalleeOperand(const CallBase *CI, unsigned OpIdx) {
42d23c5c2dSKyungwoo Lee   return &CI->getCalledOperandUse() == &CI->getOperandUse(OpIdx);
43d23c5c2dSKyungwoo Lee }
44d23c5c2dSKyungwoo Lee 
45d23c5c2dSKyungwoo Lee static bool canParameterizeCallOperand(const CallBase *CI, unsigned OpIdx) {
46d23c5c2dSKyungwoo Lee   if (CI->isInlineAsm())
47d23c5c2dSKyungwoo Lee     return false;
48d23c5c2dSKyungwoo Lee   Function *Callee = CI->getCalledOperand()
49d23c5c2dSKyungwoo Lee                          ? dyn_cast_or_null<Function>(
50d23c5c2dSKyungwoo Lee                                CI->getCalledOperand()->stripPointerCasts())
51d23c5c2dSKyungwoo Lee                          : nullptr;
52d23c5c2dSKyungwoo Lee   if (Callee) {
53d23c5c2dSKyungwoo Lee     if (Callee->isIntrinsic())
54d23c5c2dSKyungwoo Lee       return false;
55d23c5c2dSKyungwoo Lee     auto Name = Callee->getName();
56d23c5c2dSKyungwoo Lee     // objc_msgSend stubs must be called, and can't have their address taken.
57d23c5c2dSKyungwoo Lee     if (Name.starts_with("objc_msgSend$"))
58d23c5c2dSKyungwoo Lee       return false;
59d23c5c2dSKyungwoo Lee     // Calls to dtrace probes must generate unique patchpoints.
60d23c5c2dSKyungwoo Lee     if (Name.starts_with("__dtrace"))
61d23c5c2dSKyungwoo Lee       return false;
62d23c5c2dSKyungwoo Lee   }
63*815343e7SKyungwoo Lee   if (isCalleeOperand(CI, OpIdx)) {
64d23c5c2dSKyungwoo Lee     // The operand is the callee and it has already been signed. Ignore this
65d23c5c2dSKyungwoo Lee     // because we cannot add another ptrauth bundle to the call instruction.
66*815343e7SKyungwoo Lee     if (CI->getOperandBundle(LLVMContext::OB_ptrauth).has_value())
67*815343e7SKyungwoo Lee       return false;
68*815343e7SKyungwoo Lee   } else {
69*815343e7SKyungwoo Lee     // The target of the arc-attached call must be a constant and cannot be
70*815343e7SKyungwoo Lee     // parameterized.
71*815343e7SKyungwoo Lee     if (CI->isOperandBundleOfType(LLVMContext::OB_clang_arc_attachedcall,
72*815343e7SKyungwoo Lee                                   OpIdx))
73d23c5c2dSKyungwoo Lee       return false;
74d23c5c2dSKyungwoo Lee   }
75d23c5c2dSKyungwoo Lee   return true;
76d23c5c2dSKyungwoo Lee }
77d23c5c2dSKyungwoo Lee 
78d23c5c2dSKyungwoo Lee /// Returns true if function \p F is eligible for merging.
79d23c5c2dSKyungwoo Lee bool isEligibleFunction(Function *F) {
80d23c5c2dSKyungwoo Lee   if (F->isDeclaration())
81d23c5c2dSKyungwoo Lee     return false;
82d23c5c2dSKyungwoo Lee 
83d23c5c2dSKyungwoo Lee   if (F->hasFnAttribute(llvm::Attribute::NoMerge) ||
84d23c5c2dSKyungwoo Lee       F->hasFnAttribute(llvm::Attribute::AlwaysInline))
85d23c5c2dSKyungwoo Lee     return false;
86d23c5c2dSKyungwoo Lee 
87d23c5c2dSKyungwoo Lee   if (F->hasAvailableExternallyLinkage())
88d23c5c2dSKyungwoo Lee     return false;
89d23c5c2dSKyungwoo Lee 
90d23c5c2dSKyungwoo Lee   if (F->getFunctionType()->isVarArg())
91d23c5c2dSKyungwoo Lee     return false;
92d23c5c2dSKyungwoo Lee 
93d23c5c2dSKyungwoo Lee   if (F->getCallingConv() == CallingConv::SwiftTail)
94d23c5c2dSKyungwoo Lee     return false;
95d23c5c2dSKyungwoo Lee 
96d23c5c2dSKyungwoo Lee   // If function contains callsites with musttail, if we merge
97d23c5c2dSKyungwoo Lee   // it, the merged function will have the musttail callsite, but
98d23c5c2dSKyungwoo Lee   // the number of parameters can change, thus the parameter count
99d23c5c2dSKyungwoo Lee   // of the callsite will mismatch with the function itself.
100d23c5c2dSKyungwoo Lee   for (const BasicBlock &BB : *F) {
101d23c5c2dSKyungwoo Lee     for (const Instruction &I : BB) {
102d23c5c2dSKyungwoo Lee       const auto *CB = dyn_cast<CallBase>(&I);
103d23c5c2dSKyungwoo Lee       if (CB && CB->isMustTailCall())
104d23c5c2dSKyungwoo Lee         return false;
105d23c5c2dSKyungwoo Lee     }
106d23c5c2dSKyungwoo Lee   }
107d23c5c2dSKyungwoo Lee 
108d23c5c2dSKyungwoo Lee   return true;
109d23c5c2dSKyungwoo Lee }
110d23c5c2dSKyungwoo Lee 
111b3134fa2SKyungwoo Lee static bool isEligibleInstructionForConstantSharing(const Instruction *I) {
112d23c5c2dSKyungwoo Lee   switch (I->getOpcode()) {
113d23c5c2dSKyungwoo Lee   case Instruction::Load:
114d23c5c2dSKyungwoo Lee   case Instruction::Store:
115d23c5c2dSKyungwoo Lee   case Instruction::Call:
116d23c5c2dSKyungwoo Lee   case Instruction::Invoke:
117d23c5c2dSKyungwoo Lee     return true;
118d23c5c2dSKyungwoo Lee   default:
119d23c5c2dSKyungwoo Lee     return false;
120d23c5c2dSKyungwoo Lee   }
121d23c5c2dSKyungwoo Lee }
122d23c5c2dSKyungwoo Lee 
123b3134fa2SKyungwoo Lee // This function takes an instruction, \p I, and an operand index, \p OpIdx.
124b3134fa2SKyungwoo Lee // It returns true if the operand should be ignored in the hash computation.
125b3134fa2SKyungwoo Lee // If \p OpIdx is out of range based on the other instruction context, it cannot
126b3134fa2SKyungwoo Lee // be ignored.
127d23c5c2dSKyungwoo Lee static bool ignoreOp(const Instruction *I, unsigned OpIdx) {
128b3134fa2SKyungwoo Lee   if (OpIdx >= I->getNumOperands())
129b3134fa2SKyungwoo Lee     return false;
130d23c5c2dSKyungwoo Lee 
131b3134fa2SKyungwoo Lee   if (!isEligibleInstructionForConstantSharing(I))
132d23c5c2dSKyungwoo Lee     return false;
133d23c5c2dSKyungwoo Lee 
134d23c5c2dSKyungwoo Lee   if (!isa<Constant>(I->getOperand(OpIdx)))
135d23c5c2dSKyungwoo Lee     return false;
136d23c5c2dSKyungwoo Lee 
137d23c5c2dSKyungwoo Lee   if (const auto *CI = dyn_cast<CallBase>(I))
138d23c5c2dSKyungwoo Lee     return canParameterizeCallOperand(CI, OpIdx);
139d23c5c2dSKyungwoo Lee 
140d23c5c2dSKyungwoo Lee   return true;
141d23c5c2dSKyungwoo Lee }
142d23c5c2dSKyungwoo Lee 
143d23c5c2dSKyungwoo Lee static Value *createCast(IRBuilder<> &Builder, Value *V, Type *DestTy) {
144d23c5c2dSKyungwoo Lee   Type *SrcTy = V->getType();
145d23c5c2dSKyungwoo Lee   if (SrcTy->isStructTy()) {
146d23c5c2dSKyungwoo Lee     assert(DestTy->isStructTy());
147d23c5c2dSKyungwoo Lee     assert(SrcTy->getStructNumElements() == DestTy->getStructNumElements());
148d23c5c2dSKyungwoo Lee     Value *Result = PoisonValue::get(DestTy);
149d23c5c2dSKyungwoo Lee     for (unsigned int I = 0, E = SrcTy->getStructNumElements(); I < E; ++I) {
150d23c5c2dSKyungwoo Lee       Value *Element =
151d23c5c2dSKyungwoo Lee           createCast(Builder, Builder.CreateExtractValue(V, ArrayRef(I)),
152d23c5c2dSKyungwoo Lee                      DestTy->getStructElementType(I));
153d23c5c2dSKyungwoo Lee 
154d23c5c2dSKyungwoo Lee       Result = Builder.CreateInsertValue(Result, Element, ArrayRef(I));
155d23c5c2dSKyungwoo Lee     }
156d23c5c2dSKyungwoo Lee     return Result;
157d23c5c2dSKyungwoo Lee   }
158d23c5c2dSKyungwoo Lee   assert(!DestTy->isStructTy());
159d23c5c2dSKyungwoo Lee   if (auto *SrcAT = dyn_cast<ArrayType>(SrcTy)) {
160d23c5c2dSKyungwoo Lee     auto *DestAT = dyn_cast<ArrayType>(DestTy);
161d23c5c2dSKyungwoo Lee     assert(DestAT);
162d23c5c2dSKyungwoo Lee     assert(SrcAT->getNumElements() == DestAT->getNumElements());
16320b071c0SPedro Lobo     Value *Result = PoisonValue::get(DestTy);
164d23c5c2dSKyungwoo Lee     for (unsigned int I = 0, E = SrcAT->getNumElements(); I < E; ++I) {
165d23c5c2dSKyungwoo Lee       Value *Element =
166d23c5c2dSKyungwoo Lee           createCast(Builder, Builder.CreateExtractValue(V, ArrayRef(I)),
167d23c5c2dSKyungwoo Lee                      DestAT->getElementType());
168d23c5c2dSKyungwoo Lee 
169d23c5c2dSKyungwoo Lee       Result = Builder.CreateInsertValue(Result, Element, ArrayRef(I));
170d23c5c2dSKyungwoo Lee     }
171d23c5c2dSKyungwoo Lee     return Result;
172d23c5c2dSKyungwoo Lee   }
173d23c5c2dSKyungwoo Lee   assert(!DestTy->isArrayTy());
174d23c5c2dSKyungwoo Lee   if (SrcTy->isIntegerTy() && DestTy->isPointerTy())
175d23c5c2dSKyungwoo Lee     return Builder.CreateIntToPtr(V, DestTy);
176d23c5c2dSKyungwoo Lee   if (SrcTy->isPointerTy() && DestTy->isIntegerTy())
177d23c5c2dSKyungwoo Lee     return Builder.CreatePtrToInt(V, DestTy);
178d23c5c2dSKyungwoo Lee   return Builder.CreateBitCast(V, DestTy);
179d23c5c2dSKyungwoo Lee }
180d23c5c2dSKyungwoo Lee 
181d23c5c2dSKyungwoo Lee void GlobalMergeFunc::analyze(Module &M) {
182d23c5c2dSKyungwoo Lee   ++NumAnalyzedModues;
183d23c5c2dSKyungwoo Lee   for (Function &Func : M) {
184d23c5c2dSKyungwoo Lee     ++NumAnalyzedFunctions;
185d23c5c2dSKyungwoo Lee     if (isEligibleFunction(&Func)) {
186d23c5c2dSKyungwoo Lee       ++NumEligibleFunctions;
187d23c5c2dSKyungwoo Lee 
188d23c5c2dSKyungwoo Lee       auto FI = llvm::StructuralHashWithDifferences(Func, ignoreOp);
189d23c5c2dSKyungwoo Lee 
190d23c5c2dSKyungwoo Lee       // Convert the operand map to a vector for a serialization-friendly
191d23c5c2dSKyungwoo Lee       // format.
192d23c5c2dSKyungwoo Lee       IndexOperandHashVecType IndexOperandHashes;
193d23c5c2dSKyungwoo Lee       for (auto &Pair : *FI.IndexOperandHashMap)
194d23c5c2dSKyungwoo Lee         IndexOperandHashes.emplace_back(Pair);
195d23c5c2dSKyungwoo Lee 
196d23c5c2dSKyungwoo Lee       StableFunction SF(FI.FunctionHash, get_stable_name(Func.getName()).str(),
197d23c5c2dSKyungwoo Lee                         M.getModuleIdentifier(), FI.IndexInstruction->size(),
198d23c5c2dSKyungwoo Lee                         std::move(IndexOperandHashes));
199d23c5c2dSKyungwoo Lee 
200d23c5c2dSKyungwoo Lee       LocalFunctionMap->insert(SF);
201d23c5c2dSKyungwoo Lee     }
202d23c5c2dSKyungwoo Lee   }
203d23c5c2dSKyungwoo Lee }
204d23c5c2dSKyungwoo Lee 
205d23c5c2dSKyungwoo Lee /// Tuple to hold function info to process merging.
206d23c5c2dSKyungwoo Lee struct FuncMergeInfo {
207d23c5c2dSKyungwoo Lee   StableFunctionMap::StableFunctionEntry *SF;
208d23c5c2dSKyungwoo Lee   Function *F;
209b3134fa2SKyungwoo Lee   IndexInstrMap *IndexInstruction;
210d23c5c2dSKyungwoo Lee   FuncMergeInfo(StableFunctionMap::StableFunctionEntry *SF, Function *F,
211b3134fa2SKyungwoo Lee                 IndexInstrMap *IndexInstruction)
212d23c5c2dSKyungwoo Lee       : SF(SF), F(F), IndexInstruction(std::move(IndexInstruction)) {}
213d23c5c2dSKyungwoo Lee };
214d23c5c2dSKyungwoo Lee 
215d23c5c2dSKyungwoo Lee // Given the func info, and the parameterized locations, create and return
216d23c5c2dSKyungwoo Lee // a new merged function by replacing the original constants with the new
217d23c5c2dSKyungwoo Lee // parameters.
218d23c5c2dSKyungwoo Lee static Function *createMergedFunction(FuncMergeInfo &FI,
219d23c5c2dSKyungwoo Lee                                       ArrayRef<Type *> ConstParamTypes,
220d23c5c2dSKyungwoo Lee                                       const ParamLocsVecTy &ParamLocsVec) {
221d23c5c2dSKyungwoo Lee   // Synthesize a new merged function name by appending ".Tgm" to the root
222d23c5c2dSKyungwoo Lee   // function's name.
223d23c5c2dSKyungwoo Lee   auto *MergedFunc = FI.F;
224d23c5c2dSKyungwoo Lee   std::string NewFunctionName =
225d23c5c2dSKyungwoo Lee       MergedFunc->getName().str() + GlobalMergeFunc::MergingInstanceSuffix;
226d23c5c2dSKyungwoo Lee   auto *M = MergedFunc->getParent();
227d23c5c2dSKyungwoo Lee   assert(!M->getFunction(NewFunctionName));
228d23c5c2dSKyungwoo Lee 
229d23c5c2dSKyungwoo Lee   FunctionType *OrigTy = MergedFunc->getFunctionType();
230d23c5c2dSKyungwoo Lee   // Get the original params' types.
231d23c5c2dSKyungwoo Lee   SmallVector<Type *> ParamTypes(OrigTy->param_begin(), OrigTy->param_end());
232d23c5c2dSKyungwoo Lee   // Append const parameter types that are passed in.
233d23c5c2dSKyungwoo Lee   ParamTypes.append(ConstParamTypes.begin(), ConstParamTypes.end());
234d23c5c2dSKyungwoo Lee   FunctionType *FuncType = FunctionType::get(OrigTy->getReturnType(),
235d23c5c2dSKyungwoo Lee                                              ParamTypes, /*isVarArg=*/false);
236d23c5c2dSKyungwoo Lee 
237d23c5c2dSKyungwoo Lee   // Declare a new function
238d23c5c2dSKyungwoo Lee   Function *NewFunction =
239d23c5c2dSKyungwoo Lee       Function::Create(FuncType, MergedFunc->getLinkage(), NewFunctionName);
240d23c5c2dSKyungwoo Lee   if (auto *SP = MergedFunc->getSubprogram())
241d23c5c2dSKyungwoo Lee     NewFunction->setSubprogram(SP);
242d23c5c2dSKyungwoo Lee   NewFunction->copyAttributesFrom(MergedFunc);
243d23c5c2dSKyungwoo Lee   NewFunction->setDLLStorageClass(GlobalValue::DefaultStorageClass);
244d23c5c2dSKyungwoo Lee 
245d23c5c2dSKyungwoo Lee   NewFunction->setLinkage(GlobalValue::InternalLinkage);
246d23c5c2dSKyungwoo Lee   NewFunction->addFnAttr(Attribute::NoInline);
247d23c5c2dSKyungwoo Lee 
248d23c5c2dSKyungwoo Lee   // Add the new function before the root function.
249d23c5c2dSKyungwoo Lee   M->getFunctionList().insert(MergedFunc->getIterator(), NewFunction);
250d23c5c2dSKyungwoo Lee 
251d23c5c2dSKyungwoo Lee   // Move the body of MergedFunc into the NewFunction.
252d23c5c2dSKyungwoo Lee   NewFunction->splice(NewFunction->begin(), MergedFunc);
253d23c5c2dSKyungwoo Lee 
254d23c5c2dSKyungwoo Lee   // Update the original args by the new args.
255d23c5c2dSKyungwoo Lee   auto NewArgIter = NewFunction->arg_begin();
256d23c5c2dSKyungwoo Lee   for (Argument &OrigArg : MergedFunc->args()) {
257d23c5c2dSKyungwoo Lee     Argument &NewArg = *NewArgIter++;
258d23c5c2dSKyungwoo Lee     OrigArg.replaceAllUsesWith(&NewArg);
259d23c5c2dSKyungwoo Lee   }
260d23c5c2dSKyungwoo Lee 
261d23c5c2dSKyungwoo Lee   // Replace the original Constants by the new args.
262d23c5c2dSKyungwoo Lee   unsigned NumOrigArgs = MergedFunc->arg_size();
263d23c5c2dSKyungwoo Lee   for (unsigned ParamIdx = 0; ParamIdx < ParamLocsVec.size(); ++ParamIdx) {
264d23c5c2dSKyungwoo Lee     Argument *NewArg = NewFunction->getArg(NumOrigArgs + ParamIdx);
265d23c5c2dSKyungwoo Lee     for (auto [InstIndex, OpndIndex] : ParamLocsVec[ParamIdx]) {
266d23c5c2dSKyungwoo Lee       auto *Inst = FI.IndexInstruction->lookup(InstIndex);
267d23c5c2dSKyungwoo Lee       auto *OrigC = Inst->getOperand(OpndIndex);
268d23c5c2dSKyungwoo Lee       if (OrigC->getType() != NewArg->getType()) {
269d23c5c2dSKyungwoo Lee         IRBuilder<> Builder(Inst->getParent(), Inst->getIterator());
270d23c5c2dSKyungwoo Lee         Inst->setOperand(OpndIndex,
271d23c5c2dSKyungwoo Lee                          createCast(Builder, NewArg, OrigC->getType()));
272d23c5c2dSKyungwoo Lee       } else {
273d23c5c2dSKyungwoo Lee         Inst->setOperand(OpndIndex, NewArg);
274d23c5c2dSKyungwoo Lee       }
275d23c5c2dSKyungwoo Lee     }
276d23c5c2dSKyungwoo Lee   }
277d23c5c2dSKyungwoo Lee 
278d23c5c2dSKyungwoo Lee   return NewFunction;
279d23c5c2dSKyungwoo Lee }
280d23c5c2dSKyungwoo Lee 
281d23c5c2dSKyungwoo Lee // Given the original function (Thunk) and the merged function (ToFunc), create
282d23c5c2dSKyungwoo Lee // a thunk to the merged function.
283d23c5c2dSKyungwoo Lee static void createThunk(FuncMergeInfo &FI, ArrayRef<Constant *> Params,
284d23c5c2dSKyungwoo Lee                         Function *ToFunc) {
285d23c5c2dSKyungwoo Lee   auto *Thunk = FI.F;
286d23c5c2dSKyungwoo Lee 
287d23c5c2dSKyungwoo Lee   assert(Thunk->arg_size() + Params.size() ==
288d23c5c2dSKyungwoo Lee          ToFunc->getFunctionType()->getNumParams());
289d23c5c2dSKyungwoo Lee   Thunk->dropAllReferences();
290d23c5c2dSKyungwoo Lee 
291d23c5c2dSKyungwoo Lee   BasicBlock *BB = BasicBlock::Create(Thunk->getContext(), "", Thunk);
292d23c5c2dSKyungwoo Lee   IRBuilder<> Builder(BB);
293d23c5c2dSKyungwoo Lee 
294d23c5c2dSKyungwoo Lee   SmallVector<Value *> Args;
295d23c5c2dSKyungwoo Lee   unsigned ParamIdx = 0;
296d23c5c2dSKyungwoo Lee   FunctionType *ToFuncTy = ToFunc->getFunctionType();
297d23c5c2dSKyungwoo Lee 
298d23c5c2dSKyungwoo Lee   // Add arguments which are passed through Thunk.
299d23c5c2dSKyungwoo Lee   for (Argument &AI : Thunk->args()) {
300d23c5c2dSKyungwoo Lee     Args.push_back(createCast(Builder, &AI, ToFuncTy->getParamType(ParamIdx)));
301d23c5c2dSKyungwoo Lee     ++ParamIdx;
302d23c5c2dSKyungwoo Lee   }
303d23c5c2dSKyungwoo Lee 
304d23c5c2dSKyungwoo Lee   // Add new arguments defined by Params.
305d23c5c2dSKyungwoo Lee   for (auto *Param : Params) {
306d23c5c2dSKyungwoo Lee     assert(ParamIdx < ToFuncTy->getNumParams());
307d23c5c2dSKyungwoo Lee     Args.push_back(
308d23c5c2dSKyungwoo Lee         createCast(Builder, Param, ToFuncTy->getParamType(ParamIdx)));
309d23c5c2dSKyungwoo Lee     ++ParamIdx;
310d23c5c2dSKyungwoo Lee   }
311d23c5c2dSKyungwoo Lee 
312d23c5c2dSKyungwoo Lee   CallInst *CI = Builder.CreateCall(ToFunc, Args);
313d23c5c2dSKyungwoo Lee   bool isSwiftTailCall = ToFunc->getCallingConv() == CallingConv::SwiftTail &&
314d23c5c2dSKyungwoo Lee                          Thunk->getCallingConv() == CallingConv::SwiftTail;
315d23c5c2dSKyungwoo Lee   CI->setTailCallKind(isSwiftTailCall ? llvm::CallInst::TCK_MustTail
316d23c5c2dSKyungwoo Lee                                       : llvm::CallInst::TCK_Tail);
317d23c5c2dSKyungwoo Lee   CI->setCallingConv(ToFunc->getCallingConv());
318d23c5c2dSKyungwoo Lee   CI->setAttributes(ToFunc->getAttributes());
319d23c5c2dSKyungwoo Lee   if (Thunk->getReturnType()->isVoidTy())
320d23c5c2dSKyungwoo Lee     Builder.CreateRetVoid();
321d23c5c2dSKyungwoo Lee   else
322d23c5c2dSKyungwoo Lee     Builder.CreateRet(createCast(Builder, CI, Thunk->getReturnType()));
323d23c5c2dSKyungwoo Lee }
324d23c5c2dSKyungwoo Lee 
325d23c5c2dSKyungwoo Lee // Check if the old merged/optimized IndexOperandHashMap is compatible with
326d23c5c2dSKyungwoo Lee // the current IndexOperandHashMap. An operand hash may not be stable across
327d23c5c2dSKyungwoo Lee // different builds due to varying modules combined. To address this, we relax
328d23c5c2dSKyungwoo Lee // the hash check condition by comparing Const hash patterns instead of absolute
329d23c5c2dSKyungwoo Lee // hash values. For example, let's assume we have three Consts located at idx1,
330d23c5c2dSKyungwoo Lee // idx3, and idx6, where their corresponding hashes are hash1, hash2, and hash1
331d23c5c2dSKyungwoo Lee // in the old merged map below:
332d23c5c2dSKyungwoo Lee //   Old (Merged): [(idx1, hash1), (idx3, hash2), (idx6, hash1)]
333d23c5c2dSKyungwoo Lee //   Current: [(idx1, hash1'), (idx3, hash2'), (idx6, hash1')]
334d23c5c2dSKyungwoo Lee // If the current function also has three Consts in the same locations,
335d23c5c2dSKyungwoo Lee // with hash sequences hash1', hash2', and hash1' where the first and third
336d23c5c2dSKyungwoo Lee // are the same as the old hash sequences, we consider them matched.
337d23c5c2dSKyungwoo Lee static bool checkConstHashCompatible(
338d23c5c2dSKyungwoo Lee     const DenseMap<IndexPair, stable_hash> &OldInstOpndIndexToConstHash,
339d23c5c2dSKyungwoo Lee     const DenseMap<IndexPair, stable_hash> &CurrInstOpndIndexToConstHash) {
340d23c5c2dSKyungwoo Lee 
341d23c5c2dSKyungwoo Lee   DenseMap<stable_hash, stable_hash> OldHashToCurrHash;
342d23c5c2dSKyungwoo Lee   for (const auto &[Index, OldHash] : OldInstOpndIndexToConstHash) {
343d23c5c2dSKyungwoo Lee     auto It = CurrInstOpndIndexToConstHash.find(Index);
344d23c5c2dSKyungwoo Lee     if (It == CurrInstOpndIndexToConstHash.end())
345d23c5c2dSKyungwoo Lee       return false;
346d23c5c2dSKyungwoo Lee 
347d23c5c2dSKyungwoo Lee     auto CurrHash = It->second;
348d23c5c2dSKyungwoo Lee     auto J = OldHashToCurrHash.find(OldHash);
349d23c5c2dSKyungwoo Lee     if (J == OldHashToCurrHash.end())
350d23c5c2dSKyungwoo Lee       OldHashToCurrHash.insert({OldHash, CurrHash});
351d23c5c2dSKyungwoo Lee     else if (J->second != CurrHash)
352d23c5c2dSKyungwoo Lee       return false;
353d23c5c2dSKyungwoo Lee   }
354d23c5c2dSKyungwoo Lee 
355d23c5c2dSKyungwoo Lee   return true;
356d23c5c2dSKyungwoo Lee }
357d23c5c2dSKyungwoo Lee 
358d23c5c2dSKyungwoo Lee // Validate the locations pointed by a param has the same hash and Constant.
359d23c5c2dSKyungwoo Lee static bool
360d23c5c2dSKyungwoo Lee checkConstLocationCompatible(const StableFunctionMap::StableFunctionEntry &SF,
361d23c5c2dSKyungwoo Lee                              const IndexInstrMap &IndexInstruction,
362d23c5c2dSKyungwoo Lee                              const ParamLocsVecTy &ParamLocsVec) {
363d23c5c2dSKyungwoo Lee   for (auto &ParamLocs : ParamLocsVec) {
364d23c5c2dSKyungwoo Lee     std::optional<stable_hash> OldHash;
365d23c5c2dSKyungwoo Lee     std::optional<Constant *> OldConst;
366d23c5c2dSKyungwoo Lee     for (auto &Loc : ParamLocs) {
367d23c5c2dSKyungwoo Lee       assert(SF.IndexOperandHashMap->count(Loc));
368d23c5c2dSKyungwoo Lee       auto CurrHash = SF.IndexOperandHashMap.get()->at(Loc);
369d23c5c2dSKyungwoo Lee       auto [InstIndex, OpndIndex] = Loc;
370d23c5c2dSKyungwoo Lee       assert(InstIndex < IndexInstruction.size());
371d23c5c2dSKyungwoo Lee       const auto *Inst = IndexInstruction.lookup(InstIndex);
372d23c5c2dSKyungwoo Lee       auto *CurrConst = cast<Constant>(Inst->getOperand(OpndIndex));
373d23c5c2dSKyungwoo Lee       if (!OldHash) {
374d23c5c2dSKyungwoo Lee         OldHash = CurrHash;
375d23c5c2dSKyungwoo Lee         OldConst = CurrConst;
376d23c5c2dSKyungwoo Lee       } else if (CurrConst != *OldConst || CurrHash != *OldHash) {
377d23c5c2dSKyungwoo Lee         return false;
378d23c5c2dSKyungwoo Lee       }
379d23c5c2dSKyungwoo Lee     }
380d23c5c2dSKyungwoo Lee   }
381d23c5c2dSKyungwoo Lee   return true;
382d23c5c2dSKyungwoo Lee }
383d23c5c2dSKyungwoo Lee 
384d23c5c2dSKyungwoo Lee static ParamLocsVecTy computeParamInfo(
385d23c5c2dSKyungwoo Lee     const SmallVector<std::unique_ptr<StableFunctionMap::StableFunctionEntry>>
386d23c5c2dSKyungwoo Lee         &SFS) {
387d23c5c2dSKyungwoo Lee   std::map<std::vector<stable_hash>, ParamLocs> HashSeqToLocs;
388d23c5c2dSKyungwoo Lee   auto &RSF = *SFS[0];
389d23c5c2dSKyungwoo Lee   unsigned StableFunctionCount = SFS.size();
390d23c5c2dSKyungwoo Lee 
391d23c5c2dSKyungwoo Lee   for (auto &[IndexPair, Hash] : *RSF.IndexOperandHashMap) {
392d23c5c2dSKyungwoo Lee     // Const hash sequence across stable functions.
393d23c5c2dSKyungwoo Lee     // We will allocate a parameter per unique hash squence.
394d23c5c2dSKyungwoo Lee     // can't use SmallVector as key
395d23c5c2dSKyungwoo Lee     std::vector<stable_hash> ConstHashSeq;
396d23c5c2dSKyungwoo Lee     ConstHashSeq.push_back(Hash);
397d23c5c2dSKyungwoo Lee     bool Identical = true;
398d23c5c2dSKyungwoo Lee     for (unsigned J = 1; J < StableFunctionCount; ++J) {
399d23c5c2dSKyungwoo Lee       auto &SF = SFS[J];
400d23c5c2dSKyungwoo Lee       auto SHash = SF->IndexOperandHashMap->at(IndexPair);
401d23c5c2dSKyungwoo Lee       if (Hash != SHash)
402d23c5c2dSKyungwoo Lee         Identical = false;
403d23c5c2dSKyungwoo Lee       ConstHashSeq.push_back(SHash);
404d23c5c2dSKyungwoo Lee     }
405d23c5c2dSKyungwoo Lee 
406d23c5c2dSKyungwoo Lee     if (Identical)
407d23c5c2dSKyungwoo Lee       continue;
408d23c5c2dSKyungwoo Lee 
409d23c5c2dSKyungwoo Lee     // For each unique Const hash sequence (parameter), add the locations.
410d23c5c2dSKyungwoo Lee     HashSeqToLocs[ConstHashSeq].push_back(IndexPair);
411d23c5c2dSKyungwoo Lee   }
412d23c5c2dSKyungwoo Lee 
413d23c5c2dSKyungwoo Lee   ParamLocsVecTy ParamLocsVec;
414fe69a20cSKyungwoo Lee   for (auto &[HashSeq, Locs] : HashSeqToLocs)
415d23c5c2dSKyungwoo Lee     ParamLocsVec.push_back(std::move(Locs));
416fe69a20cSKyungwoo Lee 
417d23c5c2dSKyungwoo Lee   llvm::sort(ParamLocsVec, [&](const ParamLocs &L, const ParamLocs &R) {
418d23c5c2dSKyungwoo Lee     return L[0] < R[0];
419d23c5c2dSKyungwoo Lee   });
420fe69a20cSKyungwoo Lee 
421d23c5c2dSKyungwoo Lee   return ParamLocsVec;
422d23c5c2dSKyungwoo Lee }
423d23c5c2dSKyungwoo Lee 
424d23c5c2dSKyungwoo Lee bool GlobalMergeFunc::merge(Module &M, const StableFunctionMap *FunctionMap) {
425d23c5c2dSKyungwoo Lee   bool Changed = false;
426d23c5c2dSKyungwoo Lee 
427b3134fa2SKyungwoo Lee   // Collect stable functions related to the current module.
428b3134fa2SKyungwoo Lee   DenseMap<stable_hash, SmallVector<std::pair<Function *, FunctionHashInfo>>>
429b3134fa2SKyungwoo Lee       HashToFuncs;
430b3134fa2SKyungwoo Lee   auto &Maps = FunctionMap->getFunctionMap();
431b3134fa2SKyungwoo Lee   for (auto &F : M) {
432b3134fa2SKyungwoo Lee     if (!isEligibleFunction(&F))
433b3134fa2SKyungwoo Lee       continue;
434b3134fa2SKyungwoo Lee     auto FI = llvm::StructuralHashWithDifferences(F, ignoreOp);
435b3134fa2SKyungwoo Lee     if (Maps.contains(FI.FunctionHash))
436b3134fa2SKyungwoo Lee       HashToFuncs[FI.FunctionHash].emplace_back(&F, std::move(FI));
437b3134fa2SKyungwoo Lee   }
4385a2888ddSKyungwoo Lee 
439b3134fa2SKyungwoo Lee   for (auto &[Hash, Funcs] : HashToFuncs) {
4405a2888ddSKyungwoo Lee     std::optional<ParamLocsVecTy> ParamLocsVec;
4415a2888ddSKyungwoo Lee     SmallVector<FuncMergeInfo> FuncMergeInfos;
442b3134fa2SKyungwoo Lee     auto &SFS = Maps.at(Hash);
443b3134fa2SKyungwoo Lee     assert(!SFS.empty());
444b3134fa2SKyungwoo Lee     auto &RFS = SFS[0];
445b3134fa2SKyungwoo Lee 
446b3134fa2SKyungwoo Lee     // Iterate functions with the same hash.
447b3134fa2SKyungwoo Lee     for (auto &[F, FI] : Funcs) {
448b3134fa2SKyungwoo Lee       // Check if the function is compatible with any stable function
449b3134fa2SKyungwoo Lee       // in terms of the number of instructions and ignored operands.
450b3134fa2SKyungwoo Lee       if (RFS->InstCount != FI.IndexInstruction->size())
4515a2888ddSKyungwoo Lee         continue;
4525a2888ddSKyungwoo Lee 
453b3134fa2SKyungwoo Lee       auto hasValidSharedConst = [&](StableFunctionMap::StableFunctionEntry *SF,
454b3134fa2SKyungwoo Lee                                      FunctionHashInfo &FHI) {
455d23c5c2dSKyungwoo Lee         for (auto &[Index, Hash] : *SF->IndexOperandHashMap) {
456d23c5c2dSKyungwoo Lee           auto [InstIndex, OpndIndex] = Index;
457b3134fa2SKyungwoo Lee           assert(InstIndex < FHI.IndexInstruction->size());
458b3134fa2SKyungwoo Lee           auto *Inst = FHI.IndexInstruction->lookup(InstIndex);
459b3134fa2SKyungwoo Lee           if (!ignoreOp(Inst, OpndIndex))
460b3134fa2SKyungwoo Lee             return false;
461d23c5c2dSKyungwoo Lee         }
462b3134fa2SKyungwoo Lee         return true;
463b3134fa2SKyungwoo Lee       };
464b3134fa2SKyungwoo Lee       if (!hasValidSharedConst(RFS.get(), FI))
465d23c5c2dSKyungwoo Lee         continue;
466b3134fa2SKyungwoo Lee 
467b3134fa2SKyungwoo Lee       for (auto &SF : SFS) {
468b3134fa2SKyungwoo Lee         assert(SF->InstCount == FI.IndexInstruction->size());
469b3134fa2SKyungwoo Lee         assert(hasValidSharedConst(SF.get(), FI));
470b3134fa2SKyungwoo Lee         // Check if there is any stable function that is compatiable with the
471b3134fa2SKyungwoo Lee         // current one.
472d23c5c2dSKyungwoo Lee         if (!checkConstHashCompatible(*SF->IndexOperandHashMap,
473b3134fa2SKyungwoo Lee                                       *FI.IndexOperandHashMap))
474d23c5c2dSKyungwoo Lee           continue;
475d23c5c2dSKyungwoo Lee         if (!ParamLocsVec.has_value()) {
476d23c5c2dSKyungwoo Lee           ParamLocsVec = computeParamInfo(SFS);
477d23c5c2dSKyungwoo Lee           LLVM_DEBUG(dbgs() << "[GlobalMergeFunc] Merging hash: " << Hash
478d23c5c2dSKyungwoo Lee                             << " with Params " << ParamLocsVec->size() << "\n");
479d23c5c2dSKyungwoo Lee         }
480d23c5c2dSKyungwoo Lee         if (!checkConstLocationCompatible(*SF, *FI.IndexInstruction,
481b3134fa2SKyungwoo Lee                                           *ParamLocsVec))
482d23c5c2dSKyungwoo Lee           continue;
4835a2888ddSKyungwoo Lee 
484b3134fa2SKyungwoo Lee         // If a stable function matching the current one is found,
485b3134fa2SKyungwoo Lee         // create a candidate for merging and proceed to the next function.
486b3134fa2SKyungwoo Lee         FuncMergeInfos.emplace_back(SF.get(), F, FI.IndexInstruction.get());
487b3134fa2SKyungwoo Lee         break;
4885a2888ddSKyungwoo Lee       }
489d23c5c2dSKyungwoo Lee     }
490d23c5c2dSKyungwoo Lee     unsigned FuncMergeInfoSize = FuncMergeInfos.size();
491d23c5c2dSKyungwoo Lee     if (FuncMergeInfoSize == 0)
492d23c5c2dSKyungwoo Lee       continue;
493d23c5c2dSKyungwoo Lee 
494d23c5c2dSKyungwoo Lee     LLVM_DEBUG(dbgs() << "[GlobalMergeFunc] Merging function count "
495b3134fa2SKyungwoo Lee                       << FuncMergeInfoSize << " for hash:  " << Hash << "\n");
496d23c5c2dSKyungwoo Lee 
497d23c5c2dSKyungwoo Lee     for (auto &FMI : FuncMergeInfos) {
498d23c5c2dSKyungwoo Lee       Changed = true;
499d23c5c2dSKyungwoo Lee 
500d23c5c2dSKyungwoo Lee       // We've already validated all locations of constant operands pointed by
501d23c5c2dSKyungwoo Lee       // the parameters. Populate parameters pointing to the original constants.
502d23c5c2dSKyungwoo Lee       SmallVector<Constant *> Params;
503d23c5c2dSKyungwoo Lee       SmallVector<Type *> ParamTypes;
504d23c5c2dSKyungwoo Lee       for (auto &ParamLocs : *ParamLocsVec) {
505d23c5c2dSKyungwoo Lee         assert(!ParamLocs.empty());
506d23c5c2dSKyungwoo Lee         auto &[InstIndex, OpndIndex] = ParamLocs[0];
507d23c5c2dSKyungwoo Lee         auto *Inst = FMI.IndexInstruction->lookup(InstIndex);
508d23c5c2dSKyungwoo Lee         auto *Opnd = cast<Constant>(Inst->getOperand(OpndIndex));
509d23c5c2dSKyungwoo Lee         Params.push_back(Opnd);
510d23c5c2dSKyungwoo Lee         ParamTypes.push_back(Opnd->getType());
511d23c5c2dSKyungwoo Lee       }
512d23c5c2dSKyungwoo Lee 
513d23c5c2dSKyungwoo Lee       // Create a merged function derived from the current function.
514d23c5c2dSKyungwoo Lee       Function *MergedFunc =
515d23c5c2dSKyungwoo Lee           createMergedFunction(FMI, ParamTypes, *ParamLocsVec);
516d23c5c2dSKyungwoo Lee 
517d23c5c2dSKyungwoo Lee       LLVM_DEBUG({
518d23c5c2dSKyungwoo Lee         dbgs() << "[GlobalMergeFunc] Merged function (hash:" << FMI.SF->Hash
519d23c5c2dSKyungwoo Lee                << ") " << MergedFunc->getName() << " generated from "
520d23c5c2dSKyungwoo Lee                << FMI.F->getName() << ":\n";
521d23c5c2dSKyungwoo Lee         MergedFunc->dump();
522d23c5c2dSKyungwoo Lee       });
523d23c5c2dSKyungwoo Lee 
524d23c5c2dSKyungwoo Lee       // Transform the current function into a thunk that calls the merged
525d23c5c2dSKyungwoo Lee       // function.
526d23c5c2dSKyungwoo Lee       createThunk(FMI, Params, MergedFunc);
527d23c5c2dSKyungwoo Lee       LLVM_DEBUG({
528d23c5c2dSKyungwoo Lee         dbgs() << "[GlobalMergeFunc] Thunk generated: \n";
529d23c5c2dSKyungwoo Lee         FMI.F->dump();
530d23c5c2dSKyungwoo Lee       });
531d23c5c2dSKyungwoo Lee       ++NumMergedFunctions;
532d23c5c2dSKyungwoo Lee     }
533d23c5c2dSKyungwoo Lee   }
534d23c5c2dSKyungwoo Lee 
535d23c5c2dSKyungwoo Lee   return Changed;
536d23c5c2dSKyungwoo Lee }
537d23c5c2dSKyungwoo Lee 
538d23c5c2dSKyungwoo Lee void GlobalMergeFunc::initializeMergerMode(const Module &M) {
539d23c5c2dSKyungwoo Lee   // Initialize the local function map regardless of the merger mode.
540d23c5c2dSKyungwoo Lee   LocalFunctionMap = std::make_unique<StableFunctionMap>();
541d23c5c2dSKyungwoo Lee 
542d23c5c2dSKyungwoo Lee   // Disable codegen data for merging. The local merge is still enabled.
543d23c5c2dSKyungwoo Lee   if (DisableCGDataForMerging)
544d23c5c2dSKyungwoo Lee     return;
545d23c5c2dSKyungwoo Lee 
546d23c5c2dSKyungwoo Lee   // (Full)LTO module does not have functions added to the index.
547d23c5c2dSKyungwoo Lee   // In this case, we run a local merger without using codegen data.
548d23c5c2dSKyungwoo Lee   if (Index && !Index->hasExportedFunctions(M))
549d23c5c2dSKyungwoo Lee     return;
550d23c5c2dSKyungwoo Lee 
551d23c5c2dSKyungwoo Lee   if (cgdata::emitCGData())
552d23c5c2dSKyungwoo Lee     MergerMode = HashFunctionMode::BuildingHashFuncion;
553d23c5c2dSKyungwoo Lee   else if (cgdata::hasStableFunctionMap())
554d23c5c2dSKyungwoo Lee     MergerMode = HashFunctionMode::UsingHashFunction;
555d23c5c2dSKyungwoo Lee }
556d23c5c2dSKyungwoo Lee 
557d23c5c2dSKyungwoo Lee void GlobalMergeFunc::emitFunctionMap(Module &M) {
558d23c5c2dSKyungwoo Lee   LLVM_DEBUG(dbgs() << "Emit function map. Size: " << LocalFunctionMap->size()
559d23c5c2dSKyungwoo Lee                     << "\n");
560d23c5c2dSKyungwoo Lee   // No need to emit the function map if it is empty.
561d23c5c2dSKyungwoo Lee   if (LocalFunctionMap->empty())
562d23c5c2dSKyungwoo Lee     return;
563d23c5c2dSKyungwoo Lee   SmallVector<char> Buf;
564d23c5c2dSKyungwoo Lee   raw_svector_ostream OS(Buf);
565d23c5c2dSKyungwoo Lee 
566d23c5c2dSKyungwoo Lee   StableFunctionMapRecord::serialize(OS, LocalFunctionMap.get());
567d23c5c2dSKyungwoo Lee 
568d23c5c2dSKyungwoo Lee   std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer(
569d23c5c2dSKyungwoo Lee       OS.str(), "in-memory stable function map", false);
570d23c5c2dSKyungwoo Lee 
571d23c5c2dSKyungwoo Lee   Triple TT(M.getTargetTriple());
572d23c5c2dSKyungwoo Lee   embedBufferInModule(M, *Buffer.get(),
573d23c5c2dSKyungwoo Lee                       getCodeGenDataSectionName(CG_merge, TT.getObjectFormat()),
574d23c5c2dSKyungwoo Lee                       Align(4));
575d23c5c2dSKyungwoo Lee }
576d23c5c2dSKyungwoo Lee 
577d23c5c2dSKyungwoo Lee bool GlobalMergeFunc::run(Module &M) {
578d23c5c2dSKyungwoo Lee   initializeMergerMode(M);
579d23c5c2dSKyungwoo Lee 
580d23c5c2dSKyungwoo Lee   const StableFunctionMap *FuncMap;
581d23c5c2dSKyungwoo Lee   if (MergerMode == HashFunctionMode::UsingHashFunction) {
582d23c5c2dSKyungwoo Lee     // Use the prior CG data to optimistically create global merge candidates.
583d23c5c2dSKyungwoo Lee     FuncMap = cgdata::getStableFunctionMap();
584d23c5c2dSKyungwoo Lee   } else {
585d23c5c2dSKyungwoo Lee     analyze(M);
586d23c5c2dSKyungwoo Lee     // Emit the local function map to the custom section, __llvm_merge before
587d23c5c2dSKyungwoo Lee     // finalizing it.
588d23c5c2dSKyungwoo Lee     if (MergerMode == HashFunctionMode::BuildingHashFuncion)
589d23c5c2dSKyungwoo Lee       emitFunctionMap(M);
590d23c5c2dSKyungwoo Lee     LocalFunctionMap->finalize();
591d23c5c2dSKyungwoo Lee     FuncMap = LocalFunctionMap.get();
592d23c5c2dSKyungwoo Lee   }
593d23c5c2dSKyungwoo Lee 
594d23c5c2dSKyungwoo Lee   return merge(M, FuncMap);
595d23c5c2dSKyungwoo Lee }
596d23c5c2dSKyungwoo Lee 
597d23c5c2dSKyungwoo Lee namespace {
598d23c5c2dSKyungwoo Lee 
599d23c5c2dSKyungwoo Lee class GlobalMergeFuncPassWrapper : public ModulePass {
600d23c5c2dSKyungwoo Lee 
601d23c5c2dSKyungwoo Lee public:
602d23c5c2dSKyungwoo Lee   static char ID;
603d23c5c2dSKyungwoo Lee 
604d23c5c2dSKyungwoo Lee   GlobalMergeFuncPassWrapper();
605d23c5c2dSKyungwoo Lee 
606d23c5c2dSKyungwoo Lee   void getAnalysisUsage(AnalysisUsage &AU) const override {
607d23c5c2dSKyungwoo Lee     AU.addUsedIfAvailable<ImmutableModuleSummaryIndexWrapperPass>();
608d23c5c2dSKyungwoo Lee     AU.setPreservesAll();
609d23c5c2dSKyungwoo Lee     ModulePass::getAnalysisUsage(AU);
610d23c5c2dSKyungwoo Lee   }
611d23c5c2dSKyungwoo Lee 
612d23c5c2dSKyungwoo Lee   StringRef getPassName() const override { return "Global Merge Functions"; }
613d23c5c2dSKyungwoo Lee 
614d23c5c2dSKyungwoo Lee   bool runOnModule(Module &M) override;
615d23c5c2dSKyungwoo Lee };
616d23c5c2dSKyungwoo Lee 
617d23c5c2dSKyungwoo Lee } // namespace
618d23c5c2dSKyungwoo Lee 
619d23c5c2dSKyungwoo Lee char GlobalMergeFuncPassWrapper::ID = 0;
620d23c5c2dSKyungwoo Lee INITIALIZE_PASS_BEGIN(GlobalMergeFuncPassWrapper, "global-merge-func",
621d23c5c2dSKyungwoo Lee                       "Global merge function pass", false, false)
622d23c5c2dSKyungwoo Lee INITIALIZE_PASS_END(GlobalMergeFuncPassWrapper, "global-merge-func",
623d23c5c2dSKyungwoo Lee                     "Global merge function pass", false, false)
624d23c5c2dSKyungwoo Lee 
625d23c5c2dSKyungwoo Lee namespace llvm {
626d23c5c2dSKyungwoo Lee ModulePass *createGlobalMergeFuncPass() {
627d23c5c2dSKyungwoo Lee   return new GlobalMergeFuncPassWrapper();
628d23c5c2dSKyungwoo Lee }
629d23c5c2dSKyungwoo Lee } // namespace llvm
630d23c5c2dSKyungwoo Lee 
631d23c5c2dSKyungwoo Lee GlobalMergeFuncPassWrapper::GlobalMergeFuncPassWrapper() : ModulePass(ID) {
632d23c5c2dSKyungwoo Lee   initializeGlobalMergeFuncPassWrapperPass(
633d23c5c2dSKyungwoo Lee       *llvm::PassRegistry::getPassRegistry());
634d23c5c2dSKyungwoo Lee }
635d23c5c2dSKyungwoo Lee 
636d23c5c2dSKyungwoo Lee bool GlobalMergeFuncPassWrapper::runOnModule(Module &M) {
637d23c5c2dSKyungwoo Lee   const ModuleSummaryIndex *Index = nullptr;
638d23c5c2dSKyungwoo Lee   if (auto *IndexWrapperPass =
639d23c5c2dSKyungwoo Lee           getAnalysisIfAvailable<ImmutableModuleSummaryIndexWrapperPass>())
640d23c5c2dSKyungwoo Lee     Index = IndexWrapperPass->getIndex();
641d23c5c2dSKyungwoo Lee 
642d23c5c2dSKyungwoo Lee   return GlobalMergeFunc(Index).run(M);
643d23c5c2dSKyungwoo Lee }
644d23c5c2dSKyungwoo Lee 
645d23c5c2dSKyungwoo Lee PreservedAnalyses GlobalMergeFuncPass::run(Module &M,
646d23c5c2dSKyungwoo Lee                                            AnalysisManager<Module> &AM) {
647816c975eSKyungwoo Lee   bool Changed = GlobalMergeFunc(ImportSummary).run(M);
648d23c5c2dSKyungwoo Lee   return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
649d23c5c2dSKyungwoo Lee }
650