diff --git a/bolt/merge-fdata/merge-fdata.cpp b/bolt/merge-fdata/merge-fdata.cpp index cab715648faf..4f9e292ef55e 100644 --- a/bolt/merge-fdata/merge-fdata.cpp +++ b/bolt/merge-fdata/merge-fdata.cpp @@ -27,12 +27,40 @@ using namespace bolt; namespace opts { +enum SortType : char { + ST_NONE, + ST_EXEC_COUNT, /// Sort based on function execution count. + ST_TOTAL_BRANCHES, /// Sort based on all branches in the function. +}; + static cl::list InputDataFilenames(cl::Positional, cl::CommaSeparated, cl::desc(" []..."), cl::OneOrMore); +static cl::opt +SuppressMergedDataOutput("q", + cl::desc("do not print merged data to stdout"), + cl::init(false), + cl::Optional); + +static cl::opt +PrintFunctionList( + "print", + cl::desc("print the list of objects with count to stderr"), + cl::init(ST_NONE), + cl::values(clEnumValN(ST_NONE, + "none", + "do not print objects/functions"), + clEnumValN(ST_EXEC_COUNT, + "exec", + "print functions sorted by execution count"), + clEnumValN(ST_TOTAL_BRANCHES, + "branches", + "print functions sorted by total branch count"), + clEnumValEnd)); + } // namespace opts static StringRef ToolName; @@ -98,6 +126,7 @@ int main(int argc, char **argv) { for (auto &FI : ReaderOrErr.get()->getAllFuncsData()) { auto MI = MergedFunctionsData.find(FI.second.Name); if (MI != MergedFunctionsData.end()) { + MI->second.ExecutionCount += FI.second.ExecutionCount; std::vector TmpBI; for (auto &BI : FI.second.Data) { // Find and merge a corresponding entry or copy data. @@ -132,6 +161,7 @@ int main(int argc, char **argv) { std::make_pair(*NamePtr, FuncBranchData(*NamePtr, FuncBranchData::ContainerTy()))); + MI->second.ExecutionCount = FI.second.ExecutionCount; // Copy with string conversion while eliminating duplicates. std::sort(FI.second.Data.begin(), FI.second.Data.end()); BranchInfo *PrevBI = nullptr; @@ -148,18 +178,59 @@ int main(int argc, char **argv) { } } - // Print all the data in the original format - for (auto &FDI : MergedFunctionsData) { - for (auto &BD : FDI.second.Data) { - outs() << BD.From.IsSymbol << " " << FDI.first() << " " - << Twine::utohexstr(BD.From.Offset) << " " - << BD.To.IsSymbol << " " << BD.To.Name << " " - << Twine::utohexstr(BD.To.Offset) << " " - << BD.Mispreds << " " << BD.Branches << '\n'; + if (!opts::SuppressMergedDataOutput) { + // Print all the data in the original format + for (auto &FDI : MergedFunctionsData) { + for (auto &BD : FDI.second.Data) { + outs() << BD.From.IsSymbol << " " << FDI.first() << " " + << Twine::utohexstr(BD.From.Offset) << " " + << BD.To.IsSymbol << " " << BD.To.Name << " " + << Twine::utohexstr(BD.To.Offset) << " " + << BD.Mispreds << " " << BD.Branches << '\n'; + } } } - errs() << "All data merged successfully.\n"; + errs() << "Data for " << MergedFunctionsData.size() + << " unique objects successfully merged.\n"; + + if (opts::PrintFunctionList != opts::ST_NONE) { + // List of function names with execution count. + std::vector> + FunctionList(MergedFunctionsData.size()); + using CountFuncType = + std::function( + const StringMapEntry&)>; + CountFuncType ExecCountFunc = [](const StringMapEntry &v) { + return std::make_pair(v.second.ExecutionCount, + v.second.Name); + }; + CountFuncType BranchCountFunc = [](const StringMapEntry &v){ + // Return total branch count. + uint64_t BranchCount = 0; + for (const auto &BI : v.second.Data) + BranchCount += BI.Branches; + return std::make_pair(BranchCount, + v.second.Name); + }; + + CountFuncType CountFunc = (opts::PrintFunctionList == opts::ST_EXEC_COUNT) + ? ExecCountFunc + : BranchCountFunc; + std::transform(MergedFunctionsData.begin(), + MergedFunctionsData.end(), + FunctionList.begin(), + CountFunc); + std::stable_sort(FunctionList.rbegin(), FunctionList.rend()); + errs() << "Functions sorted by " + << (opts::PrintFunctionList == opts::ST_EXEC_COUNT + ? "execution" + : "total branch") + << " count:\n"; + for (auto &FI : FunctionList) { + errs() << FI.second << " : " << FI.first << '\n'; + } + } AllStrings.clear();