llvm.org GIT mirror llvm / c96f87a
InstrProf: Support for value profiling in the indexed profile format Add support to the indexed instrprof reader and writer for the format that will be used for value profiling. Patch by Betul Buyukkurt, with minor modifications. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@248833 91177308-0d34-0410-b5e6-96231b3b80d8 Justin Bogner 3 years ago
10 changed file(s) with 364 addition(s) and 99 deletion(s). Raw diff Collapse all Expand all
1515 #ifndef LLVM_PROFILEDATA_INSTRPROF_H_
1616 #define LLVM_PROFILEDATA_INSTRPROF_H_
1717
18 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ADT/StringSet.h"
19 #include "llvm/Support/ErrorHandling.h"
1920 #include
21 #include
2022 #include
2123 #include
2224
2426 const std::error_category &instrprof_category();
2527
2628 enum class instrprof_error {
27 success = 0,
28 eof,
29 bad_magic,
30 bad_header,
31 unsupported_version,
32 unsupported_hash_type,
33 too_large,
34 truncated,
35 malformed,
36 unknown_function,
37 hash_mismatch,
38 count_mismatch,
39 counter_overflow
29 success = 0,
30 eof,
31 bad_magic,
32 bad_header,
33 unsupported_version,
34 unsupported_hash_type,
35 too_large,
36 truncated,
37 malformed,
38 unknown_function,
39 hash_mismatch,
40 count_mismatch,
41 counter_overflow,
42 value_site_count_mismatch
4043 };
4144
4245 inline std::error_code make_error_code(instrprof_error E) {
4346 return std::error_code(static_cast(E), instrprof_category());
4447 }
48
49 enum InstrProfValueKind : uint32_t {
50 IPVK_IndirectCallTarget = 0,
51
52 IPVK_First = IPVK_IndirectCallTarget,
53 IPVK_Last = IPVK_IndirectCallTarget
54 };
55
56 struct InstrProfStringTable {
57 // Set of string values in profiling data.
58 StringSet<> StringValueSet;
59 InstrProfStringTable() { StringValueSet.clear(); }
60 // Get a pointer to internal storage of a string in set
61 const char *getStringData(StringRef Str) {
62 auto Result = StringValueSet.find(Str);
63 return (Result == StringValueSet.end()) ? nullptr : Result->first().data();
64 }
65 // Insert a string to StringTable
66 const char *insertString(StringRef Str) {
67 auto Result = StringValueSet.insert(Str);
68 return Result.first->first().data();
69 }
70 };
71
72 struct InstrProfValueSiteRecord {
73 /// Typedef for a single TargetValue-NumTaken pair.
74 typedef std::pair ValueDataPair;
75 /// Value profiling data pairs at a given value site.
76 std::list ValueData;
77
78 InstrProfValueSiteRecord() { ValueData.clear(); }
79
80 /// Sort ValueData ascending by TargetValue
81 void sortByTargetValues() {
82 ValueData.sort([](const ValueDataPair &left, const ValueDataPair &right) {
83 return left.first < right.first;
84 });
85 }
86
87 /// Merge data from another InstrProfValueSiteRecord
88 void mergeValueData(InstrProfValueSiteRecord &Input) {
89 this->sortByTargetValues();
90 Input.sortByTargetValues();
91 auto I = ValueData.begin();
92 auto IE = ValueData.end();
93 for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE;
94 ++J) {
95 while (I != IE && I->first < J->first)
96 ++I;
97 if (I != IE && I->first == J->first) {
98 I->second += J->second;
99 ++I;
100 continue;
101 }
102 ValueData.insert(I, *J);
103 }
104 }
105 };
45106
46107 /// Profiling information for a single function.
47108 struct InstrProfRecord {
51112 StringRef Name;
52113 uint64_t Hash;
53114 std::vector Counts;
115 std::vector IndirectCallSites;
116
117 const std::vector &
118 getValueSitesForKind(uint32_t ValueKind) const {
119 switch (ValueKind) {
120 case IPVK_IndirectCallTarget:
121 return IndirectCallSites;
122 }
123 llvm_unreachable("Unknown value kind!");
124 }
125
126 std::vector &
127 getValueSitesForKind(uint32_t ValueKind) {
128 return const_cast &>(
129 this->getValueSitesForKind(ValueKind));
130 }
54131 };
55132
56133 } // end namespace llvm
6464 InstrProfIterator end() { return InstrProfIterator(); }
6565
6666 protected:
67 /// String table for holding a unique copy of all the strings in the profile.
68 InstrProfStringTable StringTable;
69
6770 /// Set the current std::error_code and return same.
6871 std::error_code error(std::error_code EC) {
6972 LastError = EC;
194197 std::vector DataBuffer;
195198 IndexedInstrProf::HashT HashType;
196199 unsigned FormatVersion;
200 std::vector> HashKeys;
197201
198202 public:
199203 InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion)
208212
209213 static bool EqualKey(StringRef A, StringRef B) { return A == B; }
210214 static StringRef GetInternalKey(StringRef K) { return K; }
215 static StringRef GetExternalKey(StringRef K) { return K; }
211216
212217 hash_value_type ComputeHash(StringRef K);
213218
219 void setHashKeys(std::vector> HashKeys) {
220 this->HashKeys = std::move(HashKeys);
221 }
214222 static std::pair
215223 ReadKeyDataLength(const unsigned char *&D) {
216224 using namespace support;
223231 return StringRef((const char *)D, N);
224232 }
225233
234 bool ReadValueProfilingData(const unsigned char *&D,
235 const unsigned char *const End);
226236 data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
227237 };
228238
1414 #ifndef LLVM_PROFILEDATA_INSTRPROFWRITER_H
1515 #define LLVM_PROFILEDATA_INSTRPROFWRITER_H
1616
17 #include "llvm/ADT/ArrayRef.h"
1817 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/ADT/StringMap.h"
2018 #include "llvm/ProfileData/InstrProf.h"
2119 #include "llvm/Support/DataTypes.h"
2220 #include "llvm/Support/MemoryBuffer.h"
2321 #include "llvm/Support/raw_ostream.h"
24 #include
2522
2623 namespace llvm {
2724
2825 /// Writer for instrumentation based profile data.
2926 class InstrProfWriter {
3027 public:
31 typedef SmallDenseMapstd::vector, 1> CounterData;
28 typedef SmallDenseMapInstrProfRecord, 1> ProfilingData;
29
3230 private:
33 StringMap FunctionData;
31 InstrProfStringTable StringTable;
32 StringMap FunctionData;
3433 uint64_t MaxFunctionCount;
3534 public:
3635 InstrProfWriter() : MaxFunctionCount(0) {}
3736
37 /// Update string entries in profile data with references to StringTable.
38 void updateStringTableReferences(InstrProfRecord &I);
3839 /// Add function counts for the given function. If there are already counts
3940 /// for this function and the hash and number of counts match, each counter is
4041 /// summed.
41 std::error_code addFunctionCounts(StringRef FunctionName,
42 uint64_t FunctionHash,
43 ArrayRef Counters);
42 std::error_code addRecord(InstrProfRecord &&I);
4443 /// Write the profile to \c OS
4544 void write(raw_fd_ostream &OS);
4645 /// Write the profile, returning the raw data. For testing.
4949 return "Function count mismatch";
5050 case instrprof_error::counter_overflow:
5151 return "Counter overflow";
52 case instrprof_error::value_site_count_mismatch:
53 return "Function's value site counts mismatch";
5254 }
5355 llvm_unreachable("A value of instrprof_error has no message.");
5456 }
4646 }
4747
4848 const uint64_t Magic = 0x8169666f72706cff; // "\xfflprofi\x81"
49 const uint64_t Version = 2;
49 const uint64_t Version = 3;
5050 const HashT HashType = HashT::MD5;
5151 }
5252
301301 typedef InstrProfLookupTrait::data_type data_type;
302302 typedef InstrProfLookupTrait::offset_type offset_type;
303303
304 bool InstrProfLookupTrait::ReadValueProfilingData(
305 const unsigned char *&D, const unsigned char *const End) {
306
307 using namespace support;
308 // Read number of value kinds with value sites.
309 if (D + sizeof(uint64_t) > End)
310 return false;
311 uint64_t ValueKindCount = endian::readNext(D);
312
313 for (uint32_t Kind = 0; Kind < ValueKindCount; ++Kind) {
314
315 // Read value kind and number of value sites for kind.
316 if (D + 2 * sizeof(uint64_t) > End)
317 return false;
318 uint64_t ValueKind = endian::readNext(D);
319 uint64_t ValueSiteCount = endian::readNext(D);
320
321 std::vector &ValueSites =
322 DataBuffer.back().getValueSitesForKind(ValueKind);
323 ValueSites.reserve(ValueSiteCount);
324 for (uint64_t VSite = 0; VSite < ValueSiteCount; ++VSite) {
325 // Read number of value data pairs at value site.
326 if (D + sizeof(uint64_t) > End)
327 return false;
328 uint64_t ValueDataCount =
329 endian::readNext(D);
330
331 // Check if there are as many ValueDataPairs as ValueDataCount in memory.
332 if (D + (ValueDataCount << 1) * sizeof(uint64_t) > End)
333 return false;
334
335 InstrProfValueSiteRecord VSiteRecord;
336 for (uint64_t VCount = 0; VCount < ValueDataCount; ++VCount) {
337 uint64_t Value = endian::readNext(D);
338 uint64_t NumTaken = endian::readNext(D);
339 switch (ValueKind) {
340 case IPVK_IndirectCallTarget: {
341 auto Result =
342 std::lower_bound(HashKeys.begin(), HashKeys.end(), Value,
343 [](const std::pair &LHS,
344 uint64_t RHS) { return LHS.first < RHS; });
345 assert(Result != HashKeys.end() &&
346 "Hash does not match any known keys\n");
347 Value = (uint64_t)Result->second;
348 break;
349 }
350 }
351 VSiteRecord.ValueData.push_back(std::make_pair(Value, NumTaken));
352 }
353 ValueSites.push_back(std::move(VSiteRecord));
354 }
355 }
356 return true;
357 }
358
304359 data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
305360 offset_type N) {
306
307361 // Check if the data is corrupt. If so, don't try to read it.
308362 if (N % sizeof(uint64_t))
309363 return data_type();
310364
311365 DataBuffer.clear();
312 uint64_t NumCounts;
313 uint64_t NumEntries = N / sizeof(uint64_t);
314366 std::vector CounterBuffer;
315 for (uint64_t I = 0; I < NumEntries; I += NumCounts) {
316 using namespace support;
317 // The function hash comes first.
367
368 using namespace support;
369 const unsigned char *End = D + N;
370 while (D < End) {
371 // Read hash
372 if (D + sizeof(uint64_t) >= End)
373 return data_type();
318374 uint64_t Hash = endian::readNext(D);
319375
320 if (++I >= NumEntries)
376 // Initialize number of counters for FormatVersion == 1
377 uint64_t CountsSize = N / sizeof(uint64_t) - 1;
378 // If format version is different then read number of counters
379 if (FormatVersion != 1) {
380 if (D + sizeof(uint64_t) > End)
381 return data_type();
382 CountsSize = endian::readNext(D);
383 }
384 // Read counter values
385 if (D + CountsSize * sizeof(uint64_t) > End)
321386 return data_type();
322387
323 // In v1, we have at least one count.
324 // Later, we have the number of counts.
325 NumCounts = (1 == FormatVersion)
326 ? NumEntries - I
327 : endian::readNext(D);
328 if (1 != FormatVersion)
329 ++I;
330
331 // If we have more counts than data, this is bogus.
332 if (I + NumCounts > NumEntries)
388 CounterBuffer.clear();
389 CounterBuffer.reserve(CountsSize);
390 for (uint64_t J = 0; J < CountsSize; ++J)
391 CounterBuffer.push_back(endian::readNext(D));
392
393 DataBuffer.push_back(InstrProfRecord(K, Hash, std::move(CounterBuffer)));
394
395 // Read value profiling data
396 if (FormatVersion > 2 && !ReadValueProfilingData(D, End)) {
397 DataBuffer.clear();
333398 return data_type();
334
335 CounterBuffer.clear();
336 for (unsigned J = 0; J < NumCounts; ++J)
337 CounterBuffer.push_back(endian::readNext(D));
338
339 DataBuffer.push_back(InstrProfRecord(K, Hash, std::move(CounterBuffer)));
399 }
340400 }
341401 return DataBuffer;
342402 }
383443 Index.reset(InstrProfReaderIndex::Create(
384444 Start + HashOffset, Cur, Start,
385445 InstrProfLookupTrait(HashType, FormatVersion)));
446
447 // Form the map of hash values to const char* keys in profiling data.
448 std::vector> HashKeys;
449 for (auto Key : Index->keys()) {
450 const char *KeyTableRef = StringTable.insertString(Key);
451 HashKeys.push_back(std::make_pair(ComputeHash(HashType, Key), KeyTableRef));
452 }
453 std::sort(HashKeys.begin(), HashKeys.end(), less_first());
454 std::unique(HashKeys.begin(), HashKeys.end(), less_first());
455 HashKeys.erase(std::unique(HashKeys.begin(), HashKeys.end()), HashKeys.end());
456 // Set the hash key map for the InstrLookupTrait
457 Index->getInfoObj().setHashKeys(std::move(HashKeys));
386458 // Set up our iterator for readNextRecord.
387459 RecordIterator = Index->data_begin();
388460
2525 typedef StringRef key_type;
2626 typedef StringRef key_type_ref;
2727
28 typedef const InstrProfWriter::CounterData *const data_type;
29 typedef const InstrProfWriter::CounterData *const data_type_ref;
28 typedef const InstrProfWriter::ProfilingData *const data_type;
29 typedef const InstrProfWriter::ProfilingData *const data_type_ref;
3030
3131 typedef uint64_t hash_value_type;
3232 typedef uint64_t offset_type;
4444 LE.write(N);
4545
4646 offset_type M = 0;
47 for (const auto &Counts : *V)
48 M += (2 + Counts.second.size()) * sizeof(uint64_t);
47 for (const auto &ProfileData : *V) {
48 M += sizeof(uint64_t); // The function hash
49 M += sizeof(uint64_t); // The size of the Counts vector
50 M += ProfileData.second.Counts.size() * sizeof(uint64_t);
51
52 // Value data
53 M += sizeof(uint64_t); // Number of value kinds with value sites.
54 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
55 const std::vector &ValueSites =
56 ProfileData.second.getValueSitesForKind(Kind);
57 if (ValueSites.empty())
58 continue;
59 M += sizeof(uint64_t); // Value kind
60 M += sizeof(uint64_t); // The number of value sites for given value kind
61 for (InstrProfValueSiteRecord I : ValueSites) {
62 M += sizeof(uint64_t); // Number of value data pairs at a value site
63 M += 2 * sizeof(uint64_t) * I.ValueData.size(); // Value data pairs
64 }
65 }
66 }
4967 LE.write(M);
5068
5169 return std::make_pair(N, M);
5977 offset_type) {
6078 using namespace llvm::support;
6179 endian::Writer LE(Out);
62
63 for (const auto &Counts : *V) {
64 LE.write(Counts.first);
65 LE.write(Counts.second.size());
66 for (uint64_t I : Counts.second)
80 for (const auto &ProfileData : *V) {
81 LE.write(ProfileData.first); // Function hash
82 LE.write(ProfileData.second.Counts.size());
83 for (uint64_t I : ProfileData.second.Counts)
6784 LE.write(I);
85
86 // Compute the number of value kinds with value sites.
87 uint64_t NumValueKinds = 0;
88 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
89 NumValueKinds +=
90 !(ProfileData.second.getValueSitesForKind(Kind).empty());
91 LE.write(NumValueKinds);
92
93 // Write value data
94 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
95 const std::vector &ValueSites =
96 ProfileData.second.getValueSitesForKind(Kind);
97 if (ValueSites.empty())
98 continue;
99 LE.write(Kind); // Write value kind
100 // Write number of value sites for current value kind
101 LE.write(ValueSites.size());
102 for (InstrProfValueSiteRecord I : ValueSites) {
103 // Write number of value data pairs at this value site
104 LE.write(I.ValueData.size());
105 for (auto V : I.ValueData) {
106 if (Kind == IPVK_IndirectCallTarget)
107 LE.write(ComputeHash((const char *)V.first));
108 else
109 LE.write(V.first);
110 LE.write(V.second);
111 }
112 }
113 }
68114 }
69115 }
70116 };
71117 }
72118
73 std::error_code
74 InstrProfWriter::addFunctionCounts(StringRef FunctionName,
75 uint64_t FunctionHash,
76 ArrayRef Counters) {
77 auto &CounterData = FunctionData[FunctionName];
78
79 auto Where = CounterData.find(FunctionHash);
80 if (Where == CounterData.end()) {
119 static std::error_code combineInstrProfRecords(InstrProfRecord &Dest,
120 InstrProfRecord &Source,
121 uint64_t &MaxFunctionCount) {
122 // If the number of counters doesn't match we either have bad data
123 // or a hash collision.
124 if (Dest.Counts.size() != Source.Counts.size())
125 return instrprof_error::count_mismatch;
126
127 for (size_t I = 0, E = Source.Counts.size(); I < E; ++I) {
128 if (Dest.Counts[I] + Source.Counts[I] < Dest.Counts[I])
129 return instrprof_error::counter_overflow;
130 Dest.Counts[I] += Source.Counts[I];
131 }
132
133 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
134
135 std::vector &SourceValueSites =
136 Source.getValueSitesForKind(Kind);
137 if (SourceValueSites.empty())
138 continue;
139
140 std::vector &DestValueSites =
141 Dest.getValueSitesForKind(Kind);
142
143 if (DestValueSites.empty()) {
144 DestValueSites.swap(SourceValueSites);
145 continue;
146 }
147
148 if (DestValueSites.size() != SourceValueSites.size())
149 return instrprof_error::value_site_count_mismatch;
150 for (size_t I = 0, E = SourceValueSites.size(); I < E; ++I)
151 DestValueSites[I].mergeValueData(SourceValueSites[I]);
152 }
153
154 // We keep track of the max function count as we go for simplicity.
155 if (Dest.Counts[0] > MaxFunctionCount)
156 MaxFunctionCount = Dest.Counts[0];
157
158 return instrprof_error::success;
159 }
160
161 void InstrProfWriter::updateStringTableReferences(InstrProfRecord &I) {
162 I.Name = StringTable.insertString(I.Name);
163 for (auto &VSite : I.IndirectCallSites)
164 for (auto &VData : VSite.ValueData)
165 VData.first =
166 (uint64_t)StringTable.insertString((const char *)VData.first);
167 }
168
169 std::error_code InstrProfWriter::addRecord(InstrProfRecord &&I) {
170 updateStringTableReferences(I);
171 auto &ProfileDataMap = FunctionData[I.Name];
172
173 auto Where = ProfileDataMap.find(I.Hash);
174 if (Where == ProfileDataMap.end()) {
81175 // We've never seen a function with this name and hash, add it.
82 CounterData[FunctionHash] = Counters;
176 ProfileDataMap[I.Hash] = I;
177
83178 // We keep track of the max function count as we go for simplicity.
84 if (Counters[0] > MaxFunctionCount)
85 MaxFunctionCount = Counters[0];
179 if (I.Counts[0] > MaxFunctionCount)
180 MaxFunctionCount = I.Counts[0];
86181 return instrprof_error::success;
87182 }
88183
89184 // We're updating a function we've seen before.
90 auto &FoundCounters = Where->second;
91 // If the number of counters doesn't match we either have bad data or a hash
92 // collision.
93 if (FoundCounters.size() != Counters.size())
94 return instrprof_error::count_mismatch;
95
96 for (size_t I = 0, E = Counters.size(); I < E; ++I) {
97 if (FoundCounters[I] + Counters[I] < FoundCounters[I])
98 return instrprof_error::counter_overflow;
99 FoundCounters[I] += Counters[I];
100 }
101 // We keep track of the max function count as we go for simplicity.
102 if (FoundCounters[0] > MaxFunctionCount)
103 MaxFunctionCount = FoundCounters[0];
104
105 return instrprof_error::success;
185 return combineInstrProfRecords(Where->second, I, MaxFunctionCount);
106186 }
107187
108188 std::pair InstrProfWriter::writeImpl(raw_ostream &OS) {
5757 exitWithError(ec.message(), Filename);
5858
5959 auto Reader = std::move(ReaderOrErr.get());
60 for (const auto &I : *Reader)
61 if (std::error_code EC =
62 Writer.addFunctionCounts(I.Name, I.Hash, I.Counts))
60 for (auto &I : *Reader)
61 if (std::error_code EC = Writer.addRecord(std::move(I)))
6362 errs() << Filename << ": " << I.Name << ": " << EC.message() << "\n";
6463 if (Reader->hasError())
6564 exitWithError(Reader->getError().message(), Filename);
133132 }
134133
135134 static int showInstrProfile(std::string Filename, bool ShowCounts,
136 bool ShowAllFunctions, std::string ShowFunction,
137 raw_fd_ostream &OS) {
135 bool ShowIndirectCallTargets, bool ShowAllFunctions,
136 std::string ShowFunction, raw_fd_ostream &OS) {
138137 auto ReaderOrErr = InstrProfReader::create(Filename);
139138 if (std::error_code EC = ReaderOrErr.getError())
140139 exitWithError(EC.message(), Filename);
161160 << " Hash: " << format("0x%016" PRIx64, Func.Hash) << "\n"
162161 << " Counters: " << Func.Counts.size() << "\n"
163162 << " Function count: " << Func.Counts[0] << "\n";
163 if (ShowIndirectCallTargets)
164 OS << " Indirect Call Site Count: " << Func.IndirectCallSites.size()
165 << "\n";
164166 }
165167
166168 if (Show && ShowCounts)
173175 }
174176 if (Show && ShowCounts)
175177 OS << "]\n";
178
179 if (Show && ShowIndirectCallTargets) {
180 OS << " Indirect Target Results: \n";
181 for (size_t I = 0, E = Func.IndirectCallSites.size(); I < E; ++I) {
182 for (auto V : Func.IndirectCallSites[I].ValueData) {
183 OS << "\t[ " << I << ", ";
184 OS << (const char *)V.first << ", " << V.second << " ]\n";
185 }
186 }
187 }
176188 }
177189 if (Reader->hasError())
178190 exitWithError(Reader->getError().message(), Filename);
211223
212224 cl::opt ShowCounts("counts", cl::init(false),
213225 cl::desc("Show counter values for shown functions"));
226 cl::opt ShowIndirectCallTargets(
227 "ic-targets", cl::init(false),
228 cl::desc("Show indirect call site target values for shown functions"));
214229 cl::opt ShowAllFunctions("all-functions", cl::init(false),
215230 cl::desc("Details for every function"));
216231 cl::opt ShowFunction("function",
239254 errs() << "warning: -function argument ignored: showing all functions\n";
240255
241256 if (ProfileKind == instr)
242 return showInstrProfile(Filename, ShowCounts, ShowAllFunctions,
243 ShowFunction, OS);
257 return showInstrProfile(Filename, ShowCounts, ShowIndirectCallTargets,
258 ShowAllFunctions, ShowFunction, OS);
244259 else
245260 return showSampleProfile(Filename, ShowCounts, ShowAllFunctions,
246261 ShowFunction, OS);
187187 }
188188
189189 TEST_F(CoverageMappingTest, basic_coverage_iteration) {
190 ProfileWriter.addFunctionCounts("func", 0x1234, {30, 20, 10, 0});
190 InstrProfRecord Record("func", 0x1234, {30, 20, 10, 0});
191 ProfileWriter.addRecord(std::move(Record));
191192 readProfCounts();
192193
193194 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
237238 }
238239
239240 TEST_F(CoverageMappingTest, combine_regions) {
240 ProfileWriter.addFunctionCounts("func", 0x1234, {10, 20, 30});
241 InstrProfRecord Record("func", 0x1234, {10, 20, 30});
242 ProfileWriter.addRecord(std::move(Record));
241243 readProfCounts();
242244
243245 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
255257 }
256258
257259 TEST_F(CoverageMappingTest, dont_combine_expansions) {
258 ProfileWriter.addFunctionCounts("func", 0x1234, {10, 20});
260 InstrProfRecord Record("func", 0x1234, {10, 20});
261 ProfileWriter.addRecord(std::move(Record));
259262 readProfCounts();
260263
261264 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
274277 }
275278
276279 TEST_F(CoverageMappingTest, strip_filename_prefix) {
277 ProfileWriter.addFunctionCounts("file1:func", 0x1234, {10});
280 InstrProfRecord Record("file1:func", 0x1234, {10});
281 ProfileWriter.addRecord(std::move(Record));
278282 readProfCounts();
279283
280284 addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
4949 }
5050
5151 TEST_F(InstrProfTest, write_and_read_one_function) {
52 Writer.addFunctionCounts("foo", 0x1234, {1, 2, 3, 4});
52 InstrProfRecord Record("foo", 0x1234, {1, 2, 3, 4});
53 Writer.addRecord(std::move(Record));
5354 auto Profile = Writer.writeBuffer();
5455 readProfile(std::move(Profile));
5556
6667 }
6768
6869 TEST_F(InstrProfTest, get_function_counts) {
69 Writer.addFunctionCounts("foo", 0x1234, {1, 2});
70 Writer.addFunctionCounts("foo", 0x1235, {3, 4});
70 InstrProfRecord Record1("foo", 0x1234, {1, 2});
71 InstrProfRecord Record2("foo", 0x1235, {3, 4});
72 Writer.addRecord(std::move(Record1));
73 Writer.addRecord(std::move(Record2));
7174 auto Profile = Writer.writeBuffer();
7275 readProfile(std::move(Profile));
7376
9194 }
9295
9396 TEST_F(InstrProfTest, get_max_function_count) {
94 Writer.addFunctionCounts("foo", 0x1234, {1ULL << 31, 2});
95 Writer.addFunctionCounts("bar", 0, {1ULL << 63});
96 Writer.addFunctionCounts("baz", 0x5678, {0, 0, 0, 0});
97 InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2});
98 InstrProfRecord Record2("bar", 0, {1ULL << 63});
99 InstrProfRecord Record3("baz", 0x5678, {0, 0, 0, 0});
100 Writer.addRecord(std::move(Record1));
101 Writer.addRecord(std::move(Record2));
102 Writer.addRecord(std::move(Record3));
97103 auto Profile = Writer.writeBuffer();
98104 readProfile(std::move(Profile));
99105