aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWei Mi <wmi@google.com>2018-03-07 16:45:33 +0000
committerWei Mi <wmi@google.com>2018-03-07 16:45:33 +0000
commitf53ccf3b4f76182e37675356b3b40a7c4e31598a (patch)
tree4d4862d78e1740f5c46cedd6c858f6bca58dfbc8
parenta446275ee2e1fef3fd2828ab458595d3e98aa726 (diff)
[SampleFDO] Extend SampleProfReader to handle demangled names.
SampleProfReader assumes function names in the profile are all mangled names. However, there are cases that few demangled names are somehow contained in the profile (usually because of debug info problems), which may trigger parsing error in SampleProfReader and cause the whole profile to be unusable. The patch extends SampleProfReader to handle profiles with demangled names, so that those profiles can still be useful. Differential revision: https://reviews.llvm.org/D44161 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@326905 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/ProfileData/SampleProfReader.cpp51
-rw-r--r--unittests/ProfileData/SampleProfTest.cpp8
2 files changed, 50 insertions, 9 deletions
diff --git a/lib/ProfileData/SampleProfReader.cpp b/lib/ProfileData/SampleProfReader.cpp
index 44547e3dffa..8048076a537 100644
--- a/lib/ProfileData/SampleProfReader.cpp
+++ b/lib/ProfileData/SampleProfReader.cpp
@@ -127,19 +127,52 @@ static bool ParseLine(const StringRef &Input, bool &IsCallsite, uint32_t &Depth,
if (Rest.substr(0, n3).getAsInteger(10, NumSamples))
return false;
}
+ // Find call targets and their sample counts.
+ // Note: In some cases, there are symbols in the profile which are not
+ // mangled. To accommodate such cases, use colon + integer pairs as the
+ // anchor points.
+ // An example:
+ // _M_construct<char *>:1000 string_view<std::allocator<char> >:437
+ // ":1000" and ":437" are used as anchor points so the string above will
+ // be interpreted as
+ // target: _M_construct<char *>
+ // count: 1000
+ // target: string_view<std::allocator<char> >
+ // count: 437
while (n3 != StringRef::npos) {
n3 += Rest.substr(n3).find_first_not_of(' ');
Rest = Rest.substr(n3);
- n3 = Rest.find(' ');
- StringRef pair = Rest;
- if (n3 != StringRef::npos) {
- pair = Rest.substr(0, n3);
- }
- size_t n4 = pair.find(':');
- uint64_t count;
- if (pair.substr(n4 + 1).getAsInteger(10, count))
+ n3 = Rest.find_first_of(':');
+ if (n3 == StringRef::npos || n3 == 0)
return false;
- TargetCountMap[pair.substr(0, n4)] = count;
+
+ StringRef Target;
+ uint64_t count, n4;
+ while (true) {
+ // Get the segment after the current colon.
+ StringRef AfterColon = Rest.substr(n3 + 1);
+ // Get the target symbol before the current colon.
+ Target = Rest.substr(0, n3);
+ // Check if the word after the current colon is an integer.
+ n4 = AfterColon.find_first_of(' ');
+ n4 = (n4 != StringRef::npos) ? n3 + n4 + 1 : Rest.size();
+ StringRef WordAfterColon = Rest.substr(n3 + 1, n4 - n3 - 1);
+ if (!WordAfterColon.getAsInteger(10, count))
+ break;
+
+ // Try to find the next colon.
+ uint64_t n5 = AfterColon.find_first_of(':');
+ if (n5 == StringRef::npos)
+ return false;
+ n3 += n5 + 1;
+ }
+
+ // An anchor point is found. Save the {target, count} pair
+ TargetCountMap[Target] = count;
+ if (n4 == Rest.size())
+ break;
+ // Change n3 to the next blank space after colon + integer pair.
+ n3 = n4;
}
} else {
IsCallsite = true;
diff --git a/unittests/ProfileData/SampleProfTest.cpp b/unittests/ProfileData/SampleProfTest.cpp
index 764bded2f03..412f36f5c9c 100644
--- a/unittests/ProfileData/SampleProfTest.cpp
+++ b/unittests/ProfileData/SampleProfTest.cpp
@@ -77,6 +77,9 @@ struct SampleProfTest : ::testing::Test {
BarSamples.addTotalSamples(20301);
BarSamples.addHeadSamples(1437);
BarSamples.addBodySamples(1, 0, 1437);
+ BarSamples.addCalledTargetSamples(1, 0, "_M_construct<char *>", 1000);
+ BarSamples.addCalledTargetSamples(
+ 1, 0, "string_view<std::allocator<char> >", 437);
StringMap<FunctionSamples> Profiles;
Profiles[FooName] = std::move(FooSamples);
@@ -104,6 +107,11 @@ struct SampleProfTest : ::testing::Test {
FunctionSamples &ReadBarSamples = ReadProfiles[BarName];
ASSERT_EQ(20301u, ReadBarSamples.getTotalSamples());
ASSERT_EQ(1437u, ReadBarSamples.getHeadSamples());
+ ErrorOr<SampleRecord::CallTargetMap> CTMap =
+ ReadBarSamples.findCallTargetMapAt(1, 0);
+ ASSERT_FALSE(CTMap.getError());
+ ASSERT_EQ(1000u, CTMap.get()["_M_construct<char *>"]);
+ ASSERT_EQ(437u, CTMap.get()["string_view<std::allocator<char> >"]);
auto VerifySummary = [](ProfileSummary &Summary) mutable {
ASSERT_EQ(ProfileSummary::PSK_Sample, Summary.getKind());