llvm.org GIT mirror llvm / fd56824
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255825 91177308-0d34-0410-b5e6-96231b3b80d8 Nathan Slingerland 3 years ago
12 changed file(s) with 250 addition(s) and 107 deletion(s). Raw diff Collapse all Expand all
183183 return std::error_code(static_cast(E), instrprof_category());
184184 }
185185
186 inline instrprof_error MergeResult(instrprof_error &Accumulator,
187 instrprof_error Result) {
188 // Prefer first error encountered as later errors may be secondary effects of
189 // the initial problem.
190 if (Accumulator == instrprof_error::success &&
191 Result != instrprof_error::success)
192 Accumulator = Result;
193 return Accumulator;
194 }
195
186196 enum InstrProfValueKind : uint32_t {
187197 #define VALUE_PROF_KIND(Enumerator, Value) Enumerator = Value,
188198 #include "llvm/ProfileData/InstrProfData.inc"
223233
224234 /// Merge data from another InstrProfValueSiteRecord
225235 /// Optionally scale merged counts by \p Weight.
226 void mergeValueData(InstrProfValueSiteRecord &Input, uint64_t Weight = 1) {
236 instrprof_error mergeValueData(InstrProfValueSiteRecord &Input,
237 uint64_t Weight = 1) {
227238 this->sortByTargetValues();
228239 Input.sortByTargetValues();
229240 auto I = ValueData.begin();
230241 auto IE = ValueData.end();
242 instrprof_error Result = instrprof_error::success;
231243 for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE;
232244 ++J) {
233245 while (I != IE && I->Value < J->Value)
234246 ++I;
235247 if (I != IE && I->Value == J->Value) {
236 // FIXME: Improve handling of counter overflow.
237248 uint64_t JCount = J->Count;
238249 bool Overflowed;
239250 if (Weight > 1) {
240251 JCount = SaturatingMultiply(JCount, Weight, &Overflowed);
241 assert(!Overflowed && "Value data counter overflowed!");
252 if (Overflowed)
253 Result = instrprof_error::counter_overflow;
242254 }
243255 I->Count = SaturatingAdd(I->Count, JCount, &Overflowed);
244 assert(!Overflowed && "Value data counter overflowed!");
256 if (Overflowed)
257 Result = instrprof_error::counter_overflow;
245258 ++I;
246259 continue;
247260 }
248261 ValueData.insert(I, *J);
249262 }
263 return Result;
250264 }
251265 };
252266
351365 getValueSitesForKind(ValueKind);
352366 std::vector &OtherSiteRecords =
353367 Src.getValueSitesForKind(ValueKind);
368 instrprof_error Result = instrprof_error::success;
354369 for (uint32_t I = 0; I < ThisNumValueSites; I++)
355 ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I], Weight);
356 return instrprof_error::success;
370 MergeResult(Result, ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I],
371 Weight));
372 return Result;
357373 }
358374 };
359375
460476 Result = instrprof_error::counter_overflow;
461477 }
462478
463 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
464 instrprof_error MergeValueResult = mergeValueProfData(Kind, Other, Weight);
465 if (MergeValueResult != instrprof_error::success)
466 Result = MergeValueResult;
467 }
479 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
480 MergeResult(Result, mergeValueProfData(Kind, Other, Weight));
468481
469482 return Result;
470483 }
479492 #include "llvm/ProfileData/InstrProfData.inc"
480493
481494 /*
482 * Initialize the record for runtime value profile data.
495 * Initialize the record for runtime value profile data.
483496 * Return 0 if the initialization is successful, otherwise
484497 * return 1.
485498 */
3737 unrecognized_format,
3838 unsupported_writing_format,
3939 truncated_name_table,
40 not_implemented
40 not_implemented,
41 counter_overflow
4142 };
4243
4344 inline std::error_code make_error_code(sampleprof_error E) {
4445 return std::error_code(static_cast(E), sampleprof_category());
46 }
47
48 inline sampleprof_error MergeResult(sampleprof_error &Accumulator,
49 sampleprof_error Result) {
50 // Prefer first error encountered as later errors may be secondary effects of
51 // the initial problem.
52 if (Accumulator == sampleprof_error::success &&
53 Result != sampleprof_error::success)
54 Accumulator = Result;
55 return Accumulator;
4556 }
4657
4758 } // end namespace llvm
126137 ///
127138 /// Sample counts accumulate using saturating arithmetic, to avoid wrapping
128139 /// around unsigned integers.
129 void addSamples(uint64_t S, uint64_t Weight = 1) {
130 // FIXME: Improve handling of counter overflow.
140 sampleprof_error addSamples(uint64_t S, uint64_t Weight = 1) {
131141 bool Overflowed;
132142 if (Weight > 1) {
133143 S = SaturatingMultiply(S, Weight, &Overflowed);
134 assert(!Overflowed && "Sample counter overflowed!");
144 if (Overflowed)
145 return sampleprof_error::counter_overflow;
135146 }
136147 NumSamples = SaturatingAdd(NumSamples, S, &Overflowed);
137 assert(!Overflowed && "Sample counter overflowed!");
148 if (Overflowed)
149 return sampleprof_error::counter_overflow;
150
151 return sampleprof_error::success;
138152 }
139153
140154 /// Add called function \p F with samples \p S.
142156 ///
143157 /// Sample counts accumulate using saturating arithmetic, to avoid wrapping
144158 /// around unsigned integers.
145 void addCalledTarget(StringRef F, uint64_t S, uint64_t Weight = 1) {
146 // FIXME: Improve handling of counter overflow.
159 sampleprof_error addCalledTarget(StringRef F, uint64_t S,
160 uint64_t Weight = 1) {
147161 uint64_t &TargetSamples = CallTargets[F];
148162 bool Overflowed;
149163 if (Weight > 1) {
150164 S = SaturatingMultiply(S, Weight, &Overflowed);
151 assert(!Overflowed && "Called target counter overflowed!");
165 if (Overflowed)
166 return sampleprof_error::counter_overflow;
152167 }
153168 TargetSamples = SaturatingAdd(TargetSamples, S, &Overflowed);
154 assert(!Overflowed && "Called target counter overflowed!");
169 if (Overflowed)
170 return sampleprof_error::counter_overflow;
171
172 return sampleprof_error::success;
155173 }
156174
157175 /// Return true if this sample record contains function calls.
162180
163181 /// Merge the samples in \p Other into this record.
164182 /// Optionally scale sample counts by \p Weight.
165 void merge(const SampleRecord &Other, uint64_t Weight = 1) {
166 addSamples(Other.getSamples(), Weight);
167 for (const auto &I : Other.getCallTargets())
168 addCalledTarget(I.first(), I.second, Weight);
183 sampleprof_error merge(const SampleRecord &Other, uint64_t Weight = 1) {
184 sampleprof_error Result = addSamples(Other.getSamples(), Weight);
185 for (const auto &I : Other.getCallTargets()) {
186 MergeResult(Result, addCalledTarget(I.first(), I.second, Weight));
187 }
188 return Result;
169189 }
170190
171191 void print(raw_ostream &OS, unsigned Indent) const;
192212 FunctionSamples() : TotalSamples(0), TotalHeadSamples(0) {}
193213 void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const;
194214 void dump() const;
195 void addTotalSamples(uint64_t Num, uint64_t Weight = 1) {
196 // FIXME: Improve handling of counter overflow.
215 sampleprof_error addTotalSamples(uint64_t Num, uint64_t Weight = 1) {
197216 bool Overflowed;
198217 if (Weight > 1) {
199218 Num = SaturatingMultiply(Num, Weight, &Overflowed);
200 assert(!Overflowed && "Total samples counter overflowed!");
219 if (Overflowed)
220 return sampleprof_error::counter_overflow;
201221 }
202222 TotalSamples = SaturatingAdd(TotalSamples, Num, &Overflowed);
203 assert(!Overflowed && "Total samples counter overflowed!");
204 }
205 void addHeadSamples(uint64_t Num, uint64_t Weight = 1) {
206 // FIXME: Improve handling of counter overflow.
223 if (Overflowed)
224 return sampleprof_error::counter_overflow;
225
226 return sampleprof_error::success;
227 }
228 sampleprof_error addHeadSamples(uint64_t Num, uint64_t Weight = 1) {
207229 bool Overflowed;
208230 if (Weight > 1) {
209231 Num = SaturatingMultiply(Num, Weight, &Overflowed);
210 assert(!Overflowed && "Total head samples counter overflowed!");
232 if (Overflowed)
233 return sampleprof_error::counter_overflow;
211234 }
212235 TotalHeadSamples = SaturatingAdd(TotalHeadSamples, Num, &Overflowed);
213 assert(!Overflowed && "Total head samples counter overflowed!");
214 }
215 void addBodySamples(uint32_t LineOffset, uint32_t Discriminator, uint64_t Num,
216 uint64_t Weight = 1) {
217 BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(Num,
218 Weight);
219 }
220 void addCalledTargetSamples(uint32_t LineOffset, uint32_t Discriminator,
221 std::string FName, uint64_t Num,
222 uint64_t Weight = 1) {
223 BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
236 if (Overflowed)
237 return sampleprof_error::counter_overflow;
238
239 return sampleprof_error::success;
240 }
241 sampleprof_error addBodySamples(uint32_t LineOffset, uint32_t Discriminator,
242 uint64_t Num, uint64_t Weight = 1) {
243 return BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(
244 Num, Weight);
245 }
246 sampleprof_error addCalledTargetSamples(uint32_t LineOffset,
247 uint32_t Discriminator,
248 std::string FName, uint64_t Num,
249 uint64_t Weight = 1) {
250 return BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(
224251 FName, Num, Weight);
225252 }
226253
271298
272299 /// Merge the samples in \p Other into this one.
273300 /// Optionally scale samples by \p Weight.
274 void merge(const FunctionSamples &Other, uint64_t Weight = 1) {
275 addTotalSamples(Other.getTotalSamples(), Weight);
276 addHeadSamples(Other.getHeadSamples(), Weight);
301 sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight = 1) {
302 sampleprof_error Result = sampleprof_error::success;
303 MergeResult(Result, addTotalSamples(Other.getTotalSamples(), Weight));
304 MergeResult(Result, addHeadSamples(Other.getHeadSamples(), Weight));
277305 for (const auto &I : Other.getBodySamples()) {
278306 const LineLocation &Loc = I.first;
279307 const SampleRecord &Rec = I.second;
280 BodySamples[Loc].merge(Rec, Weight);
308 MergeResult(Result, BodySamples[Loc].merge(Rec, Weight));
281309 }
282310 for (const auto &I : Other.getCallsiteSamples()) {
283311 const CallsiteLocation &Loc = I.first;
284312 const FunctionSamples &Rec = I.second;
285 functionSamplesAt(Loc).merge(Rec, Weight);
286 }
313 MergeResult(Result, functionSamplesAt(Loc).merge(Rec, Weight));
314 }
315 return Result;
287316 }
288317
289318 private:
4444 return "Truncated function name table";
4545 case sampleprof_error::not_implemented:
4646 return "Unimplemented feature";
47 case sampleprof_error::counter_overflow:
48 return "Counter overflow";
4749 }
4850 llvm_unreachable("A value of sampleprof_error has no message.");
4951 }
150150 /// \returns true if the file was loaded successfully, false otherwise.
151151 std::error_code SampleProfileReaderText::read() {
152152 line_iterator LineIt(*Buffer, /*SkipBlanks=*/true, '#');
153 sampleprof_error Result = sampleprof_error::success;
153154
154155 InlineCallStack InlineStack;
155156
178179 }
179180 Profiles[FName] = FunctionSamples();
180181 FunctionSamples &FProfile = Profiles[FName];
181 FProfile.addTotalSamples(NumSamples);
182 FProfile.addHeadSamples(NumHeadSamples);
182 MergeResult(Result, FProfile.addTotalSamples(NumSamples));
183 MergeResult(Result, FProfile.addHeadSamples(NumHeadSamples));
183184 InlineStack.clear();
184185 InlineStack.push_back(&FProfile);
185186 } else {
201202 }
202203 FunctionSamples &FSamples = InlineStack.back()->functionSamplesAt(
203204 CallsiteLocation(LineOffset, Discriminator, FName));
204 FSamples.addTotalSamples(NumSamples);
205 MergeResult(Result, FSamples.addTotalSamples(NumSamples));
205206 InlineStack.push_back(&FSamples);
206207 } else {
207208 while (InlineStack.size() > Depth) {
209210 }
210211 FunctionSamples &FProfile = *InlineStack.back();
211212 for (const auto &name_count : TargetCountMap) {
212 FProfile.addCalledTargetSamples(LineOffset, Discriminator,
213 name_count.first, name_count.second);
213 MergeResult(Result, FProfile.addCalledTargetSamples(
214 LineOffset, Discriminator, name_count.first,
215 name_count.second));
214216 }
215 FProfile.addBodySamples(LineOffset, Discriminator, NumSamples);
217 MergeResult(Result, FProfile.addBodySamples(LineOffset, Discriminator,
218 NumSamples));
216219 }
217220 }
218221 }
219222
220 return sampleprof_error::success;
223 return Result;
221224 }
222225
223226 bool SampleProfileReaderText::hasFormat(const MemoryBuffer &Buffer) {
0 overflow
1 1
2 3
3 18446744073709551615
4 9223372036854775808
5 18446744073709551615
0 _Z3bari:18446744073709551615:1000
1 1: 18446744073709551615
2 _Z3fooi:18446744073709551615:1000
3 1: 18446744073709551615
4 main:1000:0
5 1: 500 _Z3bari:18446744073709551615
6 2: 500 _Z3fooi:18446744073709551615
0 Tests for overflow when merging instrumented profiles.
1
2 1- Merge profile having maximum counts with itself and verify overflow detected and saturation occurred
3 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
4 RUN: llvm-profdata show -instr %t.out | FileCheck %s --check-prefix=SHOW_OVERFLOW
5 MERGE_OVERFLOW: {{.*}}: overflow: Counter overflow
6 SHOW_OVERFLOW: Total functions: 1
7 SHOW_OVERFLOW-NEXT: Maximum function count: 18446744073709551615
8 SHOW_OVERFLOW-NEXT: Maximum internal block count: 18446744073709551615
9
10 2- Merge profile having maximum counts by itself and verify no overflow
11 RUN: llvm-profdata merge -instr %p/Inputs/overflow-instr.proftext -o %t.out 2>&1 | FileCheck %s -check-prefix=MERGE_NO_OVERFLOW -allow-empty
12 RUN: llvm-profdata show -instr %t.out | FileCheck %s --check-prefix=SHOW_NO_OVERFLOW
13 MERGE_NO_OVERFLOW-NOT: {{.*}}: overflow: Counter overflow
14 SHOW_NO_OVERFLOW: Total functions: 1
15 SHOW_NO_OVERFLOW-NEXT: Maximum function count: 18446744073709551615
16 SHOW_NO_OVERFLOW-NEXT: Maximum internal block count: 18446744073709551615
0 Tests for overflow when merging sampled profiles.
1
2 1- Merge profile having maximum counts with itself and verify overflow detected
3 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
4 RUN: llvm-profdata show -sample %t.out | FileCheck %s --check-prefix=SHOW_OVERFLOW
5 MERGE_OVERFLOW: {{.*}}: main: Counter overflow
6 SHOW_OVERFLOW: Function: main: 2000, 0, 2 sampled lines
7 SHOW_OVERFLOW-NEXT: Samples collected in the function's body {
8 SHOW_OVERFLOW-NEXT: 1: 1000, calls: _Z3bari:18446744073709551615
9 SHOW_OVERFLOW-NEXT: 2: 1000, calls: _Z3fooi:18446744073709551615
10 SHOW_OVERFLOW-NEXT: }
11 SHOW_OVERFLOW-NEXT: No inlined callsites in this function
12 SHOW_OVERFLOW-NEXT: Function: _Z3fooi: 18446744073709551615, 2000, 1 sampled lines
13 SHOW_OVERFLOW-NEXT: Samples collected in the function's body {
14 SHOW_OVERFLOW-NEXT: 1: 18446744073709551615
15 SHOW_OVERFLOW-NEXT: }
16 SHOW_OVERFLOW-NEXT: No inlined callsites in this function
17 SHOW_OVERFLOW-NEXT: Function: _Z3bari: 18446744073709551615, 2000, 1 sampled lines
18 SHOW_OVERFLOW-NEXT: Samples collected in the function's body {
19 SHOW_OVERFLOW-NEXT: 1: 18446744073709551615
20 SHOW_OVERFLOW-NEXT: }
21 SHOW_OVERFLOW-NEXT: No inlined callsites in this function
22
23 2- Merge profile having maximum counts by itself and verify no overflow
24 RUN: llvm-profdata merge -sample %p/Inputs/overflow-sample.proftext -o %t.out 2>&1 | FileCheck %s -allow-empty -check-prefix=MERGE_NO_OVERFLOW
25 RUN: llvm-profdata show -sample %t.out | FileCheck %s --check-prefix=SHOW_NO_OVERFLOW
26 MERGE_NO_OVERFLOW-NOT: {{.*}}: main: Counter overflow
27 SHOW_NO_OVERFLOW: Function: main: 1000, 0, 2 sampled lines
28 SHOW_NO_OVERFLOW-NEXT: Samples collected in the function's body {
29 SHOW_NO_OVERFLOW-NEXT: 1: 500, calls: _Z3bari:18446744073709551615
30 SHOW_NO_OVERFLOW-NEXT: 2: 500, calls: _Z3fooi:18446744073709551615
31 SHOW_NO_OVERFLOW-NEXT: }
32 SHOW_NO_OVERFLOW-NEXT: No inlined callsites in this function
33 SHOW_NO_OVERFLOW-NEXT: Function: _Z3fooi: 18446744073709551615, 1000, 1 sampled lines
34 SHOW_NO_OVERFLOW-NEXT: Samples collected in the function's body {
35 SHOW_NO_OVERFLOW-NEXT: 1: 18446744073709551615
36 SHOW_NO_OVERFLOW-NEXT: }
37 SHOW_NO_OVERFLOW-NEXT: No inlined callsites in this function
38 SHOW_NO_OVERFLOW-NEXT: Function: _Z3bari: 18446744073709551615, 1000, 1 sampled lines
39 SHOW_NO_OVERFLOW-NEXT: Samples collected in the function's body {
40 SHOW_NO_OVERFLOW-NEXT: 1: 18446744073709551615
41 SHOW_NO_OVERFLOW-NEXT: }
42 SHOW_NO_OVERFLOW-NEXT: No inlined callsites in this function
+0
-20
test/tools/llvm-profdata/overflow.proftext less more
None # 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
6
7 overflow
8 1
9 3
10 18446744073709551615
11 9223372036854775808
12 18446744073709551615
13
14 overflow
15 1
16 3
17 9223372036854775808
18 9223372036854775808
19 0
179179 I != E; ++I) {
180180 StringRef FName = I->first();
181181 FunctionSamples &Samples = I->second;
182 ProfileMap[FName].merge(Samples, Input.Weight);
182 sampleprof_error Result = ProfileMap[FName].merge(Samples, Input.Weight);
183 if (Result != sampleprof_error::success) {
184 std::error_code EC = make_error_code(Result);
185 handleMergeWriterError(EC, Input.Filename, FName);
186 }
183187 }
184188 }
185189 Writer->write(ProfileMap);
352352 TEST_F(InstrProfTest, get_icall_data_merge1_saturation) {
353353 const uint64_t Max = std::numeric_limits::max();
354354
355 InstrProfRecord Record1("caller", 0x1234, {1});
356 InstrProfRecord Record2("caller", 0x1234, {Max});
357 InstrProfRecord Record3("callee1", 0x1235, {3, 4});
358
359 Record1.reserveSites(IPVK_IndirectCallTarget, 1);
360 InstrProfValueData VD1[] = {{(uint64_t) "callee1", 1}};
361 Record1.addValueData(IPVK_IndirectCallTarget, 0, VD1, 1, nullptr);
362
363 Record2.reserveSites(IPVK_IndirectCallTarget, 1);
364 // FIXME: Improve handling of counter overflow. ValueData asserts on overflow.
365 // InstrProfValueData VD2[] = {{(uint64_t) "callee1", Max}};
366 InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1}};
367 Record2.addValueData(IPVK_IndirectCallTarget, 0, VD2, 1, nullptr);
368
369 Writer.addRecord(std::move(Record1));
370 Writer.addRecord(std::move(Record2));
371 Writer.addRecord(std::move(Record3));
355 InstrProfRecord Record1("foo", 0x1234, {1});
356 auto Result1 = Writer.addRecord(std::move(Record1));
357 ASSERT_EQ(Result1, instrprof_error::success);
358
359 // Verify counter overflow.
360 InstrProfRecord Record2("foo", 0x1234, {Max});
361 auto Result2 = Writer.addRecord(std::move(Record2));
362 ASSERT_EQ(Result2, instrprof_error::counter_overflow);
363
364 InstrProfRecord Record3("bar", 0x9012, {8});
365 auto Result3 = Writer.addRecord(std::move(Record3));
366 ASSERT_EQ(Result3, instrprof_error::success);
367
368 InstrProfRecord Record4("baz", 0x5678, {3, 4});
369 Record4.reserveSites(IPVK_IndirectCallTarget, 1);
370 InstrProfValueData VD4[] = {{(uint64_t) "bar", 1}};
371 Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr);
372 auto Result4 = Writer.addRecord(std::move(Record4));
373 ASSERT_EQ(Result4, instrprof_error::success);
374
375 // Verify value data counter overflow.
376 InstrProfRecord Record5("baz", 0x5678, {5, 6});
377 Record5.reserveSites(IPVK_IndirectCallTarget, 1);
378 InstrProfValueData VD5[] = {{(uint64_t) "bar", Max}};
379 Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr);
380 auto Result5 = Writer.addRecord(std::move(Record5));
381 ASSERT_EQ(Result5, instrprof_error::counter_overflow);
372382
373383 auto Profile = Writer.writeBuffer();
374384 readProfile(std::move(Profile));
375385
376386 // Verify saturation of counts.
377 ErrorOr R = Reader->getInstrProfRecord("caller", 0x1234);
378 ASSERT_TRUE(NoError(R.getError()));
379
380 ASSERT_EQ(Max, R.get().Counts[0]);
381
382 ASSERT_EQ(1U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
387 ErrorOr ReadRecord1 =
388 Reader->getInstrProfRecord("foo", 0x1234);
389 ASSERT_TRUE(NoError(ReadRecord1.getError()));
390 ASSERT_EQ(Max, ReadRecord1.get().Counts[0]);
391
392 ErrorOr ReadRecord2 =
393 Reader->getInstrProfRecord("baz", 0x5678);
394 ASSERT_EQ(1U, ReadRecord2.get().getNumValueSites(IPVK_IndirectCallTarget));
383395 std::unique_ptr VD =
384 R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
385 ASSERT_EQ(StringRef("callee1"), StringRef((const char *)VD[0].Value, 7));
386
387 // FIXME: Improve handling of counter overflow. ValueData asserts on overflow.
388 // ASSERT_EQ(Max, VD[0].Count);
389 ASSERT_EQ(2U, VD[0].Count);
396 ReadRecord2.get().getValueForSite(IPVK_IndirectCallTarget, 0);
397 ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3));
398 ASSERT_EQ(Max, VD[0].Count);
390399 }
391400
392401 // Synthesize runtime value profile data.
9898 testRoundTrip(SampleProfileFormat::SPF_Binary);
9999 }
100100
101 TEST_F(SampleProfTest, sample_overflow_saturation) {
102 const uint64_t Max = std::numeric_limits::max();
103 sampleprof_error Result;
104
105 StringRef FooName("_Z3fooi");
106 FunctionSamples FooSamples;
107 Result = FooSamples.addTotalSamples(1);
108 ASSERT_EQ(Result, sampleprof_error::success);
109
110 Result = FooSamples.addHeadSamples(1);
111 ASSERT_EQ(Result, sampleprof_error::success);
112
113 Result = FooSamples.addBodySamples(10, 0, 1);
114 ASSERT_EQ(Result, sampleprof_error::success);
115
116 Result = FooSamples.addTotalSamples(Max);
117 ASSERT_EQ(Result, sampleprof_error::counter_overflow);
118 ASSERT_EQ(FooSamples.getTotalSamples(), Max);
119
120 Result = FooSamples.addHeadSamples(Max);
121 ASSERT_EQ(Result, sampleprof_error::counter_overflow);
122 ASSERT_EQ(FooSamples.getHeadSamples(), Max);
123
124 Result = FooSamples.addBodySamples(10, 0, Max);
125 ASSERT_EQ(Result, sampleprof_error::counter_overflow);
126 ErrorOr BodySamples = FooSamples.findSamplesAt(10, 0);
127 ASSERT_FALSE(BodySamples.getError());
128 ASSERT_EQ(BodySamples.get(), Max);
129 }
130
101131 } // end anonymous namespace