[llvm] r359612 - [llvm-profdata] Add overlap command to compute similarity b/w two profile files
Rong Xu via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 30 14:19:12 PDT 2019
Author: xur
Date: Tue Apr 30 14:19:12 2019
New Revision: 359612
URL: http://llvm.org/viewvc/llvm-project?rev=359612&view=rev
Log:
[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
Added:
llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1.proftext
llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1_cs.proftext
llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1_vp.proftext
llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2.proftext
llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2_cs.proftext
llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2_vp.proftext
llvm/trunk/test/tools/llvm-profdata/overlap.test
llvm/trunk/test/tools/llvm-profdata/overlap_cs.test
llvm/trunk/test/tools/llvm-profdata/overlap_vp.test
Modified:
llvm/trunk/docs/CommandGuide/llvm-profdata.rst
llvm/trunk/include/llvm/ProfileData/InstrProf.h
llvm/trunk/include/llvm/ProfileData/InstrProfReader.h
llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h
llvm/trunk/lib/ProfileData/InstrProf.cpp
llvm/trunk/lib/ProfileData/InstrProfReader.cpp
llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp
Modified: llvm/trunk/docs/CommandGuide/llvm-profdata.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/llvm-profdata.rst?rev=359612&r1=359611&r2=359612&view=diff
==============================================================================
--- llvm/trunk/docs/CommandGuide/llvm-profdata.rst (original)
+++ llvm/trunk/docs/CommandGuide/llvm-profdata.rst Tue Apr 30 14:19:12 2019
@@ -17,6 +17,7 @@ COMMANDS
* :ref:`merge <profdata-merge>`
* :ref:`show <profdata-show>`
+* :ref:`overlap <profdata-overlap>`
.. program:: llvm-profdata merge
@@ -231,6 +232,72 @@ OPTIONS
Only show context sensitive profile counts. The default is to filter all
context sensitive profile counts.
+.. program:: llvm-profdata overlap
+
+.. _profdata-overlap:
+
+OVERLAP
+-------
+
+SYNOPSIS
+^^^^^^^^
+
+:program:`llvm-profdata overlap` [*options*] [*base profile file*] [*test profile file*]
+
+DESCRIPTION
+^^^^^^^^^^^
+
+:program:`llvm-profdata overlap` takes two profile data files and displays the
+*overlap* of counter distribution between the whole files and between any of the
+specified functions.
+
+In this command, *overlap* is defined as follows:
+Suppose *base profile file* has the following counts:
+{c1_1, c1_2, ..., c1_n, c1_u_1, c2_u_2, ..., c2_u_s},
+and *test profile file* has
+{c2_1, c2_2, ..., c2_n, c2_v_1, c2_v_2, ..., c2_v_t}.
+Here c{1|2}_i (i = 1 .. n) are matched counters and c1_u_i (i = 1 .. s) and
+c2_v_i (i = 1 .. v) are unmatched counters (or counters only existing in)
+*base profile file* and *test profile file*, respectively.
+Let sum_1 = c1_1 + c1_2 + ... + c1_n + c1_u_1 + c2_u_2 + ... + c2_u_s, and
+sum_2 = c2_1 + c2_2 + ... + c2_n + c2_v_1 + c2_v_2 + ... + c2_v_t.
+*overlap* = min(c1_1/sum_1, c2_1/sum_2) + min(c1_2/sum_1, c2_2/sum_2) + ...
+ min(c1_n/sum_1, c2_n/sum_2).
+
+The result overlap distribution is a percentage number, ranging from 0.0% to
+100.0%, where 0.0% means there is no overlap and 100.0% means a perfect
+overlap.
+
+Here is an example, if *base profile file* has counts of {400, 600}, and
+*test profile file* has matched counts of {60000, 40000}. The *overlap* is 80%.
+
+
+OPTIONS
+^^^^^^^
+
+.. option:: -function=string
+
+ Print details for a function if the function's name contains the given string.
+
+.. option:: -help
+
+ Print a summary of command line options.
+
+.. option:: -o=output or -o output
+
+ Specify the output file name. If *output* is ``-`` or it isn't specified,
+ then the output is sent to standard output.
+
+.. option:: -value-cutoff=n
+
+ Show only those functions whose max count values are greater or equal to ``n``.
+ By default, the value-cutoff is set to max of unsigned long long.
+
+.. option:: -cs
+
+ Only show overlap for the context sensitive profile counts. The default is to show
+ non-context sensitive profile counts.
+
EXIT STATUS
-----------
Modified: llvm/trunk/include/llvm/ProfileData/InstrProf.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProf.h?rev=359612&r1=359611&r2=359612&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/InstrProf.h (original)
+++ llvm/trunk/include/llvm/ProfileData/InstrProf.h Tue Apr 30 14:19:12 2019
@@ -590,6 +590,70 @@ StringRef InstrProfSymtab::getOrigFuncNa
return PGOName.drop_front(S + 1);
}
+// To store the sums of profile count values, or the percentage of
+// the sums of the total count values.
+struct CountSumOrPercent {
+ uint64_t NumEntries;
+ double CountSum;
+ double ValueCounts[IPVK_Last - IPVK_First + 1];
+ CountSumOrPercent() : NumEntries(0), CountSum(0.0f), ValueCounts() {}
+ void reset() {
+ NumEntries = 0;
+ CountSum = 0.0f;
+ for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++)
+ ValueCounts[I] = 0.0f;
+ }
+};
+
+// Function level or program level overlap information.
+struct OverlapStats {
+ enum OverlapStatsLevel { ProgramLevel, FunctionLevel };
+ // Sum of the total count values for the base profile.
+ CountSumOrPercent Base;
+ // Sum of the total count values for the test profile.
+ CountSumOrPercent Test;
+ // Overlap lap score. Should be in range of [0.0f to 1.0f].
+ CountSumOrPercent Overlap;
+ CountSumOrPercent Mismatch;
+ CountSumOrPercent Unique;
+ OverlapStatsLevel Level;
+ const std::string *BaseFilename;
+ const std::string *TestFilename;
+ StringRef FuncName;
+ uint64_t FuncHash;
+ bool Valid;
+
+ OverlapStats(OverlapStatsLevel L = ProgramLevel)
+ : Level(L), BaseFilename(nullptr), TestFilename(nullptr), FuncHash(0),
+ Valid(false) {}
+
+ void dump(raw_fd_ostream &OS) const;
+
+ void setFuncInfo(StringRef Name, uint64_t Hash) {
+ FuncName = Name;
+ FuncHash = Hash;
+ }
+
+ Error accumuateCounts(const std::string &BaseFilename,
+ const std::string &TestFilename, bool IsCS);
+ void addOneMismatch(const CountSumOrPercent &MismatchFunc);
+ void addOneUnique(const CountSumOrPercent &UniqueFunc);
+
+ static inline double score(uint64_t Val1, uint64_t Val2, double Sum1,
+ double Sum2) {
+ if (Sum1 < 1.0f || Sum2 < 1.0f)
+ return 0.0f;
+ return std::min(Val1 / Sum1, Val2 / Sum2);
+ }
+};
+
+// This is used to filter the functions whose overlap information
+// to be output.
+struct OverlapFuncFilters {
+ uint64_t ValueCutoff;
+ const std::string NameFilter;
+};
+
struct InstrProfValueSiteRecord {
/// Value profiling data pairs at a given value site.
std::list<InstrProfValueData> ValueData;
@@ -615,6 +679,10 @@ struct InstrProfValueSiteRecord {
function_ref<void(instrprof_error)> Warn);
/// Scale up value profile data counts.
void scale(uint64_t Weight, function_ref<void(instrprof_error)> Warn);
+
+ /// Compute the overlap b/w this record and Input record.
+ void overlap(InstrProfValueSiteRecord &Input, uint32_t ValueKind,
+ OverlapStats &Overlap, OverlapStats &FuncLevelOverlap);
};
/// Profiling information for a single function.
@@ -703,6 +771,18 @@ struct InstrProfRecord {
/// Clear value data entries
void clearValueData() { ValueData = nullptr; }
+ /// Compute the sums of all counts and store in Sum.
+ void accumuateCounts(CountSumOrPercent &Sum) const;
+
+ /// Compute the overlap b/w this IntrprofRecord and Other.
+ void overlap(InstrProfRecord &Other, OverlapStats &Overlap,
+ OverlapStats &FuncLevelOverlap, uint64_t ValueCutoff);
+
+ /// Compute the overlap of value profile counts.
+ void overlapValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
+ OverlapStats &Overlap,
+ OverlapStats &FuncLevelOverlap);
+
private:
struct ValueProfData {
std::vector<InstrProfValueSiteRecord> IndirectCallSites;
@@ -1060,5 +1140,4 @@ void createIRLevelProfileFlagVar(Module
void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput);
} // end namespace llvm
-
#endif // LLVM_PROFILEDATA_INSTRPROF_H
Modified: llvm/trunk/include/llvm/ProfileData/InstrProfReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProfReader.h?rev=359612&r1=359611&r2=359612&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/InstrProfReader.h (original)
+++ llvm/trunk/include/llvm/ProfileData/InstrProfReader.h Tue Apr 30 14:19:12 2019
@@ -91,6 +91,9 @@ public:
/// compiler.
virtual InstrProfSymtab &getSymtab() = 0;
+ /// Compute the sum of counts and return in Sum.
+ void accumuateCounts(CountSumOrPercent &Sum, bool IsCS);
+
protected:
std::unique_ptr<InstrProfSymtab> Symtab;
Modified: llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h?rev=359612&r1=359611&r2=359612&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h (original)
+++ llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h Tue Apr 30 14:19:12 2019
@@ -100,6 +100,11 @@ public:
// Internal interface for testing purpose only.
void setValueProfDataEndianness(support::endianness Endianness);
void setOutputSparse(bool Sparse);
+ // Compute the overlap b/w this object and Other. Program level result is
+ // stored in Overlap and function level result is stored in FuncLevelOverlap.
+ void overlapRecord(NamedInstrProfRecord &&Other, OverlapStats &Overlap,
+ OverlapStats &FuncLevelOverlap,
+ const OverlapFuncFilters &FuncFilter);
private:
void addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I,
Modified: llvm/trunk/lib/ProfileData/InstrProf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProf.cpp?rev=359612&r1=359611&r2=359612&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/InstrProf.cpp (original)
+++ llvm/trunk/lib/ProfileData/InstrProf.cpp Tue Apr 30 14:19:12 2019
@@ -29,6 +29,7 @@
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
+#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
@@ -478,6 +479,127 @@ Error readPGOFuncNameStrings(StringRef N
return Error::success();
}
+void InstrProfRecord::accumuateCounts(CountSumOrPercent &Sum) const {
+ uint64_t FuncSum = 0;
+ Sum.NumEntries += Counts.size();
+ for (size_t F = 0, E = Counts.size(); F < E; ++F)
+ FuncSum += Counts[F];
+ Sum.CountSum += FuncSum;
+
+ for (uint32_t VK = IPVK_First; VK <= IPVK_Last; ++VK) {
+ uint64_t KindSum = 0;
+ uint32_t NumValueSites = getNumValueSites(VK);
+ for (size_t I = 0; I < NumValueSites; ++I) {
+ uint32_t NV = getNumValueDataForSite(VK, I);
+ std::unique_ptr<InstrProfValueData[]> VD = getValueForSite(VK, I);
+ for (uint32_t V = 0; V < NV; V++)
+ KindSum += VD[V].Count;
+ }
+ Sum.ValueCounts[VK] += KindSum;
+ }
+}
+
+void InstrProfValueSiteRecord::overlap(InstrProfValueSiteRecord &Input,
+ uint32_t ValueKind,
+ OverlapStats &Overlap,
+ OverlapStats &FuncLevelOverlap) {
+ this->sortByTargetValues();
+ Input.sortByTargetValues();
+ double Score = 0.0f, FuncLevelScore = 0.0f;
+ auto I = ValueData.begin();
+ auto IE = ValueData.end();
+ auto J = Input.ValueData.begin();
+ auto JE = Input.ValueData.end();
+ while (I != IE && J != JE) {
+ if (I->Value == J->Value) {
+ Score += OverlapStats::score(I->Count, J->Count,
+ Overlap.Base.ValueCounts[ValueKind],
+ Overlap.Test.ValueCounts[ValueKind]);
+ FuncLevelScore += OverlapStats::score(
+ I->Count, J->Count, FuncLevelOverlap.Base.ValueCounts[ValueKind],
+ FuncLevelOverlap.Test.ValueCounts[ValueKind]);
+ ++I;
+ } else if (I->Value < J->Value) {
+ ++I;
+ continue;
+ }
+ ++J;
+ }
+ Overlap.Overlap.ValueCounts[ValueKind] += Score;
+ FuncLevelOverlap.Overlap.ValueCounts[ValueKind] += FuncLevelScore;
+}
+
+// Return false on mismatch.
+void InstrProfRecord::overlapValueProfData(uint32_t ValueKind,
+ InstrProfRecord &Other,
+ OverlapStats &Overlap,
+ OverlapStats &FuncLevelOverlap) {
+ uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
+ uint32_t OtherNumValueSites = Other.getNumValueSites(ValueKind);
+ assert(ThisNumValueSites == OtherNumValueSites);
+ if (!ThisNumValueSites)
+ return;
+
+ std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
+ getOrCreateValueSitesForKind(ValueKind);
+ MutableArrayRef<InstrProfValueSiteRecord> OtherSiteRecords =
+ Other.getValueSitesForKind(ValueKind);
+ for (uint32_t I = 0; I < ThisNumValueSites; I++)
+ ThisSiteRecords[I].overlap(OtherSiteRecords[I], ValueKind, Overlap,
+ FuncLevelOverlap);
+}
+
+void InstrProfRecord::overlap(InstrProfRecord &Other, OverlapStats &Overlap,
+ OverlapStats &FuncLevelOverlap,
+ uint64_t ValueCutoff) {
+ // FuncLevel CountSum for other should already computed and nonzero.
+ assert(FuncLevelOverlap.Test.CountSum >= 1.0f);
+ accumuateCounts(FuncLevelOverlap.Base);
+ bool Mismatch = (Counts.size() != Other.Counts.size());
+
+ // Check if the value profiles mismatch.
+ if (!Mismatch) {
+ for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) {
+ uint32_t ThisNumValueSites = getNumValueSites(Kind);
+ uint32_t OtherNumValueSites = Other.getNumValueSites(Kind);
+ if (ThisNumValueSites != OtherNumValueSites) {
+ Mismatch = true;
+ break;
+ }
+ }
+ }
+ if (Mismatch) {
+ Overlap.addOneMismatch(FuncLevelOverlap.Test);
+ return;
+ }
+
+ // Compute overlap for value counts.
+ for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
+ overlapValueProfData(Kind, Other, Overlap, FuncLevelOverlap);
+
+ double Score = 0.0;
+ uint64_t MaxCount = 0;
+ // Compute overlap for edge counts.
+ for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
+ Score += OverlapStats::score(Counts[I], Other.Counts[I],
+ Overlap.Base.CountSum, Overlap.Test.CountSum);
+ MaxCount = std::max(Other.Counts[I], MaxCount);
+ }
+ Overlap.Overlap.CountSum += Score;
+ Overlap.Overlap.NumEntries += 1;
+
+ if (MaxCount >= ValueCutoff) {
+ double FuncScore = 0.0;
+ for (size_t I = 0, E = Other.Counts.size(); I < E; ++I)
+ FuncScore += OverlapStats::score(Counts[I], Other.Counts[I],
+ FuncLevelOverlap.Base.CountSum,
+ FuncLevelOverlap.Test.CountSum);
+ FuncLevelOverlap.Overlap.CountSum = FuncScore;
+ FuncLevelOverlap.Overlap.NumEntries = Other.Counts.size();
+ FuncLevelOverlap.Valid = true;
+ }
+}
+
void InstrProfValueSiteRecord::merge(InstrProfValueSiteRecord &Input,
uint64_t Weight,
function_ref<void(instrprof_error)> Warn) {
@@ -1046,4 +1168,117 @@ void createProfileFileNameVar(Module &M,
}
}
+Error OverlapStats::accumuateCounts(const std::string &BaseFilename,
+ const std::string &TestFilename,
+ bool IsCS) {
+ auto getProfileSum = [IsCS](const std::string &Filename,
+ CountSumOrPercent &Sum) -> Error {
+ auto ReaderOrErr = InstrProfReader::create(Filename);
+ if (Error E = ReaderOrErr.takeError()) {
+ return E;
+ }
+ auto Reader = std::move(ReaderOrErr.get());
+ Reader->accumuateCounts(Sum, IsCS);
+ return Error::success();
+ };
+ auto Ret = getProfileSum(BaseFilename, Base);
+ if (Ret)
+ return std::move(Ret);
+ Ret = getProfileSum(TestFilename, Test);
+ if (Ret)
+ return std::move(Ret);
+ this->BaseFilename = &BaseFilename;
+ this->TestFilename = &TestFilename;
+ Valid = true;
+ return Error::success();
+}
+
+void OverlapStats::addOneMismatch(const CountSumOrPercent &MismatchFunc) {
+ Mismatch.NumEntries += 1;
+ Mismatch.CountSum += MismatchFunc.CountSum / Test.CountSum;
+ for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
+ if (Test.ValueCounts[I] >= 1.0f)
+ Mismatch.ValueCounts[I] +=
+ MismatchFunc.ValueCounts[I] / Test.ValueCounts[I];
+ }
+}
+
+void OverlapStats::addOneUnique(const CountSumOrPercent &UniqueFunc) {
+ Unique.NumEntries += 1;
+ Unique.CountSum += UniqueFunc.CountSum / Test.CountSum;
+ for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
+ if (Test.ValueCounts[I] >= 1.0f)
+ Unique.ValueCounts[I] += UniqueFunc.ValueCounts[I] / Test.ValueCounts[I];
+ }
+}
+
+void OverlapStats::dump(raw_fd_ostream &OS) const {
+ if (!Valid)
+ return;
+
+ const char *EntryName =
+ (Level == ProgramLevel ? "functions" : "edge counters");
+ if (Level == ProgramLevel) {
+ OS << "Profile overlap infomation for base_profile: " << *BaseFilename
+ << " and test_profile: " << *TestFilename << "\nProgram level:\n";
+ } else {
+ OS << "Function level:\n"
+ << " Function: " << FuncName << " (Hash=" << FuncHash << ")\n";
+ }
+
+ OS << " # of " << EntryName << " overlap: " << Overlap.NumEntries << "\n";
+ if (Mismatch.NumEntries)
+ OS << " # of " << EntryName << " mismatch: " << Mismatch.NumEntries
+ << "\n";
+ if (Unique.NumEntries)
+ OS << " # of " << EntryName
+ << " only in test_profile: " << Unique.NumEntries << "\n";
+
+ OS << " Edge profile overlap: " << format("%.3f%%", Overlap.CountSum * 100)
+ << "\n";
+ if (Mismatch.NumEntries)
+ OS << " Mismatched count percentage (Edge): "
+ << format("%.3f%%", Mismatch.CountSum * 100) << "\n";
+ if (Unique.NumEntries)
+ OS << " Percentage of Edge profile only in test_profile: "
+ << format("%.3f%%", Unique.CountSum * 100) << "\n";
+ OS << " Edge profile base count sum: " << format("%.0f", Base.CountSum)
+ << "\n"
+ << " Edge profile test count sum: " << format("%.0f", Test.CountSum)
+ << "\n";
+
+ for (unsigned I = 0; I < IPVK_Last - IPVK_First + 1; I++) {
+ if (Base.ValueCounts[I] < 1.0f && Test.ValueCounts[I] < 1.0f)
+ continue;
+ char ProfileKindName[20];
+ switch (I) {
+ case IPVK_IndirectCallTarget:
+ strncpy(ProfileKindName, "IndirectCall", 19);
+ break;
+ case IPVK_MemOPSize:
+ strncpy(ProfileKindName, "MemOP", 19);
+ break;
+ default:
+ snprintf(ProfileKindName, 19, "VP[%d]", I);
+ break;
+ }
+ OS << " " << ProfileKindName
+ << " profile overlap: " << format("%.3f%%", Overlap.ValueCounts[I] * 100)
+ << "\n";
+ if (Mismatch.NumEntries)
+ OS << " Mismatched count percentage (" << ProfileKindName
+ << "): " << format("%.3f%%", Mismatch.ValueCounts[I] * 100) << "\n";
+ if (Unique.NumEntries)
+ OS << " Percentage of " << ProfileKindName
+ << " profile only in test_profile: "
+ << format("%.3f%%", Unique.ValueCounts[I] * 100) << "\n";
+ OS << " " << ProfileKindName
+ << " profile base count sum: " << format("%.0f", Base.ValueCounts[I])
+ << "\n"
+ << " " << ProfileKindName
+ << " profile test count sum: " << format("%.0f", Test.ValueCounts[I])
+ << "\n";
+ }
+}
+
} // end namespace llvm
Modified: llvm/trunk/lib/ProfileData/InstrProfReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfReader.cpp?rev=359612&r1=359611&r2=359612&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/InstrProfReader.cpp (original)
+++ llvm/trunk/lib/ProfileData/InstrProfReader.cpp Tue Apr 30 14:19:12 2019
@@ -900,3 +900,17 @@ Error IndexedInstrProfReader::readNextRe
}
return success();
}
+
+void InstrProfReader::accumuateCounts(CountSumOrPercent &Sum, bool IsCS) {
+ uint64_t NumFuncs = 0;
+ for (const auto &Func : *this) {
+ if (isIRLevelProfile()) {
+ bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
+ if (FuncIsCS != IsCS)
+ continue;
+ }
+ Func.accumuateCounts(Sum);
+ ++NumFuncs;
+ }
+ Sum.NumEntries = NumFuncs;
+}
Modified: llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfWriter.cpp?rev=359612&r1=359611&r2=359612&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/InstrProfWriter.cpp (original)
+++ llvm/trunk/lib/ProfileData/InstrProfWriter.cpp Tue Apr 30 14:19:12 2019
@@ -187,6 +187,40 @@ void InstrProfWriter::addRecord(NamedIns
addRecord(Name, Hash, std::move(I), Weight, Warn);
}
+void InstrProfWriter::overlapRecord(NamedInstrProfRecord &&Other,
+ OverlapStats &Overlap,
+ OverlapStats &FuncLevelOverlap,
+ const OverlapFuncFilters &FuncFilter) {
+ auto Name = Other.Name;
+ auto Hash = Other.Hash;
+ Other.accumuateCounts(FuncLevelOverlap.Test);
+ if (FunctionData.find(Name) == FunctionData.end()) {
+ Overlap.addOneUnique(FuncLevelOverlap.Test);
+ return;
+ }
+ if (FuncLevelOverlap.Test.CountSum < 1.0f) {
+ Overlap.Overlap.NumEntries += 1;
+ return;
+ }
+ auto &ProfileDataMap = FunctionData[Name];
+ bool NewFunc;
+ ProfilingData::iterator Where;
+ std::tie(Where, NewFunc) =
+ ProfileDataMap.insert(std::make_pair(Hash, InstrProfRecord()));
+ if (NewFunc) {
+ Overlap.addOneMismatch(FuncLevelOverlap.Test);
+ return;
+ }
+ InstrProfRecord &Dest = Where->second;
+
+ uint64_t ValueCutoff = FuncFilter.ValueCutoff;
+ if (!FuncFilter.NameFilter.empty() &&
+ Name.find(FuncFilter.NameFilter) != Name.npos)
+ ValueCutoff = 0;
+
+ Dest.overlap(Other, Overlap, FuncLevelOverlap, ValueCutoff);
+}
+
void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
InstrProfRecord &&I, uint64_t Weight,
function_ref<void(Error)> Warn) {
Added: llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1.proftext?rev=359612&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1.proftext (added)
+++ llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1.proftext Tue Apr 30 14:19:12 2019
@@ -0,0 +1,36 @@
+# IR level Instrumentation Flag
+:ir
+bar
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+100000
+
+bar1
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+100000
+
+foo
+# Func Hash:
+25571299074
+# Num Counters:
+2
+# Counter Values:
+40000
+60000
+
+main
+# Func Hash:
+29212902728
+# Num Counters:
+2
+# Counter Values:
+200000
+0
+
Added: llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1_cs.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1_cs.proftext?rev=359612&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1_cs.proftext (added)
+++ llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1_cs.proftext Tue Apr 30 14:19:12 2019
@@ -0,0 +1,11 @@
+# CSIR level Instrumentation Flag
+:csir
+bar
+# Func Hash:
+1152921534274394772
+# Num Counters:
+2
+# Counter Values:
+6000
+4000
+
Added: llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1_vp.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1_vp.proftext?rev=359612&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1_vp.proftext (added)
+++ llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_1_vp.proftext Tue Apr 30 14:19:12 2019
@@ -0,0 +1,25 @@
+:IR
+foo
+# Func Hash:
+72057649435042473
+# Num Counters:
+2
+# Counter Values:
+40000
+60000
+# Num Value Kinds:
+2
+# ValueKind = IPVK_IndirectCallTarget:
+0
+# NumValueSites:
+1
+2
+bar1:40000
+bar2:60000
+# ValueKind = IPVK_MemOPSize:
+1
+# NumValueSites:
+1
+2
+1:40000
+4:60000
Added: llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2.proftext?rev=359612&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2.proftext (added)
+++ llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2.proftext Tue Apr 30 14:19:12 2019
@@ -0,0 +1,36 @@
+# IR level Instrumentation Flag
+:ir
+bar
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+10000
+
+bar2
+# Func Hash:
+12884901887
+# Num Counters:
+1
+# Counter Values:
+10000
+
+foo
+# Func Hash:
+25571299075
+# Num Counters:
+2
+# Counter Values:
+4000
+6000
+
+main
+# Func Hash:
+29212902728
+# Num Counters:
+2
+# Counter Values:
+20000
+0
+
Added: llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2_cs.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2_cs.proftext?rev=359612&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2_cs.proftext (added)
+++ llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2_cs.proftext Tue Apr 30 14:19:12 2019
@@ -0,0 +1,11 @@
+# CSIR level Instrumentation Flag
+:csir
+bar
+# Func Hash:
+1152921534274394772
+# Num Counters:
+2
+# Counter Values:
+4000
+6000
+
Added: llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2_vp.proftext
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2_vp.proftext?rev=359612&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2_vp.proftext (added)
+++ llvm/trunk/test/tools/llvm-profdata/Inputs/overlap_2_vp.proftext Tue Apr 30 14:19:12 2019
@@ -0,0 +1,25 @@
+:IR
+foo
+# Func Hash:
+72057649435042473
+# Num Counters:
+2
+# Counter Values:
+30000
+20000
+# Num Value Kinds:
+2
+# ValueKind = IPVK_IndirectCallTarget:
+0
+# NumValueSites:
+1
+2
+bar1:30000
+bar2:20000
+# ValueKind = IPVK_MemOPSize:
+1
+# NumValueSites:
+1
+2
+1:3000
+4:2000
Added: llvm/trunk/test/tools/llvm-profdata/overlap.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/overlap.test?rev=359612&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/overlap.test (added)
+++ llvm/trunk/test/tools/llvm-profdata/overlap.test Tue Apr 30 14:19:12 2019
@@ -0,0 +1,21 @@
+RUN: llvm-profdata overlap %p/Inputs/overlap_1.proftext %p/Inputs/overlap_2.proftext | FileCheck %s -check-prefix=OVERLAP
+RUN: llvm-profdata overlap -function=main %p/Inputs/overlap_1.proftext %p/Inputs/overlap_2.proftext | FileCheck %s -check-prefix=MAINFUNC -check-prefix=OVERLAP
+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
+RUN: llvm-profdata merge %p/Inputs/overlap_1.proftext -o %t_1.profdata
+RUN: llvm-profdata merge %p/Inputs/overlap_2.proftext -o %t_2.profdata
+RUN: llvm-profdata overlap %t_1.profdata %t_2.profdata | FileCheck %s -check-prefix=OVERLAP
+MAINFUNC: Function: main (Hash=29212902728)
+MAINFUNC: # of edge counters overlap: 2
+MAINFUNC: Edge profile overlap: 100.000%
+MAINFUNC: Edge profile base count sum: 200000
+MAINFUNC: Edge profile test count sum: 20000
+OVERLAP: Profile overlap infomation for base_profile: {{.*}} and test_profile:
+OVERLAP: Program level:
+OVERLAP: # of functions overlap: 2
+OVERLAP: # of functions mismatch: 1
+OVERLAP: # of functions only in test_profile: 1
+OVERLAP: Edge profile overlap: 60.000%
+OVERLAP: Mismatched count percentage (Edge): 20.000%
+OVERLAP: Percentage of Edge profile only in test_profile: 20.000%
+OVERLAP: Edge profile base count sum: 500000
+OVERLAP: Edge profile test count sum: 50000
Added: llvm/trunk/test/tools/llvm-profdata/overlap_cs.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/overlap_cs.test?rev=359612&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/overlap_cs.test (added)
+++ llvm/trunk/test/tools/llvm-profdata/overlap_cs.test Tue Apr 30 14:19:12 2019
@@ -0,0 +1,10 @@
+RUN: llvm-profdata overlap -cs %p/Inputs/overlap_1_cs.proftext %p/Inputs/overlap_2_cs.proftext | FileCheck %s -check-prefix=OVERLAP
+RUN: llvm-profdata merge %p/Inputs/overlap_1_cs.proftext -o %t_1_cs.profdata
+RUN: llvm-profdata merge %p/Inputs/overlap_2_cs.proftext -o %t_2_cs.profdata
+RUN: llvm-profdata overlap -cs %t_1_cs.profdata %t_2_cs.profdata | FileCheck %s -check-prefix=OVERLAP
+OVERLAP: Profile overlap infomation for base_profile: {{.*}} and test_profile:
+OVERLAP: Program level:
+OVERLAP: # of functions overlap: 1
+OVERLAP: Edge profile overlap: 80.000%
+OVERLAP: Edge profile base count sum: 10000
+OVERLAP: Edge profile test count sum: 10000
Added: llvm/trunk/test/tools/llvm-profdata/overlap_vp.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-profdata/overlap_vp.test?rev=359612&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-profdata/overlap_vp.test (added)
+++ llvm/trunk/test/tools/llvm-profdata/overlap_vp.test Tue Apr 30 14:19:12 2019
@@ -0,0 +1,16 @@
+RUN: llvm-profdata overlap %p/Inputs/overlap_1_vp.proftext %p/Inputs/overlap_2_vp.proftext | FileCheck %s -check-prefix=OVERLAP
+RUN: llvm-profdata merge %p/Inputs/overlap_1_vp.proftext -o %t_1_vp.profdata
+RUN: llvm-profdata merge %p/Inputs/overlap_2_vp.proftext -o %t_2_vp.profdata
+RUN: llvm-profdata overlap %t_1_vp.profdata %t_2_vp.profdata | FileCheck %s -check-prefix=OVERLAP
+OVERLAP: Profile overlap infomation for base_profile: {{.*}} and test_profile:
+OVERLAP: Program level:
+OVERLAP: # of functions overlap: 1
+OVERLAP: Edge profile overlap: 80.000%
+OVERLAP: Edge profile base count sum: 100000
+OVERLAP: Edge profile test count sum: 50000
+OVERLAP: IndirectCall profile overlap: 80.000%
+OVERLAP: IndirectCall profile base count sum: 100000
+OVERLAP: IndirectCall profile test count sum: 50000
+OVERLAP: MemOP profile overlap: 80.000%
+OVERLAP: MemOP profile base count sum: 100000
+OVERLAP: MemOP profile test count sum: 5000
Modified: llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp?rev=359612&r1=359611&r2=359612&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp (original)
+++ llvm/trunk/tools/llvm-profdata/llvm-profdata.cpp Tue Apr 30 14:19:12 2019
@@ -200,6 +200,32 @@ static bool isFatalError(instrprof_error
}
}
+/// Computer the overlap b/w profile BaseFilename and TestFileName,
+/// and store the program level result to Overlap.
+static void overlapInput(const std::string &BaseFilename,
+ const std::string &TestFilename, WriterContext *WC,
+ OverlapStats &Overlap,
+ const OverlapFuncFilters &FuncFilter,
+ raw_fd_ostream &OS, bool IsCS) {
+ auto ReaderOrErr = InstrProfReader::create(TestFilename);
+ if (Error E = ReaderOrErr.takeError()) {
+ // Skip the empty profiles by returning sliently.
+ instrprof_error IPE = InstrProfError::take(std::move(E));
+ if (IPE != instrprof_error::empty_raw_profile)
+ WC->Err = make_error<InstrProfError>(IPE);
+ return;
+ }
+
+ auto Reader = std::move(ReaderOrErr.get());
+ for (auto &I : *Reader) {
+ OverlapStats FuncOverlap(OverlapStats::FunctionLevel);
+ FuncOverlap.setFuncInfo(I.Name, I.Hash);
+
+ WC->Writer.overlapRecord(std::move(I), Overlap, FuncOverlap, FuncFilter);
+ FuncOverlap.dump(OS);
+ }
+}
+
/// Load an input into a writer context.
static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
WriterContext *WC) {
@@ -608,6 +634,65 @@ static int merge_main(int argc, const ch
return 0;
}
+/// Computer the overlap b/w profile BaseFilename and profile TestFilename.
+static void overlapInstrProfile(const std::string &BaseFilename,
+ const std::string &TestFilename,
+ const OverlapFuncFilters &FuncFilter,
+ raw_fd_ostream &OS, bool IsCS) {
+ std::mutex ErrorLock;
+ SmallSet<instrprof_error, 4> WriterErrorCodes;
+ WriterContext Context(false, ErrorLock, WriterErrorCodes);
+ WeightedFile WeightedInput{BaseFilename, 1};
+ OverlapStats Overlap;
+ Error E = Overlap.accumuateCounts(BaseFilename, TestFilename, IsCS);
+ if (E)
+ exitWithError(std::move(E), "Error in getting profile count sums");
+ if (Overlap.Base.CountSum < 1.0f) {
+ OS << "Sum of edge counts for profile " << BaseFilename << " is 0.\n";
+ exit(0);
+ }
+ if (Overlap.Test.CountSum < 1.0f) {
+ OS << "Sum of edge counts for profile " << TestFilename << " is 0.\n";
+ exit(0);
+ }
+ loadInput(WeightedInput, nullptr, &Context);
+ overlapInput(BaseFilename, TestFilename, &Context, Overlap, FuncFilter, OS,
+ IsCS);
+ Overlap.dump(OS);
+}
+
+static int overlap_main(int argc, const char *argv[]) {
+ cl::opt<std::string> BaseFilename(cl::Positional, cl::Required,
+ cl::desc("<base profile file>"));
+ cl::opt<std::string> TestFilename(cl::Positional, cl::Required,
+ cl::desc("<test profile file>"));
+ cl::opt<std::string> Output("output", cl::value_desc("output"), cl::init("-"),
+ cl::desc("Output file"));
+ cl::alias OutputA("o", cl::desc("Alias for --output"), cl::aliasopt(Output));
+ cl::opt<bool> IsCS("cs", cl::init(false),
+ cl::desc("For context sensitive counts"));
+ cl::opt<unsigned long long> ValueCutoff(
+ "value-cutoff", cl::init(-1),
+ cl::desc(
+ "Function level overlap information for every function in test "
+ "profile with max count value greater then the parameter value"));
+ cl::opt<std::string> FuncNameFilter(
+ "function",
+ cl::desc("Function level overlap information for matching functions"));
+ cl::ParseCommandLineOptions(argc, argv, "LLVM profile data overlap tool\n");
+
+ std::error_code EC;
+ raw_fd_ostream OS(Output.data(), EC, sys::fs::F_Text);
+ if (EC)
+ exitWithErrorCode(EC, Output);
+
+ overlapInstrProfile(BaseFilename, TestFilename,
+ OverlapFuncFilters{ValueCutoff, FuncNameFilter}, OS,
+ IsCS);
+
+ return 0;
+}
+
typedef struct ValueSitesStats {
ValueSitesStats()
: TotalNumValueSites(0), TotalNumValueSitesWithValueProfile(0),
@@ -965,6 +1050,8 @@ int main(int argc, const char *argv[]) {
func = merge_main;
else if (strcmp(argv[1], "show") == 0)
func = show_main;
+ else if (strcmp(argv[1], "overlap") == 0)
+ func = overlap_main;
if (func) {
std::string Invocation(ProgName.str() + " " + argv[1]);
@@ -979,7 +1066,7 @@ int main(int argc, const char *argv[]) {
<< "USAGE: " << ProgName << " <command> [args...]\n"
<< "USAGE: " << ProgName << " <command> -help\n\n"
<< "See each individual command --help for more details.\n"
- << "Available commands: merge, show\n";
+ << "Available commands: merge, show, overlap\n";
return 0;
}
}
@@ -989,6 +1076,6 @@ int main(int argc, const char *argv[]) {
else
errs() << ProgName << ": Unknown command!\n";
- errs() << "USAGE: " << ProgName << " <merge|show> [args...]\n";
+ errs() << "USAGE: " << ProgName << " <merge|show|overlap> [args...]\n";
return 1;
}
More information about the llvm-commits
mailing list