From: Xinliang David Li Date: Sat, 19 Dec 2015 07:44:57 +0000 (+0000) Subject: [PGO] Add hash to name mapping in InstrProfSymtab X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=ab49f7c709fbdce97fba0c331552840c3fc327b0 [PGO] Add hash to name mapping in InstrProfSymtab Creator and lookup interfaces are added to this symtab class. The new interfaces will be used by InstrProf Readers and writer. A unit test is also added for the new APIs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256092 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index b0d08a5886f..ac60e8053c2 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -202,6 +202,11 @@ enum InstrProfValueKind : uint32_t { namespace object { class SectionRef; } + +namespace IndexedInstrProf { +uint64_t ComputeHash(StringRef K); +} + /// A symbol table used for function PGO name look-up with keys /// (such as pointers, md5hash values) to the function. A function's /// PGO name or name's md5hash are used in retrieving the profile @@ -211,6 +216,7 @@ class InstrProfSymtab { private: StringRef Data; uint64_t Address; + std::vector> HashNameMap; public: InstrProfSymtab() : Data(), Address(0) {} @@ -223,11 +229,45 @@ public: Address = BaseAddr; return std::error_code(); } + template void create(NameIterRange &IterRange) { + for (auto Name : IterRange) + HashNameMap.push_back( + std::make_pair(IndexedInstrProf::ComputeHash(Name), Name.str())); + finalizeSymtab(); + } + + // If the symtab is created by a series calls to \c addFuncName, \c + // finalizeSymtab needs to + // be called before function name/symbol lookup using MD5 hash. This is + // required because + // the underlying map is vector (for space efficiency) which needs to be + // sorted. + void finalizeSymtab() { + std::sort(HashNameMap.begin(), HashNameMap.end(), less_first()); + HashNameMap.erase(std::unique(HashNameMap.begin(), HashNameMap.end()), + HashNameMap.end()); + } + + void addFuncName(StringRef FuncName) { + HashNameMap.push_back(std::make_pair( + IndexedInstrProf::ComputeHash(FuncName), FuncName.str())); + } /// Return function's PGO name from the function name's symabol /// address in the object file. If an error occurs, Return /// an empty string. StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize); + /// Return function's PGO name from the name's md5 hash value. + /// If not found, return an empty string. + StringRef getFuncName(uint64_t FuncMD5Hash) { + auto Result = + std::lower_bound(HashNameMap.begin(), HashNameMap.end(), FuncMD5Hash, + [](const std::pair &LHS, + uint64_t RHS) { return LHS.first < RHS; }); + if (Result != HashNameMap.end()) + return Result->second; + return StringRef(); + } }; struct InstrProfStringTable { @@ -481,7 +521,7 @@ static inline uint64_t MD5Hash(StringRef Str) { return endian::read(Result); } -static inline uint64_t ComputeHash(HashT Type, StringRef K) { +inline uint64_t ComputeHash(HashT Type, StringRef K) { switch (Type) { case HashT::MD5: return IndexedInstrProf::MD5Hash(K); @@ -493,9 +533,7 @@ const uint64_t Magic = 0x8169666f72706cff; // "\xfflprofi\x81" const uint64_t Version = INSTR_PROF_INDEX_VERSION; const HashT HashType = HashT::MD5; -static inline uint64_t ComputeHash(StringRef K) { - return ComputeHash(HashType, K); -} +inline uint64_t ComputeHash(StringRef K) { return ComputeHash(HashType, K); } // This structure defines the file header of the LLVM profile // data file in indexed-format. diff --git a/unittests/ProfileData/InstrProfTest.cpp b/unittests/ProfileData/InstrProfTest.cpp index ee357053a17..994f75502d9 100644 --- a/unittests/ProfileData/InstrProfTest.cpp +++ b/unittests/ProfileData/InstrProfTest.cpp @@ -524,4 +524,28 @@ TEST_F(InstrProfTest, get_weighted_function_counts) { ASSERT_EQ(20U, Counts[1]); } +TEST_F(InstrProfTest, instr_prof_symtab_test) { + std::vector FuncNames; + FuncNames.push_back("func1"); + FuncNames.push_back("func2"); + FuncNames.push_back("func3"); + FuncNames.push_back("bar1"); + FuncNames.push_back("bar2"); + FuncNames.push_back("bar3"); + InstrProfSymtab Symtab; + Symtab.create(FuncNames); + StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1")); + ASSERT_EQ(StringRef("func1"), R); + R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2")); + ASSERT_EQ(StringRef("func2"), R); + R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3")); + ASSERT_EQ(StringRef("func3"), R); + R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1")); + ASSERT_EQ(StringRef("bar1"), R); + R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2")); + ASSERT_EQ(StringRef("bar2"), R); + R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3")); + ASSERT_EQ(StringRef("bar3"), R); +} + } // end anonymous namespace