Index: include/llvm/ProfileData/SampleProfWriter.h =================================================================== --- include/llvm/ProfileData/SampleProfWriter.h +++ include/llvm/ProfileData/SampleProfWriter.h @@ -43,16 +43,7 @@ /// Write all the sample profiles in the given map of samples. /// /// \returns status code of the file update operation. - std::error_code write(const StringMap &ProfileMap) { - if (std::error_code EC = writeHeader(ProfileMap)) - return EC; - for (const auto &I : ProfileMap) { - const FunctionSamples &Profile = I.second; - if (std::error_code EC = write(Profile)) - return EC; - } - return sampleprof_error::success; - } + std::error_code write(const StringMap &ProfileMap); raw_ostream &getOutputStream() { return *OutputStream; } Index: lib/ProfileData/SampleProfWriter.cpp =================================================================== --- lib/ProfileData/SampleProfWriter.cpp +++ lib/ProfileData/SampleProfWriter.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,32 @@ using namespace llvm; using namespace sampleprof; +std::error_code +SampleProfileWriter::write(const StringMap &ProfileMap) { + if (std::error_code EC = writeHeader(ProfileMap)) + return EC; + + // Sort the ProfileMap by total samples. + typedef std::pair NameFunctionSamples; + std::vector V; + for (const auto &I : ProfileMap) + V.push_back(std::make_pair(I.getKey(), &I.second)); + + std::stable_sort( + V.begin(), V.end(), + [](const NameFunctionSamples &A, const NameFunctionSamples &B) { + if (A.second->getTotalSamples() == B.second->getTotalSamples()) + return A.first > B.first; + return A.second->getTotalSamples() > B.second->getTotalSamples(); + }); + + for (const auto &I : V) { + if (std::error_code EC = write(*I.second)) + return EC; + } + return sampleprof_error::success; +} + /// \brief Write samples to a text file. /// /// Note: it may be tempting to implement this in terms of @@ -97,8 +124,7 @@ } void SampleProfileWriterBinary::addName(StringRef FName) { - auto NextIdx = NameTable.size(); - NameTable.insert(std::make_pair(FName, NextIdx)); + NameTable.insert(std::make_pair(FName, 0)); } void SampleProfileWriterBinary::addNames(const FunctionSamples &S) { @@ -136,10 +162,18 @@ addNames(I.second); } + // Sort the names to make NameTable is deterministic. + std::set V; + for (const auto &I : NameTable) + V.insert(I.first); + int i = 0; + for (const StringRef &N : V) + NameTable[N] = i++; + // Write out the name table. encodeULEB128(NameTable.size(), OS); - for (auto N : NameTable) { - OS << N.first; + for (auto N : V) { + OS << N; encodeULEB128(0, OS); } return sampleprof_error::success; Index: test/tools/llvm-profdata/sample-profile-basic.test =================================================================== --- test/tools/llvm-profdata/sample-profile-basic.test +++ test/tools/llvm-profdata/sample-profile-basic.test @@ -25,9 +25,10 @@ counters have doubled. RUN: llvm-profdata merge --sample %p/Inputs/sample-profile.proftext -o %t-binprof RUN: llvm-profdata merge --sample --text %p/Inputs/sample-profile.proftext %t-binprof -o - | FileCheck %s --check-prefix=MERGE1 -MERGE1-DAG: main:368038:0 -MERGE1-DAG: 9: 4128 _Z3fooi:1262 _Z3bari:2942 -MERGE1-DAG: _Z3fooi:15422:1220 +MERGE1: main:368038:0 +MERGE1: 9: 4128 _Z3fooi:1262 _Z3bari:2942 +MERGE1: _Z3bari:40602:2874 +MERGE1: _Z3fooi:15422:1220 5- Detect invalid text encoding (e.g. instrumentation profile text format). RUN: not llvm-profdata show --sample %p/Inputs/foo3bar3-1.proftext 2>&1 | FileCheck %s --check-prefix=BADTEXT