Index: include/llvm/IR/ModuleSummaryIndex.h =================================================================== --- include/llvm/IR/ModuleSummaryIndex.h +++ include/llvm/IR/ModuleSummaryIndex.h @@ -814,6 +814,20 @@ StringSaver Saver; BumpPtrAllocator Alloc; + /// Functions with hash code as a measure of structural similarity. + /// Used by MergeSimilarFunctions. The value_type is the hash code + /// computed by profileFunction. + std::map FunctionSimilarityHashes; + /// Reverse map of @var SimilarFunctionsHash to be used during thin-lto. + /// Each GUID in the vector corresponds to functions with same hash (id). + std::map> SimilarFunctions; + /// Functions having multiple entries in ModuleSummaryIndex. + std::set DuplicateFunctions; + /// All similar functions w.r.t the one in this set will be imported into + /// the module of these functions during thin-lto stage. + /// FIXME: Maybe use a vector? + std::set HostSimilarFunction; + // YAML I/O support. friend yaml::MappingTraits; Index: include/llvm/Transforms/IPO/WholeProgramDevirt.h =================================================================== --- include/llvm/Transforms/IPO/WholeProgramDevirt.h +++ include/llvm/Transforms/IPO/WholeProgramDevirt.h @@ -229,6 +229,10 @@ PreservedAnalyses run(Module &M, ModuleAnalysisManager &); }; +/// Decide which functions to import for function merging during the thinlto. +/// Populates information from each function summary to module summary index. +void computeMergeSimilarFunctions(ModuleSummaryIndex &Index); + } // end namespace llvm #endif // LLVM_TRANSFORMS_IPO_WHOLEPROGRAMDEVIRT_H Index: lib/LTO/ThinLTOCodeGenerator.cpp =================================================================== --- lib/LTO/ThinLTOCodeGenerator.cpp +++ lib/LTO/ThinLTOCodeGenerator.cpp @@ -72,6 +72,8 @@ extern cl::opt LTOPassRemarksWithHotness; } +extern cl::opt EnableMergeSimilarFunctions; + namespace { static cl::opt @@ -870,6 +872,9 @@ ProducedBinaryFiles.resize(Modules.size()); } + if (EnableMergeSimilarFunctions) + computeMergeSimilarFunctions(*Index); + if (CodeGenOnly) { // Perform only parallel codegen and return. ThreadPool Pool; Index: lib/Transforms/IPO/MergeSimilarFunctions.cpp =================================================================== --- lib/Transforms/IPO/MergeSimilarFunctions.cpp +++ lib/Transforms/IPO/MergeSimilarFunctions.cpp @@ -40,6 +40,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/IPO/WholeProgramDevirt.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/ValueMapper.h" @@ -1298,6 +1299,42 @@ return new MergeSimilarFunctions(S); } +void llvm::computeMergeSimilarFunctions(ModuleSummaryIndex &Index) { + assert(Index.getSimilarFunctions().empty() && "Inserting SimHash twice"); + for (auto &P : Index) { + for (auto &S : P.second.SummaryList) { + FunctionSummary *FS = dyn_cast(S.get()); + if (!FS) + continue; + LLVM_DEBUG(llvm::errs() << "\nSimilarity hash: " << FS->similarityHash()); + Index.addToSimilarFunctions(FS->similarityHash(), FS->getOriginalName()); + } + } + Index.populateReverseSimilarityHashMap(); + llvm::errs() << "\nSize SimilarFunctionsHash: " + << Index.getSimilarFunctionsHash().size(); + llvm::errs() << "\nSize SimilarFunctions: " + << Index.getSimilarFunctions().size(); + Index.removeSingleEntriesFromSimHashMaps(); + + LLVM_DEBUG(llvm::errs() << "\nSize SimilarFunctionsHash: " + << Index.getSimilarFunctionsHash().size()); + LLVM_DEBUG(llvm::errs() << "\nSize SimilarFunctions: " + << Index.getSimilarFunctions().size()); + + auto &SimFunctions = Index.getSimilarFunctions(); + // Shouldn't have entries with hash of 0, because those are placeholders. + assert(!SimFunctions.count(0)); + auto &HostSimFunction = Index.getHostSimilarFunction(); + for (auto I = SimFunctions.begin(), E = SimFunctions.end(); I != E; ++I) { + // Make the first of all similar functions as host. + HostSimFunction.insert(I->second[0]); + } + LLVM_DEBUG(llvm::errs() << "\nSize getHostSimilarFunction: " + << Index.getHostSimilarFunction().size()); + return; +} + bool MergeSimilarFunctions::runOnModule(Module &M) { if (Opt::MergeLevel == Opt::none) return false; Index: lib/Transforms/IPO/PassManagerBuilder.cpp =================================================================== --- lib/Transforms/IPO/PassManagerBuilder.cpp +++ lib/Transforms/IPO/PassManagerBuilder.cpp @@ -159,7 +159,7 @@ EnableCHR("enable-chr", cl::init(true), cl::Hidden, cl::desc("Enable control height reduction optimization (CHR)")); -static cl::opt EnableMergeSimilarFunctions( +cl::opt EnableMergeSimilarFunctions( "enable-merge-sim-functions", cl::init(false), cl::Hidden, cl::desc("Enable the Function merging pass (default = on)"));