[llvm] r255825 - [PGO] Handle and report overflow during profile merge for all types of data
Nathan Slingerland via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 16 13:45:44 PST 2015
Author: slingn
Date: Wed Dec 16 15:45:43 2015
New Revision: 255825
URL: http://llvm.org/viewvc/llvm-project?rev=255825&view=rev
Log:
[PGO] Handle and report overflow during profile merge for all types of data
Summary: Surface counter overflow when merging profile data. Merging still occurs on overflow but counts saturate to the maximum representable value. Overflow is reported to the user.
Reviewers: davidxl, dnovillo, silvas
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D15547
Added:
llvm/trunk/test/tools/llvm-profdata/Inputs/overflow-instr.proftext
llvm/trunk/test/tools/llvm-profdata/Inputs/overflow-sample.proftext
llvm/trunk/test/tools/llvm-profdata/overflow-instr.test
llvm/trunk/test/tools/llvm-profdata/overflow-sample.test
Removed:
llvm/trunk/test/tools/llvm-profdata/overflow.proftext
Modified:
llvm/trunk/include/llvm/ProfileData/InstrProf.h
llvm/trunk/include/llvm/ProfileData/SampleProf.h
llvm/trunk/lib/ProfileData/SampleProf.cpp
llvm/trunk/lib/ProfileData/SampleProfReader.cpp
llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp
llvm/trunk/unittests/ProfileData/InstrProfTest.cpp
llvm/trunk/unittests/ProfileData/SampleProfTest.cpp
Modified: llvm/trunk/include/llvm/ProfileData/InstrProf.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProf.h?rev=255825&r1=255824&r2=255825&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/InstrProf.h (original)
+++ llvm/trunk/include/llvm/ProfileData/InstrProf.h Wed Dec 16 15:45:43 2015
@@ -184,6 +184,16 @@ inline std::error_code make_error_code(i
return std::error_code(static_cast<int>(E), instrprof_category());
}
+inline instrprof_error MergeResult(instrprof_error &Accumulator,
+ instrprof_error Result) {
+ // Prefer first error encountered as later errors may be secondary effects of
+ // the initial problem.
+ if (Accumulator == instrprof_error::success &&
+ Result != instrprof_error::success)
+ Accumulator = Result;
+ return Accumulator;
+}
+
enum InstrProfValueKind : uint32_t {
#define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value,
#include "llvm/ProfileData/InstrProfData.inc"
@@ -224,30 +234,34 @@ struct InstrProfValueSiteRecord {
/// Merge data from another InstrProfValueSiteRecord
/// Optionally scale merged counts by \p Weight.
- void mergeValueData(InstrProfValueSiteRecord &Input, uint64_t Weight = 1) {
+ instrprof_error mergeValueData(InstrProfValueSiteRecord &Input,
+ uint64_t Weight = 1) {
this->sortByTargetValues();
Input.sortByTargetValues();
auto I = ValueData.begin();
auto IE = ValueData.end();
+ instrprof_error Result = instrprof_error::success;
for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE;
++J) {
while (I != IE && I->Value < J->Value)
++I;
if (I != IE && I->Value == J->Value) {
- // FIXME: Improve handling of counter overflow.
uint64_t JCount = J->Count;
bool Overflowed;
if (Weight > 1) {
JCount = SaturatingMultiply(JCount, Weight, &Overflowed);
- assert(!Overflowed && "Value data counter overflowed!");
+ if (Overflowed)
+ Result = instrprof_error::counter_overflow;
}
I->Count = SaturatingAdd(I->Count, JCount, &Overflowed);
- assert(!Overflowed && "Value data counter overflowed!");
+ if (Overflowed)
+ Result = instrprof_error::counter_overflow;
++I;
continue;
}
ValueData.insert(I, *J);
}
+ return Result;
}
};
@@ -352,9 +366,11 @@ private:
getValueSitesForKind(ValueKind);
std::vector<InstrProfValueSiteRecord> &OtherSiteRecords =
Src.getValueSitesForKind(ValueKind);
+ instrprof_error Result = instrprof_error::success;
for (uint32_t I = 0; I < ThisNumValueSites; I++)
- ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I], Weight);
- return instrprof_error::success;
+ MergeResult(Result, ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I],
+ Weight));
+ return Result;
}
};
@@ -461,11 +477,8 @@ instrprof_error InstrProfRecord::merge(I
Result = instrprof_error::counter_overflow;
}
- for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
- instrprof_error MergeValueResult = mergeValueProfData(Kind, Other, Weight);
- if (MergeValueResult != instrprof_error::success)
- Result = MergeValueResult;
- }
+ for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
+ MergeResult(Result, mergeValueProfData(Kind, Other, Weight));
return Result;
}
@@ -480,7 +493,7 @@ inline support::endianness getHostEndian
#include "llvm/ProfileData/InstrProfData.inc"
/*
- * Initialize the record for runtime value profile data.
+ * Initialize the record for runtime value profile data.
* Return 0 if the initialization is successful, otherwise
* return 1.
*/
Modified: llvm/trunk/include/llvm/ProfileData/SampleProf.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/SampleProf.h?rev=255825&r1=255824&r2=255825&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/SampleProf.h (original)
+++ llvm/trunk/include/llvm/ProfileData/SampleProf.h Wed Dec 16 15:45:43 2015
@@ -38,13 +38,24 @@ enum class sampleprof_error {
unrecognized_format,
unsupported_writing_format,
truncated_name_table,
- not_implemented
+ not_implemented,
+ counter_overflow
};
inline std::error_code make_error_code(sampleprof_error E) {
return std::error_code(static_cast<int>(E), sampleprof_category());
}
+inline sampleprof_error MergeResult(sampleprof_error &Accumulator,
+ sampleprof_error Result) {
+ // Prefer first error encountered as later errors may be secondary effects of
+ // the initial problem.
+ if (Accumulator == sampleprof_error::success &&
+ Result != sampleprof_error::success)
+ Accumulator = Result;
+ return Accumulator;
+}
+
} // end namespace llvm
namespace std {
@@ -127,15 +138,18 @@ public:
///
/// Sample counts accumulate using saturating arithmetic, to avoid wrapping
/// around unsigned integers.
- void addSamples(uint64_t S, uint64_t Weight = 1) {
- // FIXME: Improve handling of counter overflow.
+ sampleprof_error addSamples(uint64_t S, uint64_t Weight = 1) {
bool Overflowed;
if (Weight > 1) {
S = SaturatingMultiply(S, Weight, &Overflowed);
- assert(!Overflowed && "Sample counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
}
NumSamples = SaturatingAdd(NumSamples, S, &Overflowed);
- assert(!Overflowed && "Sample counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
+
+ return sampleprof_error::success;
}
/// Add called function \p F with samples \p S.
@@ -143,16 +157,20 @@ public:
///
/// Sample counts accumulate using saturating arithmetic, to avoid wrapping
/// around unsigned integers.
- void addCalledTarget(StringRef F, uint64_t S, uint64_t Weight = 1) {
- // FIXME: Improve handling of counter overflow.
+ sampleprof_error addCalledTarget(StringRef F, uint64_t S,
+ uint64_t Weight = 1) {
uint64_t &TargetSamples = CallTargets[F];
bool Overflowed;
if (Weight > 1) {
S = SaturatingMultiply(S, Weight, &Overflowed);
- assert(!Overflowed && "Called target counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
}
TargetSamples = SaturatingAdd(TargetSamples, S, &Overflowed);
- assert(!Overflowed && "Called target counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
+
+ return sampleprof_error::success;
}
/// Return true if this sample record contains function calls.
@@ -163,10 +181,12 @@ public:
/// Merge the samples in \p Other into this record.
/// Optionally scale sample counts by \p Weight.
- void merge(const SampleRecord &Other, uint64_t Weight = 1) {
- addSamples(Other.getSamples(), Weight);
- for (const auto &I : Other.getCallTargets())
- addCalledTarget(I.first(), I.second, Weight);
+ sampleprof_error merge(const SampleRecord &Other, uint64_t Weight = 1) {
+ sampleprof_error Result = addSamples(Other.getSamples(), Weight);
+ for (const auto &I : Other.getCallTargets()) {
+ MergeResult(Result, addCalledTarget(I.first(), I.second, Weight));
+ }
+ return Result;
}
void print(raw_ostream &OS, unsigned Indent) const;
@@ -193,35 +213,42 @@ public:
FunctionSamples() : TotalSamples(0), TotalHeadSamples(0) {}
void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const;
void dump() const;
- void addTotalSamples(uint64_t Num, uint64_t Weight = 1) {
- // FIXME: Improve handling of counter overflow.
+ sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) {
bool Overflowed;
if (Weight > 1) {
Num = SaturatingMultiply(Num, Weight, &Overflowed);
- assert(!Overflowed && "Total samples counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
}
TotalSamples = SaturatingAdd(TotalSamples, Num, &Overflowed);
- assert(!Overflowed && "Total samples counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
+
+ return sampleprof_error::success;
}
- void addHeadSamples(uint64_t Num, uint64_t Weight = 1) {
- // FIXME: Improve handling of counter overflow.
+ sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight = 1) {
bool Overflowed;
if (Weight > 1) {
Num = SaturatingMultiply(Num, Weight, &Overflowed);
- assert(!Overflowed && "Total head samples counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
}
TotalHeadSamples = SaturatingAdd(TotalHeadSamples, Num, &Overflowed);
- assert(!Overflowed && "Total head samples counter overflowed!");
+ if (Overflowed)
+ return sampleprof_error::counter_overflow;
+
+ return sampleprof_error::success;
}
- void addBodySamples(uint32_t LineOffset, uint32_t Discriminator, uint64_t Num,
- uint64_t Weight = 1) {
- BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(Num,
- Weight);
- }
- void addCalledTargetSamples(uint32_t LineOffset, uint32_t Discriminator,
- std::string FName, uint64_t Num,
- uint64_t Weight = 1) {
- BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
+ sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator,
+ uint64_t Num, uint64_t Weight = 1) {
+ return BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(
+ Num, Weight);
+ }
+ sampleprof_error addCalledTargetSamples(uint32_t LineOffset,
+ uint32_t Discriminator,
+ std::string FName, uint64_t Num,
+ uint64_t Weight = 1) {
+ return BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
FName, Num, Weight);
}
@@ -272,19 +299,21 @@ public:
/// Merge the samples in \p Other into this one.
/// Optionally scale samples by \p Weight.
- void merge(const FunctionSamples &Other, uint64_t Weight = 1) {
- addTotalSamples(Other.getTotalSamples(), Weight);
- addHeadSamples(Other.getHeadSamples(), Weight);
+ sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight = 1) {
+ sampleprof_error Result = sampleprof_error::success;
+ MergeResult(Result, addTotalSamples(Other.getTotalSamples(), Weight));
+ MergeResult(Result, addHeadSamples(Other.getHeadSamples(), Weight));
for (const auto &I : Other.getBodySamples()) {
const LineLocation &Loc = I.first;
const SampleRecord &Rec = I.second;
- BodySamples[Loc].merge(Rec, Weight);
+ MergeResult(Result, BodySamples[Loc].merge(Rec, Weight));
}
for (const auto &I : Other.getCallsiteSamples()) {
const CallsiteLocation &Loc = I.first;
const FunctionSamples &Rec = I.second;
- functionSamplesAt(Loc).merge(Rec, Weight);
+ MergeResult(Result, functionSamplesAt(Loc).merge(Rec, Weight));
}
+ return Result;
}
private:
Modified: llvm/trunk/lib/ProfileData/SampleProf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProf.cpp?rev=255825&r1=255824&r2=255825&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/SampleProf.cpp (original)
+++ llvm/trunk/lib/ProfileData/SampleProf.cpp Wed Dec 16 15:45:43 2015
@@ -45,6 +45,8 @@ class SampleProfErrorCategoryType : publ
return "Truncated function name table";
case sampleprof_error::not_implemented:
return "Unimplemented feature";
+ case sampleprof_error::counter_overflow:
+ return "Counter overflow";
}
llvm_unreachable("A value of sampleprof_error has no message.");
}
Modified: llvm/trunk/lib/ProfileData/SampleProfReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProfReader.cpp?rev=255825&r1=255824&r2=255825&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/SampleProfReader.cpp (original)
+++ llvm/trunk/lib/ProfileData/SampleProfReader.cpp Wed Dec 16 15:45:43 2015
@@ -151,6 +151,7 @@ static bool ParseLine(const StringRef &I
/// \returns true if the file was loaded successfully, false otherwise.
std::error_code SampleProfileReaderText::read() {
line_iterator LineIt(*Buffer, /*SkipBlanks=*/true, '#');
+ sampleprof_error Result = sampleprof_error::success;
InlineCallStack InlineStack;
@@ -179,8 +180,8 @@ std::error_code SampleProfileReaderText:
}
Profiles[FName] = FunctionSamples();
FunctionSamples &FProfile = Profiles[FName];
- FProfile.addTotalSamples(NumSamples);
- FProfile.addHeadSamples(NumHeadSamples);
+ MergeResult(Result, FProfile.addTotalSamples(NumSamples));
+ MergeResult(Result, FProfile.addHeadSamples(NumHeadSamples));
InlineStack.clear();
InlineStack.push_back(&FProfile);
} else {
@@ -202,7 +203,7 @@ std::error_code SampleProfileReaderText:
}
FunctionSamples &FSamples = InlineStack.back()->functionSamplesAt(
CallsiteLocation(LineOffset, Discriminator, FName));
- FSamples.addTotalSamples(NumSamples);
+ MergeResult(Result, FSamples.addTotalSamples(NumSamples));
InlineStack.push_back(&FSamples);
} else {
while (InlineStack.size() > Depth) {
@@ -210,15 +211,17 @@ std::error_code SampleProfileReaderText:
}
FunctionSamples &FProfile = *InlineStack.back();
for (const auto &name_count : TargetCountMap) {
- FProfile.addCalledTargetSamples(LineOffset, Discriminator,
- name_count.first, name_count.second);
+ MergeResult(Result, FProfile.addCalledTargetSamples(
+ LineOffset, Discriminator, name_count.first,
+ name_count.second));
}
- FProfile.addBodySamples(LineOffset, Discriminator, NumSamples);
+ MergeResult(Result, FProfile.addBodySamples(LineOffset, Discriminator,
+ NumSamples));
}
}
}
- return sampleprof_error::success;
+ return Result;
}
bool SampleProfileReaderText::hasFormat(const MemoryBuffer &Buffer) {
Added: llvm/trunk/test/tools/llvm-profdata/Inputs/overflow-instr.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/Inputs/overflow-instr.proftext?rev=255825&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/Inputs/overflow-instr.proftext (added)
+++ llvm/trunk/test/tools/llvm-profdata/Inputs/overflow-instr.proftext Wed Dec 16 15:45:43 2015
@@ -0,0 +1,6 @@
+overflow
+1
+3
+18446744073709551615
+9223372036854775808
+18446744073709551615
Added: llvm/trunk/test/tools/llvm-profdata/Inputs/overflow-sample.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/Inputs/overflow-sample.proftext?rev=255825&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/Inputs/overflow-sample.proftext (added)
+++ llvm/trunk/test/tools/llvm-profdata/Inputs/overflow-sample.proftext Wed Dec 16 15:45:43 2015
@@ -0,0 +1,7 @@
+_Z3bari:18446744073709551615:1000
+ 1: 18446744073709551615
+_Z3fooi:18446744073709551615:1000
+ 1: 18446744073709551615
+main:1000:0
+ 1: 500 _Z3bari:18446744073709551615
+ 2: 500 _Z3fooi:18446744073709551615
Added: llvm/trunk/test/tools/llvm-profdata/overflow-instr.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/overflow-instr.test?rev=255825&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/overflow-instr.test (added)
+++ llvm/trunk/test/tools/llvm-profdata/overflow-instr.test Wed Dec 16 15:45:43 2015
@@ -0,0 +1,17 @@
+Tests for overflow when merging instrumented profiles.
+
+1- Merge profile having maximum counts with itself and verify overflow detected and saturation occurred
+RUN: llvm-profdata merge -instr %p/Inputs/overflow-instr.proftext %p/Inputs/overflow-instr.proftext -o %t.out 2>&1 | FileCheck %s -check-prefix=MERGE_OVERFLOW
+RUN: llvm-profdata show -instr %t.out | FileCheck %s --check-prefix=SHOW_OVERFLOW
+MERGE_OVERFLOW: {{.*}}: overflow: Counter overflow
+SHOW_OVERFLOW: Total functions: 1
+SHOW_OVERFLOW-NEXT: Maximum function count: 18446744073709551615
+SHOW_OVERFLOW-NEXT: Maximum internal block count: 18446744073709551615
+
+2- Merge profile having maximum counts by itself and verify no overflow
+RUN: llvm-profdata merge -instr %p/Inputs/overflow-instr.proftext -o %t.out 2>&1 | FileCheck %s -check-prefix=MERGE_NO_OVERFLOW -allow-empty
+RUN: llvm-profdata show -instr %t.out | FileCheck %s --check-prefix=SHOW_NO_OVERFLOW
+MERGE_NO_OVERFLOW-NOT: {{.*}}: overflow: Counter overflow
+SHOW_NO_OVERFLOW: Total functions: 1
+SHOW_NO_OVERFLOW-NEXT: Maximum function count: 18446744073709551615
+SHOW_NO_OVERFLOW-NEXT: Maximum internal block count: 18446744073709551615
Added: llvm/trunk/test/tools/llvm-profdata/overflow-sample.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/overflow-sample.test?rev=255825&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/overflow-sample.test (added)
+++ llvm/trunk/test/tools/llvm-profdata/overflow-sample.test Wed Dec 16 15:45:43 2015
@@ -0,0 +1,43 @@
+Tests for overflow when merging sampled profiles.
+
+1- Merge profile having maximum counts with itself and verify overflow detected
+RUN: llvm-profdata merge -sample %p/Inputs/overflow-sample.proftext %p/Inputs/overflow-sample.proftext -o %t.out 2>&1 | FileCheck %s -check-prefix=MERGE_OVERFLOW
+RUN: llvm-profdata show -sample %t.out | FileCheck %s --check-prefix=SHOW_OVERFLOW
+MERGE_OVERFLOW: {{.*}}: main: Counter overflow
+SHOW_OVERFLOW: Function: main: 2000, 0, 2 sampled lines
+SHOW_OVERFLOW-NEXT: Samples collected in the function's body {
+SHOW_OVERFLOW-NEXT: 1: 1000, calls: _Z3bari:18446744073709551615
+SHOW_OVERFLOW-NEXT: 2: 1000, calls: _Z3fooi:18446744073709551615
+SHOW_OVERFLOW-NEXT: }
+SHOW_OVERFLOW-NEXT: No inlined callsites in this function
+SHOW_OVERFLOW-NEXT: Function: _Z3fooi: 18446744073709551615, 2000, 1 sampled lines
+SHOW_OVERFLOW-NEXT: Samples collected in the function's body {
+SHOW_OVERFLOW-NEXT: 1: 18446744073709551615
+SHOW_OVERFLOW-NEXT: }
+SHOW_OVERFLOW-NEXT: No inlined callsites in this function
+SHOW_OVERFLOW-NEXT: Function: _Z3bari: 18446744073709551615, 2000, 1 sampled lines
+SHOW_OVERFLOW-NEXT: Samples collected in the function's body {
+SHOW_OVERFLOW-NEXT: 1: 18446744073709551615
+SHOW_OVERFLOW-NEXT: }
+SHOW_OVERFLOW-NEXT: No inlined callsites in this function
+
+2- Merge profile having maximum counts by itself and verify no overflow
+RUN: llvm-profdata merge -sample %p/Inputs/overflow-sample.proftext -o %t.out 2>&1 | FileCheck %s -allow-empty -check-prefix=MERGE_NO_OVERFLOW
+RUN: llvm-profdata show -sample %t.out | FileCheck %s --check-prefix=SHOW_NO_OVERFLOW
+MERGE_NO_OVERFLOW-NOT: {{.*}}: main: Counter overflow
+SHOW_NO_OVERFLOW: Function: main: 1000, 0, 2 sampled lines
+SHOW_NO_OVERFLOW-NEXT: Samples collected in the function's body {
+SHOW_NO_OVERFLOW-NEXT: 1: 500, calls: _Z3bari:18446744073709551615
+SHOW_NO_OVERFLOW-NEXT: 2: 500, calls: _Z3fooi:18446744073709551615
+SHOW_NO_OVERFLOW-NEXT: }
+SHOW_NO_OVERFLOW-NEXT: No inlined callsites in this function
+SHOW_NO_OVERFLOW-NEXT: Function: _Z3fooi: 18446744073709551615, 1000, 1 sampled lines
+SHOW_NO_OVERFLOW-NEXT: Samples collected in the function's body {
+SHOW_NO_OVERFLOW-NEXT: 1: 18446744073709551615
+SHOW_NO_OVERFLOW-NEXT: }
+SHOW_NO_OVERFLOW-NEXT: No inlined callsites in this function
+SHOW_NO_OVERFLOW-NEXT: Function: _Z3bari: 18446744073709551615, 1000, 1 sampled lines
+SHOW_NO_OVERFLOW-NEXT: Samples collected in the function's body {
+SHOW_NO_OVERFLOW-NEXT: 1: 18446744073709551615
+SHOW_NO_OVERFLOW-NEXT: }
+SHOW_NO_OVERFLOW-NEXT: No inlined callsites in this function
Removed: llvm/trunk/test/tools/llvm-profdata/overflow.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/overflow.proftext?rev=255824&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/overflow.proftext (original)
+++ llvm/trunk/test/tools/llvm-profdata/overflow.proftext (removed)
@@ -1,20 +0,0 @@
-# RUN: llvm-profdata merge %s -o %t.out 2>&1 | FileCheck %s --check-prefix=MERGE
-# RUN: llvm-profdata show %t.out | FileCheck %s --check-prefix=SHOW
-# MERGE: overflow.proftext: overflow: Counter overflow
-# SHOW: Total functions: 1
-# SHOW: Maximum function count: 18446744073709551615
-# SHOW: Maximum internal block count: 18446744073709551615
-
-overflow
-1
-3
-18446744073709551615
-9223372036854775808
-18446744073709551615
-
-overflow
-1
-3
-9223372036854775808
-9223372036854775808
-0
Modified: llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp?rev=255825&r1=255824&r2=255825&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp (original)
+++ llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp Wed Dec 16 15:45:43 2015
@@ -180,7 +180,11 @@ static void mergeSampleProfile(const Wei
I != E; ++I) {
StringRef FName = I->first();
FunctionSamples &Samples = I->second;
- ProfileMap[FName].merge(Samples, Input.Weight);
+ sampleprof_error Result = ProfileMap[FName].merge(Samples, Input.Weight);
+ if (Result != sampleprof_error::success) {
+ std::error_code EC = make_error_code(Result);
+ handleMergeWriterError(EC, Input.Filename, FName);
+ }
}
}
Writer->write(ProfileMap);
Modified: llvm/trunk/unittests/ProfileData/InstrProfTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/InstrProfTest.cpp?rev=255825&r1=255824&r2=255825&view=diff
==============================================================================
--- llvm/trunk/unittests/ProfileData/InstrProfTest.cpp (original)
+++ llvm/trunk/unittests/ProfileData/InstrProfTest.cpp Wed Dec 16 15:45:43 2015
@@ -353,41 +353,50 @@ TEST_F(InstrProfTest, get_icall_data_mer
TEST_F(InstrProfTest, get_icall_data_merge1_saturation) {
const uint64_t Max = std::numeric_limits<uint64_t>::max();
- InstrProfRecord Record1("caller", 0x1234, {1});
- InstrProfRecord Record2("caller", 0x1234, {Max});
- InstrProfRecord Record3("callee1", 0x1235, {3, 4});
-
- Record1.reserveSites(IPVK_IndirectCallTarget, 1);
- InstrProfValueData VD1[] = {{(uint64_t) "callee1", 1}};
- Record1.addValueData(IPVK_IndirectCallTarget, 0, VD1, 1, nullptr);
-
- Record2.reserveSites(IPVK_IndirectCallTarget, 1);
- // FIXME: Improve handling of counter overflow. ValueData asserts on overflow.
- // InstrProfValueData VD2[] = {{(uint64_t) "callee1", Max}};
- InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}};
- Record2.addValueData(IPVK_IndirectCallTarget, 0, VD2, 1, nullptr);
-
- Writer.addRecord(std::move(Record1));
- Writer.addRecord(std::move(Record2));
- Writer.addRecord(std::move(Record3));
+ InstrProfRecord Record1("foo", 0x1234, {1});
+ auto Result1 = Writer.addRecord(std::move(Record1));
+ ASSERT_EQ(Result1, instrprof_error::success);
+
+ // Verify counter overflow.
+ InstrProfRecord Record2("foo", 0x1234, {Max});
+ auto Result2 = Writer.addRecord(std::move(Record2));
+ ASSERT_EQ(Result2, instrprof_error::counter_overflow);
+
+ InstrProfRecord Record3("bar", 0x9012, {8});
+ auto Result3 = Writer.addRecord(std::move(Record3));
+ ASSERT_EQ(Result3, instrprof_error::success);
+
+ InstrProfRecord Record4("baz", 0x5678, {3, 4});
+ Record4.reserveSites(IPVK_IndirectCallTarget, 1);
+ InstrProfValueData VD4[] = {{(uint64_t) "bar", 1}};
+ Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr);
+ auto Result4 = Writer.addRecord(std::move(Record4));
+ ASSERT_EQ(Result4, instrprof_error::success);
+
+ // Verify value data counter overflow.
+ InstrProfRecord Record5("baz", 0x5678, {5, 6});
+ Record5.reserveSites(IPVK_IndirectCallTarget, 1);
+ InstrProfValueData VD5[] = {{(uint64_t) "bar", Max}};
+ Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr);
+ auto Result5 = Writer.addRecord(std::move(Record5));
+ ASSERT_EQ(Result5, instrprof_error::counter_overflow);
auto Profile = Writer.writeBuffer();
readProfile(std::move(Profile));
// Verify saturation of counts.
- ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
- ASSERT_TRUE(NoError(R.getError()));
-
- ASSERT_EQ(Max, R.get().Counts[0]);
-
- ASSERT_EQ(1U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
+ ErrorOr<InstrProfRecord> ReadRecord1 =
+ Reader->getInstrProfRecord("foo", 0x1234);
+ ASSERT_TRUE(NoError(ReadRecord1.getError()));
+ ASSERT_EQ(Max, ReadRecord1.get().Counts[0]);
+
+ ErrorOr<InstrProfRecord> ReadRecord2 =
+ Reader->getInstrProfRecord("baz", 0x5678);
+ ASSERT_EQ(1U, ReadRecord2.get().getNumValueSites(IPVK_IndirectCallTarget));
std::unique_ptr<InstrProfValueData[]> VD =
- R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
- ASSERT_EQ(StringRef("callee1"), StringRef((const char *)VD[0].Value, 7));
-
- // FIXME: Improve handling of counter overflow. ValueData asserts on overflow.
- // ASSERT_EQ(Max, VD[0].Count);
- ASSERT_EQ(2U, VD[0].Count);
+ ReadRecord2.get().getValueForSite(IPVK_IndirectCallTarget, 0);
+ ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3));
+ ASSERT_EQ(Max, VD[0].Count);
}
// Synthesize runtime value profile data.
Modified: llvm/trunk/unittests/ProfileData/SampleProfTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ProfileData/SampleProfTest.cpp?rev=255825&r1=255824&r2=255825&view=diff
==============================================================================
--- llvm/trunk/unittests/ProfileData/SampleProfTest.cpp (original)
+++ llvm/trunk/unittests/ProfileData/SampleProfTest.cpp Wed Dec 16 15:45:43 2015
@@ -99,4 +99,34 @@ TEST_F(SampleProfTest, roundtrip_binary_
testRoundTrip(SampleProfileFormat::SPF_Binary);
}
+TEST_F(SampleProfTest, sample_overflow_saturation) {
+ const uint64_t Max = std::numeric_limits<uint64_t>::max();
+ sampleprof_error Result;
+
+ StringRef FooName("_Z3fooi");
+ FunctionSamples FooSamples;
+ Result = FooSamples.addTotalSamples(1);
+ ASSERT_EQ(Result, sampleprof_error::success);
+
+ Result = FooSamples.addHeadSamples(1);
+ ASSERT_EQ(Result, sampleprof_error::success);
+
+ Result = FooSamples.addBodySamples(10, 0, 1);
+ ASSERT_EQ(Result, sampleprof_error::success);
+
+ Result = FooSamples.addTotalSamples(Max);
+ ASSERT_EQ(Result, sampleprof_error::counter_overflow);
+ ASSERT_EQ(FooSamples.getTotalSamples(), Max);
+
+ Result = FooSamples.addHeadSamples(Max);
+ ASSERT_EQ(Result, sampleprof_error::counter_overflow);
+ ASSERT_EQ(FooSamples.getHeadSamples(), Max);
+
+ Result = FooSamples.addBodySamples(10, 0, Max);
+ ASSERT_EQ(Result, sampleprof_error::counter_overflow);
+ ErrorOr<uint64_t> BodySamples = FooSamples.findSamplesAt(10, 0);
+ ASSERT_FALSE(BodySamples.getError());
+ ASSERT_EQ(BodySamples.get(), Max);
+}
+
} // end anonymous namespace
More information about the llvm-commits
mailing list