llvm.org GIT mirror llvm / 6967efe
[llvm-profdata] Add overlap command to compute similarity b/w two profile files Add overlap functionality to llvm-profdata tool to compute the similarity between two profile files. Differential Revision: https://reviews.llvm.org/D60977 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359612 91177308-0d34-0410-b5e6-96231b3b80d8 Rong Xu 1 year, 5 months ago
17 changed file(s) with 718 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
1616
1717 * :ref:`merge `
1818 * :ref:`show `
19 * :ref:`overlap `
1920
2021 .. program:: llvm-profdata merge
2122
230231 Only show context sensitive profile counts. The default is to filter all
231232 context sensitive profile counts.
232233
234 .. program:: llvm-profdata overlap
235
236 .. _profdata-overlap:
237
238 OVERLAP
239 -------
240
241 SYNOPSIS
242 ^^^^^^^^
243
244 :program:`llvm-profdata overlap` [*options*] [*base profile file*] [*test profile file*]
245
246 DESCRIPTION
247 ^^^^^^^^^^^
248
249 :program:`llvm-profdata overlap` takes two profile data files and displays the
250 *overlap* of counter distribution between the whole files and between any of the
251 specified functions.
252
253 In this command, *overlap* is defined as follows:
254 Suppose *base profile file* has the following counts:
255 {c1_1, c1_2, ..., c1_n, c1_u_1, c2_u_2, ..., c2_u_s},
256 and *test profile file* has
257 {c2_1, c2_2, ..., c2_n, c2_v_1, c2_v_2, ..., c2_v_t}.
258 Here c{1|2}_i (i = 1 .. n) are matched counters and c1_u_i (i = 1 .. s) and
259 c2_v_i (i = 1 .. v) are unmatched counters (or counters only existing in)
260 *base profile file* and *test profile file*, respectively.
261 Let sum_1 = c1_1 + c1_2 + ... + c1_n + c1_u_1 + c2_u_2 + ... + c2_u_s, and
262 sum_2 = c2_1 + c2_2 + ... + c2_n + c2_v_1 + c2_v_2 + ... + c2_v_t.
263 *overlap* = min(c1_1/sum_1, c2_1/sum_2) + min(c1_2/sum_1, c2_2/sum_2) + ...
264 min(c1_n/sum_1, c2_n/sum_2).
265
266 The result overlap distribution is a percentage number, ranging from 0.0% to
267 100.0%, where 0.0% means there is no overlap and 100.0% means a perfect
268 overlap.
269
270 Here is an example, if *base profile file* has counts of {400, 600}, and
271 *test profile file* has matched counts of {60000, 40000}. The *overlap* is 80%.
272
273
274 OPTIONS
275 ^^^^^^^
276
277 .. option:: -function=string
278
279 Print details for a function if the function's name contains the given string.
280
281 .. option:: -help
282
283 Print a summary of command line options.
284
285 .. option:: -o=output or -o output
286
287 Specify the output file name. If *output* is ``-`` or it isn't specified,
288 then the output is sent to standard output.
289
290 .. option:: -value-cutoff=n
291
292 Show only those functions whose max count values are greater or equal to ``n``.
293 By default, the value-cutoff is set to max of unsigned long long.
294
295 .. option:: -cs
296
297 Only show overlap for the context sensitive profile counts. The default is to show
298 non-context sensitive profile counts.
299
233300 EXIT STATUS
234301 -----------
235302
589589 return PGOName.drop_front(S + 1);
590590 }
591591
592 // To store the sums of profile count values, or the percentage of
593 // the sums of the total count values.
594 struct CountSumOrPercent {
595 uint64_t NumEntries;
596 double CountSum;
597 double ValueCounts[IPVK_Last - IPVK_First + 1];
598 CountSumOrPercent() : NumEntries(0), CountSum(0.0f), ValueCounts() {}
599 void reset() {
600 NumEntries = 0;
601 CountSum = 0.0f;
602 for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++)
603 ValueCounts[I] = 0.0f;
604 }
605 };
606
607 // Function level or program level overlap information.
608 struct OverlapStats {
609 enum OverlapStatsLevel { ProgramLevel, FunctionLevel };
610 // Sum of the total count values for the base profile.
611 CountSumOrPercent Base;
612 // Sum of the total count values for the test profile.
613 CountSumOrPercent Test;
614 // Overlap lap score. Should be in range of [0.0f to 1.0f].
615 CountSumOrPercent Overlap;
616 CountSumOrPercent Mismatch;
617 CountSumOrPercent Unique;
618 OverlapStatsLevel Level;
619 const std::string *BaseFilename;
620 const std::string *TestFilename;
621 StringRef FuncName;
622 uint64_t FuncHash;
623 bool Valid;
624
625 OverlapStats(OverlapStatsLevel L = ProgramLevel)
626 : Level(L), BaseFilename(nullptr), TestFilename(nullptr), FuncHash(0),
627 Valid(false) {}
628
629 void dump(raw_fd_ostream &OS) const;
630
631 void setFuncInfo(StringRef Name, uint64_t Hash) {
632 FuncName = Name;
633 FuncHash = Hash;
634 }
635
636 Error accumuateCounts(const std::string &BaseFilename,
637 const std::string &TestFilename, bool IsCS);
638 void addOneMismatch(const CountSumOrPercent &MismatchFunc);
639 void addOneUnique(const CountSumOrPercent &UniqueFunc);
640
641 static inline double score(uint64_t Val1, uint64_t Val2, double Sum1,
642 double Sum2) {
643 if (Sum1 < 1.0f || Sum2 < 1.0f)
644 return 0.0f;
645 return std::min(Val1 / Sum1, Val2 / Sum2);
646 }
647 };
648
649 // This is used to filter the functions whose overlap information
650 // to be output.
651 struct OverlapFuncFilters {
652 uint64_t ValueCutoff;
653 const std::string NameFilter;
654 };
655
592656 struct InstrProfValueSiteRecord {
593657 /// Value profiling data pairs at a given value site.
594658 std::list ValueData;
614678 function_ref Warn);
615679 /// Scale up value profile data counts.
616680 void scale(uint64_t Weight, function_ref Warn);
681
682 /// Compute the overlap b/w this record and Input record.
683 void overlap(InstrProfValueSiteRecord &Input, uint32_t ValueKind,
684 OverlapStats &Overlap, OverlapStats &FuncLevelOverlap);
617685 };
618686
619687 /// Profiling information for a single function.
701769
702770 /// Clear value data entries
703771 void clearValueData() { ValueData = nullptr; }
772
773 /// Compute the sums of all counts and store in Sum.
774 void accumuateCounts(CountSumOrPercent &Sum) const;
775
776 /// Compute the overlap b/w this IntrprofRecord and Other.
777 void overlap(InstrProfRecord &Other, OverlapStats &Overlap,
778 OverlapStats &FuncLevelOverlap, uint64_t ValueCutoff);
779
780 /// Compute the overlap of value profile counts.
781 void overlapValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
782 OverlapStats &Overlap,
783 OverlapStats &FuncLevelOverlap);
704784
705785 private:
706786 struct ValueProfData {
10591139 void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput);
10601140
10611141 } // end namespace llvm
1062
10631142 #endif // LLVM_PROFILEDATA_INSTRPROF_H
8989 /// only used for dumping purpose with llvm-proftool, not with the
9090 /// compiler.
9191 virtual InstrProfSymtab &getSymtab() = 0;
92
93 /// Compute the sum of counts and return in Sum.
94 void accumuateCounts(CountSumOrPercent &Sum, bool IsCS);
9295
9396 protected:
9497 std::unique_ptr Symtab;
9999 // Internal interface for testing purpose only.
100100 void setValueProfDataEndianness(support::endianness Endianness);
101101 void setOutputSparse(bool Sparse);
102 // Compute the overlap b/w this object and Other. Program level result is
103 // stored in Overlap and function level result is stored in FuncLevelOverlap.
104 void overlapRecord(NamedInstrProfRecord &&Other, OverlapStats &Overlap,
105 OverlapStats &FuncLevelOverlap,
106 const OverlapFuncFilters &FuncFilter);
102107
103108 private:
104109 void addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I,
2828 #include "llvm/IR/Metadata.h"
2929 #include "llvm/IR/Module.h"
3030 #include "llvm/IR/Type.h"
31 #include "llvm/ProfileData/InstrProfReader.h"
3132 #include "llvm/Support/Casting.h"
3233 #include "llvm/Support/CommandLine.h"
3334 #include "llvm/Support/Compiler.h"
477478 return Error::success();
478479 }
479480
481 void InstrProfRecord::accumuateCounts(CountSumOrPercent &Sum) const {
482 uint64_t FuncSum = 0;
483 Sum.NumEntries += Counts.size();
484 for (size_t F = 0, E = Counts.size(); F < E; ++F)
485 FuncSum += Counts[F];
486 Sum.CountSum += FuncSum;
487
488 for (uint32_t VK = IPVK_First; VK <= IPVK_Last; ++VK) {
489 uint64_t KindSum = 0;
490 uint32_t NumValueSites = getNumValueSites(VK);
491 for (size_t I = 0; I < NumValueSites; ++I) {
492 uint32_t NV = getNumValueDataForSite(VK, I);
493 std::unique_ptr VD = getValueForSite(VK, I);
494 for (uint32_t V = 0; V < NV; V++)
495 KindSum += VD[V].Count;
496 }
497 Sum.ValueCounts[VK] += KindSum;
498 }
499 }
500
501 void InstrProfValueSiteRecord::overlap(InstrProfValueSiteRecord &Input,
502 uint32_t ValueKind,
503 OverlapStats &Overlap,
504 OverlapStats &FuncLevelOverlap) {
505 this->sortByTargetValues();
506 Input.sortByTargetValues();
507 double Score = 0.0f, FuncLevelScore = 0.0f;
508 auto I = ValueData.begin();
509 auto IE = ValueData.end();
510 auto J = Input.ValueData.begin();
511 auto JE = Input.ValueData.end();
512 while (I != IE && J != JE) {
513 if (I->Value == J->Value) {
514 Score += OverlapStats::score(I->Count, J->Count,
515 Overlap.Base.ValueCounts[ValueKind],
516 Overlap.Test.ValueCounts[ValueKind]);
517 FuncLevelScore += OverlapStats::score(
518 I->Count, J->Count, FuncLevelOverlap.Base.ValueCounts[ValueKind],
519 FuncLevelOverlap.Test.ValueCounts[ValueKind]);
520 ++I;
521 } else if (I->Value < J->Value) {
522 ++I;
523 continue;
524 }
525 ++J;
526 }
527 Overlap.Overlap.ValueCounts[ValueKind] += Score;
528 FuncLevelOverlap.Overlap.ValueCounts[ValueKind] += FuncLevelScore;
529 }
530
531 // Return false on mismatch.
532 void InstrProfRecord::overlapValueProfData(uint32_t ValueKind,
533 InstrProfRecord &Other,
534 OverlapStats &Overlap,
535 OverlapStats &FuncLevelOverlap) {
536 uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
537 uint32_t OtherNumValueSites = Other.getNumValueSites(ValueKind);
538 assert(ThisNumValueSites == OtherNumValueSites);
539 if (!ThisNumValueSites)
540 return;
541
542 std::vector &ThisSiteRecords =
543 getOrCreateValueSitesForKind(ValueKind);
544 MutableArrayRef OtherSiteRecords =
545 Other.getValueSitesForKind(ValueKind);
546 for (uint32_t I = 0; I < ThisNumValueSites; I++)
547 ThisSiteRecords[I].overlap(OtherSiteRecords[I], ValueKind, Overlap,
548 FuncLevelOverlap);
549 }
550
551 void InstrProfRecord::overlap(InstrProfRecord &Other, OverlapStats &Overlap,
552 OverlapStats &FuncLevelOverlap,
553 uint64_t ValueCutoff) {
554 // FuncLevel CountSum for other should already computed and nonzero.
555 assert(FuncLevelOverlap.Test.CountSum >= 1.0f);
556 accumuateCounts(FuncLevelOverlap.Base);
557 bool Mismatch = (Counts.size() != Other.Counts.size());
558
559 // Check if the value profiles mismatch.
560 if (!Mismatch) {
561 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
562 uint32_t ThisNumValueSites = getNumValueSites(Kind);
563 uint32_t OtherNumValueSites = Other.getNumValueSites(Kind);
564 if (ThisNumValueSites != OtherNumValueSites) {
565 Mismatch = true;
566 break;
567 }
568 }
569 }
570 if (Mismatch) {
571 Overlap.addOneMismatch(FuncLevelOverlap.Test);
572 return;
573 }
574
575 // Compute overlap for value counts.
576 for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
577 overlapValueProfData(Kind, Other, Overlap, FuncLevelOverlap);
578
579 double Score = 0.0;
580 uint64_t MaxCount = 0;
581 // Compute overlap for edge counts.
582 for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
583 Score += OverlapStats::score(Counts[I], Other.Counts[I],
584 Overlap.Base.CountSum, Overlap.Test.CountSum);
585 MaxCount = std::max(Other.Counts[I], MaxCount);
586 }
587 Overlap.Overlap.CountSum += Score;
588 Overlap.Overlap.NumEntries += 1;
589
590 if (MaxCount >= ValueCutoff) {
591 double FuncScore = 0.0;
592 for (size_t I = 0, E = Other.Counts.size(); I < E; ++I)
593 FuncScore += OverlapStats::score(Counts[I], Other.Counts[I],
594 FuncLevelOverlap.Base.CountSum,
595 FuncLevelOverlap.Test.CountSum);
596 FuncLevelOverlap.Overlap.CountSum = FuncScore;
597 FuncLevelOverlap.Overlap.NumEntries = Other.Counts.size();
598 FuncLevelOverlap.Valid = true;
599 }
600 }
601
480602 void InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input,
481603 uint64_t Weight,
482604 function_ref Warn) {
10451167 }
10461168 }
10471169
1170 Error OverlapStats::accumuateCounts(const std::string &BaseFilename,
1171 const std::string &TestFilename,
1172 bool IsCS) {
1173 auto getProfileSum = [IsCS](const std::string &Filename,
1174 CountSumOrPercent &Sum) -> Error {
1175 auto ReaderOrErr = InstrProfReader::create(Filename);
1176 if (Error E = ReaderOrErr.takeError()) {
1177 return E;
1178 }
1179 auto Reader = std::move(ReaderOrErr.get());
1180 Reader->accumuateCounts(Sum, IsCS);
1181 return Error::success();
1182 };
1183 auto Ret = getProfileSum(BaseFilename, Base);
1184 if (Ret)
1185 return std::move(Ret);
1186 Ret = getProfileSum(TestFilename, Test);
1187 if (Ret)
1188 return std::move(Ret);
1189 this->BaseFilename = &BaseFilename;
1190 this->TestFilename = &TestFilename;
1191 Valid = true;
1192 return Error::success();
1193 }
1194
1195 void OverlapStats::addOneMismatch(const CountSumOrPercent &MismatchFunc) {
1196 Mismatch.NumEntries += 1;
1197 Mismatch.CountSum += MismatchFunc.CountSum / Test.CountSum;
1198 for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
1199 if (Test.ValueCounts[I] >= 1.0f)
1200 Mismatch.ValueCounts[I] +=
1201 MismatchFunc.ValueCounts[I] / Test.ValueCounts[I];
1202 }
1203 }
1204
1205 void OverlapStats::addOneUnique(const CountSumOrPercent &UniqueFunc) {
1206 Unique.NumEntries += 1;
1207 Unique.CountSum += UniqueFunc.CountSum / Test.CountSum;
1208 for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
1209 if (Test.ValueCounts[I] >= 1.0f)
1210 Unique.ValueCounts[I] += UniqueFunc.ValueCounts[I] / Test.ValueCounts[I];
1211 }
1212 }
1213
1214 void OverlapStats::dump(raw_fd_ostream &OS) const {
1215 if (!Valid)
1216 return;
1217
1218 const char *EntryName =
1219 (Level == ProgramLevel ? "functions" : "edge counters");
1220 if (Level == ProgramLevel) {
1221 OS << "Profile overlap infomation for base_profile: " << *BaseFilename
1222 << " and test_profile: " << *TestFilename << "\nProgram level:\n";
1223 } else {
1224 OS << "Function level:\n"
1225 << " Function: " << FuncName << " (Hash=" << FuncHash << ")\n";
1226 }
1227
1228 OS << " # of " << EntryName << " overlap: " << Overlap.NumEntries << "\n";
1229 if (Mismatch.NumEntries)
1230 OS << " # of " << EntryName << " mismatch: " << Mismatch.NumEntries
1231 << "\n";
1232 if (Unique.NumEntries)
1233 OS << " # of " << EntryName
1234 << " only in test_profile: " << Unique.NumEntries << "\n";
1235
1236 OS << " Edge profile overlap: " << format("%.3f%%", Overlap.CountSum * 100)
1237 << "\n";
1238 if (Mismatch.NumEntries)
1239 OS << " Mismatched count percentage (Edge): "
1240 << format("%.3f%%", Mismatch.CountSum * 100) << "\n";
1241 if (Unique.NumEntries)
1242 OS << " Percentage of Edge profile only in test_profile: "
1243 << format("%.3f%%", Unique.CountSum * 100) << "\n";
1244 OS << " Edge profile base count sum: " << format("%.0f", Base.CountSum)
1245 << "\n"
1246 << " Edge profile test count sum: " << format("%.0f", Test.CountSum)
1247 << "\n";
1248
1249 for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
1250 if (Base.ValueCounts[I] < 1.0f && Test.ValueCounts[I] < 1.0f)
1251 continue;
1252 char ProfileKindName[20];
1253 switch (I) {
1254 case IPVK_IndirectCallTarget:
1255 strncpy(ProfileKindName, "IndirectCall", 19);
1256 break;
1257 case IPVK_MemOPSize:
1258 strncpy(ProfileKindName, "MemOP", 19);
1259 break;
1260 default:
1261 snprintf(ProfileKindName, 19, "VP[%d]", I);
1262 break;
1263 }
1264 OS << " " << ProfileKindName
1265 << " profile overlap: " << format("%.3f%%", Overlap.ValueCounts[I] * 100)
1266 << "\n";
1267 if (Mismatch.NumEntries)
1268 OS << " Mismatched count percentage (" << ProfileKindName
1269 << "): " << format("%.3f%%", Mismatch.ValueCounts[I] * 100) << "\n";
1270 if (Unique.NumEntries)
1271 OS << " Percentage of " << ProfileKindName
1272 << " profile only in test_profile: "
1273 << format("%.3f%%", Unique.ValueCounts[I] * 100) << "\n";
1274 OS << " " << ProfileKindName
1275 << " profile base count sum: " << format("%.0f", Base.ValueCounts[I])
1276 << "\n"
1277 << " " << ProfileKindName
1278 << " profile test count sum: " << format("%.0f", Test.ValueCounts[I])
1279 << "\n";
1280 }
1281 }
1282
10481283 } // end namespace llvm
899899 }
900900 return success();
901901 }
902
903 void InstrProfReader::accumuateCounts(CountSumOrPercent &Sum, bool IsCS) {
904 uint64_t NumFuncs = 0;
905 for (const auto &Func : *this) {
906 if (isIRLevelProfile()) {
907 bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
908 if (FuncIsCS != IsCS)
909 continue;
910 }
911 Func.accumuateCounts(Sum);
912 ++NumFuncs;
913 }
914 Sum.NumEntries = NumFuncs;
915 }
186186 addRecord(Name, Hash, std::move(I), Weight, Warn);
187187 }
188188
189 void InstrProfWriter::overlapRecord(NamedInstrProfRecord &&Other,
190 OverlapStats &Overlap,
191 OverlapStats &FuncLevelOverlap,
192 const OverlapFuncFilters &FuncFilter) {
193 auto Name = Other.Name;
194 auto Hash = Other.Hash;
195 Other.accumuateCounts(FuncLevelOverlap.Test);
196 if (FunctionData.find(Name) == FunctionData.end()) {
197 Overlap.addOneUnique(FuncLevelOverlap.Test);
198 return;
199 }
200 if (FuncLevelOverlap.Test.CountSum < 1.0f) {
201 Overlap.Overlap.NumEntries += 1;
202 return;
203 }
204 auto &ProfileDataMap = FunctionData[Name];
205 bool NewFunc;
206 ProfilingData::iterator Where;
207 std::tie(Where, NewFunc) =
208 ProfileDataMap.insert(std::make_pair(Hash, InstrProfRecord()));
209 if (NewFunc) {
210 Overlap.addOneMismatch(FuncLevelOverlap.Test);
211 return;
212 }
213 InstrProfRecord &Dest = Where->second;
214
215 uint64_t ValueCutoff = FuncFilter.ValueCutoff;
216 if (!FuncFilter.NameFilter.empty() &&
217 Name.find(FuncFilter.NameFilter) != Name.npos)
218 ValueCutoff = 0;
219
220 Dest.overlap(Other, Overlap, FuncLevelOverlap, ValueCutoff);
221 }
222
189223 void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
190224 InstrProfRecord &&I, uint64_t Weight,
191225 function_ref Warn) {
0 # IR level Instrumentation Flag
1 :ir
2 bar
3 # Func Hash:
4 12884901887
5 # Num Counters:
6 1
7 # Counter Values:
8 100000
9
10 bar1
11 # Func Hash:
12 12884901887
13 # Num Counters:
14 1
15 # Counter Values:
16 100000
17
18 foo
19 # Func Hash:
20 25571299074
21 # Num Counters:
22 2
23 # Counter Values:
24 40000
25 60000
26
27 main
28 # Func Hash:
29 29212902728
30 # Num Counters:
31 2
32 # Counter Values:
33 200000
34 0
35
0 # CSIR level Instrumentation Flag
1 :csir
2 bar
3 # Func Hash:
4 1152921534274394772
5 # Num Counters:
6 2
7 # Counter Values:
8 6000
9 4000
10
0 :IR
1 foo
2 # Func Hash:
3 72057649435042473
4 # Num Counters:
5 2
6 # Counter Values:
7 40000
8 60000
9 # Num Value Kinds:
10 2
11 # ValueKind = IPVK_IndirectCallTarget:
12 0
13 # NumValueSites:
14 1
15 2
16 bar1:40000
17 bar2:60000
18 # ValueKind = IPVK_MemOPSize:
19 1
20 # NumValueSites:
21 1
22 2
23 1:40000
24 4:60000
0 # IR level Instrumentation Flag
1 :ir
2 bar
3 # Func Hash:
4 12884901887
5 # Num Counters:
6 1
7 # Counter Values:
8 10000
9
10 bar2
11 # Func Hash:
12 12884901887
13 # Num Counters:
14 1
15 # Counter Values:
16 10000
17
18 foo
19 # Func Hash:
20 25571299075
21 # Num Counters:
22 2
23 # Counter Values:
24 4000
25 6000
26
27 main
28 # Func Hash:
29 29212902728
30 # Num Counters:
31 2
32 # Counter Values:
33 20000
34 0
35
0 # CSIR level Instrumentation Flag
1 :csir
2 bar
3 # Func Hash:
4 1152921534274394772
5 # Num Counters:
6 2
7 # Counter Values:
8 4000
9 6000
10
0 :IR
1 foo
2 # Func Hash:
3 72057649435042473
4 # Num Counters:
5 2
6 # Counter Values:
7 30000
8 20000
9 # Num Value Kinds:
10 2
11 # ValueKind = IPVK_IndirectCallTarget:
12 0
13 # NumValueSites:
14 1
15 2
16 bar1:30000
17 bar2:20000
18 # ValueKind = IPVK_MemOPSize:
19 1
20 # NumValueSites:
21 1
22 2
23 1:3000
24 4:2000
0 RUN: llvm-profdata overlap %p/Inputs/overlap_1.proftext %p/Inputs/overlap_2.proftext | FileCheck %s -check-prefix=OVERLAP
1 RUN: llvm-profdata overlap -function=main %p/Inputs/overlap_1.proftext %p/Inputs/overlap_2.proftext | FileCheck %s -check-prefix=MAINFUNC -check-prefix=OVERLAP
2 RUN: llvm-profdata overlap -value-cutoff=15000 %p/Inputs/overlap_1.proftext %p/Inputs/overlap_2.proftext | FileCheck %s -check-prefix=MAINFUNC -check-prefix=OVERLAP
3 RUN: llvm-profdata merge %p/Inputs/overlap_1.proftext -o %t_1.profdata
4 RUN: llvm-profdata merge %p/Inputs/overlap_2.proftext -o %t_2.profdata
5 RUN: llvm-profdata overlap %t_1.profdata %t_2.profdata | FileCheck %s -check-prefix=OVERLAP
6 MAINFUNC: Function: main (Hash=29212902728)
7 MAINFUNC: # of edge counters overlap: 2
8 MAINFUNC: Edge profile overlap: 100.000%
9 MAINFUNC: Edge profile base count sum: 200000
10 MAINFUNC: Edge profile test count sum: 20000
11 OVERLAP: Profile overlap infomation for base_profile: {{.*}} and test_profile:
12 OVERLAP: Program level:
13 OVERLAP: # of functions overlap: 2
14 OVERLAP: # of functions mismatch: 1
15 OVERLAP: # of functions only in test_profile: 1
16 OVERLAP: Edge profile overlap: 60.000%
17 OVERLAP: Mismatched count percentage (Edge): 20.000%
18 OVERLAP: Percentage of Edge profile only in test_profile: 20.000%
19 OVERLAP: Edge profile base count sum: 500000
20 OVERLAP: Edge profile test count sum: 50000
0 RUN: llvm-profdata overlap -cs %p/Inputs/overlap_1_cs.proftext %p/Inputs/overlap_2_cs.proftext | FileCheck %s -check-prefix=OVERLAP
1 RUN: llvm-profdata merge %p/Inputs/overlap_1_cs.proftext -o %t_1_cs.profdata
2 RUN: llvm-profdata merge %p/Inputs/overlap_2_cs.proftext -o %t_2_cs.profdata
3 RUN: llvm-profdata overlap -cs %t_1_cs.profdata %t_2_cs.profdata | FileCheck %s -check-prefix=OVERLAP
4 OVERLAP: Profile overlap infomation for base_profile: {{.*}} and test_profile:
5 OVERLAP: Program level:
6 OVERLAP: # of functions overlap: 1
7 OVERLAP: Edge profile overlap: 80.000%
8 OVERLAP: Edge profile base count sum: 10000
9 OVERLAP: Edge profile test count sum: 10000
0 RUN: llvm-profdata overlap %p/Inputs/overlap_1_vp.proftext %p/Inputs/overlap_2_vp.proftext | FileCheck %s -check-prefix=OVERLAP
1 RUN: llvm-profdata merge %p/Inputs/overlap_1_vp.proftext -o %t_1_vp.profdata
2 RUN: llvm-profdata merge %p/Inputs/overlap_2_vp.proftext -o %t_2_vp.profdata
3 RUN: llvm-profdata overlap %t_1_vp.profdata %t_2_vp.profdata | FileCheck %s -check-prefix=OVERLAP
4 OVERLAP: Profile overlap infomation for base_profile: {{.*}} and test_profile:
5 OVERLAP: Program level:
6 OVERLAP: # of functions overlap: 1
7 OVERLAP: Edge profile overlap: 80.000%
8 OVERLAP: Edge profile base count sum: 100000
9 OVERLAP: Edge profile test count sum: 50000
10 OVERLAP: IndirectCall profile overlap: 80.000%
11 OVERLAP: IndirectCall profile base count sum: 100000
12 OVERLAP: IndirectCall profile test count sum: 50000
13 OVERLAP: MemOP profile overlap: 80.000%
14 OVERLAP: MemOP profile base count sum: 100000
15 OVERLAP: MemOP profile test count sum: 5000
196196 case instrprof_error::counter_overflow:
197197 case instrprof_error::value_site_count_mismatch:
198198 return false;
199 }
200 }
201
202 /// Computer the overlap b/w profile BaseFilename and TestFileName,
203 /// and store the program level result to Overlap.
204 static void overlapInput(const std::string &BaseFilename,
205 const std::string &TestFilename, WriterContext *WC,
206 OverlapStats &Overlap,
207 const OverlapFuncFilters &FuncFilter,
208 raw_fd_ostream &OS, bool IsCS) {
209 auto ReaderOrErr = InstrProfReader::create(TestFilename);
210 if (Error E = ReaderOrErr.takeError()) {
211 // Skip the empty profiles by returning sliently.
212 instrprof_error IPE = InstrProfError::take(std::move(E));
213 if (IPE != instrprof_error::empty_raw_profile)
214 WC->Err = make_error(IPE);
215 return;
216 }
217
218 auto Reader = std::move(ReaderOrErr.get());
219 for (auto &I : *Reader) {
220 OverlapStats FuncOverlap(OverlapStats::FunctionLevel);
221 FuncOverlap.setFuncInfo(I.Name, I.Hash);
222
223 WC->Writer.overlapRecord(std::move(I), Overlap, FuncOverlap, FuncFilter);
224 FuncOverlap.dump(OS);
199225 }
200226 }
201227
607633 return 0;
608634 }
609635
636 /// Computer the overlap b/w profile BaseFilename and profile TestFilename.
637 static void overlapInstrProfile(const std::string &BaseFilename,
638 const std::string &TestFilename,
639 const OverlapFuncFilters &FuncFilter,
640 raw_fd_ostream &OS, bool IsCS) {
641 std::mutex ErrorLock;
642 SmallSet WriterErrorCodes;
643 WriterContext Context(false, ErrorLock, WriterErrorCodes);
644 WeightedFile WeightedInput{BaseFilename, 1};
645 OverlapStats Overlap;
646 Error E = Overlap.accumuateCounts(BaseFilename, TestFilename, IsCS);
647 if (E)
648 exitWithError(std::move(E), "Error in getting profile count sums");
649 if (Overlap.Base.CountSum < 1.0f) {
650 OS << "Sum of edge counts for profile " << BaseFilename << " is 0.\n";
651 exit(0);
652 }
653 if (Overlap.Test.CountSum < 1.0f) {
654 OS << "Sum of edge counts for profile " << TestFilename << " is 0.\n";
655 exit(0);
656 }
657 loadInput(WeightedInput, nullptr, &Context);
658 overlapInput(BaseFilename, TestFilename, &Context, Overlap, FuncFilter, OS,
659 IsCS);
660 Overlap.dump(OS);
661 }
662
663 static int overlap_main(int argc, const char *argv[]) {
664 cl::opt BaseFilename(cl::Positional, cl::Required,
665 cl::desc(""));
666 cl::opt TestFilename(cl::Positional, cl::Required,
667 cl::desc(""));
668 cl::opt Output("output", cl::value_desc("output"), cl::init("-"),
669 cl::desc("Output file"));
670 cl::alias OutputA("o", cl::desc("Alias for --output"), cl::aliasopt(Output));
671 cl::opt IsCS("cs", cl::init(false),
672 cl::desc("For context sensitive counts"));
673 cl::opt ValueCutoff(
674 "value-cutoff", cl::init(-1),
675 cl::desc(
676 "Function level overlap information for every function in test "
677 "profile with max count value greater then the parameter value"));
678 cl::opt FuncNameFilter(
679 "function",
680 cl::desc("Function level overlap information for matching functions"));
681 cl::ParseCommandLineOptions(argc, argv, "LLVM profile data overlap tool\n");
682
683 std::error_code EC;
684 raw_fd_ostream OS(Output.data(), EC, sys::fs::F_Text);
685 if (EC)
686 exitWithErrorCode(EC, Output);
687
688 overlapInstrProfile(BaseFilename, TestFilename,
689 OverlapFuncFilters{ValueCutoff, FuncNameFilter}, OS,
690 IsCS);
691
692 return 0;
693 }
694
610695 typedef struct ValueSitesStats {
611696 ValueSitesStats()
612697 : TotalNumValueSites(0), TotalNumValueSitesWithValueProfile(0),
9641049 func = merge_main;
9651050 else if (strcmp(argv[1], "show") == 0)
9661051 func = show_main;
1052 else if (strcmp(argv[1], "overlap") == 0)
1053 func = overlap_main;
9671054
9681055 if (func) {
9691056 std::string Invocation(ProgName.str() + " " + argv[1]);
9781065 << "USAGE: " << ProgName << " [args...]\n"
9791066 << "USAGE: " << ProgName << " -help\n\n"
9801067 << "See each individual command --help for more details.\n"
981 << "Available commands: merge, show\n";
1068 << "Available commands: merge, show, overlap\n";
9821069 return 0;
9831070 }
9841071 }
9881075 else
9891076 errs() << ProgName << ": Unknown command!\n";
9901077
991 errs() << "USAGE: " << ProgName << " > [args...]\n";
1078 errs() << "USAGE: " << ProgName << " |overlap> [args...]\n";
9921079 return 1;
9931080 }