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