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