llvm.org GIT mirror llvm / cb16061
llvm-profdata: Reduce memory usage by using Error callback rather than member Reduces llvm-profdata memory usage on a large profile from 7.8GB to 5.1GB. The ProfData API now supports reporting all the errors/warnings rather than only the first, though llvm-profdata ignores everything after the first for now to preserve existing behavior. (if there's a desire for other behavior, happy to implement that - but might be as well left for a separate patch) Reviewers: davidxl Differential Revision: https://reviews.llvm.org/D35149 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307516 91177308-0d34-0410-b5e6-96231b3b80d8 David Blaikie 2 years ago
7 changed file(s) with 177 addition(s) and 162 deletion(s). Raw diff Collapse all Expand all
580580
581581 /// Merge data from another InstrProfValueSiteRecord
582582 /// Optionally scale merged counts by \p Weight.
583 void merge(SoftInstrProfErrors &SIPE, InstrProfValueSiteRecord &Input,
584 uint64_t Weight = 1);
583 void merge(InstrProfValueSiteRecord &Input, uint64_t Weight,
584 function_ref Warn);
585585 /// Scale up value profile data counts.
586 void scale(SoftInstrProfErrors &SIPE, uint64_t Weight);
586 void scale(uint64_t Weight, function_ref Warn);
587587 };
588588
589589 /// Profiling information for a single function.
590590 struct InstrProfRecord {
591591 std::vector Counts;
592 SoftInstrProfErrors SIPE;
593592
594593 InstrProfRecord() = default;
595594 InstrProfRecord(std::vector Counts) : Counts(std::move(Counts)) {}
652651
653652 /// Merge the counts in \p Other into this one.
654653 /// Optionally scale merged counts by \p Weight.
655 void merge(InstrProfRecord &Other, uint64_t Weight = 1);
654 void merge(InstrProfRecord &Other, uint64_t Weight,
655 function_ref Warn);
656656
657657 /// Scale up profile counts (including value profile data) by
658658 /// \p Weight.
659 void scale(uint64_t Weight);
659 void scale(uint64_t Weight, function_ref Warn);
660660
661661 /// Sort value profile data (per site) by count.
662662 void sortValueData() {
673673
674674 /// Clear value data entries
675675 void clearValueData() { ValueData = nullptr; }
676
677 /// Get the error contained within the record's soft error counter.
678 Error takeError() { return SIPE.takeError(); }
679676
680677 private:
681678 struct ValueProfData {
728725
729726 // Merge Value Profile data from Src record to this record for ValueKind.
730727 // Scale merged value counts by \p Weight.
731 void mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
732 uint64_t Weight);
728 void mergeValueProfData(uint32_t ValkeKind, InstrProfRecord &Src,
729 uint64_t Weight,
730 function_ref Warn);
733731
734732 // Scale up value profile data count.
735 void scaleValueProfData(uint32_t ValueKind, uint64_t Weight);
733 void scaleValueProfData(uint32_t ValueKind, uint64_t Weight,
734 function_ref Warn);
736735 };
737736
738737 struct NamedInstrProfRecord : InstrProfRecord {
5050 /// Add function counts for the given function. If there are already counts
5151 /// for this function and the hash and number of counts match, each counter is
5252 /// summed. Optionally scale counts by \p Weight.
53 Error addRecord(NamedInstrProfRecord &&I, uint64_t Weight = 1);
53 void addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
54 function_ref Warn);
55 void addRecord(NamedInstrProfRecord &&I, function_ref Warn) {
56 addRecord(std::move(I), 1, Warn);
57 }
5458
5559 /// Merge existing function counts from the given writer.
56 Error mergeRecordsFromWriter(InstrProfWriter &&IPW);
60 void mergeRecordsFromWriter(InstrProfWriter &&IPW,
61 function_ref Warn);
5762
5863 /// Write the profile to \c OS
5964 void write(raw_fd_ostream &OS);
8691 void setOutputSparse(bool Sparse);
8792
8893 private:
89 Error addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I,
90 uint64_t Weight = 1);
94 void addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I,
95 uint64_t Weight, function_ref Warn);
9196 bool shouldEncodeData(const ProfilingData &PD);
9297 void writeImpl(ProfOStream &OS);
9398 };
459459 return Error::success();
460460 }
461461
462 void InstrProfValueSiteRecord::merge(SoftInstrProfErrors &SIPE,
463 InstrProfValueSiteRecord &Input,
464 uint64_t Weight) {
462 void InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input,
463 uint64_t Weight,
464 function_ref Warn) {
465465 this->sortByTargetValues();
466466 Input.sortByTargetValues();
467467 auto I = ValueData.begin();
474474 bool Overflowed;
475475 I->Count = SaturatingMultiplyAdd(J->Count, Weight, I->Count, &Overflowed);
476476 if (Overflowed)
477 SIPE.addError(instrprof_error::counter_overflow);
477 Warn(instrprof_error::counter_overflow);
478478 ++I;
479479 continue;
480480 }
482482 }
483483 }
484484
485 void InstrProfValueSiteRecord::scale(SoftInstrProfErrors &SIPE,
486 uint64_t Weight) {
485 void InstrProfValueSiteRecord::scale(uint64_t Weight,
486 function_ref Warn) {
487487 for (auto I = ValueData.begin(), IE = ValueData.end(); I != IE; ++I) {
488488 bool Overflowed;
489489 I->Count = SaturatingMultiply(I->Count, Weight, &Overflowed);
490490 if (Overflowed)
491 SIPE.addError(instrprof_error::counter_overflow);
491 Warn(instrprof_error::counter_overflow);
492492 }
493493 }
494494
495495 // Merge Value Profile data from Src record to this record for ValueKind.
496496 // Scale merged value counts by \p Weight.
497 void InstrProfRecord::mergeValueProfData(uint32_t ValueKind,
498 InstrProfRecord &Src,
499 uint64_t Weight) {
497 void InstrProfRecord::mergeValueProfData(
498 uint32_t ValueKind, InstrProfRecord &Src, uint64_t Weight,
499 function_ref Warn) {
500500 uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
501501 uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind);
502502 if (ThisNumValueSites != OtherNumValueSites) {
503 SIPE.addError(instrprof_error::value_site_count_mismatch);
503 Warn(instrprof_error::value_site_count_mismatch);
504504 return;
505505 }
506506 if (!ThisNumValueSites)
510510 MutableArrayRef OtherSiteRecords =
511511 Src.getValueSitesForKind(ValueKind);
512512 for (uint32_t I = 0; I < ThisNumValueSites; I++)
513 ThisSiteRecords[I].merge(SIPE, OtherSiteRecords[I], Weight);
514 }
515
516 void InstrProfRecord::merge(InstrProfRecord &Other, uint64_t Weight) {
513 ThisSiteRecords[I].merge(OtherSiteRecords[I], Weight, Warn);
514 }
515
516 void InstrProfRecord::merge(InstrProfRecord &Other, uint64_t Weight,
517 function_ref Warn) {
517518 // If the number of counters doesn't match we either have bad data
518519 // or a hash collision.
519520 if (Counts.size() != Other.Counts.size()) {
520 SIPE.addError(instrprof_error::count_mismatch);
521 Warn(instrprof_error::count_mismatch);
521522 return;
522523 }
523524
526527 Counts[I] =
527528 SaturatingMultiplyAdd(Other.Counts[I], Weight, Counts[I], &Overflowed);
528529 if (Overflowed)
529 SIPE.addError(instrprof_error::counter_overflow);
530 Warn(instrprof_error::counter_overflow);
530531 }
531532
532533 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
533 mergeValueProfData(Kind, Other, Weight);
534 }
535
536 void InstrProfRecord::scaleValueProfData(uint32_t ValueKind, uint64_t Weight) {
534 mergeValueProfData(Kind, Other, Weight, Warn);
535 }
536
537 void InstrProfRecord::scaleValueProfData(
538 uint32_t ValueKind, uint64_t Weight,
539 function_ref Warn) {
537540 for (auto &R : getValueSitesForKind(ValueKind))
538 R.scale(SIPE, Weight);
539 }
540
541 void InstrProfRecord::scale(uint64_t Weight) {
541 R.scale(Weight, Warn);
542 }
543
544 void InstrProfRecord::scale(uint64_t Weight,
545 function_ref Warn) {
542546 for (auto &Count : this->Counts) {
543547 bool Overflowed;
544548 Count = SaturatingMultiply(Count, Weight, &Overflowed);
545549 if (Overflowed)
546 SIPE.addError(instrprof_error::counter_overflow);
550 Warn(instrprof_error::counter_overflow);
547551 }
548552 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
549 scaleValueProfData(Kind, Weight);
553 scaleValueProfData(Kind, Weight, Warn);
550554 }
551555
552556 // Map indirect call target name hash to name string.
175175 this->Sparse = Sparse;
176176 }
177177
178 Error InstrProfWriter::addRecord(NamedInstrProfRecord &&I, uint64_t Weight) {
178 void InstrProfWriter::addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
179 function_ref Warn) {
179180 auto Name = I.Name;
180181 auto Hash = I.Hash;
181 return addRecord(Name, Hash, std::move(I), Weight);
182 }
183
184 Error InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
185 InstrProfRecord &&I, uint64_t Weight) {
182 addRecord(Name, Hash, std::move(I), Weight, Warn);
183 }
184
185 void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
186 InstrProfRecord &&I, uint64_t Weight,
187 function_ref Warn) {
186188 auto &ProfileDataMap = FunctionData[Name];
187189
188190 bool NewFunc;
191193 ProfileDataMap.insert(std::make_pair(Hash, InstrProfRecord()));
192194 InstrProfRecord &Dest = Where->second;
193195
196 auto MapWarn = [&](instrprof_error E) {
197 Warn(make_error(E));
198 };
199
194200 if (NewFunc) {
195201 // We've never seen a function with this name and hash, add it.
196202 Dest = std::move(I);
197203 if (Weight > 1)
198 Dest.scale(Weight);
204 Dest.scale(Weight, MapWarn);
199205 } else {
200206 // We're updating a function we've seen before.
201 Dest.merge(I, Weight);
207 Dest.merge(I, Weight, MapWarn);
202208 }
203209
204210 Dest.sortValueData();
205
206 return Dest.takeError();
207 }
208
209 Error InstrProfWriter::mergeRecordsFromWriter(InstrProfWriter &&IPW) {
211 }
212
213 void InstrProfWriter::mergeRecordsFromWriter(InstrProfWriter &&IPW,
214 function_ref Warn) {
210215 for (auto &I : IPW.FunctionData)
211216 for (auto &Func : I.getValue())
212 if (Error E = addRecord(I.getKey(), Func.first, std::move(Func.second)))
213 return E;
214 return Error::success();
217 addRecord(I.getKey(), Func.first, std::move(Func.second), 1, Warn);
215218 }
216219
217220 bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) {
158158
159159 for (auto &I : *Reader) {
160160 const StringRef FuncName = I.Name;
161 if (Error E = WC->Writer.addRecord(std::move(I), Input.Weight)) {
161 bool Reported = false;
162 WC->Writer.addRecord(std::move(I), Input.Weight, [&](Error E) {
163 if (Reported) {
164 consumeError(std::move(E));
165 return;
166 }
167 Reported = true;
162168 // Only show hint the first time an error occurs.
163169 instrprof_error IPE = InstrProfError::take(std::move(E));
164170 std::unique_lock ErrGuard{WC->ErrLock};
165171 bool firstTime = WC->WriterErrorCodes.insert(IPE).second;
166172 handleMergeWriterError(make_error(IPE), Input.Filename,
167173 FuncName, firstTime);
168 }
174 });
169175 }
170176 if (Reader->hasError())
171177 WC->Err = Reader->getError();
173179
174180 /// Merge the \p Src writer context into \p Dst.
175181 static void mergeWriterContexts(WriterContext *Dst, WriterContext *Src) {
176 if (Error E = Dst->Writer.mergeRecordsFromWriter(std::move(Src->Writer)))
182 bool Reported = false;
183 Dst->Writer.mergeRecordsFromWriter(std::move(Src->Writer), [&](Error E) {
184 if (Reported) {
185 consumeError(std::move(E));
186 return;
187 }
188 Reported = true;
177189 Dst->Err = std::move(E);
190 });
178191 }
179192
180193 static void mergeInstrProfile(const WeightedFileVector &Inputs,
302302 }
303303 }
304304
305 static const auto Err = [](Error E) { FAIL(); };
306
305307 TEST_P(CoverageMappingTest, load_coverage_for_more_than_two_files) {
306 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"func", 0x1234, {0}}),
307 Succeeded());
308 ProfileWriter.addRecord({"func", 0x1234, {0}}, Err);
308309
309310 const char *FileNames[] = {"bar", "baz", "foo"};
310311 static const unsigned N = array_lengthof(FileNames);
325326 }
326327
327328 TEST_P(CoverageMappingTest, load_coverage_with_bogus_function_name) {
328 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"", 0x1234, {10}}), Succeeded());
329 ProfileWriter.addRecord({"", 0x1234, {10}}, Err);
329330 startFunction("", 0x1234);
330331 addCMR(Counter::getCounter(0), "foo", 1, 1, 5, 5);
331332 EXPECT_TRUE(ErrorEquals(coveragemap_error::malformed, loadCoverageMapping()));
332333 }
333334
334335 TEST_P(CoverageMappingTest, load_coverage_for_several_functions) {
335 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"func1", 0x1234, {10}}),
336 Succeeded());
337 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"func2", 0x2345, {20}}),
338 Succeeded());
336 ProfileWriter.addRecord({"func1", 0x1234, {10}}, Err);
337 ProfileWriter.addRecord({"func2", 0x2345, {20}}, Err);
339338
340339 startFunction("func1", 0x1234);
341340 addCMR(Counter::getCounter(0), "foo", 1, 1, 5, 5);
379378 }
380379
381380 TEST_P(CoverageMappingTest, basic_coverage_iteration) {
382 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"func", 0x1234, {30, 20, 10, 0}}),
383 Succeeded());
381 ProfileWriter.addRecord({"func", 0x1234, {30, 20, 10, 0}}, Err);
384382
385383 startFunction("func", 0x1234);
386384 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
428426 }
429427
430428 TEST_P(CoverageMappingTest, combine_regions) {
431 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"func", 0x1234, {10, 20, 30}}),
432 Succeeded());
429 ProfileWriter.addRecord({"func", 0x1234, {10, 20, 30}}, Err);
433430
434431 startFunction("func", 0x1234);
435432 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
447444 }
448445
449446 TEST_P(CoverageMappingTest, restore_combined_counter_after_nested_region) {
450 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"func", 0x1234, {10, 20, 40}}),
451 Succeeded());
447 ProfileWriter.addRecord({"func", 0x1234, {10, 20, 40}}, Err);
452448
453449 startFunction("func", 0x1234);
454450 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
468464 // If CodeRegions and ExpansionRegions cover the same area,
469465 // only counts of CodeRegions should be used.
470466 TEST_P(CoverageMappingTest, dont_combine_expansions) {
471 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"func", 0x1234, {10, 20}}),
472 Succeeded());
473 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"func", 0x1234, {0, 0}}),
474 Succeeded());
467 ProfileWriter.addRecord({"func", 0x1234, {10, 20}}, Err);
468 ProfileWriter.addRecord({"func", 0x1234, {0, 0}}, Err);
475469
476470 startFunction("func", 0x1234);
477471 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
491485
492486 // If an area is covered only by ExpansionRegions, they should be combinated.
493487 TEST_P(CoverageMappingTest, combine_expansions) {
494 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"func", 0x1234, {2, 3, 7}}),
495 Succeeded());
488 ProfileWriter.addRecord({"func", 0x1234, {2, 3, 7}}, Err);
496489
497490 startFunction("func", 0x1234);
498491 addCMR(Counter::getCounter(1), "include1", 1, 1, 1, 10);
513506 }
514507
515508 TEST_P(CoverageMappingTest, strip_filename_prefix) {
516 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"file1:func", 0x1234, {0}}),
517 Succeeded());
509 ProfileWriter.addRecord({"file1:func", 0x1234, {0}}, Err);
518510
519511 startFunction("file1:func", 0x1234);
520512 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
528520 }
529521
530522 TEST_P(CoverageMappingTest, strip_unknown_filename_prefix) {
531 EXPECT_THAT_ERROR(ProfileWriter.addRecord({":func", 0x1234, {0}}),
532 Succeeded());
523 ProfileWriter.addRecord({":func", 0x1234, {0}}, Err);
533524
534525 startFunction(":func", 0x1234);
535526 addCMR(Counter::getCounter(0), "", 1, 1, 9, 9);
543534 }
544535
545536 TEST_P(CoverageMappingTest, dont_detect_false_instantiations) {
546 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"foo", 0x1234, {10}}),
547 Succeeded());
548 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"bar", 0x2345, {20}}),
549 Succeeded());
537 ProfileWriter.addRecord({"foo", 0x1234, {10}}, Err);
538 ProfileWriter.addRecord({"bar", 0x2345, {20}}, Err);
550539
551540 startFunction("foo", 0x1234);
552541 addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10);
564553 }
565554
566555 TEST_P(CoverageMappingTest, load_coverage_for_expanded_file) {
567 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"func", 0x1234, {10}}),
568 Succeeded());
556 ProfileWriter.addRecord({"func", 0x1234, {10}}, Err);
569557
570558 startFunction("func", 0x1234);
571559 addCMR(Counter::getCounter(0), "expanded", 1, 1, 1, 10);
581569 }
582570
583571 TEST_P(CoverageMappingTest, skip_duplicate_function_record) {
584 EXPECT_THAT_ERROR(ProfileWriter.addRecord({"func", 0x1234, {1}}),
585 Succeeded());
572 ProfileWriter.addRecord({"func", 0x1234, {1}}, Err);
586573
587574 startFunction("func", 0x1234);
588575 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
6363 ASSERT_TRUE(Reader->begin() == Reader->end());
6464 }
6565
66 static const auto Err = [](Error E) {
67 consumeError(std::move(E));
68 FAIL();
69 };
70
6671 TEST_P(MaybeSparseInstrProfTest, write_and_read_one_function) {
67 EXPECT_THAT_ERROR(Writer.addRecord({"foo", 0x1234, {1, 2, 3, 4}}),
68 Succeeded());
72 Writer.addRecord({"foo", 0x1234, {1, 2, 3, 4}}, Err);
6973 auto Profile = Writer.writeBuffer();
7074 readProfile(std::move(Profile));
7175
8286 }
8387
8488 TEST_P(MaybeSparseInstrProfTest, get_instr_prof_record) {
85 EXPECT_THAT_ERROR(Writer.addRecord({"foo", 0x1234, {1, 2}}), Succeeded());
86 EXPECT_THAT_ERROR(Writer.addRecord({"foo", 0x1235, {3, 4}}), Succeeded());
89 Writer.addRecord({"foo", 0x1234, {1, 2}}, Err);
90 Writer.addRecord({"foo", 0x1235, {3, 4}}, Err);
8791 auto Profile = Writer.writeBuffer();
8892 readProfile(std::move(Profile));
8993
107111 }
108112
109113 TEST_P(MaybeSparseInstrProfTest, get_function_counts) {
110 EXPECT_THAT_ERROR(Writer.addRecord({"foo", 0x1234, {1, 2}}), Succeeded());
111 EXPECT_THAT_ERROR(Writer.addRecord({"foo", 0x1235, {3, 4}}), Succeeded());
114 Writer.addRecord({"foo", 0x1234, {1, 2}}, Err);
115 Writer.addRecord({"foo", 0x1235, {3, 4}}, Err);
112116 auto Profile = Writer.writeBuffer();
113117 readProfile(std::move(Profile));
114118
134138
135139 // Profile data is copied from general.proftext
136140 TEST_F(InstrProfTest, get_profile_summary) {
137 EXPECT_THAT_ERROR(Writer.addRecord({"func1", 0x1234, {97531}}), Succeeded());
138 EXPECT_THAT_ERROR(Writer.addRecord({"func2", 0x1234, {0, 0}}), Succeeded());
139 EXPECT_THAT_ERROR(Writer.addRecord({"func3",
140 0x1234,
141 {2305843009213693952, 1152921504606846976,
142 576460752303423488, 288230376151711744,
143 144115188075855872, 72057594037927936}}),
144 Succeeded());
145 EXPECT_THAT_ERROR(Writer.addRecord({"func4", 0x1234, {0}}), Succeeded());
141 Writer.addRecord({"func1", 0x1234, {97531}}, Err);
142 Writer.addRecord({"func2", 0x1234, {0, 0}}, Err);
143 Writer.addRecord(
144 {"func3",
145 0x1234,
146 {2305843009213693952, 1152921504606846976, 576460752303423488,
147 288230376151711744, 144115188075855872, 72057594037927936}},
148 Err);
149 Writer.addRecord({"func4", 0x1234, {0}}, Err);
146150 auto Profile = Writer.writeBuffer();
147151 readProfile(std::move(Profile));
148152
193197 }
194198
195199 TEST_F(InstrProfTest, test_writer_merge) {
196 EXPECT_THAT_ERROR(Writer.addRecord({"func1", 0x1234, {42}}), Succeeded());
200 Writer.addRecord({"func1", 0x1234, {42}}, Err);
197201
198202 InstrProfWriter Writer2;
199 EXPECT_THAT_ERROR(Writer2.addRecord({"func2", 0x1234, {0, 0}}), Succeeded());
200
201 EXPECT_THAT_ERROR(Writer.mergeRecordsFromWriter(std::move(Writer2)),
202 Succeeded());
203 Writer2.addRecord({"func2", 0x1234, {0, 0}}, Err);
204
205 Writer.mergeRecordsFromWriter(std::move(Writer2), Err);
203206
204207 auto Profile = Writer.writeBuffer();
205208 readProfile(std::move(Profile));
238241 InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}};
239242 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
240243
241 EXPECT_THAT_ERROR(Writer.addRecord(std::move(Record1)), Succeeded());
242 EXPECT_THAT_ERROR(Writer.addRecord({"callee1", 0x1235, {3, 4}}), Succeeded());
243 EXPECT_THAT_ERROR(Writer.addRecord({"callee2", 0x1235, {3, 4}}), Succeeded());
244 EXPECT_THAT_ERROR(Writer.addRecord({"callee3", 0x1235, {3, 4}}), Succeeded());
244 Writer.addRecord(std::move(Record1), Err);
245 Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
246 Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
247 Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);
245248 auto Profile = Writer.writeBuffer();
246249 readProfile(std::move(Profile));
247250
273276 InstrProfValueData VD0[] = {{1000, 1}, {2000, 2}, {3000, 3}, {5000, 5},
274277 {4000, 4}, {6000, 6}};
275278 Record.addValueData(IPVK_IndirectCallTarget, 0, VD0, 6, nullptr);
276 EXPECT_THAT_ERROR(Writer.addRecord(std::move(Record)), Succeeded());
279 Writer.addRecord(std::move(Record), Err);
277280 auto Profile = Writer.writeBuffer();
278281 readProfile(std::move(Profile));
279282 Expected R = Reader->getInstrProfRecord("caller", 0x1234);
378381 InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}};
379382 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
380383
381 EXPECT_THAT_ERROR(Writer.addRecord(std::move(Record1), 10), Succeeded());
382 EXPECT_THAT_ERROR(Writer.addRecord({"callee1", 0x1235, {3, 4}}), Succeeded());
383 EXPECT_THAT_ERROR(Writer.addRecord({"callee2", 0x1235, {3, 4}}), Succeeded());
384 EXPECT_THAT_ERROR(Writer.addRecord({"callee3", 0x1235, {3, 4}}), Succeeded());
384 Writer.addRecord(std::move(Record1), 10, Err);
385 Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
386 Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
387 Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);
385388 auto Profile = Writer.writeBuffer();
386389 readProfile(std::move(Profile));
387390
421424 InstrProfValueData VD3[] = {{(uint64_t)callee1, 1}};
422425 Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
423426
424 EXPECT_THAT_ERROR(Writer.addRecord(std::move(Record1)), Succeeded());
425 EXPECT_THAT_ERROR(Writer.addRecord({"callee1", 0x1235, {3, 4}}), Succeeded());
426 EXPECT_THAT_ERROR(Writer.addRecord({"callee2", 0x1235, {3, 4}}), Succeeded());
427 EXPECT_THAT_ERROR(Writer.addRecord({"callee3", 0x1235, {3, 4}}), Succeeded());
427 Writer.addRecord(std::move(Record1), Err);
428 Writer.addRecord({"callee1", 0x1235, {3, 4}}, Err);
429 Writer.addRecord({"callee2", 0x1235, {3, 4}}, Err);
430 Writer.addRecord({"callee3", 0x1235, {3, 4}}, Err);
428431
429432 // Set big endian output.
430433 Writer.setValueProfDataEndianness(support::big);
500503 {uint64_t(callee3), 3}};
501504 Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr);
502505
503 EXPECT_THAT_ERROR(Writer.addRecord(std::move(Record11)), Succeeded());
506 Writer.addRecord(std::move(Record11), Err);
504507 // Merge profile data.
505 EXPECT_THAT_ERROR(Writer.addRecord(std::move(Record12)), Succeeded());
506
507 EXPECT_THAT_ERROR(Writer.addRecord({callee1, 0x1235, {3, 4}}), Succeeded());
508 EXPECT_THAT_ERROR(Writer.addRecord({callee2, 0x1235, {3, 4}}), Succeeded());
509 EXPECT_THAT_ERROR(Writer.addRecord({callee3, 0x1235, {3, 4}}), Succeeded());
510 EXPECT_THAT_ERROR(Writer.addRecord({callee3, 0x1235, {3, 4}}), Succeeded());
511 EXPECT_THAT_ERROR(Writer.addRecord({callee4, 0x1235, {3, 5}}), Succeeded());
508 Writer.addRecord(std::move(Record12), Err);
509
510 Writer.addRecord({callee1, 0x1235, {3, 4}}, Err);
511 Writer.addRecord({callee2, 0x1235, {3, 4}}, Err);
512 Writer.addRecord({callee3, 0x1235, {3, 4}}, Err);
513 Writer.addRecord({callee3, 0x1235, {3, 4}}, Err);
514 Writer.addRecord({callee4, 0x1235, {3, 5}}, Err);
512515 auto Profile = Writer.writeBuffer();
513516 readProfile(std::move(Profile));
514517
563566
564567 const uint64_t Max = std::numeric_limits::max();
565568
566 auto Result1 = Writer.addRecord({"foo", 0x1234, {1}});
567 ASSERT_EQ(InstrProfError::take(std::move(Result1)),
568 instrprof_error::success);
569 instrprof_error Result;
570 auto Err = [&](Error E) { Result = InstrProfError::take(std::move(E)); };
571 Result = instrprof_error::success;
572 Writer.addRecord({"foo", 0x1234, {1}}, Err);
573 ASSERT_EQ(Result, instrprof_error::success);
569574
570575 // Verify counter overflow.
571 auto Result2 = Writer.addRecord({"foo", 0x1234, {Max}});
572 ASSERT_EQ(InstrProfError::take(std::move(Result2)),
573 instrprof_error::counter_overflow);
574
575 auto Result3 = Writer.addRecord({bar, 0x9012, {8}});
576 ASSERT_EQ(InstrProfError::take(std::move(Result3)),
577 instrprof_error::success);
576 Result = instrprof_error::success;
577 Writer.addRecord({"foo", 0x1234, {Max}}, Err);
578 ASSERT_EQ(Result, instrprof_error::counter_overflow);
579
580 Result = instrprof_error::success;
581 Writer.addRecord({bar, 0x9012, {8}}, Err);
582 ASSERT_EQ(Result, instrprof_error::success);
578583
579584 NamedInstrProfRecord Record4("baz", 0x5678, {3, 4});
580585 Record4.reserveSites(IPVK_IndirectCallTarget, 1);
581586 InstrProfValueData VD4[] = {{uint64_t(bar), 1}};
582587 Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr);
583 auto Result4 = Writer.addRecord(std::move(Record4));
584 ASSERT_EQ(InstrProfError::take(std::move(Result4)),
585 instrprof_error::success);
588 Result = instrprof_error::success;
589 Writer.addRecord(std::move(Record4), Err);
590 ASSERT_EQ(Result, instrprof_error::success);
586591
587592 // Verify value data counter overflow.
588593 NamedInstrProfRecord Record5("baz", 0x5678, {5, 6});
589594 Record5.reserveSites(IPVK_IndirectCallTarget, 1);
590595 InstrProfValueData VD5[] = {{uint64_t(bar), Max}};
591596 Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr);
592 auto Result5 = Writer.addRecord(std::move(Record5));
593 ASSERT_EQ(InstrProfError::take(std::move(Result5)),
594 instrprof_error::counter_overflow);
597 Result = instrprof_error::success;
598 Writer.addRecord(std::move(Record5), Err);
599 ASSERT_EQ(Result, instrprof_error::counter_overflow);
595600
596601 auto Profile = Writer.writeBuffer();
597602 readProfile(std::move(Profile));
642647 Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr);
643648 Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
644649
645 EXPECT_THAT_ERROR(Writer.addRecord(std::move(Record11)), Succeeded());
650 Writer.addRecord(std::move(Record11), Err);
646651 // Merge profile data.
647 EXPECT_THAT_ERROR(Writer.addRecord(std::move(Record12)), Succeeded());
652 Writer.addRecord(std::move(Record12), Err);
648653
649654 auto Profile = Writer.writeBuffer();
650655 readProfile(std::move(Profile));
789794 }
790795
791796 TEST_P(MaybeSparseInstrProfTest, get_max_function_count) {
792 EXPECT_THAT_ERROR(Writer.addRecord({"foo", 0x1234, {1ULL << 31, 2}}),
793 Succeeded());
794 EXPECT_THAT_ERROR(Writer.addRecord({"bar", 0, {1ULL << 63}}), Succeeded());
795 EXPECT_THAT_ERROR(Writer.addRecord({"baz", 0x5678, {0, 0, 0, 0}}),
796 Succeeded());
797 Writer.addRecord({"foo", 0x1234, {1ULL << 31, 2}}, Err);
798 Writer.addRecord({"bar", 0, {1ULL << 63}}, Err);
799 Writer.addRecord({"baz", 0x5678, {0, 0, 0, 0}}, Err);
797800 auto Profile = Writer.writeBuffer();
798801 readProfile(std::move(Profile));
799802
801804 }
802805
803806 TEST_P(MaybeSparseInstrProfTest, get_weighted_function_counts) {
804 EXPECT_THAT_ERROR(Writer.addRecord({"foo", 0x1234, {1, 2}}, 3), Succeeded());
805 EXPECT_THAT_ERROR(Writer.addRecord({"foo", 0x1235, {3, 4}}, 5), Succeeded());
807 Writer.addRecord({"foo", 0x1234, {1, 2}}, 3, Err);
808 Writer.addRecord({"foo", 0x1235, {3, 4}}, 5, Err);
806809 auto Profile = Writer.writeBuffer();
807810 readProfile(std::move(Profile));
808811
990993 }
991994
992995 TEST_F(SparseInstrProfTest, preserve_no_records) {
993 EXPECT_THAT_ERROR(Writer.addRecord({"foo", 0x1234, {0}}), Succeeded());
994 EXPECT_THAT_ERROR(Writer.addRecord({"bar", 0x4321, {0, 0}}), Succeeded());
996 Writer.addRecord({"foo", 0x1234, {0}}, Err);
997 Writer.addRecord({"bar", 0x4321, {0, 0}}, Err);
995998 // FIXME: I'm guessing this data should be different, but the original author
996999 // should check/update this test so it doesn't produce errors.
997 consumeError(Writer.addRecord({"bar", 0x4321, {0, 0, 0}}));
1000 Writer.addRecord({"bar", 0x4321, {0, 0, 0}},
1001 [](Error E) { consumeError(std::move(E)); });
9981002
9991003 auto Profile = Writer.writeBuffer();
10001004 readProfile(std::move(Profile));