[llvm] [llvm-profdata] Do not create numerical strings for MD5 function names read from a Sample Profile. (PR #66164)
William Junda Huang via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 14 12:43:54 PDT 2023
https://github.com/huangjd updated https://github.com/llvm/llvm-project/pull/66164:
>From cd6a7b3241fdedec4016eb1c90d1c828762ca123 Mon Sep 17 00:00:00 2001
From: William Huang <williamjhuang at google.com>
Date: Thu, 24 Aug 2023 01:12:00 +0000
Subject: [PATCH 1/4] Fix dangling reference after D147740
---
llvm/include/llvm/ProfileData/SampleProf.h | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h
index aacea59f2821111..27ffd6439ac2c96 100644
--- a/llvm/include/llvm/ProfileData/SampleProf.h
+++ b/llvm/include/llvm/ProfileData/SampleProf.h
@@ -1603,13 +1603,25 @@ class ProfileConverter {
? TotalSamples - CalleeProfile.getTotalSamples()
: 0;
TotalSamples += CalleeProfile.getHeadSamplesEstimate();
+
+ }
+ }
+
+ // FlattenNestedProfile adds new FunctionSamples to the output, which may
+ // invalidate the reference Profile, so it needs to be reset after all
+ // flattening.
+ for (const auto &I : FS.getCallsiteSamples()) {
+ for (const auto &Callee : I.second) {
+ const auto &CalleeProfile = Callee.second;
// Recursively convert callee profile.
flattenNestedProfile(OutputProfiles, CalleeProfile);
}
}
- Profile.addTotalSamples(TotalSamples);
+ FunctionSamples &NewProfile = OutputProfiles[Context];
+
+ NewProfile.addTotalSamples(TotalSamples);
- Profile.setHeadSamples(Profile.getHeadSamplesEstimate());
+ NewProfile.setHeadSamples(NewProfile.getHeadSamplesEstimate());
}
// Nest all children profiles into the profile of Node.
>From cb3ed703d8f51619261e630408964b9b170a939e Mon Sep 17 00:00:00 2001
From: William Huang <williamjhuang at google.com>
Date: Wed, 23 Aug 2023 21:03:20 +0000
Subject: [PATCH 2/4] Remove collision check
---
llvm/include/llvm/ProfileData/SampleProf.h | 68 ++-----
.../tools/llvm-profdata/CMakeLists.txt | 1 -
.../tools/llvm-profdata/MD5CollisionTest.cpp | 166 ------------------
3 files changed, 10 insertions(+), 225 deletions(-)
delete mode 100644 llvm/unittests/tools/llvm-profdata/MD5CollisionTest.cpp
diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h
index 27ffd6439ac2c96..cf9b80b08932bea 100644
--- a/llvm/include/llvm/ProfileData/SampleProf.h
+++ b/llvm/include/llvm/ProfileData/SampleProf.h
@@ -1299,19 +1299,13 @@ raw_ostream &operator<<(raw_ostream &OS, const FunctionSamples &FS);
/// performance of insert and query operations especially when hash values of
/// keys are available a priori, and reduces memory usage if KeyT has a large
/// size.
-/// When performing any action, if an existing entry with a given key is found,
-/// and the interface "KeyT ValueT::getKey<KeyT>() const" to retrieve a value's
-/// original key exists, this class checks if the given key actually matches
-/// the existing entry's original key. If they do not match, this class behaves
-/// as if the entry did not exist (for insertion, this means the new value will
-/// replace the existing entry's value, as if it is newly inserted). If
-/// ValueT::getKey<KeyT>() is not available, all keys with the same hash value
-/// are considered equivalent (i.e. hash collision is silently ignored). Given
-/// such feature this class should only be used where it does not affect
-/// compilation correctness, for example, when loading a sample profile.
+/// All keys with the same hash value are considered equivalent (i.e. hash
+/// collision is silently ignored). Given such feature this class should only be
+/// used where it does not affect compilation correctness, for example, when
+/// loading a sample profile.
/// Assuming the hashing algorithm is uniform, the probability of hash collision
/// with 1,000,000 entries is
-/// (2^64)!/((2^64-1000000)!*(2^64)^1000000) ~= 3*10^-8.
+/// 1 - (2^64)!/((2^64-1000000)!*(2^64)^1000000) ~= 3*10^-8.
template <template <typename, typename, typename...> typename MapT,
typename KeyT, typename ValueT, typename... MapTArgs>
class HashKeyMap : public MapT<hash_code, ValueT, MapTArgs...> {
@@ -1325,42 +1319,12 @@ class HashKeyMap : public MapT<hash_code, ValueT, MapTArgs...> {
using iterator = typename base_type::iterator;
using const_iterator = typename base_type::const_iterator;
-private:
- // If the value type has getKey(), retrieve its original key for comparison.
- template <typename U = mapped_type,
- typename = decltype(U().template getKey<original_key_type>())>
- static bool
- CheckKeyMatch(const original_key_type &Key, const mapped_type &ExistingValue,
- original_key_type *ExistingKeyIfDifferent = nullptr) {
- const original_key_type &ExistingKey =
- ExistingValue.template getKey<original_key_type>();
- bool Result = (Key == ExistingKey);
- if (!Result && ExistingKeyIfDifferent)
- *ExistingKeyIfDifferent = ExistingKey;
- return Result;
- }
-
- // If getKey() does not exist, this overload is selected, which assumes all
- // keys with the same hash are equivalent.
- static bool CheckKeyMatch(...) { return true; }
-
-public:
template <typename... Ts>
std::pair<iterator, bool> try_emplace(const key_type &Hash,
const original_key_type &Key,
Ts &&...Args) {
assert(Hash == hash_value(Key));
- auto Ret = base_type::try_emplace(Hash, std::forward<Ts>(Args)...);
- if (!Ret.second) {
- original_key_type ExistingKey;
- if (LLVM_UNLIKELY(!CheckKeyMatch(Key, Ret.first->second, &ExistingKey))) {
- dbgs() << "MD5 collision detected: " << Key << " and " << ExistingKey
- << " has same hash value " << Hash << "\n";
- Ret.second = true;
- Ret.first->second = mapped_type(std::forward<Ts>(Args)...);
- }
- }
- return Ret;
+ return base_type::try_emplace(Hash, std::forward<Ts>(Args)...);
}
template <typename... Ts>
@@ -1382,8 +1346,7 @@ class HashKeyMap : public MapT<hash_code, ValueT, MapTArgs...> {
key_type Hash = hash_value(Key);
auto It = base_type::find(Hash);
if (It != base_type::end())
- if (LLVM_LIKELY(CheckKeyMatch(Key, It->second)))
- return It;
+ return It;
return base_type::end();
}
@@ -1391,8 +1354,7 @@ class HashKeyMap : public MapT<hash_code, ValueT, MapTArgs...> {
key_type Hash = hash_value(Key);
auto It = base_type::find(Hash);
if (It != base_type::end())
- if (LLVM_LIKELY(CheckKeyMatch(Key, It->second)))
- return It;
+ return It;
return base_type::end();
}
@@ -1433,19 +1395,9 @@ class SampleProfileMap
Ctx);
}
- // Overloaded find() to lookup a function by name. This is called by IPO
- // passes with an actual function name, and it is possible that the profile
- // reader converted function names in the profile to MD5 strings, so we need
- // to check if either representation matches.
+ // Overloaded find() to lookup a function by name.
iterator find(StringRef Fname) {
- uint64_t Hash = hashFuncName(Fname);
- auto It = base_type::find(hash_code(Hash));
- if (It != end()) {
- StringRef CtxName = It->second.getContext().getName();
- if (LLVM_LIKELY(CtxName == Fname || CtxName == std::to_string(Hash)))
- return It;
- }
- return end();
+ return base_type::find(hashFuncName(Fname));
}
size_t erase(const SampleContext &Ctx) {
diff --git a/llvm/unittests/tools/llvm-profdata/CMakeLists.txt b/llvm/unittests/tools/llvm-profdata/CMakeLists.txt
index c53baf69bbc0ef8..ad91ce36bcb5bef 100644
--- a/llvm/unittests/tools/llvm-profdata/CMakeLists.txt
+++ b/llvm/unittests/tools/llvm-profdata/CMakeLists.txt
@@ -6,7 +6,6 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(LLVMProfdataTests
OutputSizeLimitTest.cpp
- MD5CollisionTest.cpp
)
target_link_libraries(LLVMProfdataTests PRIVATE LLVMTestingSupport)
diff --git a/llvm/unittests/tools/llvm-profdata/MD5CollisionTest.cpp b/llvm/unittests/tools/llvm-profdata/MD5CollisionTest.cpp
deleted file mode 100644
index 8af74249188dd14..000000000000000
--- a/llvm/unittests/tools/llvm-profdata/MD5CollisionTest.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-//===- llvm/unittests/tools/llvm-profdata/MD5CollisionTest.cpp ------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-/// Test whether the MD5-key SampleProfileMap can handle collision correctly.
-/// Probability of collision is rare but not negligible since we only use the
-/// lower 64 bits of the MD5 value. A unit test is required because the function
-/// names are not printable ASCII characters.
-
-#include "llvm/ProfileData/SampleProfReader.h"
-#include "llvm/Support/VirtualFileSystem.h"
-#include "llvm/Testing/Support/Error.h"
-#include "gtest/gtest.h"
-
-/// According to https://en.wikipedia.org/wiki/MD5#Preimage_vulnerability, the
-/// MD5 of the two strings are 79054025255fb1a26e4bc422aef54eb4.
-
-// First 8 bytes of the MD5.
-const uint64_t ExpectedHash = 0xa2b15f2525400579;
-
-// clang-format off
-const uint8_t ProfileData[] = {
- 0x84, 0xe4, 0xd0, 0xb1, 0xf4, 0xc9, 0x94, 0xa8,
- 0x53, 0x67, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00,
-
- /// Name Table
- 0x02,
- /// String1
- 0xd1, 0x31, 0xdd, 0x02, 0xc5, 0xe6, 0xee, 0xc4,
- 0x69, 0x3d, 0x9a, 0x06, 0x98, 0xaf, 0xf9, 0x5c,
- 0x2f, 0xca, 0xb5, 0x87, 0x12, 0x46, 0x7e, 0xab,
- 0x40, 0x04, 0x58, 0x3e, 0xb8, 0xfb, 0x7f, 0x89,
- 0x55, 0xad, 0x34, 0x06, 0x09, 0xf4, 0xb3, 0x02,
- 0x83, 0xe4, 0x88, 0x83, 0x25, 0x71, 0x41, 0x5a,
- 0x08, 0x51, 0x25, 0xe8, 0xf7, 0xcd, 0xc9, 0x9f,
- 0xd9, 0x1d, 0xbd, 0xf2, 0x80, 0x37, 0x3c, 0x5b,
- 0xd8, 0x82, 0x3e, 0x31, 0x56, 0x34, 0x8f, 0x5b,
- 0xae, 0x6d, 0xac, 0xd4, 0x36, 0xc9, 0x19, 0xc6,
- 0xdd, 0x53, 0xe2, 0xb4, 0x87, 0xda, 0x03, 0xfd,
- 0x02, 0x39, 0x63, 0x06, 0xd2, 0x48, 0xcd, 0xa0,
- 0xe9, 0x9f, 0x33, 0x42, 0x0f, 0x57, 0x7e, 0xe8,
- 0xce, 0x54, 0xb6, 0x70, 0x80, 0xa8, 0x0d, 0x1e,
- 0xc6, 0x98, 0x21, 0xbc, 0xb6, 0xa8, 0x83, 0x93,
- 0x96, 0xf9, 0x65, 0x2b, 0x6f, 0xf7, 0x2a, 0x70, 0x00,
- /// String2
- 0xd1, 0x31, 0xdd, 0x02, 0xc5, 0xe6, 0xee, 0xc4,
- 0x69, 0x3d, 0x9a, 0x06, 0x98, 0xaf, 0xf9, 0x5c,
- 0x2f, 0xca, 0xb5, 0x07, 0x12, 0x46, 0x7e, 0xab,
- 0x40, 0x04, 0x58, 0x3e, 0xb8, 0xfb, 0x7f, 0x89,
- 0x55, 0xad, 0x34, 0x06, 0x09, 0xf4, 0xb3, 0x02,
- 0x83, 0xe4, 0x88, 0x83, 0x25, 0xf1, 0x41, 0x5a,
- 0x08, 0x51, 0x25, 0xe8, 0xf7, 0xcd, 0xc9, 0x9f,
- 0xd9, 0x1d, 0xbd, 0x72, 0x80, 0x37, 0x3c, 0x5b,
- 0xd8, 0x82, 0x3e, 0x31, 0x56, 0x34, 0x8f, 0x5b,
- 0xae, 0x6d, 0xac, 0xd4, 0x36, 0xc9, 0x19, 0xc6,
- 0xdd, 0x53, 0xe2, 0x34, 0x87, 0xda, 0x03, 0xfd,
- 0x02, 0x39, 0x63, 0x06, 0xd2, 0x48, 0xcd, 0xa0,
- 0xe9, 0x9f, 0x33, 0x42, 0x0f, 0x57, 0x7e, 0xe8,
- 0xce, 0x54, 0xb6, 0x70, 0x80, 0x28, 0x0d, 0x1e,
- 0xc6, 0x98, 0x21, 0xbc, 0xb6, 0xa8, 0x83, 0x93,
- 0x96, 0xf9, 0x65, 0xab, 0x6f, 0xf7, 0x2a, 0x70, 0x00,
-
- /// FuncOffsetTable
- 0x02, 0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
- /// Samples
- /// String1:10:1
- /// 1: 5
- /// 2.3: 6
- /// 4: String2:100
- /// 1: 100
- /// String2:7:3
- /// 9: 0
- 0x01, 0x00, 0x0a, 0x02, 0x01, 0x00, 0x05, 0x00,
- 0x02, 0x03, 0x06, 0x00, 0x01, 0x04, 0x00, 0x01,
- 0x64, 0x01, 0x01, 0x00, 0x64, 0x00, 0x00,
-
- 0x03, 0x01, 0x07, 0x01, 0x09, 0x00, 0x00, 0x00,
- 0x00};
-// clang-format on
-
-using namespace llvm;
-using namespace llvm::sampleprof;
-
-TEST(MD5CollisionTest, TestCollision) {
- auto InputBuffer = MemoryBuffer::getMemBuffer(
- StringRef(reinterpret_cast<const char *>(ProfileData),
- sizeof(ProfileData)),
- "", false);
- LLVMContext Context;
- auto FileSystem = vfs::getRealFileSystem();
- auto Result = SampleProfileReader::create(InputBuffer, Context, *FileSystem);
- ASSERT_TRUE(Result);
- SampleProfileReader *Reader = Result->get();
- ASSERT_FALSE(Reader->read());
-
- std::vector<StringRef> &NameTable = *Reader->getNameTable();
- ASSERT_EQ(NameTable.size(), 2U);
- StringRef S1 = NameTable[0];
- StringRef S2 = NameTable[1];
- ASSERT_NE(S1, S2);
- ASSERT_EQ(MD5Hash(S1), ExpectedHash);
- ASSERT_EQ(MD5Hash(S2), ExpectedHash);
-
- // S2's MD5 value collides with S1, S1 is expected to be dropped when S2 is
- // inserted, as if S1 never existed.
-
- FunctionSamples ExpectedFS;
- ExpectedFS.setName(S2);
- ExpectedFS.setHeadSamples(3);
- ExpectedFS.setTotalSamples(7);
- ExpectedFS.addBodySamples(9, 0, 0);
-
- SampleProfileMap &Profiles = Reader->getProfiles();
- EXPECT_EQ(Profiles.size(), 1U);
- if (Profiles.size()) {
- auto &[Hash, FS] = *Profiles.begin();
- EXPECT_EQ(Hash, hash_code(ExpectedHash));
- EXPECT_EQ(FS, ExpectedFS);
- }
-
- // Inserting S2 again should fail, returning the existing sample unchanged.
- auto [It1, Inserted1] = Profiles.try_emplace(S2, FunctionSamples());
- EXPECT_FALSE(Inserted1);
- EXPECT_EQ(Profiles.size(), 1U);
- if (Profiles.size()) {
- auto &[Hash, FS] = *It1;
- EXPECT_EQ(Hash, hash_code(ExpectedHash));
- EXPECT_EQ(FS, ExpectedFS);
- }
-
- // Inserting S1 should success as if S2 never existed, and S2 is erased.
- FunctionSamples FS1;
- FS1.setName(S1);
- FS1.setHeadSamples(5);
- FS1.setTotalSamples(10);
- FS1.addBodySamples(1, 2, 5);
-
- auto [It2, Inserted2] = Profiles.try_emplace(S1, FS1);
- EXPECT_TRUE(Inserted2);
- EXPECT_EQ(Profiles.size(), 1U);
- if (Profiles.size()) {
- auto &[Hash, FS] = *It2;
- EXPECT_EQ(Hash, hash_code(ExpectedHash));
- EXPECT_EQ(FS, FS1);
- }
-}
>From 00d64b2502fd0cf4b45b0aba062c1039cf1664be Mon Sep 17 00:00:00 2001
From: William Huang <williamjhuang at google.com>
Date: Wed, 13 Sep 2023 01:17:16 +0000
Subject: [PATCH 3/4] [llvm-profdata] Do not create numerical strings for MD5
function names read from a Sample Profile.
This is phase 2 of the MD5 refactoring on Sample Profile following https://reviews.llvm.org/D147740
It extends the StringRef class as ProfiledBinary to represent MD5 values
directly, and use this class in ProfileData/* and Transforms/IPO/*.
---
llvm/include/llvm/ADT/StringRef.h | 11 +
.../llvm/ProfileData/ProfileFuncName.h | 260 ++++++++++++++++++
llvm/include/llvm/ProfileData/SampleProf.h | 126 +++++----
.../llvm/ProfileData/SampleProfReader.h | 27 +-
.../llvm/ProfileData/SampleProfWriter.h | 12 +-
.../llvm/Transforms/IPO/ProfiledCallGraph.h | 24 +-
.../Transforms/IPO/SampleContextTracker.h | 27 +-
llvm/lib/ProfileData/SampleProf.cpp | 25 +-
llvm/lib/ProfileData/SampleProfReader.cpp | 76 ++---
llvm/lib/ProfileData/SampleProfWriter.cpp | 30 +-
llvm/lib/Target/X86/X86InsertPrefetch.cpp | 3 +-
.../Transforms/IPO/SampleContextTracker.cpp | 64 ++---
llvm/lib/Transforms/IPO/SampleProfile.cpp | 68 ++---
llvm/tools/llvm-profdata/llvm-profdata.cpp | 16 +-
llvm/tools/llvm-profgen/CSPreInliner.cpp | 8 +-
llvm/tools/llvm-profgen/CSPreInliner.h | 7 +-
llvm/tools/llvm-profgen/ProfileGenerator.cpp | 19 +-
llvm/tools/llvm-profgen/ProfiledBinary.cpp | 15 +-
llvm/tools/llvm-profgen/ProfiledBinary.h | 20 +-
llvm/unittests/ProfileData/SampleProfTest.cpp | 45 ++-
20 files changed, 587 insertions(+), 296 deletions(-)
create mode 100644 llvm/include/llvm/ProfileData/ProfileFuncName.h
diff --git a/llvm/include/llvm/ADT/StringRef.h b/llvm/include/llvm/ADT/StringRef.h
index 235a7b27c384406..2fa2398e6c50dac 100644
--- a/llvm/include/llvm/ADT/StringRef.h
+++ b/llvm/include/llvm/ADT/StringRef.h
@@ -30,6 +30,10 @@ namespace llvm {
template <typename T> class SmallVectorImpl;
class StringRef;
+ namespace sampleprof {
+ class ProfileFuncName;
+ }
+
/// Helper functions for StringRef::getAsInteger.
bool getAsUnsignedInteger(StringRef Str, unsigned Radix,
unsigned long long &Result);
@@ -48,6 +52,8 @@ namespace llvm {
/// lifetime extends past that of the StringRef. For this reason, it is not in
/// general safe to store a StringRef.
class LLVM_GSL_POINTER StringRef {
+ friend class llvm::sampleprof::ProfileFuncName;
+
public:
static constexpr size_t npos = ~size_t(0);
@@ -80,6 +86,11 @@ namespace llvm {
/// if (S == nullptr)
StringRef(std::nullptr_t) = delete;
+ /// Disallow casting from ProfileFuncName because if it is representing a
+ /// MD5 value, most string method will not work. Use
+ /// stringRef(std::string &) instead.
+ StringRef(const sampleprof::ProfileFuncName) = delete;
+
/// Construct a string ref from a cstring.
/*implicit*/ constexpr StringRef(const char *Str)
: Data(Str), Length(Str ?
diff --git a/llvm/include/llvm/ProfileData/ProfileFuncName.h b/llvm/include/llvm/ProfileData/ProfileFuncName.h
new file mode 100644
index 000000000000000..e287d519155798f
--- /dev/null
+++ b/llvm/include/llvm/ProfileData/ProfileFuncName.h
@@ -0,0 +1,260 @@
+//===--- ProfileFuncName.h - Sample profile function name ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the StringRefOrHashCode class. It is to represent function
+// names in a sample profile, which can be in one of two forms - either a
+// regular string, or a 64-bit hash code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PROFILEDATA_PROFILEFUNCNAME_H
+#define LLVM_PROFILEDATA_PROFILEFUNCNAME_H
+
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
+
+namespace llvm {
+namespace sampleprof {
+
+/// This class represents a function name that is read from a sample profile. It
+/// comes with two forms: a string or a hash code. For efficient storage, a
+/// sample profile may store function names as 64-bit MD5 values, so when
+/// reading the profile, this class can represnet them without converting it to
+/// a string first.
+/// When representing a hash code, we utilize the Length field to store it, and
+/// Data is set to null. When representing a string, it is same as StringRef,
+/// and can be pointer-casted as one.
+/// We disallow implicit cast to StringRef because there are too many instances
+/// that it may cause break the code, such as using it in a StringMap.
+class ProfileFuncName : private StringRef {
+
+ // Add placeholder to make sure there are enough space after Length field so
+ // that it can fit a 64-bit hash code, if the machine is 32-bit or any other
+ // weird architecture. The placeholder field should be set to zero so that it
+ // will not contain undefined values and break optimized comparison methods.
+#if UINTPTR_MAX < UINT64_MAX || SIZE_MAX < UINT64_MAX
+ uint64_t Placeholder;
+#endif
+
+ /// Get the hash code if it is representing one, otherwise this equals to
+ /// the Length of the StringRef.
+ uint64_t &getIntValue() {
+ return *reinterpret_cast<uint64_t *>(&this->Length);
+ }
+
+ const uint64_t &getIntValue() const {
+ return *reinterpret_cast<const uint64_t *>(&this->Length);
+ }
+
+ /// Extension to memcmp to handle hash code representation. If both are hash
+ /// values, Lhs and Rhs are both null, function returns 0 (and needs an extra
+ /// comparison using getIntValue). If only one is hash code, it is considered
+ /// less than the StringRef one. Otherwise perform normal string comparison.
+ static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) {
+ if (Lhs == Rhs)
+ return 0;
+ if (!Lhs)
+ return -1;
+ if (!Rhs)
+ return 1;
+ return ::memcmp(Lhs, Rhs, Length);
+ }
+
+public:
+ /// Default constructor. Use memset because there may be padding bytes between
+ /// Length and Placeholder containing undefined values on certain
+ /// architectures, which breaks comparison methods.
+ ProfileFuncName() {
+ memset(this, 0, sizeof(ProfileFuncName));
+ }
+
+ /// Constructor from a StringRef.
+ explicit ProfileFuncName(StringRef Str) : ProfileFuncName() {
+ Data = Str.Data;
+ Length = Str.Length;
+ }
+
+ /// Constructor from a hash code.
+ explicit ProfileFuncName(uint64_t HashCode) : ProfileFuncName() {
+ assert(HashCode != 0);
+ getIntValue() = HashCode;
+ }
+
+ /// Constructor from a string. Check if Str is a number, which is generated by
+ /// converting a MD5 sample profile to a format that does not support MD5, and
+ /// if so, convert the numerical string to a hash code first. We assume that
+ /// no function name (from a profile) can be a pure number.
+ explicit ProfileFuncName(const std::string &Str) : ProfileFuncName() {
+ uint64_t Hash;
+ // Faster
+ if (Str.length() > 0 && isdigit(Str[0]) && !getAsInteger(10, Hash))
+ *this = ProfileFuncName(Hash);
+ else
+ *this = ProfileFuncName(StringRef(Str));
+ }
+
+ /// Check for equality. Similar to StringRef::equals, but will also cover for
+ /// the case where one or both are hash codes. Comparing their int values are
+ /// sufficient. A hash code ProfileFuncName is considered not equal to a
+ /// StringRef ProfileFuncName regardless of actual contents.
+ bool equals(const ProfileFuncName &Other) const {
+ return getIntValue() == Other.getIntValue() &&
+ compareMemory(data(), Other.data(), size()) == 0;
+ }
+
+ /// Total order comparison. If both ProfileFuncName are StringRef, this is the
+ /// same as StringRef::compare. If one of them is StringRef, it is considered
+ /// greater than the hash code ProfileFuncName. Otherwise this is the the
+ /// same as comparing their int values.
+ int compare(const ProfileFuncName &Other) const {
+ auto Res = compareMemory(data(), Other.data(),
+ std::min(size(), Other.size()));
+ if (Res != 0)
+ return Res;
+ if (getIntValue() == Other.getIntValue())
+ return 0;
+ return getIntValue() < Other.getIntValue() ? -1 : 1;
+ }
+
+ /// Convert to a string, usually for output purpose.
+ std::string str() const {
+ if (data())
+ return std::string(data(), size());
+ if (getIntValue() != 0)
+ return std::to_string(getIntValue());
+ return std::string();
+ }
+
+ /// Convert to StringRef, a backing buffer must be provided in case this
+ /// object represents a hash code, which will be converted to a string into
+ /// the buffer. If this object represents a StringRef, the buffer is not used.
+ StringRef stringRef(std::string &Buffer) const {
+ if (data())
+ return static_cast<const StringRef &>(*this);
+ if (getIntValue() != 0) {
+ Buffer = std::to_string(getIntValue());
+ return Buffer;
+ }
+ return StringRef();
+ }
+
+ friend raw_ostream &operator<<(raw_ostream &OS,
+ const ProfileFuncName &Obj);
+
+ /// Get hash code of this object. Returns this object's hash code if it is
+ /// already representing one, otherwise returns the MD5 of its string content.
+ /// Note that it is not the same as std::hash because we want to keep the
+ /// consistency that the same sample profile function in string form or MD5
+ /// form has the same hash code.
+ uint64_t getHashCode() const {
+ if (data())
+ return MD5Hash(static_cast<const StringRef &>(*this));
+ return getIntValue();
+ }
+
+ bool empty() const {
+ return getIntValue() == 0;
+ }
+
+ /// Check if this object represents a StringRef, or a hash code.
+ bool isStringRef() const {
+ return data();
+ }
+};
+
+inline bool operator==(const ProfileFuncName &LHS,
+ const ProfileFuncName &RHS) {
+ return LHS.equals(RHS);
+}
+
+inline bool operator!=(const ProfileFuncName &LHS,
+ const ProfileFuncName &RHS) {
+ return !LHS.equals(RHS);
+}
+
+inline bool operator<(const ProfileFuncName &LHS,
+ const ProfileFuncName &RHS) {
+ return LHS.compare(RHS) < 0;
+}
+
+inline bool operator<=(const ProfileFuncName &LHS,
+ const ProfileFuncName &RHS) {
+ return LHS.compare(RHS) <= 0;
+}
+
+inline bool operator>(const ProfileFuncName &LHS,
+ const ProfileFuncName &RHS) {
+ return LHS.compare(RHS) > 0;
+}
+
+inline bool operator>=(const ProfileFuncName &LHS,
+ const ProfileFuncName &RHS) {
+ return LHS.compare(RHS) >= 0;
+}
+
+inline raw_ostream &operator<<(raw_ostream &OS, const ProfileFuncName &Obj) {
+ if (Obj.data())
+ return OS << static_cast<const StringRef &>(Obj);
+ if (Obj.getIntValue() != 0)
+ return OS << Obj.getIntValue();
+ return OS;
+}
+
+inline uint64_t MD5Hash(const sampleprof::ProfileFuncName &Obj) {
+ return Obj.getHashCode();
+}
+
+inline hash_code hash_value(const sampleprof::ProfileFuncName &Obj) {
+ return Obj.getHashCode();
+}
+
+} // end namespace sampleprof
+
+/// Template specialization for ProfileFuncName so that it can be used in LLVM
+/// map containers.
+template <>
+struct DenseMapInfo<sampleprof::ProfileFuncName, void> {
+
+ static inline sampleprof::ProfileFuncName getEmptyKey() {
+ return sampleprof::ProfileFuncName(~0ULL);
+ }
+
+ static inline sampleprof::ProfileFuncName getTombstoneKey() {
+ return sampleprof::ProfileFuncName(~1ULL);
+ }
+
+ static unsigned getHashValue(const sampleprof::ProfileFuncName &Val) {
+ return Val.getHashCode();
+ }
+
+ static bool isEqual(const sampleprof::ProfileFuncName &LHS,
+ const sampleprof::ProfileFuncName &RHS) {
+ return LHS == RHS;
+ }
+};
+
+} // end namespace llvm
+
+namespace std {
+
+/// Template specialization for ProfileFuncName so that it can be used in STL
+/// containers.
+template <>
+struct hash<llvm::sampleprof::ProfileFuncName> {
+ size_t operator()(const llvm::sampleprof::ProfileFuncName &Val) const {
+ return Val.getHashCode();
+ }
+};
+
+} // end namespace std
+
+#endif // LLVM_PROFILEDATA_PROFILEFUNCNAME_H
diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h
index cf9b80b08932bea..845066dc8a0c3f2 100644
--- a/llvm/include/llvm/ProfileData/SampleProf.h
+++ b/llvm/include/llvm/ProfileData/SampleProf.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
+#include "llvm/ProfileData/ProfileFuncName.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorOr.h"
@@ -111,12 +112,10 @@ static inline uint64_t SPMagic(SampleProfileFormat Format = SPF_Binary) {
/// Get the proper representation of a string according to whether the
/// current Format uses MD5 to represent the string.
-static inline StringRef getRepInFormat(StringRef Name, bool UseMD5,
- std::string &GUIDBuf) {
+static inline ProfileFuncName getRepInFormat(StringRef Name, bool UseMD5) {
if (Name.empty() || !UseMD5)
- return Name;
- GUIDBuf = std::to_string(Function::getGUID(Name));
- return GUIDBuf;
+ return ProfileFuncName(Name);
+ return ProfileFuncName(Function::getGUID(Name));
}
static inline uint64_t SPVersion() { return 103; }
@@ -305,6 +304,10 @@ struct LineLocation {
return LineOffset != O.LineOffset || Discriminator != O.Discriminator;
}
+ uint64_t getHashCode() const {
+ return ((uint64_t) Discriminator << 32) | LineOffset;
+ }
+
uint32_t LineOffset;
uint32_t Discriminator;
};
@@ -318,14 +321,6 @@ struct LineLocationHash {
raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc);
-static inline uint64_t hashFuncName(StringRef F) {
- // If function name is already MD5 string, do not hash again.
- uint64_t Hash;
- if (F.getAsInteger(10, Hash))
- Hash = MD5Hash(F);
- return Hash;
-}
-
/// Representation of a single sample record.
///
/// A sample record is represented by a positive integer value, which
@@ -338,7 +333,7 @@ static inline uint64_t hashFuncName(StringRef F) {
/// will be a list of one or more functions.
class SampleRecord {
public:
- using CallTarget = std::pair<StringRef, uint64_t>;
+ using CallTarget = std::pair<ProfileFuncName, uint64_t>;
struct CallTargetComparator {
bool operator()(const CallTarget &LHS, const CallTarget &RHS) const {
if (LHS.second != RHS.second)
@@ -349,7 +344,7 @@ class SampleRecord {
};
using SortedCallTargetSet = std::set<CallTarget, CallTargetComparator>;
- using CallTargetMap = StringMap<uint64_t>;
+ using CallTargetMap = std::unordered_map<ProfileFuncName, uint64_t>;
SampleRecord() = default;
/// Increment the number of samples for this record by \p S.
@@ -378,7 +373,7 @@ class SampleRecord {
///
/// Sample counts accumulate using saturating arithmetic, to avoid wrapping
/// around unsigned integers.
- sampleprof_error addCalledTarget(StringRef F, uint64_t S,
+ sampleprof_error addCalledTarget(ProfileFuncName F, uint64_t S,
uint64_t Weight = 1) {
uint64_t &TargetSamples = CallTargets[F];
bool Overflowed;
@@ -390,7 +385,7 @@ class SampleRecord {
/// Remove called function from the call target map. Return the target sample
/// count of the called function.
- uint64_t removeCalledTarget(StringRef F) {
+ uint64_t removeCalledTarget(ProfileFuncName F) {
uint64_t Count = 0;
auto I = CallTargets.find(F);
if (I != CallTargets.end()) {
@@ -476,12 +471,12 @@ enum ContextAttributeMask {
// Represents a context frame with function name and line location
struct SampleContextFrame {
- StringRef FuncName;
+ ProfileFuncName FuncName;
LineLocation Location;
SampleContextFrame() : Location(0, 0) {}
- SampleContextFrame(StringRef FuncName, LineLocation Location)
+ SampleContextFrame(ProfileFuncName FuncName, LineLocation Location)
: FuncName(FuncName), Location(Location) {}
bool operator==(const SampleContextFrame &That) const {
@@ -502,6 +497,12 @@ struct SampleContextFrame {
}
return OContextStr.str();
}
+
+ uint64_t getHashCode() const {
+ uint64_t NameHash = FuncName.getHashCode();
+ uint64_t LocId = Location.getHashCode();
+ return NameHash + (LocId << 5) + LocId;
+ }
};
static inline hash_code hash_value(const SampleContextFrame &arg) {
@@ -535,6 +536,9 @@ class SampleContext {
SampleContext(StringRef Name)
: Name(Name), State(UnknownContext), Attributes(ContextNone) {}
+ SampleContext(ProfileFuncName Name)
+ : Name(Name), State(UnknownContext), Attributes(ContextNone) {}
+
SampleContext(SampleContextFrames Context,
ContextStateMask CState = RawContext)
: Attributes(ContextNone) {
@@ -555,7 +559,7 @@ class SampleContext {
bool HasContext = ContextStr.startswith("[");
if (!HasContext) {
State = UnknownContext;
- Name = ContextStr;
+ Name = ProfileFuncName(ContextStr);
} else {
CSNameTable.emplace_back();
SampleContextFrameVector &Context = CSNameTable.back();
@@ -572,7 +576,7 @@ class SampleContext {
ContextStr = ContextStr.substr(1, ContextStr.size() - 2);
StringRef ContextRemain = ContextStr;
StringRef ChildContext;
- StringRef CalleeName;
+ ProfileFuncName CalleeName;
while (!ContextRemain.empty()) {
auto ContextSplit = ContextRemain.split(" @ ");
ChildContext = ContextSplit.first;
@@ -585,11 +589,12 @@ class SampleContext {
// Decode context string for a frame to get function name and location.
// `ContextStr` is in the form of `FuncName:StartLine.Discriminator`.
- static void decodeContextString(StringRef ContextStr, StringRef &FName,
+ static void decodeContextString(StringRef ContextStr,
+ ProfileFuncName &FName,
LineLocation &LineLoc) {
// Get function name
auto EntrySplit = ContextStr.split(':');
- FName = EntrySplit.first;
+ FName = ProfileFuncName(EntrySplit.first);
LineLoc = {0, 0};
if (!EntrySplit.second.empty()) {
@@ -616,7 +621,7 @@ class SampleContext {
void clearState(ContextStateMask S) { State &= (uint32_t)~S; }
bool hasContext() const { return State != UnknownContext; }
bool isBaseContext() const { return FullContext.size() == 1; }
- StringRef getName() const { return Name; }
+ ProfileFuncName getName() const { return Name; }
SampleContextFrames getContextFrames() const { return FullContext; }
static std::string getContextString(SampleContextFrames Context,
@@ -641,14 +646,11 @@ class SampleContext {
uint64_t getHashCode() const {
if (hasContext())
return hash_value(getContextFrames());
-
- // For non-context function name, use its MD5 as hash value, so that it is
- // consistent with the profile map's key.
- return hashFuncName(getName());
+ return getName().getHashCode();
}
/// Set the name of the function and clear the current context.
- void setName(StringRef FunctionName) {
+ void setName(ProfileFuncName FunctionName) {
Name = FunctionName;
FullContext = SampleContextFrames();
State = UnknownContext;
@@ -713,7 +715,7 @@ class SampleContext {
private:
/// Mangled name of the function.
- StringRef Name;
+ ProfileFuncName Name;
// Full context including calling context and leaf function name
SampleContextFrames FullContext;
// State of the associated sample profile
@@ -736,7 +738,7 @@ class SampleProfileReaderItaniumRemapper;
using BodySampleMap = std::map<LineLocation, SampleRecord>;
// NOTE: Using a StringMap here makes parsed profiles consume around 17% more
// memory, which is *very* significant for large profiles.
-using FunctionSamplesMap = std::map<std::string, FunctionSamples, std::less<>>;
+using FunctionSamplesMap = std::map<ProfileFuncName, FunctionSamples>;
using CallsiteSampleMap = std::map<LineLocation, FunctionSamplesMap>;
using LocToLocMap =
std::unordered_map<LineLocation, LineLocation, LineLocationHash>;
@@ -788,14 +790,16 @@ class FunctionSamples {
sampleprof_error addCalledTargetSamples(uint32_t LineOffset,
uint32_t Discriminator,
- StringRef FName, uint64_t Num,
+ ProfileFuncName FName,
+ uint64_t Num,
uint64_t Weight = 1) {
return BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
FName, Num, Weight);
}
sampleprof_error addSampleRecord(LineLocation Location,
- const SampleRecord &SampleRecord, uint64_t Weight = 1) {
+ const SampleRecord &SampleRecord,
+ uint64_t Weight = 1) {
return BodySamples[Location].merge(SampleRecord, Weight);
}
@@ -803,7 +807,7 @@ class FunctionSamples {
// the number of body samples actually decreased.
uint64_t removeCalledTargetAndBodySample(uint32_t LineOffset,
uint32_t Discriminator,
- StringRef FName) {
+ ProfileFuncName FName) {
uint64_t Count = 0;
auto I = BodySamples.find(LineLocation(LineOffset, Discriminator));
if (I != BodySamples.end()) {
@@ -1046,16 +1050,16 @@ class FunctionSamples {
};
if (isDeclaration(SymbolMap.lookup(getFuncName()))) {
// Add to the import list only when it's defined out of module.
- S.insert(getGUID(getName()));
+ S.insert(getGUID());
}
// Import hot CallTargets, which may not be available in IR because full
// profile annotation cannot be done until backend compilation in ThinLTO.
for (const auto &BS : BodySamples)
for (const auto &TS : BS.second.getCallTargets())
- if (TS.getValue() > Threshold) {
- const Function *Callee = SymbolMap.lookup(getFuncName(TS.getKey()));
+ if (TS.second > Threshold) {
+ const Function *Callee = SymbolMap.lookup(getFuncName(TS.first));
if (isDeclaration(Callee))
- S.insert(getGUID(TS.getKey()));
+ S.insert(TS.first.getHashCode());
}
for (const auto &CS : CallsiteSamples)
for (const auto &NameFS : CS.second)
@@ -1063,10 +1067,12 @@ class FunctionSamples {
}
/// Set the name of the function.
- void setName(StringRef FunctionName) { Context.setName(FunctionName); }
+ void setName(ProfileFuncName FunctionName) {
+ Context.setName(FunctionName);
+ }
/// Return the function name.
- StringRef getName() const { return Context.getName(); }
+ ProfileFuncName getName() const { return Context.getName(); }
/// Return the original function name.
StringRef getFuncName() const { return getFuncName(getName()); }
@@ -1133,12 +1139,12 @@ class FunctionSamples {
/// translate \p Name in current FunctionSamples into its original name
/// by looking up in the function map GUIDToFuncNameMap.
/// If the original name doesn't exist in the map, return empty StringRef.
- StringRef getFuncName(StringRef Name) const {
+ StringRef getFuncName(ProfileFuncName Name) const {
if (!UseMD5)
- return Name;
+ return reinterpret_cast<StringRef &>(Name);
assert(GUIDToFuncNameMap && "GUIDToFuncNameMap needs to be populated first");
- return GUIDToFuncNameMap->lookup(std::stoull(Name.data()));
+ return GUIDToFuncNameMap->lookup(Name.getHashCode());
}
/// Returns the line offset to the start line of the subprogram.
@@ -1154,7 +1160,9 @@ class FunctionSamples {
/// Returns a unique hash code for a combination of a callsite location and
/// the callee function name.
- static uint64_t getCallSiteHash(StringRef CalleeName,
+ /// Guarantee MD5 and non-MD5 representation of the same function results in
+ /// the same hash.
+ static uint64_t getCallSiteHash(ProfileFuncName CalleeName,
const LineLocation &Callsite);
/// Get the FunctionSamples of the inline instance where DIL originates
@@ -1195,16 +1203,15 @@ class FunctionSamples {
/// all the function symbols defined or declared in current module.
DenseMap<uint64_t, StringRef> *GUIDToFuncNameMap = nullptr;
- // Assume the input \p Name is a name coming from FunctionSamples itself.
- // If UseMD5 is true, the name is already a GUID and we
- // don't want to return the GUID of GUID.
- static uint64_t getGUID(StringRef Name) {
- return UseMD5 ? std::stoull(Name.data()) : Function::getGUID(Name);
+ /// Return the GUID of the context's name. If the context is already using
+ /// MD5, don't hash it again.
+ uint64_t getGUID() const {
+ return getName().getHashCode();
}
// Find all the names in the current FunctionSamples including names in
// all the inline instances and names of call targets.
- void findAllNames(DenseSet<StringRef> &NameSet) const;
+ void findAllNames(DenseSet<ProfileFuncName> &NameSet) const;
bool operator==(const FunctionSamples &Other) const {
return (GUIDToFuncNameMap == Other.GUIDToFuncNameMap ||
@@ -1287,9 +1294,8 @@ class FunctionSamples {
const LocToLocMap *IRToProfileLocationMap = nullptr;
};
-template <>
-inline const SampleContext &FunctionSamples::getKey<SampleContext>() const {
- return getContext();
+static inline ProfileFuncName getRepInFormat(StringRef Name) {
+ return getRepInFormat(Name, FunctionSamples::UseMD5);
}
raw_ostream &operator<<(raw_ostream &OS, const FunctionSamples &FS);
@@ -1396,8 +1402,8 @@ class SampleProfileMap
}
// Overloaded find() to lookup a function by name.
- iterator find(StringRef Fname) {
- return base_type::find(hashFuncName(Fname));
+ iterator find(ProfileFuncName Fname) {
+ return base_type::find(Fname.getHashCode());
}
size_t erase(const SampleContext &Ctx) {
@@ -1470,7 +1476,7 @@ class ProfileConverter {
// profile.
void convertCSProfiles();
struct FrameNode {
- FrameNode(StringRef FName = StringRef(),
+ FrameNode(ProfileFuncName FName = ProfileFuncName(),
FunctionSamples *FSamples = nullptr,
LineLocation CallLoc = {0, 0})
: FuncName(FName), FuncSamples(FSamples), CallSiteLoc(CallLoc){};
@@ -1478,14 +1484,14 @@ class ProfileConverter {
// Map line+discriminator location to child frame
std::map<uint64_t, FrameNode> AllChildFrames;
// Function name for current frame
- StringRef FuncName;
+ ProfileFuncName FuncName;
// Function Samples for current frame
FunctionSamples *FuncSamples;
// Callsite location in parent context
LineLocation CallSiteLoc;
FrameNode *getOrCreateChildFrame(const LineLocation &CallSite,
- StringRef CalleeName);
+ ProfileFuncName CalleeName);
};
static void flattenProfile(SampleProfileMap &ProfileMap,
@@ -1632,7 +1638,9 @@ using namespace sampleprof;
template <> struct DenseMapInfo<SampleContext> {
static inline SampleContext getEmptyKey() { return SampleContext(); }
- static inline SampleContext getTombstoneKey() { return SampleContext("@"); }
+ static inline SampleContext getTombstoneKey() {
+ return SampleContext(ProfileFuncName(~1ULL));
+ }
static unsigned getHashValue(const SampleContext &Val) {
return Val.getHashCode();
diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h
index a5b1df3ef550b2b..d739a948b9ca010 100644
--- a/llvm/include/llvm/ProfileData/SampleProfReader.h
+++ b/llvm/include/llvm/ProfileData/SampleProfReader.h
@@ -409,13 +409,13 @@ class SampleProfileReader {
/// Return the samples collected for function \p F.
FunctionSamples *getSamplesFor(StringRef Fname) {
- auto It = Profiles.find(Fname);
+ auto It = Profiles.find(ProfileFuncName(Fname));
if (It != Profiles.end())
return &It->second;
if (Remapper) {
if (auto NameInProfile = Remapper->lookUpNameInProfile(Fname)) {
- auto It = Profiles.find(*NameInProfile);
+ auto It = Profiles.find(ProfileFuncName(*NameInProfile));
if (It != Profiles.end())
return &It->second;
}
@@ -474,7 +474,7 @@ class SampleProfileReader {
/// It includes all the names that have samples either in outline instance
/// or inline instance.
- virtual std::vector<StringRef> *getNameTable() { return nullptr; }
+ virtual std::vector<ProfileFuncName> *getNameTable() { return nullptr; }
virtual bool dumpSectionInfo(raw_ostream &OS = dbgs()) { return false; };
/// Return whether names in the profile are all MD5 numbers.
@@ -508,10 +508,6 @@ class SampleProfileReader {
/// Memory buffer holding the profile file.
std::unique_ptr<MemoryBuffer> Buffer;
- /// Extra name buffer holding names created on demand.
- /// This should only be needed for md5 profiles.
- std::unordered_set<std::string> MD5NameBuffer;
-
/// Profile summary information.
std::unique_ptr<ProfileSummary> Summary;
@@ -595,7 +591,9 @@ class SampleProfileReaderBinary : public SampleProfileReader {
/// It includes all the names that have samples either in outline instance
/// or inline instance.
- std::vector<StringRef> *getNameTable() override { return &NameTable; }
+ std::vector<ProfileFuncName> *getNameTable() override {
+ return &NameTable;
+ }
protected:
/// Read a numeric value of type T from the profile.
@@ -637,7 +635,7 @@ class SampleProfileReaderBinary : public SampleProfileReader {
std::error_code readNameTable();
/// Read a string indirectly via the name table. Optionally return the index.
- ErrorOr<StringRef> readStringFromTable(size_t *RetIdx = nullptr);
+ ErrorOr<ProfileFuncName> readStringFromTable(size_t *RetIdx = nullptr);
/// Read a context indirectly via the CSNameTable. Optionally return the
/// index.
@@ -654,16 +652,7 @@ class SampleProfileReaderBinary : public SampleProfileReader {
const uint8_t *End = nullptr;
/// Function name table.
- std::vector<StringRef> NameTable;
-
- /// If MD5 is used in NameTable section, the section saves uint64_t data.
- /// The uint64_t data has to be converted to a string and then the string
- /// will be used to initialize StringRef in NameTable.
- /// Note NameTable contains StringRef so it needs another buffer to own
- /// the string data. MD5StringBuf serves as the string buffer that is
- /// referenced by NameTable (vector of StringRef). We make sure
- /// the lifetime of MD5StringBuf is not shorter than that of NameTable.
- std::vector<std::string> MD5StringBuf;
+ std::vector<ProfileFuncName> NameTable;
/// The starting address of fixed length MD5 name table section.
const uint8_t *MD5NameMemStart = nullptr;
diff --git a/llvm/include/llvm/ProfileData/SampleProfWriter.h b/llvm/include/llvm/ProfileData/SampleProfWriter.h
index 1f19283ea1dd0a8..5d69a7f59ae0f21 100644
--- a/llvm/include/llvm/ProfileData/SampleProfWriter.h
+++ b/llvm/include/llvm/ProfileData/SampleProfWriter.h
@@ -196,20 +196,20 @@ class SampleProfileWriterBinary : public SampleProfileWriter {
std::error_code writeSample(const FunctionSamples &S) override;
protected:
- virtual MapVector<StringRef, uint32_t> &getNameTable() { return NameTable; }
+ virtual MapVector<ProfileFuncName, uint32_t> &getNameTable() { return NameTable; }
virtual std::error_code writeMagicIdent(SampleProfileFormat Format);
virtual std::error_code writeNameTable();
std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
std::error_code writeSummary();
virtual std::error_code writeContextIdx(const SampleContext &Context);
- std::error_code writeNameIdx(StringRef FName);
+ std::error_code writeNameIdx(ProfileFuncName FName);
std::error_code writeBody(const FunctionSamples &S);
- inline void stablizeNameTable(MapVector<StringRef, uint32_t> &NameTable,
- std::set<StringRef> &V);
+ inline void stablizeNameTable(MapVector<ProfileFuncName, uint32_t> &NameTable,
+ std::set<ProfileFuncName> &V);
- MapVector<StringRef, uint32_t> NameTable;
+ MapVector<ProfileFuncName, uint32_t> NameTable;
- void addName(StringRef FName);
+ void addName(ProfileFuncName FName);
virtual void addContext(const SampleContext &Context);
void addNames(const FunctionSamples &S);
diff --git a/llvm/include/llvm/Transforms/IPO/ProfiledCallGraph.h b/llvm/include/llvm/Transforms/IPO/ProfiledCallGraph.h
index bc8360a80bc02bd..1625060bdc92f78 100644
--- a/llvm/include/llvm/Transforms/IPO/ProfiledCallGraph.h
+++ b/llvm/include/llvm/Transforms/IPO/ProfiledCallGraph.h
@@ -53,9 +53,10 @@ struct ProfiledCallGraphNode {
using iterator = edges::iterator;
using const_iterator = edges::const_iterator;
- ProfiledCallGraphNode(StringRef FName = StringRef()) : Name(FName) {}
+ ProfiledCallGraphNode(ProfileFuncName FName = ProfileFuncName()) : Name(FName)
+ {}
- StringRef Name;
+ ProfileFuncName Name;
edges Edges;
};
@@ -85,7 +86,7 @@ class ProfiledCallGraph {
std::queue<ContextTrieNode *> Queue;
for (auto &Child : ContextTracker.getRootContext().getAllChildContext()) {
ContextTrieNode *Callee = &Child.second;
- addProfiledFunction(ContextTracker.getFuncNameFor(Callee));
+ addProfiledFunction(Callee->getFuncName());
Queue.push(Callee);
}
@@ -102,7 +103,7 @@ class ProfiledCallGraph {
// context-based one, which may in turn block context-based inlining.
for (auto &Child : Caller->getAllChildContext()) {
ContextTrieNode *Callee = &Child.second;
- addProfiledFunction(ContextTracker.getFuncNameFor(Callee));
+ addProfiledFunction(Callee->getFuncName());
Queue.push(Callee);
// Fetch edge weight from the profile.
@@ -123,8 +124,7 @@ class ProfiledCallGraph {
Weight = std::max(CallsiteCount, CalleeEntryCount);
}
- addProfiledCall(ContextTracker.getFuncNameFor(Caller),
- ContextTracker.getFuncNameFor(Callee), Weight);
+ addProfiledCall(Caller->getFuncName(), Callee->getFuncName(), Weight);
}
}
@@ -137,7 +137,7 @@ class ProfiledCallGraph {
iterator end() { return Root.Edges.end(); }
ProfiledCallGraphNode *getEntryNode() { return &Root; }
- void addProfiledFunction(StringRef Name) {
+ void addProfiledFunction(ProfileFuncName Name) {
if (!ProfiledFunctions.count(Name)) {
// Link to synthetic root to make sure every node is reachable
// from root. This does not affect SCC order.
@@ -147,7 +147,7 @@ class ProfiledCallGraph {
}
private:
- void addProfiledCall(StringRef CallerName, StringRef CalleeName,
+ void addProfiledCall(ProfileFuncName CallerName, ProfileFuncName CalleeName,
uint64_t Weight = 0) {
assert(ProfiledFunctions.count(CallerName));
auto CalleeIt = ProfiledFunctions.find(CalleeName);
@@ -168,19 +168,19 @@ class ProfiledCallGraph {
}
void addProfiledCalls(const FunctionSamples &Samples) {
- addProfiledFunction(Samples.getFuncName());
+ addProfiledFunction(Samples.getName());
for (const auto &Sample : Samples.getBodySamples()) {
for (const auto &[Target, Frequency] : Sample.second.getCallTargets()) {
addProfiledFunction(Target);
- addProfiledCall(Samples.getFuncName(), Target, Frequency);
+ addProfiledCall(Samples.getName(), Target, Frequency);
}
}
for (const auto &CallsiteSamples : Samples.getCallsiteSamples()) {
for (const auto &InlinedSamples : CallsiteSamples.second) {
addProfiledFunction(InlinedSamples.first);
- addProfiledCall(Samples.getFuncName(), InlinedSamples.first,
+ addProfiledCall(Samples.getName(), InlinedSamples.first,
InlinedSamples.second.getHeadSamplesEstimate());
addProfiledCalls(InlinedSamples.second);
}
@@ -206,7 +206,7 @@ class ProfiledCallGraph {
}
ProfiledCallGraphNode Root;
- StringMap<ProfiledCallGraphNode> ProfiledFunctions;
+ std::unordered_map<ProfileFuncName, ProfiledCallGraphNode> ProfiledFunctions;
};
} // end namespace sampleprof
diff --git a/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h b/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h
index 347dac1e9684db1..d6735ceba948bd8 100644
--- a/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h
+++ b/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h
@@ -35,20 +35,20 @@ class Instruction;
class ContextTrieNode {
public:
ContextTrieNode(ContextTrieNode *Parent = nullptr,
- StringRef FName = StringRef(),
+ ProfileFuncName FName = ProfileFuncName(),
FunctionSamples *FSamples = nullptr,
LineLocation CallLoc = {0, 0})
: ParentContext(Parent), FuncName(FName), FuncSamples(FSamples),
CallSiteLoc(CallLoc){};
ContextTrieNode *getChildContext(const LineLocation &CallSite,
- StringRef ChildName);
+ ProfileFuncName ChildName);
ContextTrieNode *getHottestChildContext(const LineLocation &CallSite);
ContextTrieNode *getOrCreateChildContext(const LineLocation &CallSite,
- StringRef ChildName,
+ ProfileFuncName ChildName,
bool AllowCreate = true);
- void removeChildContext(const LineLocation &CallSite, StringRef ChildName);
+ void removeChildContext(const LineLocation &CallSite, ProfileFuncName ChildName);
std::map<uint64_t, ContextTrieNode> &getAllChildContext();
- StringRef getFuncName() const;
+ ProfileFuncName getFuncName() const;
FunctionSamples *getFunctionSamples() const;
void setFunctionSamples(FunctionSamples *FSamples);
std::optional<uint32_t> getFunctionSize() const;
@@ -68,7 +68,7 @@ class ContextTrieNode {
ContextTrieNode *ParentContext;
// Function name for current context
- StringRef FuncName;
+ ProfileFuncName FuncName;
// Function Samples for current context
FunctionSamples *FuncSamples;
@@ -118,7 +118,8 @@ class SampleContextTracker {
FunctionSamples *getBaseSamplesFor(const Function &Func,
bool MergeContext = true);
// Query base profile for a given function by name.
- FunctionSamples *getBaseSamplesFor(StringRef Name, bool MergeContext = true);
+ FunctionSamples *getBaseSamplesFor(ProfileFuncName Name,
+ bool MergeContext = true);
// Retrieve the context trie node for given profile context
ContextTrieNode *getContextFor(const SampleContext &Context);
// Get real function name for a given trie node.
@@ -129,7 +130,7 @@ class SampleContextTracker {
void markContextSamplesInlined(const FunctionSamples *InlinedSamples);
ContextTrieNode &getRootContext();
void promoteMergeContextSamplesTree(const Instruction &Inst,
- StringRef CalleeName);
+ ProfileFuncName CalleeName);
// Create a merged conext-less profile map.
void createContextLessProfileMap(SampleProfileMap &ContextLessProfiles);
@@ -140,7 +141,7 @@ class SampleContextTracker {
return nullptr;
return I->second;
}
- StringMap<ContextSamplesTy> &getFuncToCtxtProfiles() {
+ std::unordered_map<ProfileFuncName, ContextSamplesTy> &getFuncToCtxtProfiles() {
return FuncToCtxtProfiles;
}
@@ -189,9 +190,9 @@ class SampleContextTracker {
private:
ContextTrieNode *getContextFor(const DILocation *DIL);
ContextTrieNode *getCalleeContextFor(const DILocation *DIL,
- StringRef CalleeName);
- ContextTrieNode *getTopLevelContextNode(StringRef FName);
- ContextTrieNode &addTopLevelContextNode(StringRef FName);
+ ProfileFuncName CalleeName);
+ ContextTrieNode *getTopLevelContextNode(ProfileFuncName FName);
+ ContextTrieNode &addTopLevelContextNode(ProfileFuncName FName);
ContextTrieNode &promoteMergeContextSamplesTree(ContextTrieNode &NodeToPromo);
void mergeContextNode(ContextTrieNode &FromNode, ContextTrieNode &ToNode);
ContextTrieNode &
@@ -204,7 +205,7 @@ class SampleContextTracker {
ProfileToNodeMap[FSample] = Node;
}
// Map from function name to context profiles (excluding base profile)
- StringMap<ContextSamplesTy> FuncToCtxtProfiles;
+ std::unordered_map<ProfileFuncName, ContextSamplesTy> FuncToCtxtProfiles;
// Map from current FunctionSample to the belonged context trie.
std::unordered_map<const FunctionSamples *, ContextTrieNode *>
diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp
index b14dc01be236245..757132ae351e522 100644
--- a/llvm/lib/ProfileData/SampleProf.cpp
+++ b/llvm/lib/ProfileData/SampleProf.cpp
@@ -121,7 +121,7 @@ sampleprof_error SampleRecord::merge(const SampleRecord &Other,
sampleprof_error Result;
Result = addSamples(Other.getSamples(), Weight);
for (const auto &I : Other.getCallTargets()) {
- MergeResult(Result, addCalledTarget(I.first(), I.second, Weight));
+ MergeResult(Result, addCalledTarget(I.first, I.second, Weight));
}
return Result;
}
@@ -234,9 +234,9 @@ LineLocation FunctionSamples::getCallSiteIdentifier(const DILocation *DIL,
}
}
-uint64_t FunctionSamples::getCallSiteHash(StringRef CalleeName,
+uint64_t FunctionSamples::getCallSiteHash(ProfileFuncName CalleeName,
const LineLocation &Callsite) {
- uint64_t NameHash = std::hash<std::string>{}(CalleeName.str());
+ uint64_t NameHash = CalleeName.getHashCode();
uint64_t LocId =
(((uint64_t)Callsite.LineOffset) << 32) | Callsite.Discriminator;
return NameHash + (LocId << 5) + LocId;
@@ -268,11 +268,11 @@ const FunctionSamples *FunctionSamples::findFunctionSamples(
return FS;
}
-void FunctionSamples::findAllNames(DenseSet<StringRef> &NameSet) const {
+void FunctionSamples::findAllNames(DenseSet<ProfileFuncName> &NameSet) const {
NameSet.insert(getName());
for (const auto &BS : BodySamples)
for (const auto &TS : BS.second.getCallTargets())
- NameSet.insert(TS.getKey());
+ NameSet.insert(TS.first);
for (const auto &CS : CallsiteSamples) {
for (const auto &NameFS : CS.second) {
@@ -287,18 +287,15 @@ const FunctionSamples *FunctionSamples::findFunctionSamplesAt(
SampleProfileReaderItaniumRemapper *Remapper) const {
CalleeName = getCanonicalFnName(CalleeName);
- std::string CalleeGUID;
- CalleeName = getRepInFormat(CalleeName, UseMD5, CalleeGUID);
-
auto iter = CallsiteSamples.find(mapIRLocToProfileLoc(Loc));
if (iter == CallsiteSamples.end())
return nullptr;
- auto FS = iter->second.find(CalleeName);
+ auto FS = iter->second.find(getRepInFormat(CalleeName));
if (FS != iter->second.end())
return &FS->second;
if (Remapper) {
if (auto NameInProfile = Remapper->lookUpNameInProfile(CalleeName)) {
- auto FS = iter->second.find(*NameInProfile);
+ auto FS = iter->second.find(getRepInFormat(*NameInProfile));
if (FS != iter->second.end())
return &FS->second;
}
@@ -422,7 +419,7 @@ void ProfileSymbolList::dump(raw_ostream &OS) const {
ProfileConverter::FrameNode *
ProfileConverter::FrameNode::getOrCreateChildFrame(const LineLocation &CallSite,
- StringRef CalleeName) {
+ ProfileFuncName CalleeName) {
uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
auto It = AllChildFrames.find(Hash);
if (It != AllChildFrames.end()) {
@@ -468,7 +465,7 @@ void ProfileConverter::convertCSProfiles(ProfileConverter::FrameNode &Node) {
if (!ChildProfile)
continue;
SampleContext OrigChildContext = ChildProfile->getContext();
- hash_code OrigChildContextHash = OrigChildContext.getHashCode();
+ uint64_t OrigChildContextHash = OrigChildContext.getHashCode();
// Reset the child context to be contextless.
ChildProfile->getContext().setName(OrigChildContext.getName());
if (NodeProfile) {
@@ -484,7 +481,7 @@ void ProfileConverter::convertCSProfiles(ProfileConverter::FrameNode &Node) {
NodeProfile->removeTotalSamples(Count);
}
- hash_code NewChildProfileHash(0);
+ uint64_t NewChildProfileHash = 0;
// Separate child profile to be a standalone profile, if the current parent
// profile doesn't exist. This is a duplicating operation when the child
// profile is already incorporated into the parent which is still useful and
@@ -498,7 +495,7 @@ void ProfileConverter::convertCSProfiles(ProfileConverter::FrameNode &Node) {
ProfileMap[ChildProfile->getContext()].merge(*ChildProfile);
NewChildProfileHash = ChildProfile->getContext().getHashCode();
auto &SamplesMap = NodeProfile->functionSamplesAt(ChildNode.CallSiteLoc);
- SamplesMap[ChildProfile->getName().str()].getContext().setAttribute(
+ SamplesMap[ChildProfile->getName()].getContext().setAttribute(
ContextDuplicatedIntoBase);
}
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index 6d355cdc41840b4..eb5e9368914c6b2 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -91,7 +91,7 @@ static void dumpFunctionProfileJson(const FunctionSamples &S,
JOS.attributeArray("calls", [&] {
for (const auto &J : CallTargets) {
JOS.object([&] {
- JOS.attribute("function", J.first);
+ JOS.attribute("function", J.first.str());
JOS.attribute("samples", J.second);
});
}
@@ -117,7 +117,7 @@ static void dumpFunctionProfileJson(const FunctionSamples &S,
};
JOS.object([&] {
- JOS.attribute("name", S.getName());
+ JOS.attribute("name", S.getName().str());
JOS.attribute("total", S.getTotalSamples());
if (TopLevel)
JOS.attribute("head", S.getHeadSamples());
@@ -392,8 +392,8 @@ std::error_code SampleProfileReaderText::readImpl() {
switch (LineTy) {
case LineType::CallSiteProfile: {
FunctionSamples &FSamples = InlineStack.back()->functionSamplesAt(
- LineLocation(LineOffset, Discriminator))[std::string(FName)];
- FSamples.setName(FName);
+ LineLocation(LineOffset, Discriminator))[ProfileFuncName(FName)];
+ FSamples.setName(ProfileFuncName(FName));
MergeResult(Result, FSamples.addTotalSamples(NumSamples));
InlineStack.push_back(&FSamples);
DepthMetadata = 0;
@@ -406,7 +406,8 @@ std::error_code SampleProfileReaderText::readImpl() {
FunctionSamples &FProfile = *InlineStack.back();
for (const auto &name_count : TargetCountMap) {
MergeResult(Result, FProfile.addCalledTargetSamples(
- LineOffset, Discriminator, name_count.first,
+ LineOffset, Discriminator,
+ ProfileFuncName(name_count.first),
name_count.second));
}
MergeResult(Result, FProfile.addBodySamples(LineOffset, Discriminator,
@@ -523,24 +524,21 @@ inline ErrorOr<size_t> SampleProfileReaderBinary::readStringIndex(T &Table) {
return *Idx;
}
-ErrorOr<StringRef>
+ErrorOr<ProfileFuncName>
SampleProfileReaderBinary::readStringFromTable(size_t *RetIdx) {
auto Idx = readStringIndex(NameTable);
if (std::error_code EC = Idx.getError())
return EC;
- // Lazy loading, if the string has not been materialized from memory storing
- // MD5 values, then it is default initialized with the null pointer. This can
- // only happen when using fixed length MD5, that bounds check is performed
- // while parsing the name table to ensure MD5NameMemStart points to an array
- // with enough MD5 entries.
- StringRef &SR = NameTable[*Idx];
- if (!SR.data()) {
+ // If using fixed length MD5, just read directly from the pointer to the name
+ // table.
+ ProfileFuncName &SR = NameTable[*Idx];
+ if (SR.empty()) {
assert(MD5NameMemStart);
using namespace support;
uint64_t FID = endian::read<uint64_t, little, unaligned>(
MD5NameMemStart + (*Idx) * sizeof(uint64_t));
- SR = MD5StringBuf.emplace_back(std::to_string(FID));
+ SR = ProfileFuncName(FID);
}
if (RetIdx)
*RetIdx = *Idx;
@@ -662,7 +660,7 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
FunctionSamples &CalleeProfile = FProfile.functionSamplesAt(
- LineLocation(*LineOffset, DiscriminatorVal))[std::string(*FName)];
+ LineLocation(*LineOffset, DiscriminatorVal))[*FName];
CalleeProfile.setName(*FName);
if (std::error_code EC = readProfile(CalleeProfile))
return EC;
@@ -902,12 +900,16 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
for (const auto &NameOffset : FuncOffsetList) {
const auto &FContext = NameOffset.first;
auto FName = FContext.getName();
+ StringRef FNameString;
+ if (!useMD5()) {
+ FNameString = reinterpret_cast<StringRef &>(FName);
+ }
// For function in the current module, keep its farthest ancestor
// context. This can be used to load itself and its child and
// sibling contexts.
- if ((useMD5() && FuncGuidsToUse.count(std::stoull(FName.data()))) ||
- (!useMD5() && (FuncsToUse.count(FName) ||
- (Remapper && Remapper->exist(FName))))) {
+ if ((useMD5() && FuncGuidsToUse.count(FName.getHashCode())) ||
+ (!useMD5() && (FuncsToUse.count(FNameString) ||
+ (Remapper && Remapper->exist(FNameString))))) {
if (!CommonContext || !CommonContext->IsPrefixOf(FContext))
CommonContext = &FContext;
}
@@ -937,7 +939,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
for (auto NameOffset : FuncOffsetList) {
SampleContext FContext(NameOffset.first);
auto FuncName = FContext.getName();
- if (!FuncsToUse.count(FuncName) && !Remapper->exist(FuncName))
+ StringRef FuncNameStr = reinterpret_cast<StringRef &>(FuncName);
+ if (!FuncsToUse.count(FuncNameStr) && !Remapper->exist(FuncNameStr))
continue;
const uint8_t *FuncProfileAddr = Start + NameOffset.second;
if (std::error_code EC = readFuncProfile(FuncProfileAddr))
@@ -1069,8 +1072,6 @@ std::error_code SampleProfileReaderBinary::readNameTable() {
// tables mixing string and MD5, all of them have to be normalized to use MD5,
// because optimization passes can only handle either type.
bool UseMD5 = useMD5();
- if (UseMD5)
- MD5StringBuf.reserve(MD5StringBuf.size() + *Size);
NameTable.clear();
NameTable.reserve(*Size);
@@ -1089,12 +1090,12 @@ std::error_code SampleProfileReaderBinary::readNameTable() {
if (std::error_code EC = Name.getError())
return EC;
if (UseMD5) {
- uint64_t FID = hashFuncName(*Name);
+ ProfileFuncName FID(*Name);
if (!ProfileIsCS)
- MD5SampleContextTable.emplace_back(FID);
- NameTable.emplace_back(MD5StringBuf.emplace_back(std::to_string(FID)));
+ MD5SampleContextTable.emplace_back(FID.getHashCode());
+ NameTable.emplace_back(FID);
} else
- NameTable.push_back(*Name);
+ NameTable.push_back(ProfileFuncName(*Name));
}
if (!ProfileIsCS)
MD5SampleContextStart = MD5SampleContextTable.data();
@@ -1121,7 +1122,6 @@ SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5,
// index has been read before by checking whether the element in the
// NameTable is empty, meanwhile readStringIndex can do the boundary
// check using the size of NameTable.
- MD5StringBuf.reserve(MD5StringBuf.size() + *Size);
NameTable.clear();
NameTable.resize(*Size);
MD5NameMemStart = Data;
@@ -1137,7 +1137,6 @@ SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5,
if (std::error_code EC = Size.getError())
return EC;
- MD5StringBuf.reserve(MD5StringBuf.size() + *Size);
NameTable.clear();
NameTable.reserve(*Size);
if (!ProfileIsCS)
@@ -1148,7 +1147,7 @@ SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5,
return EC;
if (!ProfileIsCS)
support::endian::write64le(&MD5SampleContextTable[I], *FID);
- NameTable.emplace_back(MD5StringBuf.emplace_back(std::to_string(*FID)));
+ NameTable.emplace_back(ProfileFuncName(*FID));
}
if (!ProfileIsCS)
MD5SampleContextStart = MD5SampleContextTable.data();
@@ -1250,7 +1249,7 @@ SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute,
CalleeProfile = const_cast<FunctionSamples *>(
&FProfile->functionSamplesAt(LineLocation(
*LineOffset,
- *Discriminator))[std::string(FContext.getName())]);
+ *Discriminator))[FContext.getName()]);
}
if (std::error_code EC =
readFuncMetadata(ProfileHasAttribute, CalleeProfile))
@@ -1660,7 +1659,7 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
// body, there will be identical replicated profiles for the
// original function. In this case, we simply not bother updating
// the profile of the original function.
- FProfile = &Profiles[Name];
+ FProfile = &Profiles[ProfileFuncName(Name)];
FProfile->addHeadSamples(HeadCount);
if (FProfile->getTotalSamples() > 0)
Update = false;
@@ -1672,9 +1671,9 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
uint32_t LineOffset = Offset >> 16;
uint32_t Discriminator = Offset & 0xffff;
FProfile = &CallerProfile->functionSamplesAt(
- LineLocation(LineOffset, Discriminator))[std::string(Name)];
+ LineLocation(LineOffset, Discriminator))[ProfileFuncName(Name)];
}
- FProfile->setName(Name);
+ FProfile->setName(ProfileFuncName(Name));
for (uint32_t I = 0; I < NumPosCounts; ++I) {
uint32_t Offset;
@@ -1730,7 +1729,8 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
if (Update)
FProfile->addCalledTargetSamples(LineOffset, Discriminator,
- TargetName, TargetCount);
+ ProfileFuncName(TargetName),
+ TargetCount);
}
}
@@ -1791,11 +1791,13 @@ void SampleProfileReaderItaniumRemapper::applyRemapping(LLVMContext &Ctx) {
// We will need to remap the entire context string.
assert(Remappings && "should be initialized while creating remapper");
for (auto &Sample : Reader.getProfiles()) {
- DenseSet<StringRef> NamesInSample;
+ DenseSet<ProfileFuncName> NamesInSample;
Sample.second.findAllNames(NamesInSample);
- for (auto &Name : NamesInSample)
- if (auto Key = Remappings->insert(Name))
- NameMap.insert({Key, Name});
+ for (auto &Name : NamesInSample) {
+ StringRef NameStr = reinterpret_cast<StringRef &>(Name);
+ if (auto Key = Remappings->insert(NameStr))
+ NameMap.insert({Key, NameStr});
+ }
}
RemappingApplied = true;
diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp
index f418dbe71057095..ccfde3907780eba 100644
--- a/llvm/lib/ProfileData/SampleProfWriter.cpp
+++ b/llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -348,7 +348,7 @@ std::error_code SampleProfileWriterExtBinaryBase::writeNameTable() {
return SampleProfileWriterBinary::writeNameTable();
auto &OS = *OutputStream;
- std::set<StringRef> V;
+ std::set<ProfileFuncName> V;
stablizeNameTable(NameTable, V);
// Write out the MD5 name table. We wrote unencoded MD5 so reader can
@@ -357,7 +357,7 @@ std::error_code SampleProfileWriterExtBinaryBase::writeNameTable() {
encodeULEB128(NameTable.size(), OS);
support::endian::Writer Writer(OS, support::little);
for (auto N : V)
- Writer.write(hashFuncName(N));
+ Writer.write(N.getHashCode());
return sampleprof_error::success;
}
@@ -371,10 +371,14 @@ std::error_code SampleProfileWriterExtBinaryBase::writeNameTableSection(
// If NameTable contains ".__uniq." suffix, set SecFlagUniqSuffix flag
// so compiler won't strip the suffix during profile matching after
// seeing the flag in the profile.
- for (const auto &I : NameTable) {
- if (I.first.contains(FunctionSamples::UniqSuffix)) {
- addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagUniqSuffix);
- break;
+ // Original names are unavailable if using MD5, so this option has no use.
+ if (!UseMD5) {
+ std::string Dummy;
+ for (const auto &I : NameTable) {
+ if (I.first.stringRef(Dummy).contains(FunctionSamples::UniqSuffix)) {
+ addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagUniqSuffix);
+ break;
+ }
}
}
@@ -632,7 +636,7 @@ SampleProfileWriterBinary::writeContextIdx(const SampleContext &Context) {
return writeNameIdx(Context.getName());
}
-std::error_code SampleProfileWriterBinary::writeNameIdx(StringRef FName) {
+std::error_code SampleProfileWriterBinary::writeNameIdx(ProfileFuncName FName) {
auto &NTable = getNameTable();
const auto &Ret = NTable.find(FName);
if (Ret == NTable.end())
@@ -641,7 +645,7 @@ std::error_code SampleProfileWriterBinary::writeNameIdx(StringRef FName) {
return sampleprof_error::success;
}
-void SampleProfileWriterBinary::addName(StringRef FName) {
+void SampleProfileWriterBinary::addName(ProfileFuncName FName) {
auto &NTable = getNameTable();
NTable.insert(std::make_pair(FName, 0));
}
@@ -655,7 +659,7 @@ void SampleProfileWriterBinary::addNames(const FunctionSamples &S) {
for (const auto &I : S.getBodySamples()) {
const SampleRecord &Sample = I.second;
for (const auto &J : Sample.getCallTargets())
- addName(J.first());
+ addName(J.first);
}
// Recursively add all the names for inlined callsites.
@@ -679,18 +683,18 @@ void SampleProfileWriterExtBinaryBase::addContext(
}
void SampleProfileWriterBinary::stablizeNameTable(
- MapVector<StringRef, uint32_t> &NameTable, std::set<StringRef> &V) {
+ MapVector<ProfileFuncName, uint32_t> &NameTable, std::set<ProfileFuncName> &V) {
// Sort the names to make NameTable deterministic.
for (const auto &I : NameTable)
V.insert(I.first);
int i = 0;
- for (const StringRef &N : V)
+ for (const ProfileFuncName &N : V)
NameTable[N] = i++;
}
std::error_code SampleProfileWriterBinary::writeNameTable() {
auto &OS = *OutputStream;
- std::set<StringRef> V;
+ std::set<ProfileFuncName> V;
stablizeNameTable(NameTable, V);
// Write out the name table.
@@ -836,7 +840,7 @@ std::error_code SampleProfileWriterBinary::writeBody(const FunctionSamples &S) {
encodeULEB128(Sample.getSamples(), OS);
encodeULEB128(Sample.getCallTargets().size(), OS);
for (const auto &J : Sample.getSortedCallTargets()) {
- StringRef Callee = J.first;
+ auto Callee = J.first;
uint64_t CalleeSamples = J.second;
if (std::error_code EC = writeNameIdx(Callee))
return EC;
diff --git a/llvm/lib/Target/X86/X86InsertPrefetch.cpp b/llvm/lib/Target/X86/X86InsertPrefetch.cpp
index 29ae05bf0c94673..a7d74275670d521 100644
--- a/llvm/lib/Target/X86/X86InsertPrefetch.cpp
+++ b/llvm/lib/Target/X86/X86InsertPrefetch.cpp
@@ -125,7 +125,8 @@ bool X86InsertPrefetch::findPrefetchInfo(const FunctionSamples *TopSamples,
// Convert serialized prefetch hints into PrefetchInfo objects, and populate
// the Prefetches vector.
for (const auto &S_V : *T) {
- StringRef Name = S_V.getKey();
+ std::string Buffer;
+ StringRef Name = S_V.first.stringRef(Buffer);
if (Name.consume_front(SerializedPrefetchPrefix)) {
int64_t D = static_cast<int64_t>(S_V.second);
unsigned IID = 0;
diff --git a/llvm/lib/Transforms/IPO/SampleContextTracker.cpp b/llvm/lib/Transforms/IPO/SampleContextTracker.cpp
index 79bee8362ef8a9c..bbd649ad3899cd5 100644
--- a/llvm/lib/Transforms/IPO/SampleContextTracker.cpp
+++ b/llvm/lib/Transforms/IPO/SampleContextTracker.cpp
@@ -29,7 +29,7 @@ using namespace sampleprof;
namespace llvm {
ContextTrieNode *ContextTrieNode::getChildContext(const LineLocation &CallSite,
- StringRef CalleeName) {
+ ProfileFuncName CalleeName) {
if (CalleeName.empty())
return getHottestChildContext(CallSite);
@@ -104,7 +104,7 @@ SampleContextTracker::moveContextSamples(ContextTrieNode &ToNodeParent,
}
void ContextTrieNode::removeChildContext(const LineLocation &CallSite,
- StringRef CalleeName) {
+ ProfileFuncName CalleeName) {
uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
// Note this essentially calls dtor and destroys that child context
AllChildContext.erase(Hash);
@@ -114,7 +114,7 @@ std::map<uint64_t, ContextTrieNode> &ContextTrieNode::getAllChildContext() {
return AllChildContext;
}
-StringRef ContextTrieNode::getFuncName() const { return FuncName; }
+ProfileFuncName ContextTrieNode::getFuncName() const { return FuncName; }
FunctionSamples *ContextTrieNode::getFunctionSamples() const {
return FuncSamples;
@@ -178,7 +178,7 @@ void ContextTrieNode::dumpTree() {
}
ContextTrieNode *ContextTrieNode::getOrCreateChildContext(
- const LineLocation &CallSite, StringRef CalleeName, bool AllowCreate) {
+ const LineLocation &CallSite, ProfileFuncName CalleeName, bool AllowCreate) {
uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
auto It = AllChildContext.find(Hash);
if (It != AllChildContext.end()) {
@@ -232,14 +232,12 @@ SampleContextTracker::getCalleeContextSamplesFor(const CallBase &Inst,
return nullptr;
CalleeName = FunctionSamples::getCanonicalFnName(CalleeName);
- // Convert real function names to MD5 names, if the input profile is
- // MD5-based.
- std::string FGUID;
- CalleeName = getRepInFormat(CalleeName, FunctionSamples::UseMD5, FGUID);
+
+ ProfileFuncName FName = getRepInFormat(CalleeName);
// For indirect call, CalleeName will be empty, in which case the context
// profile for callee with largest total samples will be returned.
- ContextTrieNode *CalleeContext = getCalleeContextFor(DIL, CalleeName);
+ ContextTrieNode *CalleeContext = getCalleeContextFor(DIL, FName);
if (CalleeContext) {
FunctionSamples *FSamples = CalleeContext->getFunctionSamples();
LLVM_DEBUG(if (FSamples) {
@@ -305,27 +303,23 @@ SampleContextTracker::getContextSamplesFor(const SampleContext &Context) {
SampleContextTracker::ContextSamplesTy &
SampleContextTracker::getAllContextSamplesFor(const Function &Func) {
StringRef CanonName = FunctionSamples::getCanonicalFnName(Func);
- return FuncToCtxtProfiles[CanonName];
+ return FuncToCtxtProfiles[getRepInFormat(CanonName)];
}
SampleContextTracker::ContextSamplesTy &
SampleContextTracker::getAllContextSamplesFor(StringRef Name) {
- return FuncToCtxtProfiles[Name];
+ return FuncToCtxtProfiles[getRepInFormat(Name)];
}
FunctionSamples *SampleContextTracker::getBaseSamplesFor(const Function &Func,
bool MergeContext) {
StringRef CanonName = FunctionSamples::getCanonicalFnName(Func);
- return getBaseSamplesFor(CanonName, MergeContext);
+ return getBaseSamplesFor(getRepInFormat(CanonName), MergeContext);
}
-FunctionSamples *SampleContextTracker::getBaseSamplesFor(StringRef Name,
+FunctionSamples *SampleContextTracker::getBaseSamplesFor(ProfileFuncName Name,
bool MergeContext) {
LLVM_DEBUG(dbgs() << "Getting base profile for function: " << Name << "\n");
- // Convert real function names to MD5 names, if the input profile is
- // MD5-based.
- std::string FGUID;
- Name = getRepInFormat(Name, FunctionSamples::UseMD5, FGUID);
// Base profile is top-level node (child of root node), so try to retrieve
// existing top-level node for given function first. If it exists, it could be
@@ -373,7 +367,7 @@ void SampleContextTracker::markContextSamplesInlined(
ContextTrieNode &SampleContextTracker::getRootContext() { return RootContext; }
void SampleContextTracker::promoteMergeContextSamplesTree(
- const Instruction &Inst, StringRef CalleeName) {
+ const Instruction &Inst, ProfileFuncName CalleeName) {
LLVM_DEBUG(dbgs() << "Promoting and merging context tree for instr: \n"
<< Inst << "\n");
// Get the caller context for the call instruction, we don't use callee
@@ -457,10 +451,11 @@ SampleContextTracker::getContextString(ContextTrieNode *Node) const {
void SampleContextTracker::dump() { RootContext.dumpTree(); }
StringRef SampleContextTracker::getFuncNameFor(ContextTrieNode *Node) const {
+ std::string Dummy;
if (!FunctionSamples::UseMD5)
- return Node->getFuncName();
+ return Node->getFuncName().stringRef(Dummy);
assert(GUIDToFuncNameMap && "GUIDToFuncNameMap needs to be populated first");
- return GUIDToFuncNameMap->lookup(std::stoull(Node->getFuncName().data()));
+ return GUIDToFuncNameMap->lookup(Node->getFuncName().getHashCode());
}
ContextTrieNode *
@@ -470,7 +465,7 @@ SampleContextTracker::getContextFor(const SampleContext &Context) {
ContextTrieNode *
SampleContextTracker::getCalleeContextFor(const DILocation *DIL,
- StringRef CalleeName) {
+ ProfileFuncName CalleeName) {
assert(DIL && "Expect non-null location");
ContextTrieNode *CallContext = getContextFor(DIL);
@@ -485,7 +480,7 @@ SampleContextTracker::getCalleeContextFor(const DILocation *DIL,
ContextTrieNode *SampleContextTracker::getContextFor(const DILocation *DIL) {
assert(DIL && "Expect non-null location");
- SmallVector<std::pair<LineLocation, StringRef>, 10> S;
+ SmallVector<std::pair<LineLocation, ProfileFuncName>, 10> S;
// Use C++ linkage name if possible.
const DILocation *PrevDIL = DIL;
@@ -494,7 +489,8 @@ ContextTrieNode *SampleContextTracker::getContextFor(const DILocation *DIL) {
if (Name.empty())
Name = PrevDIL->getScope()->getSubprogram()->getName();
S.push_back(
- std::make_pair(FunctionSamples::getCallSiteIdentifier(DIL), Name));
+ std::make_pair(FunctionSamples::getCallSiteIdentifier(DIL),
+ getRepInFormat(Name)));
PrevDIL = DIL;
}
@@ -503,24 +499,14 @@ ContextTrieNode *SampleContextTracker::getContextFor(const DILocation *DIL) {
StringRef RootName = PrevDIL->getScope()->getSubprogram()->getLinkageName();
if (RootName.empty())
RootName = PrevDIL->getScope()->getSubprogram()->getName();
- S.push_back(std::make_pair(LineLocation(0, 0), RootName));
-
- // Convert real function names to MD5 names, if the input profile is
- // MD5-based.
- std::list<std::string> MD5Names;
- if (FunctionSamples::UseMD5) {
- for (auto &Location : S) {
- MD5Names.emplace_back();
- getRepInFormat(Location.second, FunctionSamples::UseMD5, MD5Names.back());
- Location.second = MD5Names.back();
- }
- }
+ S.push_back(std::make_pair(LineLocation(0, 0),
+ getRepInFormat(RootName)));
ContextTrieNode *ContextNode = &RootContext;
int I = S.size();
while (--I >= 0 && ContextNode) {
LineLocation &CallSite = S[I].first;
- StringRef CalleeName = S[I].second;
+ ProfileFuncName CalleeName = S[I].second;
ContextNode = ContextNode->getChildContext(CallSite, CalleeName);
}
@@ -553,12 +539,14 @@ SampleContextTracker::getOrCreateContextPath(const SampleContext &Context,
return ContextNode;
}
-ContextTrieNode *SampleContextTracker::getTopLevelContextNode(StringRef FName) {
+ContextTrieNode *
+SampleContextTracker::getTopLevelContextNode(ProfileFuncName FName) {
assert(!FName.empty() && "Top level node query must provide valid name");
return RootContext.getChildContext(LineLocation(0, 0), FName);
}
-ContextTrieNode &SampleContextTracker::addTopLevelContextNode(StringRef FName) {
+ContextTrieNode &
+SampleContextTracker::addTopLevelContextNode(ProfileFuncName FName) {
assert(!getTopLevelContextNode(FName) && "Node to add must not exist");
return *RootContext.getOrCreateChildContext(LineLocation(0, 0), FName);
}
diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp
index 85431fb32b4b4d6..a79525d71eee02f 100644
--- a/llvm/lib/Transforms/IPO/SampleProfile.cpp
+++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp
@@ -429,7 +429,7 @@ struct CandidateComparer {
return LCS->getBodySamples().size() > RCS->getBodySamples().size();
// Tie breaker using GUID so we have stable/deterministic inlining order
- return LCS->getGUID(LCS->getName()) < RCS->getGUID(RCS->getName());
+ return LCS->getGUID() < RCS->getGUID();
}
};
@@ -472,7 +472,7 @@ class SampleProfileMatcher {
private:
FunctionSamples *getFlattenedSamplesFor(const Function &F) {
StringRef CanonFName = FunctionSamples::getCanonicalFnName(F);
- auto It = FlattenedProfiles.find(CanonFName);
+ auto It = FlattenedProfiles.find(ProfileFuncName(CanonFName));
if (It != FlattenedProfiles.end())
return &It->second;
return nullptr;
@@ -491,12 +491,10 @@ class SampleProfileMatcher {
}
void distributeIRToProfileLocationMap();
void distributeIRToProfileLocationMap(FunctionSamples &FS);
- void populateProfileCallsites(
- const FunctionSamples &FS,
- StringMap<std::set<LineLocation>> &CalleeToCallsitesMap);
- void runStaleProfileMatching(
- const std::map<LineLocation, StringRef> &IRLocations,
- StringMap<std::set<LineLocation>> &CalleeToCallsitesMap,
+ void populateProfileCallsites(const FunctionSamples &FS,
+ std::unordered_map<ProfileFuncName, std::set<LineLocation> > &CalleeToCallsitesMap);
+ void runStaleProfileMatching(const std::map<LineLocation, ProfileFuncName> &IRLocations,
+ std::unordered_map<ProfileFuncName, std::set<LineLocation> > &CalleeToCallsitesMap,
LocToLocMap &IRToProfileLocationMap);
};
@@ -614,7 +612,7 @@ class SampleProfileLoader final : public SampleProfileLoaderBaseImpl<Function> {
// All the Names used in FunctionSamples including outline function
// names, inline instance names and call target names.
- StringSet<> NamesInProfile;
+ std::unordered_set<ProfileFuncName> NamesInProfile;
// For symbol in profile symbol list, whether to regard their profiles
// to be accurate. It is mainly decided by existance of profile symbol
@@ -759,8 +757,7 @@ SampleProfileLoader::findIndirectCallFunctionSamples(
assert(L && R && "Expect non-null FunctionSamples");
if (L->getHeadSamplesEstimate() != R->getHeadSamplesEstimate())
return L->getHeadSamplesEstimate() > R->getHeadSamplesEstimate();
- return FunctionSamples::getGUID(L->getName()) <
- FunctionSamples::getGUID(R->getName());
+ return L->getGUID() < R->getGUID();
};
if (FunctionSamples::ProfileIsCS) {
@@ -1080,7 +1077,7 @@ void SampleProfileLoader::findExternalInlineCandidate(
// just add the direct GUID and move on
if (!Samples) {
InlinedGUIDs.insert(
- FunctionSamples::getGUID(CB->getCalledFunction()->getName()));
+ Function::getGUID(CB->getCalledFunction()->getName()));
return;
}
// Otherwise, drop the threshold to import everything that we can
@@ -1126,17 +1123,17 @@ void SampleProfileLoader::findExternalInlineCandidate(
Function *Func = SymbolMap.lookup(Name);
// Add to the import list only when it's defined out of module.
if (!Func || Func->isDeclaration())
- InlinedGUIDs.insert(FunctionSamples::getGUID(CalleeSample->getName()));
+ InlinedGUIDs.insert(CalleeSample->getGUID());
// Import hot CallTargets, which may not be available in IR because full
// profile annotation cannot be done until backend compilation in ThinLTO.
for (const auto &BS : CalleeSample->getBodySamples())
for (const auto &TS : BS.second.getCallTargets())
- if (TS.getValue() > Threshold) {
- StringRef CalleeName = CalleeSample->getFuncName(TS.getKey());
+ if (TS.second > Threshold) {
+ StringRef CalleeName = CalleeSample->getFuncName(TS.first);
const Function *Callee = SymbolMap.lookup(CalleeName);
if (!Callee || Callee->isDeclaration())
- InlinedGUIDs.insert(FunctionSamples::getGUID(TS.getKey()));
+ InlinedGUIDs.insert(TS.first.getHashCode());
}
// Import hot child context profile associted with callees. Note that this
@@ -1643,7 +1640,7 @@ GetSortedValueDataFromCallTargets(const SampleRecord::CallTargetMap &M) {
SmallVector<InstrProfValueData, 2> R;
for (const auto &I : SampleRecord::SortCallTargets(M)) {
R.emplace_back(
- InstrProfValueData{FunctionSamples::getGUID(I.first), I.second});
+ InstrProfValueData{I.first.getHashCode(), I.second});
}
return R;
}
@@ -1870,7 +1867,8 @@ SampleProfileLoader::buildProfiledCallGraph(Module &M) {
for (Function &F : M) {
if (F.isDeclaration() || !F.hasFnAttribute("use-sample-profile"))
continue;
- ProfiledCG->addProfiledFunction(FunctionSamples::getCanonicalFnName(F));
+ ProfiledCG->addProfiledFunction(
+ getRepInFormat(FunctionSamples::getCanonicalFnName(F)));
}
return ProfiledCG;
@@ -1961,7 +1959,10 @@ SampleProfileLoader::buildFunctionOrder(Module &M, LazyCallGraph &CG) {
Range = *SI;
}
for (auto *Node : Range) {
- Function *F = SymbolMap.lookup(Node->Name);
+ Function *F = SymbolMap.lookup(
+ FunctionSamples::UseMD5
+ ? GUIDToFuncNameMap.lookup(Node->Name.getHashCode())
+ : reinterpret_cast<StringRef &>(Node->Name));
if (F && !F->isDeclaration() && F->hasFnAttribute("use-sample-profile"))
FunctionOrderList.push_back(F);
}
@@ -2157,13 +2158,14 @@ void SampleProfileMatcher::countProfileMismatches(
// Populate the anchors(direct callee name) from profile.
void SampleProfileMatcher::populateProfileCallsites(
const FunctionSamples &FS,
- StringMap<std::set<LineLocation>> &CalleeToCallsitesMap) {
+ std::unordered_map<ProfileFuncName, std::set<LineLocation>>
+ &CalleeToCallsitesMap) {
for (const auto &I : FS.getBodySamples()) {
const auto &Loc = I.first;
const auto &CTM = I.second.getCallTargets();
// Filter out possible indirect calls, use direct callee name as anchor.
if (CTM.size() == 1) {
- StringRef CalleeName = CTM.begin()->first();
+ auto CalleeName = CTM.begin()->first;
const auto &Candidates = CalleeToCallsitesMap.try_emplace(
CalleeName, std::set<LineLocation>());
Candidates.first->second.insert(Loc);
@@ -2175,7 +2177,7 @@ void SampleProfileMatcher::populateProfileCallsites(
const auto &CalleeMap = I.second;
// Filter out possible indirect calls, use direct callee name as anchor.
if (CalleeMap.size() == 1) {
- StringRef CalleeName = CalleeMap.begin()->first;
+ auto CalleeName = CalleeMap.begin()->first;
const auto &Candidates = CalleeToCallsitesMap.try_emplace(
CalleeName, std::set<LineLocation>());
Candidates.first->second.insert(Loc);
@@ -2201,8 +2203,9 @@ void SampleProfileMatcher::populateProfileCallsites(
// [1, 2, 3(foo), 4, 7, 8(bar), 9]
// The output mapping: [2->3, 3->4, 5->7, 6->8, 7->9].
void SampleProfileMatcher::runStaleProfileMatching(
- const std::map<LineLocation, StringRef> &IRLocations,
- StringMap<std::set<LineLocation>> &CalleeToCallsitesMap,
+ const std::map<LineLocation, ProfileFuncName> &IRLocations,
+ std::unordered_map<ProfileFuncName, std::set<LineLocation>>
+ &CalleeToCallsitesMap,
LocToLocMap &IRToProfileLocationMap) {
assert(IRToProfileLocationMap.empty() &&
"Run stale profile matching only once per function");
@@ -2219,7 +2222,7 @@ void SampleProfileMatcher::runStaleProfileMatching(
for (const auto &IR : IRLocations) {
const auto &Loc = IR.first;
- StringRef CalleeName = IR.second;
+ auto CalleeName = IR.second;
bool IsMatchedAnchor = false;
// Match the anchor location in lexical order.
if (!CalleeName.empty()) {
@@ -2283,7 +2286,7 @@ void SampleProfileMatcher::runOnFunction(const Function &F,
std::unordered_set<LineLocation, LineLocationHash> MatchedCallsiteLocs;
// The value of the map is the name of direct callsite and use empty StringRef
// for non-direct-call site.
- std::map<LineLocation, StringRef> IRLocations;
+ std::map<LineLocation, ProfileFuncName> IRLocations;
// Extract profile matching anchors and profile mismatch metrics in the IR.
for (auto &BB : F) {
@@ -2291,7 +2294,7 @@ void SampleProfileMatcher::runOnFunction(const Function &F,
// TODO: Support line-number based location(AutoFDO).
if (FunctionSamples::ProfileIsProbeBased && isa<PseudoProbeInst>(&I)) {
if (std::optional<PseudoProbe> Probe = extractProbe(I))
- IRLocations.emplace(LineLocation(Probe->Id, 0), StringRef());
+ IRLocations.emplace(LineLocation(Probe->Id, 0), ProfileFuncName());
}
if (!isa<CallBase>(&I) || isa<IntrinsicInst>(&I))
@@ -2301,9 +2304,10 @@ void SampleProfileMatcher::runOnFunction(const Function &F,
if (auto &DLoc = I.getDebugLoc()) {
LineLocation IRCallsite = FunctionSamples::getCallSiteIdentifier(DLoc);
- StringRef CalleeName;
+ ProfileFuncName CalleeName;
if (Function *Callee = CB->getCalledFunction())
- CalleeName = FunctionSamples::getCanonicalFnName(Callee->getName());
+ CalleeName = ProfileFuncName(
+ FunctionSamples::getCanonicalFnName(Callee->getName()));
// Force to overwrite the callee name in case any non-call location was
// written before.
@@ -2358,7 +2362,7 @@ void SampleProfileMatcher::runOnFunction(const Function &F,
LLVM_DEBUG(dbgs() << "Run stale profile matching for " << F.getName()
<< "\n");
- StringMap<std::set<LineLocation>> CalleeToCallsitesMap;
+ std::unordered_map<ProfileFuncName, std::set<LineLocation>> CalleeToCallsitesMap;
populateProfileCallsites(FS, CalleeToCallsitesMap);
// The matching result will be saved to IRToProfileLocationMap, create a new
@@ -2429,7 +2433,7 @@ void SampleProfileMatcher::runOnModule() {
void SampleProfileMatcher::distributeIRToProfileLocationMap(
FunctionSamples &FS) {
- const auto ProfileMappings = FuncMappings.find(FS.getName());
+ const auto ProfileMappings = FuncMappings.find(FS.getFuncName());
if (ProfileMappings != FuncMappings.end()) {
FS.setIRToProfileLocationMap(&(ProfileMappings->second));
}
@@ -2555,7 +2559,7 @@ bool SampleProfileLoader::runOnFunction(Function &F, ModuleAnalysisManager *AM)
// but not cold accumulatively...), so the outline function showing up as
// cold in sampled binary will actually not be cold after current build.
StringRef CanonName = FunctionSamples::getCanonicalFnName(F);
- if (NamesInProfile.count(CanonName))
+ if (NamesInProfile.count(getRepInFormat(CanonName)))
initialEntryCount = -1;
}
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 4592dc0d77a49dc..beb6afc4ab00ac7 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -199,6 +199,12 @@ class SymbolRemapper {
StringRef New = RemappingTable.lookup(Name);
return New.empty() ? Name : New;
}
+
+ ProfileFuncName operator()(ProfileFuncName Name) {
+ std::string Buffer;
+ StringRef New = RemappingTable.lookup(Name.stringRef(Buffer));
+ return New.empty() ? Name : ProfileFuncName(New);
+ }
};
}
@@ -716,7 +722,8 @@ adjustInstrProfile(std::unique_ptr<WriterContext> &WC,
auto BuildMaxSampleMapImpl = [&](const FunctionSamples &FS,
const StringRef &RootName,
auto &BuildImpl) -> void {
- const StringRef &Name = FS.getName();
+ std::string Buffer;
+ const StringRef &Name = FS.getName().stringRef(Buffer);
const StringRef *NewRootName = &RootName;
uint64_t EntrySample = FS.getHeadSamplesEstimate();
uint64_t MaxBodySample = FS.getMaxCountInside(/* SkipCallSite*/ true);
@@ -770,7 +777,8 @@ adjustInstrProfile(std::unique_ptr<WriterContext> &WC,
for (auto &PD : Reader->getProfiles()) {
sampleprof::FunctionSamples &FS = PD.second;
- BuildMaxSampleMap(FS, FS.getName());
+ std::string Buffer;
+ BuildMaxSampleMap(FS, FS.getName().stringRef(Buffer));
}
ProfileSummary InstrPS = *IPBuilder.getSummary();
@@ -896,7 +904,7 @@ remapSamples(const sampleprof::FunctionSamples &Samples,
for (const auto &Target : BodySample.second.getCallTargets()) {
Result.addCalledTargetSamples(BodySample.first.LineOffset,
MaskedDiscriminator,
- Remapper(Target.first()), Target.second);
+ Remapper(Target.first), Target.second);
}
}
for (const auto &CallsiteSamples : Samples.getCallsiteSamples()) {
@@ -906,7 +914,7 @@ remapSamples(const sampleprof::FunctionSamples &Samples,
sampleprof::FunctionSamples Remapped =
remapSamples(Callsite.second, Remapper, Error);
MergeResult(Error,
- Target[std::string(Remapped.getName())].merge(Remapped));
+ Target[Remapped.getName()].merge(Remapped));
}
}
return Result;
diff --git a/llvm/tools/llvm-profgen/CSPreInliner.cpp b/llvm/tools/llvm-profgen/CSPreInliner.cpp
index ae0fd6d0b069298..51e9782242ddde3 100644
--- a/llvm/tools/llvm-profgen/CSPreInliner.cpp
+++ b/llvm/tools/llvm-profgen/CSPreInliner.cpp
@@ -80,8 +80,8 @@ CSPreInliner::CSPreInliner(SampleContextTracker &Tracker,
ProfileInlineLimitMax = 50000;
}
-std::vector<StringRef> CSPreInliner::buildTopDownOrder() {
- std::vector<StringRef> Order;
+std::vector<ProfileFuncName> CSPreInliner::buildTopDownOrder() {
+ std::vector<ProfileFuncName> Order;
// Trim cold edges to get a more stable call graph. This allows for a more
// stable top-down order which in turns helps the stablity of the generated
// profile from run to run.
@@ -202,7 +202,7 @@ bool CSPreInliner::shouldInline(ProfiledInlineCandidate &Candidate) {
return (Candidate.SizeCost < SampleThreshold);
}
-void CSPreInliner::processFunction(const StringRef Name) {
+void CSPreInliner::processFunction(const ProfileFuncName Name) {
FunctionSamples *FSamples = ContextTracker.getBaseSamplesFor(Name);
if (!FSamples)
return;
@@ -303,7 +303,7 @@ void CSPreInliner::run() {
// It also helps better compress context profile to control profile
// size, as we now only need context profile for functions going to
// be inlined.
- for (StringRef FuncName : buildTopDownOrder()) {
+ for (ProfileFuncName FuncName : buildTopDownOrder()) {
processFunction(FuncName);
}
diff --git a/llvm/tools/llvm-profgen/CSPreInliner.h b/llvm/tools/llvm-profgen/CSPreInliner.h
index 4d848aafdab914d..c6b4d77a737399e 100644
--- a/llvm/tools/llvm-profgen/CSPreInliner.h
+++ b/llvm/tools/llvm-profgen/CSPreInliner.h
@@ -57,8 +57,7 @@ struct ProfiledCandidateComparer {
// Tie breaker using GUID so we have stable/deterministic inlining order
assert(LHS.CalleeSamples && RHS.CalleeSamples &&
"Expect non-null FunctionSamples");
- return LHS.CalleeSamples->getGUID(LHS.CalleeSamples->getName()) <
- RHS.CalleeSamples->getGUID(RHS.CalleeSamples->getName());
+ return LHS.CalleeSamples->getGUID() < RHS.CalleeSamples->getGUID();
}
};
@@ -81,8 +80,8 @@ class CSPreInliner {
private:
bool getInlineCandidates(ProfiledCandidateQueue &CQueue,
const FunctionSamples *FCallerContextSamples);
- std::vector<StringRef> buildTopDownOrder();
- void processFunction(StringRef Name);
+ std::vector<ProfileFuncName> buildTopDownOrder();
+ void processFunction(ProfileFuncName Name);
bool shouldInline(ProfiledInlineCandidate &Candidate);
uint32_t getFuncSize(const ContextTrieNode *ContextNode);
bool UseContextCost;
diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp
index d307ab465676296..e71683ccb0f3bce 100644
--- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp
+++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp
@@ -586,20 +586,21 @@ void ProfileGenerator::populateBoundarySamplesWithProbesForAllFunctions(
FunctionProfile.addCalledTargetSamples(
FrameVec.back().Location.LineOffset,
FrameVec.back().Location.Discriminator,
- CalleeName, Count);
+ ProfileFuncName(CalleeName), Count);
}
}
}
FunctionSamples &ProfileGenerator::getLeafProfileAndAddTotalSamples(
const SampleContextFrameVector &FrameVec, uint64_t Count) {
+ std::string Buffer;
// Get top level profile
FunctionSamples *FunctionProfile =
- &getTopLevelFunctionProfile(FrameVec[0].FuncName);
+ &getTopLevelFunctionProfile(FrameVec[0].FuncName.stringRef(Buffer));
FunctionProfile->addTotalSamples(Count);
if (Binary->usePseudoProbes()) {
const auto *FuncDesc = Binary->getFuncDescForGUID(
- Function::getGUID(FunctionProfile->getName()));
+ FunctionProfile->getName().getHashCode());
FunctionProfile->setFunctionHash(FuncDesc->FuncHash);
}
@@ -619,7 +620,7 @@ FunctionSamples &ProfileGenerator::getLeafProfileAndAddTotalSamples(
FunctionProfile->addTotalSamples(Count);
if (Binary->usePseudoProbes()) {
const auto *FuncDesc = Binary->getFuncDescForGUID(
- Function::getGUID(FunctionProfile->getName()));
+ FunctionProfile->getName().getHashCode());
FunctionProfile->setFunctionHash(FuncDesc->FuncHash);
}
}
@@ -716,7 +717,7 @@ void ProfileGenerator::populateBoundarySamplesForAllFunctions(
FunctionProfile.addCalledTargetSamples(
FrameVec.back().Location.LineOffset,
getBaseDiscriminator(FrameVec.back().Location.Discriminator),
- CalleeName, Count);
+ ProfileFuncName(CalleeName), Count);
}
// Add head samples for callee.
FunctionSamples &CalleeProfile = getTopLevelFunctionProfile(CalleeName);
@@ -899,7 +900,8 @@ void CSProfileGenerator::populateBoundarySamplesForFunction(
if (LeafLoc) {
CallerNode->getFunctionSamples()->addCalledTargetSamples(
LeafLoc->Location.LineOffset,
- getBaseDiscriminator(LeafLoc->Location.Discriminator), CalleeName,
+ getBaseDiscriminator(LeafLoc->Location.Discriminator),
+ ProfileFuncName(CalleeName),
Count);
// Record head sample for called target(callee)
CalleeCallSite = LeafLoc->Location;
@@ -907,7 +909,8 @@ void CSProfileGenerator::populateBoundarySamplesForFunction(
}
ContextTrieNode *CalleeNode =
- CallerNode->getOrCreateChildContext(CalleeCallSite, CalleeName);
+ CallerNode->getOrCreateChildContext(CalleeCallSite,
+ ProfileFuncName(CalleeName));
FunctionSamples *CalleeProfile = getOrCreateFunctionSamples(CalleeNode);
CalleeProfile->addHeadSamples(Count);
}
@@ -1212,7 +1215,7 @@ void CSProfileGenerator::populateBoundarySamplesWithProbes(
continue;
FunctionProfile.addCalledTargetSamples(CallProbe->getIndex(),
CallProbe->getDiscriminator(),
- CalleeName, Count);
+ ProfileFuncName(CalleeName), Count);
}
}
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index 4755f758a828b8a..32d4f5cff37252f 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -77,7 +77,7 @@ void BinarySizeContextTracker::addInstructionForContext(
ContextTrieNode *CurNode = &RootContext;
bool IsLeaf = true;
for (const auto &Callsite : reverse(Context)) {
- StringRef CallerName = Callsite.FuncName;
+ ProfileFuncName CallerName = Callsite.FuncName;
LineLocation CallsiteLoc = IsLeaf ? LineLocation(0, 0) : Callsite.Location;
CurNode = CurNode->getOrCreateChildContext(CallsiteLoc, CallerName);
IsLeaf = false;
@@ -145,7 +145,8 @@ void BinarySizeContextTracker::trackInlineesOptimizedAway(
StringRef CallerName = ProbeFrame.first;
LineLocation CallsiteLoc(ProbeFrame.second, 0);
SizeContext =
- SizeContext->getOrCreateChildContext(CallsiteLoc, CallerName);
+ SizeContext->getOrCreateChildContext(CallsiteLoc,
+ ProfileFuncName(CallerName));
}
// Add 0 size to make known.
SizeContext->addFunctionSize(0);
@@ -831,6 +832,14 @@ void ProfiledBinary::loadSymbolsFromDWARF(ObjectFile &Obj) {
if (BinaryFunctions.empty())
WithColor::warning() << "Loading of DWARF info completed, but no binary "
"functions have been retrieved.\n";
+
+
+ // Populate the hash binary function map for MD5 function name lookup. This
+ // is done after BinaryFunctions are finalized.
+ for (auto &BinaryFunction : BinaryFunctions) {
+ HashBinaryFunctions[MD5Hash(StringRef(BinaryFunction.first))] =
+ &BinaryFunction.second;
+ }
}
void ProfiledBinary::populateSymbolListFromDWARF(
@@ -882,7 +891,7 @@ SampleContextFrameVector ProfiledBinary::symbolize(const InstructionPointer &IP,
LineLocation Line(LineOffset, Discriminator);
auto It = NameStrings.insert(FunctionName.str());
- CallStack.emplace_back(*It.first, Line);
+ CallStack.emplace_back(ProfileFuncName(*It.first), Line);
}
return CallStack;
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h
index a6d78c661cc1c31..c5f3b7d7fe7a01f 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.h
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.h
@@ -220,6 +220,10 @@ class ProfiledBinary {
// A map of mapping function name to BinaryFunction info.
std::unordered_map<std::string, BinaryFunction> BinaryFunctions;
+ // Lookup BinaryFunctions using the function name's MD5 hash. Needed if the
+ // profile is using MD5.
+ std::unordered_map<uint64_t, BinaryFunction *> HashBinaryFunctions;
+
// A list of binary functions that have samples.
std::unordered_set<const BinaryFunction *> ProfiledFunctions;
@@ -477,11 +481,17 @@ class ProfiledBinary {
ProfiledFunctions = Funcs;
}
- BinaryFunction *getBinaryFunction(StringRef FName) {
- auto I = BinaryFunctions.find(FName.str());
- if (I == BinaryFunctions.end())
+ BinaryFunction *getBinaryFunction(ProfileFuncName FName) {
+ if (FName.isStringRef()) {
+ auto I = BinaryFunctions.find(FName.str());
+ if (I == BinaryFunctions.end())
+ return nullptr;
+ return &I->second;
+ }
+ auto I = HashBinaryFunctions.find(FName.getHashCode());
+ if (I == HashBinaryFunctions.end())
return nullptr;
- return &I->second;
+ return I->second;
}
uint32_t getFuncSizeForContext(const ContextTrieNode *ContextNode) {
@@ -556,7 +566,7 @@ class ProfiledBinary {
InlineContextStack.clear();
continue;
}
- InlineContextStack.emplace_back(Callsite.first,
+ InlineContextStack.emplace_back(ProfileFuncName(Callsite.first),
LineLocation(Callsite.second, 0));
}
}
diff --git a/llvm/unittests/ProfileData/SampleProfTest.cpp b/llvm/unittests/ProfileData/SampleProfTest.cpp
index e01025440e4a56a..90d62cbcc93648a 100644
--- a/llvm/unittests/ProfileData/SampleProfTest.cpp
+++ b/llvm/unittests/ProfileData/SampleProfTest.cpp
@@ -145,7 +145,7 @@ struct SampleProfTest : ::testing::Test {
StringRef FooName("_Z3fooi");
FunctionSamples FooSamples;
- FooSamples.setName(FooName);
+ FooSamples.setName(ProfileFuncName(FooName));
FooSamples.addTotalSamples(7711);
FooSamples.addHeadSamples(610);
FooSamples.addBodySamples(1, 0, 610);
@@ -155,43 +155,43 @@ struct SampleProfTest : ::testing::Test {
FooSamples.addBodySamples(10, 0, 605);
// Add inline instance with name "_Z3gooi".
- StringRef GooName("_Z3gooi");
+ ProfileFuncName GooName(StringRef("_Z3gooi"));
auto &GooSamples =
- FooSamples.functionSamplesAt(LineLocation(7, 0))[GooName.str()];
+ FooSamples.functionSamplesAt(LineLocation(7, 0))[GooName];
GooSamples.setName(GooName);
GooSamples.addTotalSamples(502);
GooSamples.addBodySamples(3, 0, 502);
// Add inline instance with name "_Z3hooi".
- StringRef HooName("_Z3hooi");
+ ProfileFuncName HooName(StringRef("_Z3hooi"));
auto &HooSamples =
- GooSamples.functionSamplesAt(LineLocation(9, 0))[HooName.str()];
+ GooSamples.functionSamplesAt(LineLocation(9, 0))[HooName];
HooSamples.setName(HooName);
HooSamples.addTotalSamples(317);
HooSamples.addBodySamples(4, 0, 317);
StringRef BarName("_Z3bari");
FunctionSamples BarSamples;
- BarSamples.setName(BarName);
+ BarSamples.setName(ProfileFuncName(BarName));
BarSamples.addTotalSamples(20301);
BarSamples.addHeadSamples(1437);
BarSamples.addBodySamples(1, 0, 1437);
// Test how reader/writer handles unmangled names.
StringRef MconstructName("_M_construct<char *>");
StringRef StringviewName("string_view<std::allocator<char> >");
- BarSamples.addCalledTargetSamples(1, 0, MconstructName, 1000);
- BarSamples.addCalledTargetSamples(1, 0, StringviewName, 437);
+ BarSamples.addCalledTargetSamples(1, 0, ProfileFuncName(MconstructName), 1000);
+ BarSamples.addCalledTargetSamples(1, 0, ProfileFuncName(StringviewName), 437);
StringRef BazName("_Z3bazi");
FunctionSamples BazSamples;
- BazSamples.setName(BazName);
+ BazSamples.setName(ProfileFuncName(BazName));
BazSamples.addTotalSamples(12557);
BazSamples.addHeadSamples(1257);
BazSamples.addBodySamples(1, 0, 12557);
StringRef BooName("_Z3booi");
FunctionSamples BooSamples;
- BooSamples.setName(BooName);
+ BooSamples.setName(ProfileFuncName(BooName));
BooSamples.addTotalSamples(1232);
BooSamples.addHeadSamples(1);
BooSamples.addBodySamples(1, 0, 1232);
@@ -210,8 +210,8 @@ struct SampleProfTest : ::testing::Test {
if (Remap) {
FooName = "_Z4fauxi";
BarName = "_Z3barl";
- GooName = "_Z3gool";
- HooName = "_Z3hool";
+ GooName = ProfileFuncName(StringRef("_Z3gool"));
+ HooName = ProfileFuncName(StringRef("_Z3hool"));
}
M.getOrInsertFunction(FooName, fn_type);
@@ -245,16 +245,17 @@ struct SampleProfTest : ::testing::Test {
FunctionSamples *ReadFooSamples = Reader->getSamplesFor(FooName);
ASSERT_TRUE(ReadFooSamples != nullptr);
if (!UseMD5) {
- ASSERT_EQ("_Z3fooi", ReadFooSamples->getName());
+ ASSERT_EQ("_Z3fooi", ReadFooSamples->getName().str());
}
ASSERT_EQ(7711u, ReadFooSamples->getTotalSamples());
ASSERT_EQ(610u, ReadFooSamples->getHeadSamples());
+ std::string Buffer;
// Try to find a FunctionSamples with GooName at given callsites containing
// inline instance for GooName. Test the correct FunctionSamples can be
// found with Remapper support.
const FunctionSamples *ReadGooSamples =
- ReadFooSamples->findFunctionSamplesAt(LineLocation(7, 0), GooName,
+ ReadFooSamples->findFunctionSamplesAt(LineLocation(7, 0), GooName.stringRef(Buffer),
Reader->getRemapper());
ASSERT_TRUE(ReadGooSamples != nullptr);
ASSERT_EQ(502u, ReadGooSamples->getTotalSamples());
@@ -263,7 +264,7 @@ struct SampleProfTest : ::testing::Test {
// no inline instance for GooName. Test no FunctionSamples will be
// found with Remapper support.
const FunctionSamples *ReadGooSamplesAgain =
- ReadFooSamples->findFunctionSamplesAt(LineLocation(9, 0), GooName,
+ ReadFooSamples->findFunctionSamplesAt(LineLocation(9, 0), GooName.stringRef(Buffer),
Reader->getRemapper());
ASSERT_TRUE(ReadGooSamplesAgain == nullptr);
@@ -272,7 +273,7 @@ struct SampleProfTest : ::testing::Test {
// inline instance for HooName. Test the correct FunctionSamples can be
// found with Remapper support.
const FunctionSamples *ReadHooSamples =
- ReadGooSamples->findFunctionSamplesAt(LineLocation(9, 0), HooName,
+ ReadGooSamples->findFunctionSamplesAt(LineLocation(9, 0), HooName.stringRef(Buffer),
Reader->getRemapper());
ASSERT_TRUE(ReadHooSamples != nullptr);
ASSERT_EQ(317u, ReadHooSamples->getTotalSamples());
@@ -280,7 +281,7 @@ struct SampleProfTest : ::testing::Test {
FunctionSamples *ReadBarSamples = Reader->getSamplesFor(BarName);
ASSERT_TRUE(ReadBarSamples != nullptr);
if (!UseMD5) {
- ASSERT_EQ("_Z3bari", ReadBarSamples->getName());
+ ASSERT_EQ("_Z3bari", ReadBarSamples->getName().str());
}
ASSERT_EQ(20301u, ReadBarSamples->getTotalSamples());
ASSERT_EQ(1437u, ReadBarSamples->getHeadSamples());
@@ -305,12 +306,8 @@ struct SampleProfTest : ::testing::Test {
ASSERT_TRUE(ReadBooSamples != nullptr);
ASSERT_EQ(1232u, ReadBooSamples->getTotalSamples());
- std::string MconstructGUID;
- StringRef MconstructRep =
- getRepInFormat(MconstructName, UseMD5, MconstructGUID);
- std::string StringviewGUID;
- StringRef StringviewRep =
- getRepInFormat(StringviewName, UseMD5, StringviewGUID);
+ ProfileFuncName MconstructRep = getRepInFormat(MconstructName, UseMD5);
+ ProfileFuncName StringviewRep = getRepInFormat(StringviewName, UseMD5);
ASSERT_EQ(1000u, CTMap.get()[MconstructRep]);
ASSERT_EQ(437u, CTMap.get()[StringviewRep]);
@@ -333,7 +330,7 @@ struct SampleProfTest : ::testing::Test {
uint64_t TotalSamples, uint64_t HeadSamples) {
StringRef Name(Fname);
FunctionSamples FcnSamples;
- FcnSamples.setName(Name);
+ FcnSamples.setName(ProfileFuncName(Name));
FcnSamples.addTotalSamples(TotalSamples);
FcnSamples.addHeadSamples(HeadSamples);
FcnSamples.addBodySamples(1, 0, HeadSamples);
>From 2b9efefd8436ba603c6c6999f4028a15356c711b Mon Sep 17 00:00:00 2001
From: William Huang <williamjhuang at google.com>
Date: Thu, 14 Sep 2023 19:41:30 +0000
Subject: [PATCH 4/4] Renamed ProfileFuncName to ProfileFuncRef, refactored it
so that it does not depend on StringRef
---
llvm/include/llvm/ADT/StringRef.h | 11 --
.../{ProfileFuncName.h => ProfileFuncRef.h} | 167 +++++++-----------
llvm/include/llvm/ProfileData/SampleProf.h | 64 +++----
.../llvm/ProfileData/SampleProfReader.h | 12 +-
.../llvm/ProfileData/SampleProfWriter.h | 12 +-
.../llvm/Transforms/IPO/ProfiledCallGraph.h | 10 +-
.../Transforms/IPO/SampleContextTracker.h | 26 +--
llvm/lib/ProfileData/SampleProf.cpp | 6 +-
llvm/lib/ProfileData/SampleProfReader.cpp | 28 +--
llvm/lib/ProfileData/SampleProfWriter.cpp | 12 +-
.../Transforms/IPO/SampleContextTracker.cpp | 24 +--
llvm/lib/Transforms/IPO/SampleProfile.cpp | 26 +--
llvm/tools/llvm-profdata/llvm-profdata.cpp | 4 +-
llvm/tools/llvm-profgen/CSPreInliner.cpp | 8 +-
llvm/tools/llvm-profgen/CSPreInliner.h | 4 +-
llvm/tools/llvm-profgen/ProfileGenerator.cpp | 10 +-
llvm/tools/llvm-profgen/ProfiledBinary.cpp | 6 +-
llvm/tools/llvm-profgen/ProfiledBinary.h | 4 +-
llvm/unittests/ProfileData/SampleProfTest.cpp | 26 +--
19 files changed, 207 insertions(+), 253 deletions(-)
rename llvm/include/llvm/ProfileData/{ProfileFuncName.h => ProfileFuncRef.h} (51%)
diff --git a/llvm/include/llvm/ADT/StringRef.h b/llvm/include/llvm/ADT/StringRef.h
index 2fa2398e6c50dac..235a7b27c384406 100644
--- a/llvm/include/llvm/ADT/StringRef.h
+++ b/llvm/include/llvm/ADT/StringRef.h
@@ -30,10 +30,6 @@ namespace llvm {
template <typename T> class SmallVectorImpl;
class StringRef;
- namespace sampleprof {
- class ProfileFuncName;
- }
-
/// Helper functions for StringRef::getAsInteger.
bool getAsUnsignedInteger(StringRef Str, unsigned Radix,
unsigned long long &Result);
@@ -52,8 +48,6 @@ namespace llvm {
/// lifetime extends past that of the StringRef. For this reason, it is not in
/// general safe to store a StringRef.
class LLVM_GSL_POINTER StringRef {
- friend class llvm::sampleprof::ProfileFuncName;
-
public:
static constexpr size_t npos = ~size_t(0);
@@ -86,11 +80,6 @@ namespace llvm {
/// if (S == nullptr)
StringRef(std::nullptr_t) = delete;
- /// Disallow casting from ProfileFuncName because if it is representing a
- /// MD5 value, most string method will not work. Use
- /// stringRef(std::string &) instead.
- StringRef(const sampleprof::ProfileFuncName) = delete;
-
/// Construct a string ref from a cstring.
/*implicit*/ constexpr StringRef(const char *Str)
: Data(Str), Length(Str ?
diff --git a/llvm/include/llvm/ProfileData/ProfileFuncName.h b/llvm/include/llvm/ProfileData/ProfileFuncRef.h
similarity index 51%
rename from llvm/include/llvm/ProfileData/ProfileFuncName.h
rename to llvm/include/llvm/ProfileData/ProfileFuncRef.h
index e287d519155798f..60be6232372b8c6 100644
--- a/llvm/include/llvm/ProfileData/ProfileFuncName.h
+++ b/llvm/include/llvm/ProfileData/ProfileFuncRef.h
@@ -1,4 +1,4 @@
-//===--- ProfileFuncName.h - Sample profile function name ---*- C++ -*-===//
+//===--- ProfileFuncRef.h - Sample profile function name ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_PROFILEDATA_PROFILEFUNCNAME_H
-#define LLVM_PROFILEDATA_PROFILEFUNCNAME_H
+#ifndef LLVM_PROFILEDATA_PROFILEFUNCREF_H
+#define LLVM_PROFILEDATA_PROFILEFUNCREF_H
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/Hashing.h"
@@ -35,102 +35,80 @@ namespace sampleprof {
/// and can be pointer-casted as one.
/// We disallow implicit cast to StringRef because there are too many instances
/// that it may cause break the code, such as using it in a StringMap.
-class ProfileFuncName : private StringRef {
-
- // Add placeholder to make sure there are enough space after Length field so
- // that it can fit a 64-bit hash code, if the machine is 32-bit or any other
- // weird architecture. The placeholder field should be set to zero so that it
- // will not contain undefined values and break optimized comparison methods.
-#if UINTPTR_MAX < UINT64_MAX || SIZE_MAX < UINT64_MAX
- uint64_t Placeholder;
-#endif
-
- /// Get the hash code if it is representing one, otherwise this equals to
- /// the Length of the StringRef.
- uint64_t &getIntValue() {
- return *reinterpret_cast<uint64_t *>(&this->Length);
- }
+class ProfileFuncRef {
- const uint64_t &getIntValue() const {
- return *reinterpret_cast<const uint64_t *>(&this->Length);
- }
+ const char *Data = nullptr;
+
+ /// Use uint64_t instead of size_t so that it can also hold a MD5 value.
+ uint64_t Length = 0;
/// Extension to memcmp to handle hash code representation. If both are hash
/// values, Lhs and Rhs are both null, function returns 0 (and needs an extra
/// comparison using getIntValue). If only one is hash code, it is considered
/// less than the StringRef one. Otherwise perform normal string comparison.
- static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) {
+ static int compareMemory(const char *Lhs, const char *Rhs, uint64_t Length) {
if (Lhs == Rhs)
return 0;
if (!Lhs)
return -1;
if (!Rhs)
return 1;
- return ::memcmp(Lhs, Rhs, Length);
+ return ::memcmp(Lhs, Rhs, (size_t)Length);
}
public:
- /// Default constructor. Use memset because there may be padding bytes between
- /// Length and Placeholder containing undefined values on certain
- /// architectures, which breaks comparison methods.
- ProfileFuncName() {
- memset(this, 0, sizeof(ProfileFuncName));
- }
+ ProfileFuncRef() = default;
/// Constructor from a StringRef.
- explicit ProfileFuncName(StringRef Str) : ProfileFuncName() {
- Data = Str.Data;
- Length = Str.Length;
- }
+ explicit ProfileFuncRef(StringRef Str)
+ : Data(Str.data()), Length(Str.size()) {}
/// Constructor from a hash code.
- explicit ProfileFuncName(uint64_t HashCode) : ProfileFuncName() {
+ explicit ProfileFuncRef(uint64_t HashCode)
+ : Data(nullptr), Length(HashCode) {
assert(HashCode != 0);
- getIntValue() = HashCode;
}
/// Constructor from a string. Check if Str is a number, which is generated by
/// converting a MD5 sample profile to a format that does not support MD5, and
/// if so, convert the numerical string to a hash code first. We assume that
/// no function name (from a profile) can be a pure number.
- explicit ProfileFuncName(const std::string &Str) : ProfileFuncName() {
- uint64_t Hash;
- // Faster
- if (Str.length() > 0 && isdigit(Str[0]) && !getAsInteger(10, Hash))
- *this = ProfileFuncName(Hash);
- else
- *this = ProfileFuncName(StringRef(Str));
+ explicit ProfileFuncRef(const std::string &Str)
+ : Data(Str.data()), Length(Str.size()) {
+ // Only need to check for base 10 digits, fail faster if otherwise.
+ if (Str.length() > 0 && isdigit(Str[0]) &&
+ !StringRef(Str).getAsInteger(10, Length))
+ Data = nullptr;
}
/// Check for equality. Similar to StringRef::equals, but will also cover for
/// the case where one or both are hash codes. Comparing their int values are
/// sufficient. A hash code ProfileFuncName is considered not equal to a
/// StringRef ProfileFuncName regardless of actual contents.
- bool equals(const ProfileFuncName &Other) const {
- return getIntValue() == Other.getIntValue() &&
- compareMemory(data(), Other.data(), size()) == 0;
+ bool equals(const ProfileFuncRef &Other) const {
+ return Length == Other.Length &&
+ compareMemory(Data, Other.Data, Length) == 0;
}
/// Total order comparison. If both ProfileFuncName are StringRef, this is the
/// same as StringRef::compare. If one of them is StringRef, it is considered
/// greater than the hash code ProfileFuncName. Otherwise this is the the
/// same as comparing their int values.
- int compare(const ProfileFuncName &Other) const {
- auto Res = compareMemory(data(), Other.data(),
- std::min(size(), Other.size()));
+ int compare(const ProfileFuncRef &Other) const {
+ auto Res = compareMemory(Data, Other.Data, std::min(Length, Other.Length));
if (Res != 0)
return Res;
- if (getIntValue() == Other.getIntValue())
+ if (Length == Other.Length)
return 0;
- return getIntValue() < Other.getIntValue() ? -1 : 1;
+ return Length < Other.Length ? -1 : 1;
}
/// Convert to a string, usually for output purpose.
std::string str() const {
- if (data())
- return std::string(data(), size());
- if (getIntValue() != 0)
- return std::to_string(getIntValue());
+ if (Data)
+ return std::string(Data, Length);
+ if (Length != 0)
+ return std::to_string(Length);
return std::string();
}
@@ -138,17 +116,16 @@ class ProfileFuncName : private StringRef {
/// object represents a hash code, which will be converted to a string into
/// the buffer. If this object represents a StringRef, the buffer is not used.
StringRef stringRef(std::string &Buffer) const {
- if (data())
- return static_cast<const StringRef &>(*this);
- if (getIntValue() != 0) {
- Buffer = std::to_string(getIntValue());
+ if (Data)
+ return StringRef(Data, Length);
+ if (Length != 0) {
+ Buffer = std::to_string(Length);
return Buffer;
}
return StringRef();
}
- friend raw_ostream &operator<<(raw_ostream &OS,
- const ProfileFuncName &Obj);
+ friend raw_ostream &operator<<(raw_ostream &OS, const ProfileFuncRef &Obj);
/// Get hash code of this object. Returns this object's hash code if it is
/// already representing one, otherwise returns the MD5 of its string content.
@@ -156,64 +133,54 @@ class ProfileFuncName : private StringRef {
/// consistency that the same sample profile function in string form or MD5
/// form has the same hash code.
uint64_t getHashCode() const {
- if (data())
- return MD5Hash(static_cast<const StringRef &>(*this));
- return getIntValue();
+ if (Data)
+ return MD5Hash(StringRef(Data, Length));
+ return Length;
}
- bool empty() const {
- return getIntValue() == 0;
- }
+ bool empty() const { return Length == 0; }
/// Check if this object represents a StringRef, or a hash code.
- bool isStringRef() const {
- return data();
- }
+ bool isStringRef() const { return Data != nullptr; }
};
-inline bool operator==(const ProfileFuncName &LHS,
- const ProfileFuncName &RHS) {
+inline bool operator==(const ProfileFuncRef &LHS, const ProfileFuncRef &RHS) {
return LHS.equals(RHS);
}
-inline bool operator!=(const ProfileFuncName &LHS,
- const ProfileFuncName &RHS) {
+inline bool operator!=(const ProfileFuncRef &LHS, const ProfileFuncRef &RHS) {
return !LHS.equals(RHS);
}
-inline bool operator<(const ProfileFuncName &LHS,
- const ProfileFuncName &RHS) {
+inline bool operator<(const ProfileFuncRef &LHS, const ProfileFuncRef &RHS) {
return LHS.compare(RHS) < 0;
}
-inline bool operator<=(const ProfileFuncName &LHS,
- const ProfileFuncName &RHS) {
+inline bool operator<=(const ProfileFuncRef &LHS, const ProfileFuncRef &RHS) {
return LHS.compare(RHS) <= 0;
}
-inline bool operator>(const ProfileFuncName &LHS,
- const ProfileFuncName &RHS) {
+inline bool operator>(const ProfileFuncRef &LHS, const ProfileFuncRef &RHS) {
return LHS.compare(RHS) > 0;
}
-inline bool operator>=(const ProfileFuncName &LHS,
- const ProfileFuncName &RHS) {
+inline bool operator>=(const ProfileFuncRef &LHS, const ProfileFuncRef &RHS) {
return LHS.compare(RHS) >= 0;
}
-inline raw_ostream &operator<<(raw_ostream &OS, const ProfileFuncName &Obj) {
- if (Obj.data())
- return OS << static_cast<const StringRef &>(Obj);
- if (Obj.getIntValue() != 0)
- return OS << Obj.getIntValue();
+inline raw_ostream &operator<<(raw_ostream &OS, const ProfileFuncRef &Obj) {
+ if (Obj.Data)
+ return OS << StringRef(Obj.Data, Obj.Length);
+ if (Obj.Length != 0)
+ return OS << Obj.Length;
return OS;
}
-inline uint64_t MD5Hash(const sampleprof::ProfileFuncName &Obj) {
+inline uint64_t MD5Hash(const sampleprof::ProfileFuncRef &Obj) {
return Obj.getHashCode();
}
-inline hash_code hash_value(const sampleprof::ProfileFuncName &Obj) {
+inline hash_code hash_value(const sampleprof::ProfileFuncRef &Obj) {
return Obj.getHashCode();
}
@@ -221,23 +188,22 @@ inline hash_code hash_value(const sampleprof::ProfileFuncName &Obj) {
/// Template specialization for ProfileFuncName so that it can be used in LLVM
/// map containers.
-template <>
-struct DenseMapInfo<sampleprof::ProfileFuncName, void> {
+template <> struct DenseMapInfo<sampleprof::ProfileFuncRef, void> {
- static inline sampleprof::ProfileFuncName getEmptyKey() {
- return sampleprof::ProfileFuncName(~0ULL);
+ static inline sampleprof::ProfileFuncRef getEmptyKey() {
+ return sampleprof::ProfileFuncRef(~0ULL);
}
- static inline sampleprof::ProfileFuncName getTombstoneKey() {
- return sampleprof::ProfileFuncName(~1ULL);
+ static inline sampleprof::ProfileFuncRef getTombstoneKey() {
+ return sampleprof::ProfileFuncRef(~1ULL);
}
- static unsigned getHashValue(const sampleprof::ProfileFuncName &Val) {
+ static unsigned getHashValue(const sampleprof::ProfileFuncRef &Val) {
return Val.getHashCode();
}
- static bool isEqual(const sampleprof::ProfileFuncName &LHS,
- const sampleprof::ProfileFuncName &RHS) {
+ static bool isEqual(const sampleprof::ProfileFuncRef &LHS,
+ const sampleprof::ProfileFuncRef &RHS) {
return LHS == RHS;
}
};
@@ -248,13 +214,12 @@ namespace std {
/// Template specialization for ProfileFuncName so that it can be used in STL
/// containers.
-template <>
-struct hash<llvm::sampleprof::ProfileFuncName> {
- size_t operator()(const llvm::sampleprof::ProfileFuncName &Val) const {
+template <> struct hash<llvm::sampleprof::ProfileFuncRef> {
+ size_t operator()(const llvm::sampleprof::ProfileFuncRef &Val) const {
return Val.getHashCode();
}
};
} // end namespace std
-#endif // LLVM_PROFILEDATA_PROFILEFUNCNAME_H
+#endif // LLVM_PROFILEDATA_PROFILEFUNCREF_H
diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h
index 845066dc8a0c3f2..f9d169d4fd1aa24 100644
--- a/llvm/include/llvm/ProfileData/SampleProf.h
+++ b/llvm/include/llvm/ProfileData/SampleProf.h
@@ -21,7 +21,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
-#include "llvm/ProfileData/ProfileFuncName.h"
+#include "llvm/ProfileData/ProfileFuncRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorOr.h"
@@ -112,10 +112,10 @@ static inline uint64_t SPMagic(SampleProfileFormat Format = SPF_Binary) {
/// Get the proper representation of a string according to whether the
/// current Format uses MD5 to represent the string.
-static inline ProfileFuncName getRepInFormat(StringRef Name, bool UseMD5) {
+static inline ProfileFuncRef getRepInFormat(StringRef Name, bool UseMD5) {
if (Name.empty() || !UseMD5)
- return ProfileFuncName(Name);
- return ProfileFuncName(Function::getGUID(Name));
+ return ProfileFuncRef(Name);
+ return ProfileFuncRef(Function::getGUID(Name));
}
static inline uint64_t SPVersion() { return 103; }
@@ -333,7 +333,7 @@ raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc);
/// will be a list of one or more functions.
class SampleRecord {
public:
- using CallTarget = std::pair<ProfileFuncName, uint64_t>;
+ using CallTarget = std::pair<ProfileFuncRef, uint64_t>;
struct CallTargetComparator {
bool operator()(const CallTarget &LHS, const CallTarget &RHS) const {
if (LHS.second != RHS.second)
@@ -344,7 +344,7 @@ class SampleRecord {
};
using SortedCallTargetSet = std::set<CallTarget, CallTargetComparator>;
- using CallTargetMap = std::unordered_map<ProfileFuncName, uint64_t>;
+ using CallTargetMap = std::unordered_map<ProfileFuncRef, uint64_t>;
SampleRecord() = default;
/// Increment the number of samples for this record by \p S.
@@ -373,7 +373,7 @@ class SampleRecord {
///
/// Sample counts accumulate using saturating arithmetic, to avoid wrapping
/// around unsigned integers.
- sampleprof_error addCalledTarget(ProfileFuncName F, uint64_t S,
+ sampleprof_error addCalledTarget(ProfileFuncRef F, uint64_t S,
uint64_t Weight = 1) {
uint64_t &TargetSamples = CallTargets[F];
bool Overflowed;
@@ -385,7 +385,7 @@ class SampleRecord {
/// Remove called function from the call target map. Return the target sample
/// count of the called function.
- uint64_t removeCalledTarget(ProfileFuncName F) {
+ uint64_t removeCalledTarget(ProfileFuncRef F) {
uint64_t Count = 0;
auto I = CallTargets.find(F);
if (I != CallTargets.end()) {
@@ -471,12 +471,12 @@ enum ContextAttributeMask {
// Represents a context frame with function name and line location
struct SampleContextFrame {
- ProfileFuncName FuncName;
+ ProfileFuncRef FuncName;
LineLocation Location;
SampleContextFrame() : Location(0, 0) {}
- SampleContextFrame(ProfileFuncName FuncName, LineLocation Location)
+ SampleContextFrame(ProfileFuncRef FuncName, LineLocation Location)
: FuncName(FuncName), Location(Location) {}
bool operator==(const SampleContextFrame &That) const {
@@ -536,7 +536,7 @@ class SampleContext {
SampleContext(StringRef Name)
: Name(Name), State(UnknownContext), Attributes(ContextNone) {}
- SampleContext(ProfileFuncName Name)
+ SampleContext(ProfileFuncRef Name)
: Name(Name), State(UnknownContext), Attributes(ContextNone) {}
SampleContext(SampleContextFrames Context,
@@ -559,7 +559,7 @@ class SampleContext {
bool HasContext = ContextStr.startswith("[");
if (!HasContext) {
State = UnknownContext;
- Name = ProfileFuncName(ContextStr);
+ Name = ProfileFuncRef(ContextStr);
} else {
CSNameTable.emplace_back();
SampleContextFrameVector &Context = CSNameTable.back();
@@ -576,7 +576,7 @@ class SampleContext {
ContextStr = ContextStr.substr(1, ContextStr.size() - 2);
StringRef ContextRemain = ContextStr;
StringRef ChildContext;
- ProfileFuncName CalleeName;
+ ProfileFuncRef CalleeName;
while (!ContextRemain.empty()) {
auto ContextSplit = ContextRemain.split(" @ ");
ChildContext = ContextSplit.first;
@@ -590,11 +590,11 @@ class SampleContext {
// Decode context string for a frame to get function name and location.
// `ContextStr` is in the form of `FuncName:StartLine.Discriminator`.
static void decodeContextString(StringRef ContextStr,
- ProfileFuncName &FName,
+ ProfileFuncRef &FName,
LineLocation &LineLoc) {
// Get function name
auto EntrySplit = ContextStr.split(':');
- FName = ProfileFuncName(EntrySplit.first);
+ FName = ProfileFuncRef(EntrySplit.first);
LineLoc = {0, 0};
if (!EntrySplit.second.empty()) {
@@ -621,7 +621,7 @@ class SampleContext {
void clearState(ContextStateMask S) { State &= (uint32_t)~S; }
bool hasContext() const { return State != UnknownContext; }
bool isBaseContext() const { return FullContext.size() == 1; }
- ProfileFuncName getName() const { return Name; }
+ ProfileFuncRef getName() const { return Name; }
SampleContextFrames getContextFrames() const { return FullContext; }
static std::string getContextString(SampleContextFrames Context,
@@ -650,7 +650,7 @@ class SampleContext {
}
/// Set the name of the function and clear the current context.
- void setName(ProfileFuncName FunctionName) {
+ void setName(ProfileFuncRef FunctionName) {
Name = FunctionName;
FullContext = SampleContextFrames();
State = UnknownContext;
@@ -715,7 +715,7 @@ class SampleContext {
private:
/// Mangled name of the function.
- ProfileFuncName Name;
+ ProfileFuncRef Name;
// Full context including calling context and leaf function name
SampleContextFrames FullContext;
// State of the associated sample profile
@@ -738,7 +738,7 @@ class SampleProfileReaderItaniumRemapper;
using BodySampleMap = std::map<LineLocation, SampleRecord>;
// NOTE: Using a StringMap here makes parsed profiles consume around 17% more
// memory, which is *very* significant for large profiles.
-using FunctionSamplesMap = std::map<ProfileFuncName, FunctionSamples>;
+using FunctionSamplesMap = std::map<ProfileFuncRef, FunctionSamples>;
using CallsiteSampleMap = std::map<LineLocation, FunctionSamplesMap>;
using LocToLocMap =
std::unordered_map<LineLocation, LineLocation, LineLocationHash>;
@@ -790,7 +790,7 @@ class FunctionSamples {
sampleprof_error addCalledTargetSamples(uint32_t LineOffset,
uint32_t Discriminator,
- ProfileFuncName FName,
+ ProfileFuncRef FName,
uint64_t Num,
uint64_t Weight = 1) {
return BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
@@ -807,7 +807,7 @@ class FunctionSamples {
// the number of body samples actually decreased.
uint64_t removeCalledTargetAndBodySample(uint32_t LineOffset,
uint32_t Discriminator,
- ProfileFuncName FName) {
+ ProfileFuncRef FName) {
uint64_t Count = 0;
auto I = BodySamples.find(LineLocation(LineOffset, Discriminator));
if (I != BodySamples.end()) {
@@ -1067,12 +1067,12 @@ class FunctionSamples {
}
/// Set the name of the function.
- void setName(ProfileFuncName FunctionName) {
+ void setName(ProfileFuncRef FunctionName) {
Context.setName(FunctionName);
}
/// Return the function name.
- ProfileFuncName getName() const { return Context.getName(); }
+ ProfileFuncRef getName() const { return Context.getName(); }
/// Return the original function name.
StringRef getFuncName() const { return getFuncName(getName()); }
@@ -1139,7 +1139,7 @@ class FunctionSamples {
/// translate \p Name in current FunctionSamples into its original name
/// by looking up in the function map GUIDToFuncNameMap.
/// If the original name doesn't exist in the map, return empty StringRef.
- StringRef getFuncName(ProfileFuncName Name) const {
+ StringRef getFuncName(ProfileFuncRef Name) const {
if (!UseMD5)
return reinterpret_cast<StringRef &>(Name);
@@ -1162,7 +1162,7 @@ class FunctionSamples {
/// the callee function name.
/// Guarantee MD5 and non-MD5 representation of the same function results in
/// the same hash.
- static uint64_t getCallSiteHash(ProfileFuncName CalleeName,
+ static uint64_t getCallSiteHash(ProfileFuncRef CalleeName,
const LineLocation &Callsite);
/// Get the FunctionSamples of the inline instance where DIL originates
@@ -1211,7 +1211,7 @@ class FunctionSamples {
// Find all the names in the current FunctionSamples including names in
// all the inline instances and names of call targets.
- void findAllNames(DenseSet<ProfileFuncName> &NameSet) const;
+ void findAllNames(DenseSet<ProfileFuncRef> &NameSet) const;
bool operator==(const FunctionSamples &Other) const {
return (GUIDToFuncNameMap == Other.GUIDToFuncNameMap ||
@@ -1294,7 +1294,7 @@ class FunctionSamples {
const LocToLocMap *IRToProfileLocationMap = nullptr;
};
-static inline ProfileFuncName getRepInFormat(StringRef Name) {
+static inline ProfileFuncRef getRepInFormat(StringRef Name) {
return getRepInFormat(Name, FunctionSamples::UseMD5);
}
@@ -1402,7 +1402,7 @@ class SampleProfileMap
}
// Overloaded find() to lookup a function by name.
- iterator find(ProfileFuncName Fname) {
+ iterator find(ProfileFuncRef Fname) {
return base_type::find(Fname.getHashCode());
}
@@ -1476,7 +1476,7 @@ class ProfileConverter {
// profile.
void convertCSProfiles();
struct FrameNode {
- FrameNode(ProfileFuncName FName = ProfileFuncName(),
+ FrameNode(ProfileFuncRef FName = ProfileFuncRef(),
FunctionSamples *FSamples = nullptr,
LineLocation CallLoc = {0, 0})
: FuncName(FName), FuncSamples(FSamples), CallSiteLoc(CallLoc){};
@@ -1484,14 +1484,14 @@ class ProfileConverter {
// Map line+discriminator location to child frame
std::map<uint64_t, FrameNode> AllChildFrames;
// Function name for current frame
- ProfileFuncName FuncName;
+ ProfileFuncRef FuncName;
// Function Samples for current frame
FunctionSamples *FuncSamples;
// Callsite location in parent context
LineLocation CallSiteLoc;
FrameNode *getOrCreateChildFrame(const LineLocation &CallSite,
- ProfileFuncName CalleeName);
+ ProfileFuncRef CalleeName);
};
static void flattenProfile(SampleProfileMap &ProfileMap,
@@ -1639,7 +1639,7 @@ template <> struct DenseMapInfo<SampleContext> {
static inline SampleContext getEmptyKey() { return SampleContext(); }
static inline SampleContext getTombstoneKey() {
- return SampleContext(ProfileFuncName(~1ULL));
+ return SampleContext(ProfileFuncRef(~1ULL));
}
static unsigned getHashValue(const SampleContext &Val) {
diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h
index d739a948b9ca010..df30722cb1b5bc3 100644
--- a/llvm/include/llvm/ProfileData/SampleProfReader.h
+++ b/llvm/include/llvm/ProfileData/SampleProfReader.h
@@ -409,13 +409,13 @@ class SampleProfileReader {
/// Return the samples collected for function \p F.
FunctionSamples *getSamplesFor(StringRef Fname) {
- auto It = Profiles.find(ProfileFuncName(Fname));
+ auto It = Profiles.find(ProfileFuncRef(Fname));
if (It != Profiles.end())
return &It->second;
if (Remapper) {
if (auto NameInProfile = Remapper->lookUpNameInProfile(Fname)) {
- auto It = Profiles.find(ProfileFuncName(*NameInProfile));
+ auto It = Profiles.find(ProfileFuncRef(*NameInProfile));
if (It != Profiles.end())
return &It->second;
}
@@ -474,7 +474,7 @@ class SampleProfileReader {
/// It includes all the names that have samples either in outline instance
/// or inline instance.
- virtual std::vector<ProfileFuncName> *getNameTable() { return nullptr; }
+ virtual std::vector<ProfileFuncRef> *getNameTable() { return nullptr; }
virtual bool dumpSectionInfo(raw_ostream &OS = dbgs()) { return false; };
/// Return whether names in the profile are all MD5 numbers.
@@ -591,7 +591,7 @@ class SampleProfileReaderBinary : public SampleProfileReader {
/// It includes all the names that have samples either in outline instance
/// or inline instance.
- std::vector<ProfileFuncName> *getNameTable() override {
+ std::vector<ProfileFuncRef> *getNameTable() override {
return &NameTable;
}
@@ -635,7 +635,7 @@ class SampleProfileReaderBinary : public SampleProfileReader {
std::error_code readNameTable();
/// Read a string indirectly via the name table. Optionally return the index.
- ErrorOr<ProfileFuncName> readStringFromTable(size_t *RetIdx = nullptr);
+ ErrorOr<ProfileFuncRef> readStringFromTable(size_t *RetIdx = nullptr);
/// Read a context indirectly via the CSNameTable. Optionally return the
/// index.
@@ -652,7 +652,7 @@ class SampleProfileReaderBinary : public SampleProfileReader {
const uint8_t *End = nullptr;
/// Function name table.
- std::vector<ProfileFuncName> NameTable;
+ std::vector<ProfileFuncRef> NameTable;
/// The starting address of fixed length MD5 name table section.
const uint8_t *MD5NameMemStart = nullptr;
diff --git a/llvm/include/llvm/ProfileData/SampleProfWriter.h b/llvm/include/llvm/ProfileData/SampleProfWriter.h
index 5d69a7f59ae0f21..3eff17e5e5f0900 100644
--- a/llvm/include/llvm/ProfileData/SampleProfWriter.h
+++ b/llvm/include/llvm/ProfileData/SampleProfWriter.h
@@ -196,20 +196,20 @@ class SampleProfileWriterBinary : public SampleProfileWriter {
std::error_code writeSample(const FunctionSamples &S) override;
protected:
- virtual MapVector<ProfileFuncName, uint32_t> &getNameTable() { return NameTable; }
+ virtual MapVector<ProfileFuncRef, uint32_t> &getNameTable() { return NameTable; }
virtual std::error_code writeMagicIdent(SampleProfileFormat Format);
virtual std::error_code writeNameTable();
std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
std::error_code writeSummary();
virtual std::error_code writeContextIdx(const SampleContext &Context);
- std::error_code writeNameIdx(ProfileFuncName FName);
+ std::error_code writeNameIdx(ProfileFuncRef FName);
std::error_code writeBody(const FunctionSamples &S);
- inline void stablizeNameTable(MapVector<ProfileFuncName, uint32_t> &NameTable,
- std::set<ProfileFuncName> &V);
+ inline void stablizeNameTable(MapVector<ProfileFuncRef, uint32_t> &NameTable,
+ std::set<ProfileFuncRef> &V);
- MapVector<ProfileFuncName, uint32_t> NameTable;
+ MapVector<ProfileFuncRef, uint32_t> NameTable;
- void addName(ProfileFuncName FName);
+ void addName(ProfileFuncRef FName);
virtual void addContext(const SampleContext &Context);
void addNames(const FunctionSamples &S);
diff --git a/llvm/include/llvm/Transforms/IPO/ProfiledCallGraph.h b/llvm/include/llvm/Transforms/IPO/ProfiledCallGraph.h
index 1625060bdc92f78..b575058614211e5 100644
--- a/llvm/include/llvm/Transforms/IPO/ProfiledCallGraph.h
+++ b/llvm/include/llvm/Transforms/IPO/ProfiledCallGraph.h
@@ -53,10 +53,10 @@ struct ProfiledCallGraphNode {
using iterator = edges::iterator;
using const_iterator = edges::const_iterator;
- ProfiledCallGraphNode(ProfileFuncName FName = ProfileFuncName()) : Name(FName)
+ ProfiledCallGraphNode(ProfileFuncRef FName = ProfileFuncRef()) : Name(FName)
{}
- ProfileFuncName Name;
+ ProfileFuncRef Name;
edges Edges;
};
@@ -137,7 +137,7 @@ class ProfiledCallGraph {
iterator end() { return Root.Edges.end(); }
ProfiledCallGraphNode *getEntryNode() { return &Root; }
- void addProfiledFunction(ProfileFuncName Name) {
+ void addProfiledFunction(ProfileFuncRef Name) {
if (!ProfiledFunctions.count(Name)) {
// Link to synthetic root to make sure every node is reachable
// from root. This does not affect SCC order.
@@ -147,7 +147,7 @@ class ProfiledCallGraph {
}
private:
- void addProfiledCall(ProfileFuncName CallerName, ProfileFuncName CalleeName,
+ void addProfiledCall(ProfileFuncRef CallerName, ProfileFuncRef CalleeName,
uint64_t Weight = 0) {
assert(ProfiledFunctions.count(CallerName));
auto CalleeIt = ProfiledFunctions.find(CalleeName);
@@ -206,7 +206,7 @@ class ProfiledCallGraph {
}
ProfiledCallGraphNode Root;
- std::unordered_map<ProfileFuncName, ProfiledCallGraphNode> ProfiledFunctions;
+ std::unordered_map<ProfileFuncRef, ProfiledCallGraphNode> ProfiledFunctions;
};
} // end namespace sampleprof
diff --git a/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h b/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h
index d6735ceba948bd8..270dd25672b9f36 100644
--- a/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h
+++ b/llvm/include/llvm/Transforms/IPO/SampleContextTracker.h
@@ -35,20 +35,20 @@ class Instruction;
class ContextTrieNode {
public:
ContextTrieNode(ContextTrieNode *Parent = nullptr,
- ProfileFuncName FName = ProfileFuncName(),
+ ProfileFuncRef FName = ProfileFuncRef(),
FunctionSamples *FSamples = nullptr,
LineLocation CallLoc = {0, 0})
: ParentContext(Parent), FuncName(FName), FuncSamples(FSamples),
CallSiteLoc(CallLoc){};
ContextTrieNode *getChildContext(const LineLocation &CallSite,
- ProfileFuncName ChildName);
+ ProfileFuncRef ChildName);
ContextTrieNode *getHottestChildContext(const LineLocation &CallSite);
ContextTrieNode *getOrCreateChildContext(const LineLocation &CallSite,
- ProfileFuncName ChildName,
+ ProfileFuncRef ChildName,
bool AllowCreate = true);
- void removeChildContext(const LineLocation &CallSite, ProfileFuncName ChildName);
+ void removeChildContext(const LineLocation &CallSite, ProfileFuncRef ChildName);
std::map<uint64_t, ContextTrieNode> &getAllChildContext();
- ProfileFuncName getFuncName() const;
+ ProfileFuncRef getFuncName() const;
FunctionSamples *getFunctionSamples() const;
void setFunctionSamples(FunctionSamples *FSamples);
std::optional<uint32_t> getFunctionSize() const;
@@ -68,7 +68,7 @@ class ContextTrieNode {
ContextTrieNode *ParentContext;
// Function name for current context
- ProfileFuncName FuncName;
+ ProfileFuncRef FuncName;
// Function Samples for current context
FunctionSamples *FuncSamples;
@@ -118,7 +118,7 @@ class SampleContextTracker {
FunctionSamples *getBaseSamplesFor(const Function &Func,
bool MergeContext = true);
// Query base profile for a given function by name.
- FunctionSamples *getBaseSamplesFor(ProfileFuncName Name,
+ FunctionSamples *getBaseSamplesFor(ProfileFuncRef Name,
bool MergeContext = true);
// Retrieve the context trie node for given profile context
ContextTrieNode *getContextFor(const SampleContext &Context);
@@ -130,7 +130,7 @@ class SampleContextTracker {
void markContextSamplesInlined(const FunctionSamples *InlinedSamples);
ContextTrieNode &getRootContext();
void promoteMergeContextSamplesTree(const Instruction &Inst,
- ProfileFuncName CalleeName);
+ ProfileFuncRef CalleeName);
// Create a merged conext-less profile map.
void createContextLessProfileMap(SampleProfileMap &ContextLessProfiles);
@@ -141,7 +141,7 @@ class SampleContextTracker {
return nullptr;
return I->second;
}
- std::unordered_map<ProfileFuncName, ContextSamplesTy> &getFuncToCtxtProfiles() {
+ std::unordered_map<ProfileFuncRef, ContextSamplesTy> &getFuncToCtxtProfiles() {
return FuncToCtxtProfiles;
}
@@ -190,9 +190,9 @@ class SampleContextTracker {
private:
ContextTrieNode *getContextFor(const DILocation *DIL);
ContextTrieNode *getCalleeContextFor(const DILocation *DIL,
- ProfileFuncName CalleeName);
- ContextTrieNode *getTopLevelContextNode(ProfileFuncName FName);
- ContextTrieNode &addTopLevelContextNode(ProfileFuncName FName);
+ ProfileFuncRef CalleeName);
+ ContextTrieNode *getTopLevelContextNode(ProfileFuncRef FName);
+ ContextTrieNode &addTopLevelContextNode(ProfileFuncRef FName);
ContextTrieNode &promoteMergeContextSamplesTree(ContextTrieNode &NodeToPromo);
void mergeContextNode(ContextTrieNode &FromNode, ContextTrieNode &ToNode);
ContextTrieNode &
@@ -205,7 +205,7 @@ class SampleContextTracker {
ProfileToNodeMap[FSample] = Node;
}
// Map from function name to context profiles (excluding base profile)
- std::unordered_map<ProfileFuncName, ContextSamplesTy> FuncToCtxtProfiles;
+ std::unordered_map<ProfileFuncRef, ContextSamplesTy> FuncToCtxtProfiles;
// Map from current FunctionSample to the belonged context trie.
std::unordered_map<const FunctionSamples *, ContextTrieNode *>
diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp
index 757132ae351e522..a3de3c8e7400f0a 100644
--- a/llvm/lib/ProfileData/SampleProf.cpp
+++ b/llvm/lib/ProfileData/SampleProf.cpp
@@ -234,7 +234,7 @@ LineLocation FunctionSamples::getCallSiteIdentifier(const DILocation *DIL,
}
}
-uint64_t FunctionSamples::getCallSiteHash(ProfileFuncName CalleeName,
+uint64_t FunctionSamples::getCallSiteHash(ProfileFuncRef CalleeName,
const LineLocation &Callsite) {
uint64_t NameHash = CalleeName.getHashCode();
uint64_t LocId =
@@ -268,7 +268,7 @@ const FunctionSamples *FunctionSamples::findFunctionSamples(
return FS;
}
-void FunctionSamples::findAllNames(DenseSet<ProfileFuncName> &NameSet) const {
+void FunctionSamples::findAllNames(DenseSet<ProfileFuncRef> &NameSet) const {
NameSet.insert(getName());
for (const auto &BS : BodySamples)
for (const auto &TS : BS.second.getCallTargets())
@@ -419,7 +419,7 @@ void ProfileSymbolList::dump(raw_ostream &OS) const {
ProfileConverter::FrameNode *
ProfileConverter::FrameNode::getOrCreateChildFrame(const LineLocation &CallSite,
- ProfileFuncName CalleeName) {
+ ProfileFuncRef CalleeName) {
uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
auto It = AllChildFrames.find(Hash);
if (It != AllChildFrames.end()) {
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index eb5e9368914c6b2..86306c14a048da4 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -392,8 +392,8 @@ std::error_code SampleProfileReaderText::readImpl() {
switch (LineTy) {
case LineType::CallSiteProfile: {
FunctionSamples &FSamples = InlineStack.back()->functionSamplesAt(
- LineLocation(LineOffset, Discriminator))[ProfileFuncName(FName)];
- FSamples.setName(ProfileFuncName(FName));
+ LineLocation(LineOffset, Discriminator))[ProfileFuncRef(FName)];
+ FSamples.setName(ProfileFuncRef(FName));
MergeResult(Result, FSamples.addTotalSamples(NumSamples));
InlineStack.push_back(&FSamples);
DepthMetadata = 0;
@@ -407,7 +407,7 @@ std::error_code SampleProfileReaderText::readImpl() {
for (const auto &name_count : TargetCountMap) {
MergeResult(Result, FProfile.addCalledTargetSamples(
LineOffset, Discriminator,
- ProfileFuncName(name_count.first),
+ ProfileFuncRef(name_count.first),
name_count.second));
}
MergeResult(Result, FProfile.addBodySamples(LineOffset, Discriminator,
@@ -524,7 +524,7 @@ inline ErrorOr<size_t> SampleProfileReaderBinary::readStringIndex(T &Table) {
return *Idx;
}
-ErrorOr<ProfileFuncName>
+ErrorOr<ProfileFuncRef>
SampleProfileReaderBinary::readStringFromTable(size_t *RetIdx) {
auto Idx = readStringIndex(NameTable);
if (std::error_code EC = Idx.getError())
@@ -532,13 +532,13 @@ SampleProfileReaderBinary::readStringFromTable(size_t *RetIdx) {
// If using fixed length MD5, just read directly from the pointer to the name
// table.
- ProfileFuncName &SR = NameTable[*Idx];
+ ProfileFuncRef &SR = NameTable[*Idx];
if (SR.empty()) {
assert(MD5NameMemStart);
using namespace support;
uint64_t FID = endian::read<uint64_t, little, unaligned>(
MD5NameMemStart + (*Idx) * sizeof(uint64_t));
- SR = ProfileFuncName(FID);
+ SR = ProfileFuncRef(FID);
}
if (RetIdx)
*RetIdx = *Idx;
@@ -1090,12 +1090,12 @@ std::error_code SampleProfileReaderBinary::readNameTable() {
if (std::error_code EC = Name.getError())
return EC;
if (UseMD5) {
- ProfileFuncName FID(*Name);
+ ProfileFuncRef FID(*Name);
if (!ProfileIsCS)
MD5SampleContextTable.emplace_back(FID.getHashCode());
NameTable.emplace_back(FID);
} else
- NameTable.push_back(ProfileFuncName(*Name));
+ NameTable.push_back(ProfileFuncRef(*Name));
}
if (!ProfileIsCS)
MD5SampleContextStart = MD5SampleContextTable.data();
@@ -1147,7 +1147,7 @@ SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5,
return EC;
if (!ProfileIsCS)
support::endian::write64le(&MD5SampleContextTable[I], *FID);
- NameTable.emplace_back(ProfileFuncName(*FID));
+ NameTable.emplace_back(ProfileFuncRef(*FID));
}
if (!ProfileIsCS)
MD5SampleContextStart = MD5SampleContextTable.data();
@@ -1659,7 +1659,7 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
// body, there will be identical replicated profiles for the
// original function. In this case, we simply not bother updating
// the profile of the original function.
- FProfile = &Profiles[ProfileFuncName(Name)];
+ FProfile = &Profiles[ProfileFuncRef(Name)];
FProfile->addHeadSamples(HeadCount);
if (FProfile->getTotalSamples() > 0)
Update = false;
@@ -1671,9 +1671,9 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
uint32_t LineOffset = Offset >> 16;
uint32_t Discriminator = Offset & 0xffff;
FProfile = &CallerProfile->functionSamplesAt(
- LineLocation(LineOffset, Discriminator))[ProfileFuncName(Name)];
+ LineLocation(LineOffset, Discriminator))[ProfileFuncRef(Name)];
}
- FProfile->setName(ProfileFuncName(Name));
+ FProfile->setName(ProfileFuncRef(Name));
for (uint32_t I = 0; I < NumPosCounts; ++I) {
uint32_t Offset;
@@ -1729,7 +1729,7 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
if (Update)
FProfile->addCalledTargetSamples(LineOffset, Discriminator,
- ProfileFuncName(TargetName),
+ ProfileFuncRef(TargetName),
TargetCount);
}
}
@@ -1791,7 +1791,7 @@ void SampleProfileReaderItaniumRemapper::applyRemapping(LLVMContext &Ctx) {
// We will need to remap the entire context string.
assert(Remappings && "should be initialized while creating remapper");
for (auto &Sample : Reader.getProfiles()) {
- DenseSet<ProfileFuncName> NamesInSample;
+ DenseSet<ProfileFuncRef> NamesInSample;
Sample.second.findAllNames(NamesInSample);
for (auto &Name : NamesInSample) {
StringRef NameStr = reinterpret_cast<StringRef &>(Name);
diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp
index ccfde3907780eba..1d5c811331cc9bf 100644
--- a/llvm/lib/ProfileData/SampleProfWriter.cpp
+++ b/llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -348,7 +348,7 @@ std::error_code SampleProfileWriterExtBinaryBase::writeNameTable() {
return SampleProfileWriterBinary::writeNameTable();
auto &OS = *OutputStream;
- std::set<ProfileFuncName> V;
+ std::set<ProfileFuncRef> V;
stablizeNameTable(NameTable, V);
// Write out the MD5 name table. We wrote unencoded MD5 so reader can
@@ -636,7 +636,7 @@ SampleProfileWriterBinary::writeContextIdx(const SampleContext &Context) {
return writeNameIdx(Context.getName());
}
-std::error_code SampleProfileWriterBinary::writeNameIdx(ProfileFuncName FName) {
+std::error_code SampleProfileWriterBinary::writeNameIdx(ProfileFuncRef FName) {
auto &NTable = getNameTable();
const auto &Ret = NTable.find(FName);
if (Ret == NTable.end())
@@ -645,7 +645,7 @@ std::error_code SampleProfileWriterBinary::writeNameIdx(ProfileFuncName FName) {
return sampleprof_error::success;
}
-void SampleProfileWriterBinary::addName(ProfileFuncName FName) {
+void SampleProfileWriterBinary::addName(ProfileFuncRef FName) {
auto &NTable = getNameTable();
NTable.insert(std::make_pair(FName, 0));
}
@@ -683,18 +683,18 @@ void SampleProfileWriterExtBinaryBase::addContext(
}
void SampleProfileWriterBinary::stablizeNameTable(
- MapVector<ProfileFuncName, uint32_t> &NameTable, std::set<ProfileFuncName> &V) {
+ MapVector<ProfileFuncRef, uint32_t> &NameTable, std::set<ProfileFuncRef> &V) {
// Sort the names to make NameTable deterministic.
for (const auto &I : NameTable)
V.insert(I.first);
int i = 0;
- for (const ProfileFuncName &N : V)
+ for (const ProfileFuncRef &N : V)
NameTable[N] = i++;
}
std::error_code SampleProfileWriterBinary::writeNameTable() {
auto &OS = *OutputStream;
- std::set<ProfileFuncName> V;
+ std::set<ProfileFuncRef> V;
stablizeNameTable(NameTable, V);
// Write out the name table.
diff --git a/llvm/lib/Transforms/IPO/SampleContextTracker.cpp b/llvm/lib/Transforms/IPO/SampleContextTracker.cpp
index bbd649ad3899cd5..7bc692e4332fe0f 100644
--- a/llvm/lib/Transforms/IPO/SampleContextTracker.cpp
+++ b/llvm/lib/Transforms/IPO/SampleContextTracker.cpp
@@ -29,7 +29,7 @@ using namespace sampleprof;
namespace llvm {
ContextTrieNode *ContextTrieNode::getChildContext(const LineLocation &CallSite,
- ProfileFuncName CalleeName) {
+ ProfileFuncRef CalleeName) {
if (CalleeName.empty())
return getHottestChildContext(CallSite);
@@ -104,7 +104,7 @@ SampleContextTracker::moveContextSamples(ContextTrieNode &ToNodeParent,
}
void ContextTrieNode::removeChildContext(const LineLocation &CallSite,
- ProfileFuncName CalleeName) {
+ ProfileFuncRef CalleeName) {
uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
// Note this essentially calls dtor and destroys that child context
AllChildContext.erase(Hash);
@@ -114,7 +114,7 @@ std::map<uint64_t, ContextTrieNode> &ContextTrieNode::getAllChildContext() {
return AllChildContext;
}
-ProfileFuncName ContextTrieNode::getFuncName() const { return FuncName; }
+ProfileFuncRef ContextTrieNode::getFuncName() const { return FuncName; }
FunctionSamples *ContextTrieNode::getFunctionSamples() const {
return FuncSamples;
@@ -178,7 +178,7 @@ void ContextTrieNode::dumpTree() {
}
ContextTrieNode *ContextTrieNode::getOrCreateChildContext(
- const LineLocation &CallSite, ProfileFuncName CalleeName, bool AllowCreate) {
+ const LineLocation &CallSite, ProfileFuncRef CalleeName, bool AllowCreate) {
uint64_t Hash = FunctionSamples::getCallSiteHash(CalleeName, CallSite);
auto It = AllChildContext.find(Hash);
if (It != AllChildContext.end()) {
@@ -233,7 +233,7 @@ SampleContextTracker::getCalleeContextSamplesFor(const CallBase &Inst,
CalleeName = FunctionSamples::getCanonicalFnName(CalleeName);
- ProfileFuncName FName = getRepInFormat(CalleeName);
+ ProfileFuncRef FName = getRepInFormat(CalleeName);
// For indirect call, CalleeName will be empty, in which case the context
// profile for callee with largest total samples will be returned.
@@ -317,7 +317,7 @@ FunctionSamples *SampleContextTracker::getBaseSamplesFor(const Function &Func,
return getBaseSamplesFor(getRepInFormat(CanonName), MergeContext);
}
-FunctionSamples *SampleContextTracker::getBaseSamplesFor(ProfileFuncName Name,
+FunctionSamples *SampleContextTracker::getBaseSamplesFor(ProfileFuncRef Name,
bool MergeContext) {
LLVM_DEBUG(dbgs() << "Getting base profile for function: " << Name << "\n");
@@ -367,7 +367,7 @@ void SampleContextTracker::markContextSamplesInlined(
ContextTrieNode &SampleContextTracker::getRootContext() { return RootContext; }
void SampleContextTracker::promoteMergeContextSamplesTree(
- const Instruction &Inst, ProfileFuncName CalleeName) {
+ const Instruction &Inst, ProfileFuncRef CalleeName) {
LLVM_DEBUG(dbgs() << "Promoting and merging context tree for instr: \n"
<< Inst << "\n");
// Get the caller context for the call instruction, we don't use callee
@@ -465,7 +465,7 @@ SampleContextTracker::getContextFor(const SampleContext &Context) {
ContextTrieNode *
SampleContextTracker::getCalleeContextFor(const DILocation *DIL,
- ProfileFuncName CalleeName) {
+ ProfileFuncRef CalleeName) {
assert(DIL && "Expect non-null location");
ContextTrieNode *CallContext = getContextFor(DIL);
@@ -480,7 +480,7 @@ SampleContextTracker::getCalleeContextFor(const DILocation *DIL,
ContextTrieNode *SampleContextTracker::getContextFor(const DILocation *DIL) {
assert(DIL && "Expect non-null location");
- SmallVector<std::pair<LineLocation, ProfileFuncName>, 10> S;
+ SmallVector<std::pair<LineLocation, ProfileFuncRef>, 10> S;
// Use C++ linkage name if possible.
const DILocation *PrevDIL = DIL;
@@ -506,7 +506,7 @@ ContextTrieNode *SampleContextTracker::getContextFor(const DILocation *DIL) {
int I = S.size();
while (--I >= 0 && ContextNode) {
LineLocation &CallSite = S[I].first;
- ProfileFuncName CalleeName = S[I].second;
+ ProfileFuncRef CalleeName = S[I].second;
ContextNode = ContextNode->getChildContext(CallSite, CalleeName);
}
@@ -540,13 +540,13 @@ SampleContextTracker::getOrCreateContextPath(const SampleContext &Context,
}
ContextTrieNode *
-SampleContextTracker::getTopLevelContextNode(ProfileFuncName FName) {
+SampleContextTracker::getTopLevelContextNode(ProfileFuncRef FName) {
assert(!FName.empty() && "Top level node query must provide valid name");
return RootContext.getChildContext(LineLocation(0, 0), FName);
}
ContextTrieNode &
-SampleContextTracker::addTopLevelContextNode(ProfileFuncName FName) {
+SampleContextTracker::addTopLevelContextNode(ProfileFuncRef FName) {
assert(!getTopLevelContextNode(FName) && "Node to add must not exist");
return *RootContext.getOrCreateChildContext(LineLocation(0, 0), FName);
}
diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp
index a79525d71eee02f..bfde52074f9c35a 100644
--- a/llvm/lib/Transforms/IPO/SampleProfile.cpp
+++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp
@@ -472,7 +472,7 @@ class SampleProfileMatcher {
private:
FunctionSamples *getFlattenedSamplesFor(const Function &F) {
StringRef CanonFName = FunctionSamples::getCanonicalFnName(F);
- auto It = FlattenedProfiles.find(ProfileFuncName(CanonFName));
+ auto It = FlattenedProfiles.find(ProfileFuncRef(CanonFName));
if (It != FlattenedProfiles.end())
return &It->second;
return nullptr;
@@ -492,9 +492,9 @@ class SampleProfileMatcher {
void distributeIRToProfileLocationMap();
void distributeIRToProfileLocationMap(FunctionSamples &FS);
void populateProfileCallsites(const FunctionSamples &FS,
- std::unordered_map<ProfileFuncName, std::set<LineLocation> > &CalleeToCallsitesMap);
- void runStaleProfileMatching(const std::map<LineLocation, ProfileFuncName> &IRLocations,
- std::unordered_map<ProfileFuncName, std::set<LineLocation> > &CalleeToCallsitesMap,
+ std::unordered_map<ProfileFuncRef, std::set<LineLocation> > &CalleeToCallsitesMap);
+ void runStaleProfileMatching(const std::map<LineLocation, ProfileFuncRef> &IRLocations,
+ std::unordered_map<ProfileFuncRef, std::set<LineLocation> > &CalleeToCallsitesMap,
LocToLocMap &IRToProfileLocationMap);
};
@@ -612,7 +612,7 @@ class SampleProfileLoader final : public SampleProfileLoaderBaseImpl<Function> {
// All the Names used in FunctionSamples including outline function
// names, inline instance names and call target names.
- std::unordered_set<ProfileFuncName> NamesInProfile;
+ std::unordered_set<ProfileFuncRef> NamesInProfile;
// For symbol in profile symbol list, whether to regard their profiles
// to be accurate. It is mainly decided by existance of profile symbol
@@ -2158,7 +2158,7 @@ void SampleProfileMatcher::countProfileMismatches(
// Populate the anchors(direct callee name) from profile.
void SampleProfileMatcher::populateProfileCallsites(
const FunctionSamples &FS,
- std::unordered_map<ProfileFuncName, std::set<LineLocation>>
+ std::unordered_map<ProfileFuncRef, std::set<LineLocation>>
&CalleeToCallsitesMap) {
for (const auto &I : FS.getBodySamples()) {
const auto &Loc = I.first;
@@ -2203,8 +2203,8 @@ void SampleProfileMatcher::populateProfileCallsites(
// [1, 2, 3(foo), 4, 7, 8(bar), 9]
// The output mapping: [2->3, 3->4, 5->7, 6->8, 7->9].
void SampleProfileMatcher::runStaleProfileMatching(
- const std::map<LineLocation, ProfileFuncName> &IRLocations,
- std::unordered_map<ProfileFuncName, std::set<LineLocation>>
+ const std::map<LineLocation, ProfileFuncRef> &IRLocations,
+ std::unordered_map<ProfileFuncRef, std::set<LineLocation>>
&CalleeToCallsitesMap,
LocToLocMap &IRToProfileLocationMap) {
assert(IRToProfileLocationMap.empty() &&
@@ -2286,7 +2286,7 @@ void SampleProfileMatcher::runOnFunction(const Function &F,
std::unordered_set<LineLocation, LineLocationHash> MatchedCallsiteLocs;
// The value of the map is the name of direct callsite and use empty StringRef
// for non-direct-call site.
- std::map<LineLocation, ProfileFuncName> IRLocations;
+ std::map<LineLocation, ProfileFuncRef> IRLocations;
// Extract profile matching anchors and profile mismatch metrics in the IR.
for (auto &BB : F) {
@@ -2294,7 +2294,7 @@ void SampleProfileMatcher::runOnFunction(const Function &F,
// TODO: Support line-number based location(AutoFDO).
if (FunctionSamples::ProfileIsProbeBased && isa<PseudoProbeInst>(&I)) {
if (std::optional<PseudoProbe> Probe = extractProbe(I))
- IRLocations.emplace(LineLocation(Probe->Id, 0), ProfileFuncName());
+ IRLocations.emplace(LineLocation(Probe->Id, 0), ProfileFuncRef());
}
if (!isa<CallBase>(&I) || isa<IntrinsicInst>(&I))
@@ -2304,9 +2304,9 @@ void SampleProfileMatcher::runOnFunction(const Function &F,
if (auto &DLoc = I.getDebugLoc()) {
LineLocation IRCallsite = FunctionSamples::getCallSiteIdentifier(DLoc);
- ProfileFuncName CalleeName;
+ ProfileFuncRef CalleeName;
if (Function *Callee = CB->getCalledFunction())
- CalleeName = ProfileFuncName(
+ CalleeName = ProfileFuncRef(
FunctionSamples::getCanonicalFnName(Callee->getName()));
// Force to overwrite the callee name in case any non-call location was
@@ -2362,7 +2362,7 @@ void SampleProfileMatcher::runOnFunction(const Function &F,
LLVM_DEBUG(dbgs() << "Run stale profile matching for " << F.getName()
<< "\n");
- std::unordered_map<ProfileFuncName, std::set<LineLocation>> CalleeToCallsitesMap;
+ std::unordered_map<ProfileFuncRef, std::set<LineLocation>> CalleeToCallsitesMap;
populateProfileCallsites(FS, CalleeToCallsitesMap);
// The matching result will be saved to IRToProfileLocationMap, create a new
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index beb6afc4ab00ac7..1a0d90ee8b56172 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -200,10 +200,10 @@ class SymbolRemapper {
return New.empty() ? Name : New;
}
- ProfileFuncName operator()(ProfileFuncName Name) {
+ ProfileFuncRef operator()(ProfileFuncRef Name) {
std::string Buffer;
StringRef New = RemappingTable.lookup(Name.stringRef(Buffer));
- return New.empty() ? Name : ProfileFuncName(New);
+ return New.empty() ? Name : ProfileFuncRef(New);
}
};
}
diff --git a/llvm/tools/llvm-profgen/CSPreInliner.cpp b/llvm/tools/llvm-profgen/CSPreInliner.cpp
index 51e9782242ddde3..84322ae555f6beb 100644
--- a/llvm/tools/llvm-profgen/CSPreInliner.cpp
+++ b/llvm/tools/llvm-profgen/CSPreInliner.cpp
@@ -80,8 +80,8 @@ CSPreInliner::CSPreInliner(SampleContextTracker &Tracker,
ProfileInlineLimitMax = 50000;
}
-std::vector<ProfileFuncName> CSPreInliner::buildTopDownOrder() {
- std::vector<ProfileFuncName> Order;
+std::vector<ProfileFuncRef> CSPreInliner::buildTopDownOrder() {
+ std::vector<ProfileFuncRef> Order;
// Trim cold edges to get a more stable call graph. This allows for a more
// stable top-down order which in turns helps the stablity of the generated
// profile from run to run.
@@ -202,7 +202,7 @@ bool CSPreInliner::shouldInline(ProfiledInlineCandidate &Candidate) {
return (Candidate.SizeCost < SampleThreshold);
}
-void CSPreInliner::processFunction(const ProfileFuncName Name) {
+void CSPreInliner::processFunction(const ProfileFuncRef Name) {
FunctionSamples *FSamples = ContextTracker.getBaseSamplesFor(Name);
if (!FSamples)
return;
@@ -303,7 +303,7 @@ void CSPreInliner::run() {
// It also helps better compress context profile to control profile
// size, as we now only need context profile for functions going to
// be inlined.
- for (ProfileFuncName FuncName : buildTopDownOrder()) {
+ for (ProfileFuncRef FuncName : buildTopDownOrder()) {
processFunction(FuncName);
}
diff --git a/llvm/tools/llvm-profgen/CSPreInliner.h b/llvm/tools/llvm-profgen/CSPreInliner.h
index c6b4d77a737399e..85e297cddfe8544 100644
--- a/llvm/tools/llvm-profgen/CSPreInliner.h
+++ b/llvm/tools/llvm-profgen/CSPreInliner.h
@@ -80,8 +80,8 @@ class CSPreInliner {
private:
bool getInlineCandidates(ProfiledCandidateQueue &CQueue,
const FunctionSamples *FCallerContextSamples);
- std::vector<ProfileFuncName> buildTopDownOrder();
- void processFunction(ProfileFuncName Name);
+ std::vector<ProfileFuncRef> buildTopDownOrder();
+ void processFunction(ProfileFuncRef Name);
bool shouldInline(ProfiledInlineCandidate &Candidate);
uint32_t getFuncSize(const ContextTrieNode *ContextNode);
bool UseContextCost;
diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp
index e71683ccb0f3bce..f5f2bc0d800e83a 100644
--- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp
+++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp
@@ -586,7 +586,7 @@ void ProfileGenerator::populateBoundarySamplesWithProbesForAllFunctions(
FunctionProfile.addCalledTargetSamples(
FrameVec.back().Location.LineOffset,
FrameVec.back().Location.Discriminator,
- ProfileFuncName(CalleeName), Count);
+ ProfileFuncRef(CalleeName), Count);
}
}
}
@@ -717,7 +717,7 @@ void ProfileGenerator::populateBoundarySamplesForAllFunctions(
FunctionProfile.addCalledTargetSamples(
FrameVec.back().Location.LineOffset,
getBaseDiscriminator(FrameVec.back().Location.Discriminator),
- ProfileFuncName(CalleeName), Count);
+ ProfileFuncRef(CalleeName), Count);
}
// Add head samples for callee.
FunctionSamples &CalleeProfile = getTopLevelFunctionProfile(CalleeName);
@@ -901,7 +901,7 @@ void CSProfileGenerator::populateBoundarySamplesForFunction(
CallerNode->getFunctionSamples()->addCalledTargetSamples(
LeafLoc->Location.LineOffset,
getBaseDiscriminator(LeafLoc->Location.Discriminator),
- ProfileFuncName(CalleeName),
+ ProfileFuncRef(CalleeName),
Count);
// Record head sample for called target(callee)
CalleeCallSite = LeafLoc->Location;
@@ -910,7 +910,7 @@ void CSProfileGenerator::populateBoundarySamplesForFunction(
ContextTrieNode *CalleeNode =
CallerNode->getOrCreateChildContext(CalleeCallSite,
- ProfileFuncName(CalleeName));
+ ProfileFuncRef(CalleeName));
FunctionSamples *CalleeProfile = getOrCreateFunctionSamples(CalleeNode);
CalleeProfile->addHeadSamples(Count);
}
@@ -1215,7 +1215,7 @@ void CSProfileGenerator::populateBoundarySamplesWithProbes(
continue;
FunctionProfile.addCalledTargetSamples(CallProbe->getIndex(),
CallProbe->getDiscriminator(),
- ProfileFuncName(CalleeName), Count);
+ ProfileFuncRef(CalleeName), Count);
}
}
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index 32d4f5cff37252f..44a2cc8d1a05f7a 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -77,7 +77,7 @@ void BinarySizeContextTracker::addInstructionForContext(
ContextTrieNode *CurNode = &RootContext;
bool IsLeaf = true;
for (const auto &Callsite : reverse(Context)) {
- ProfileFuncName CallerName = Callsite.FuncName;
+ ProfileFuncRef CallerName = Callsite.FuncName;
LineLocation CallsiteLoc = IsLeaf ? LineLocation(0, 0) : Callsite.Location;
CurNode = CurNode->getOrCreateChildContext(CallsiteLoc, CallerName);
IsLeaf = false;
@@ -146,7 +146,7 @@ void BinarySizeContextTracker::trackInlineesOptimizedAway(
LineLocation CallsiteLoc(ProbeFrame.second, 0);
SizeContext =
SizeContext->getOrCreateChildContext(CallsiteLoc,
- ProfileFuncName(CallerName));
+ ProfileFuncRef(CallerName));
}
// Add 0 size to make known.
SizeContext->addFunctionSize(0);
@@ -891,7 +891,7 @@ SampleContextFrameVector ProfiledBinary::symbolize(const InstructionPointer &IP,
LineLocation Line(LineOffset, Discriminator);
auto It = NameStrings.insert(FunctionName.str());
- CallStack.emplace_back(ProfileFuncName(*It.first), Line);
+ CallStack.emplace_back(ProfileFuncRef(*It.first), Line);
}
return CallStack;
diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h
index c5f3b7d7fe7a01f..298ec2781b38727 100644
--- a/llvm/tools/llvm-profgen/ProfiledBinary.h
+++ b/llvm/tools/llvm-profgen/ProfiledBinary.h
@@ -481,7 +481,7 @@ class ProfiledBinary {
ProfiledFunctions = Funcs;
}
- BinaryFunction *getBinaryFunction(ProfileFuncName FName) {
+ BinaryFunction *getBinaryFunction(ProfileFuncRef FName) {
if (FName.isStringRef()) {
auto I = BinaryFunctions.find(FName.str());
if (I == BinaryFunctions.end())
@@ -566,7 +566,7 @@ class ProfiledBinary {
InlineContextStack.clear();
continue;
}
- InlineContextStack.emplace_back(ProfileFuncName(Callsite.first),
+ InlineContextStack.emplace_back(ProfileFuncRef(Callsite.first),
LineLocation(Callsite.second, 0));
}
}
diff --git a/llvm/unittests/ProfileData/SampleProfTest.cpp b/llvm/unittests/ProfileData/SampleProfTest.cpp
index 90d62cbcc93648a..a13869d901bc2eb 100644
--- a/llvm/unittests/ProfileData/SampleProfTest.cpp
+++ b/llvm/unittests/ProfileData/SampleProfTest.cpp
@@ -145,7 +145,7 @@ struct SampleProfTest : ::testing::Test {
StringRef FooName("_Z3fooi");
FunctionSamples FooSamples;
- FooSamples.setName(ProfileFuncName(FooName));
+ FooSamples.setName(ProfileFuncRef(FooName));
FooSamples.addTotalSamples(7711);
FooSamples.addHeadSamples(610);
FooSamples.addBodySamples(1, 0, 610);
@@ -155,7 +155,7 @@ struct SampleProfTest : ::testing::Test {
FooSamples.addBodySamples(10, 0, 605);
// Add inline instance with name "_Z3gooi".
- ProfileFuncName GooName(StringRef("_Z3gooi"));
+ ProfileFuncRef GooName(StringRef("_Z3gooi"));
auto &GooSamples =
FooSamples.functionSamplesAt(LineLocation(7, 0))[GooName];
GooSamples.setName(GooName);
@@ -163,7 +163,7 @@ struct SampleProfTest : ::testing::Test {
GooSamples.addBodySamples(3, 0, 502);
// Add inline instance with name "_Z3hooi".
- ProfileFuncName HooName(StringRef("_Z3hooi"));
+ ProfileFuncRef HooName(StringRef("_Z3hooi"));
auto &HooSamples =
GooSamples.functionSamplesAt(LineLocation(9, 0))[HooName];
HooSamples.setName(HooName);
@@ -172,26 +172,26 @@ struct SampleProfTest : ::testing::Test {
StringRef BarName("_Z3bari");
FunctionSamples BarSamples;
- BarSamples.setName(ProfileFuncName(BarName));
+ BarSamples.setName(ProfileFuncRef(BarName));
BarSamples.addTotalSamples(20301);
BarSamples.addHeadSamples(1437);
BarSamples.addBodySamples(1, 0, 1437);
// Test how reader/writer handles unmangled names.
StringRef MconstructName("_M_construct<char *>");
StringRef StringviewName("string_view<std::allocator<char> >");
- BarSamples.addCalledTargetSamples(1, 0, ProfileFuncName(MconstructName), 1000);
- BarSamples.addCalledTargetSamples(1, 0, ProfileFuncName(StringviewName), 437);
+ BarSamples.addCalledTargetSamples(1, 0, ProfileFuncRef(MconstructName), 1000);
+ BarSamples.addCalledTargetSamples(1, 0, ProfileFuncRef(StringviewName), 437);
StringRef BazName("_Z3bazi");
FunctionSamples BazSamples;
- BazSamples.setName(ProfileFuncName(BazName));
+ BazSamples.setName(ProfileFuncRef(BazName));
BazSamples.addTotalSamples(12557);
BazSamples.addHeadSamples(1257);
BazSamples.addBodySamples(1, 0, 12557);
StringRef BooName("_Z3booi");
FunctionSamples BooSamples;
- BooSamples.setName(ProfileFuncName(BooName));
+ BooSamples.setName(ProfileFuncRef(BooName));
BooSamples.addTotalSamples(1232);
BooSamples.addHeadSamples(1);
BooSamples.addBodySamples(1, 0, 1232);
@@ -210,8 +210,8 @@ struct SampleProfTest : ::testing::Test {
if (Remap) {
FooName = "_Z4fauxi";
BarName = "_Z3barl";
- GooName = ProfileFuncName(StringRef("_Z3gool"));
- HooName = ProfileFuncName(StringRef("_Z3hool"));
+ GooName = ProfileFuncRef(StringRef("_Z3gool"));
+ HooName = ProfileFuncRef(StringRef("_Z3hool"));
}
M.getOrInsertFunction(FooName, fn_type);
@@ -306,8 +306,8 @@ struct SampleProfTest : ::testing::Test {
ASSERT_TRUE(ReadBooSamples != nullptr);
ASSERT_EQ(1232u, ReadBooSamples->getTotalSamples());
- ProfileFuncName MconstructRep = getRepInFormat(MconstructName, UseMD5);
- ProfileFuncName StringviewRep = getRepInFormat(StringviewName, UseMD5);
+ ProfileFuncRef MconstructRep = getRepInFormat(MconstructName, UseMD5);
+ ProfileFuncRef StringviewRep = getRepInFormat(StringviewName, UseMD5);
ASSERT_EQ(1000u, CTMap.get()[MconstructRep]);
ASSERT_EQ(437u, CTMap.get()[StringviewRep]);
@@ -330,7 +330,7 @@ struct SampleProfTest : ::testing::Test {
uint64_t TotalSamples, uint64_t HeadSamples) {
StringRef Name(Fname);
FunctionSamples FcnSamples;
- FcnSamples.setName(ProfileFuncName(Name));
+ FcnSamples.setName(ProfileFuncRef(Name));
FcnSamples.addTotalSamples(TotalSamples);
FcnSamples.addHeadSamples(HeadSamples);
FcnSamples.addBodySamples(1, 0, HeadSamples);
More information about the llvm-commits
mailing list