llvm.org GIT mirror llvm / 1c2b998
[llvm-profdata] Change instr prof counter overflow to saturate rather than discard Summary: This changes overflow handling during instrumentation profile merge. Rathar than throwing away records that would result in counter overflow, merged counts are instead clamped to the maximum representable value. A warning about counter overflow is still surfaced to the user as before. Reviewers: dnovillo, davidxl, silvas Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D14893 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254525 91177308-0d34-0410-b5e6-96231b3b80d8 Nathan Slingerland 3 years ago
4 changed file(s) with 34 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
427427 if (Counts.size() != Other.Counts.size())
428428 return instrprof_error::count_mismatch;
429429
430 instrprof_error Result = instrprof_error::success;
431
430432 for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
431 if (Counts[I] + Other.Counts[I] < Counts[I])
432 return instrprof_error::counter_overflow;
433 Counts[I] += Other.Counts[I];
433 bool ResultOverflowed;
434 Counts[I] = SaturatingAdd(Counts[I], Other.Counts[I], ResultOverflowed);
435 if (ResultOverflowed)
436 Result = instrprof_error::counter_overflow;
434437 }
435438
436439 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
437 instrprof_error result = mergeValueProfData(Kind, Other);
438 if (result != instrprof_error::success)
439 return result;
440 }
441
442 return instrprof_error::success;
440 instrprof_error MergeValueResult = mergeValueProfData(Kind, Other);
441 if (MergeValueResult != instrprof_error::success)
442 Result = MergeValueResult;
443 }
444
445 return Result;
443446 }
444447
445448 inline support::endianness getHostEndianness() {
106106 std::tie(Where, NewFunc) =
107107 ProfileDataMap.insert(std::make_pair(I.Hash, InstrProfRecord()));
108108 InstrProfRecord &Dest = Where->second;
109
110 instrprof_error Result;
109111 if (NewFunc) {
110112 // We've never seen a function with this name and hash, add it.
111113 Dest = std::move(I);
114 Result = instrprof_error::success;
112115 } else {
113116 // We're updating a function we've seen before.
114 instrprof_error MergeResult = Dest.merge(I);
115 if (MergeResult != instrprof_error::success) {
116 return MergeResult;
117 }
117 Result = Dest.merge(I);
118118 }
119119
120120 // We keep track of the max function count as we go for simplicity.
121 // Update this statistic no matter the result of the merge.
121122 if (Dest.Counts[0] > MaxFunctionCount)
122123 MaxFunctionCount = Dest.Counts[0];
123124
124 return instrprof_error::success;
125 return Result;
125126 }
126127
127128 std::pair InstrProfWriter::writeImpl(raw_ostream &OS) {
None # RUN: llvm-profdata merge %s -o %t.out 2>&1 | FileCheck %s
1 # CHECK: overflow.proftext: overflow: Counter overflow
0 # RUN: llvm-profdata merge %s -o %t.out 2>&1 | FileCheck %s --check-prefix=MERGE
1 # RUN: llvm-profdata show %t.out | FileCheck %s --check-prefix=SHOW
2 # MERGE: overflow.proftext: overflow: Counter overflow
3 # SHOW: Total functions: 1
4 # SHOW: Maximum function count: 18446744073709551615
5 # SHOW: Maximum internal block count: 18446744073709551615
26
37 overflow
48 1
5 1
9 3
10 18446744073709551615
611 9223372036854775808
12 18446744073709551615
713
814 overflow
915 1
10 1
16 3
1117 9223372036854775808
18 9223372036854775808
19 0
353353 const uint64_t Max = std::numeric_limits::max();
354354
355355 InstrProfRecord Record1("caller", 0x1234, {1});
356 InstrProfRecord Record2("caller", 0x1234, {1});
356 InstrProfRecord Record2("caller", 0x1234, {Max});
357357 InstrProfRecord Record3("callee1", 0x1235, {3, 4});
358358
359359 Record1.reserveSites(IPVK_IndirectCallTarget, 1);
374374 // Verify saturation of counts.
375375 ErrorOr R = Reader->getInstrProfRecord("caller", 0x1234);
376376 ASSERT_TRUE(NoError(R.getError()));
377
378 ASSERT_EQ(Max, R.get().Counts[0]);
379
377380 ASSERT_EQ(1U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
378381 std::unique_ptr VD =
379382 R.get().getValueForSite(IPVK_IndirectCallTarget, 0);