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. 43 static bool isCalleeOperand(const CallBase *CI, unsigned OpIdx) { 44 return &CI->getCalledOperandUse() == &CI->getOperandUse(OpIdx); 45 } 46 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. 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 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. 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 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; 174 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. 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. 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. 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 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 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 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 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 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 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 574 void getAnalysisUsage(AnalysisUsage &AU) const override { 575 AU.addUsedIfAvailable<ImmutableModuleSummaryIndexWrapperPass>(); 576 AU.setPreservesAll(); 577 ModulePass::getAnalysisUsage(AU); 578 } 579 580 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 { 594 ModulePass *createGlobalMergeFuncPass() { 595 return new GlobalMergeFuncPassWrapper(); 596 } 597 } // namespace llvm 598 599 GlobalMergeFuncPassWrapper::GlobalMergeFuncPassWrapper() : ModulePass(ID) { 600 initializeGlobalMergeFuncPassWrapperPass( 601 *llvm::PassRegistry::getPassRegistry()); 602 } 603 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 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