105105#include " llvm/IR/Instruction.h"
106106#include " llvm/IR/Instructions.h"
107107#include " llvm/IR/IntrinsicInst.h"
108+ #include " llvm/IR/LLVMContext.h"
108109#include " llvm/IR/Module.h"
109110#include " llvm/IR/StructuralHash.h"
110111#include " llvm/IR/Type.h"
117118#include " llvm/Support/Debug.h"
118119#include " llvm/Support/raw_ostream.h"
119120#include " llvm/Transforms/IPO.h"
121+ #include " llvm/Transforms/Utils/Cloning.h"
120122#include " llvm/Transforms/Utils/FunctionComparator.h"
121123#include " llvm/Transforms/Utils/ModuleUtils.h"
122124#include < algorithm>
@@ -197,9 +199,10 @@ class MergeFunctions {
197199 MergeFunctions () : FnTree(FunctionNodeCmp(&GlobalNumbers)) {
198200 }
199201
200- bool runOnModule (Module &M);
201- bool runOnFunctions (std::set<Function *> &F);
202- std::map<Function *, Function *> &getDelToNewMap ();
202+ template <typename FuncContainer>
203+ bool runOnModule (FuncContainer &Functions);
204+ std::pair<bool , DenseMap<Function *, Function *>>
205+ runOnFunctions (std::set<Function *> &F);
203206
204207private:
205208 // The function comparison operator is provided here so that FunctionNodes do
@@ -302,7 +305,7 @@ class MergeFunctions {
302305 DenseMap<AssertingVH<Function>, FnTreeType::iterator> FNodesInTree;
303306
304307 // / Deleted-New functions mapping
305- std::map <Function *, Function *> DelToNewMap;
308+ DenseMap <Function *, Function *> DelToNewMap;
306309};
307310} // end anonymous namespace
308311
@@ -318,11 +321,10 @@ bool MergeFunctionsPass::runOnModule(Module &M) {
318321 return MF.runOnModule (M);
319322}
320323
321- std::pair<bool , std::map <Function *, Function *>>
324+ std::pair<bool , DenseMap <Function *, Function *>>
322325MergeFunctionsPass::runOnFunctions (std::set<Function *> &F) {
323326 MergeFunctions MF;
324- bool MergeResult = MF.runOnFunctions (F);
325- return {MergeResult, MF.getDelToNewMap ()};
327+ return MF.runOnFunctions (F);
326328}
327329
328330#ifndef NDEBUG
@@ -426,24 +428,36 @@ static bool isEligibleForMerging(Function &F) {
426428 !hasDistinctMetadataIntrinsic (F);
427429}
428430
429- bool MergeFunctions::runOnModule (Module &M) {
431+ template <typename FuncContainer>
432+ bool MergeFunctions::runOnModule (FuncContainer &M) {
430433 bool Changed = false ;
431434
432- SmallVector<GlobalValue *, 4 > UsedV;
433- collectUsedGlobalVariables (M, UsedV, /* CompilerUsed=*/ false );
434- collectUsedGlobalVariables (M, UsedV, /* CompilerUsed=*/ true );
435- Used.insert (UsedV.begin (), UsedV.end ());
435+ if constexpr (std::is_same<FuncContainer, Module>::value) {
436+ SmallVector<GlobalValue *, 4 > UsedV;
437+ collectUsedGlobalVariables (M, UsedV, /* CompilerUsed=*/ false );
438+ collectUsedGlobalVariables (M, UsedV, /* CompilerUsed=*/ true );
439+ Used.insert (UsedV.begin (), UsedV.end ());
440+ }
436441
437442 // All functions in the module, ordered by hash. Functions with a unique
438443 // hash value are easily eliminated.
439444 std::vector<std::pair<stable_hash, Function *>> HashedFuncs;
440- for (Function &Func : M) {
441- if (isEligibleForMerging (Func)) {
442- HashedFuncs.push_back ({StructuralHash (Func), &Func});
445+ if constexpr (std::is_same<FuncContainer, std::set<Function *>>::value) {
446+ for (Function *Func : M) {
447+ if (isEligibleForMerging (*Func)) {
448+ HashedFuncs.push_back ({StructuralHash (*Func), Func});
449+ }
450+ }
451+ }
452+ if constexpr (std::is_same<FuncContainer, Module>::value) {
453+ for (Function &Func : M) {
454+ if (isEligibleForMerging (Func)) {
455+ HashedFuncs.push_back ({StructuralHash (Func), &Func});
456+ }
443457 }
444458 }
445459
446- llvm:: stable_sort (HashedFuncs, less_first ());
460+ stable_sort (HashedFuncs, less_first ());
447461
448462 auto S = HashedFuncs.begin ();
449463 for (auto I = HashedFuncs.begin (), IE = HashedFuncs.end (); I != IE; ++I) {
@@ -484,50 +498,16 @@ bool MergeFunctions::runOnModule(Module &M) {
484498 return Changed;
485499}
486500
487- bool MergeFunctions::runOnFunctions (std::set<Function *> &F) {
488- bool Changed = false ;
489- std::vector<std::pair<stable_hash, Function *>> HashedFuncs;
490- for (Function *Func : F) {
491- if (isEligibleForMerging (*Func)) {
492- HashedFuncs.push_back ({StructuralHash (*Func), Func});
493- }
494- }
495- llvm::stable_sort (HashedFuncs, less_first ());
496- auto S = HashedFuncs.begin ();
497- for (auto I = HashedFuncs.begin (), IE = HashedFuncs.end (); I != IE; ++I) {
498- if ((I != S && std::prev (I)->first == I->first ) ||
499- (std::next (I) != IE && std::next (I)->first == I->first )) {
500- Deferred.push_back (WeakTrackingVH (I->second ));
501- }
502- }
503- do {
504- std::vector<WeakTrackingVH> Worklist;
505- Deferred.swap (Worklist);
506- LLVM_DEBUG (dbgs () << " size of function: " << F.size () << ' \n ' );
507- LLVM_DEBUG (dbgs () << " size of worklist: " << Worklist.size () << ' \n ' );
508- for (WeakTrackingVH &I : Worklist) {
509- if (!I)
510- continue ;
511- Function *F = cast<Function>(I);
512- if (!F->isDeclaration () && !F->hasAvailableExternallyLinkage ()) {
513- Changed |= insert (F);
514- }
515- }
516- LLVM_DEBUG (dbgs () << " size of FnTree: " << FnTree.size () << ' \n ' );
517- } while (!Deferred.empty ());
518- FnTree.clear ();
519- FNodesInTree.clear ();
520- GlobalNumbers.clear ();
521- return Changed;
522- }
523-
524- std::map<Function *, Function *> &MergeFunctions::getDelToNewMap () {
525- return this ->DelToNewMap ;
501+ std::pair<bool , DenseMap<Function *, Function *>>
502+ MergeFunctions::runOnFunctions (std::set<Function *> &F) {
503+ bool MergeResult = false ;
504+ MergeResult = this ->runOnModule (F);
505+ return {MergeResult, this ->DelToNewMap };
526506}
527507
528508// Replace direct callers of Old with New.
529509void MergeFunctions::replaceDirectCallers (Function *Old, Function *New) {
530- for (Use &U : llvm:: make_early_inc_range (Old->uses ())) {
510+ for (Use &U : make_early_inc_range (Old->uses ())) {
531511 CallBase *CB = dyn_cast<CallBase>(U.getUser ());
532512 if (CB && CB->isCallee (&U)) {
533513 // Do not copy attributes from the called function to the call-site.
@@ -826,8 +806,8 @@ void MergeFunctions::writeThunk(Function *F, Function *G) {
826806 ReturnInst *RI = nullptr ;
827807 bool isSwiftTailCall = F->getCallingConv () == CallingConv::SwiftTail &&
828808 G->getCallingConv () == CallingConv::SwiftTail;
829- CI->setTailCallKind (isSwiftTailCall ? llvm:: CallInst::TCK_MustTail
830- : llvm:: CallInst::TCK_Tail);
809+ CI->setTailCallKind (isSwiftTailCall ? CallInst::TCK_MustTail
810+ : CallInst::TCK_Tail);
831811 CI->setCallingConv (F->getCallingConv ());
832812 CI->setAttributes (F->getAttributes ());
833813 if (H->getReturnType ()->isVoidTy ()) {
@@ -1061,7 +1041,7 @@ bool MergeFunctions::insert(Function *NewFunction) {
10611041
10621042 Function *DeleteF = NewFunction;
10631043 mergeTwoFunctions (OldF.getFunc (), DeleteF);
1064- this ->DelToNewMap .emplace ( DeleteF, OldF.getFunc ());
1044+ this ->DelToNewMap .insert ({ DeleteF, OldF.getFunc ()} );
10651045 return true ;
10661046}
10671047
0 commit comments