summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/llvm-profdata/llvm-profdata.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-06-23 21:36:31 +0000
committerpatrick <patrick@openbsd.org>2019-06-23 21:36:31 +0000
commit23f101f37937a1bd4a29726cab2f76e0fb038b35 (patch)
treef7da7d6b32c2e07114da399150bfa88d72187012 /gnu/llvm/tools/llvm-profdata/llvm-profdata.cpp
parentsort previous; ok deraadt (diff)
downloadwireguard-openbsd-23f101f37937a1bd4a29726cab2f76e0fb038b35.tar.xz
wireguard-openbsd-23f101f37937a1bd4a29726cab2f76e0fb038b35.zip
Import LLVM 8.0.0 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/tools/llvm-profdata/llvm-profdata.cpp')
-rw-r--r--gnu/llvm/tools/llvm-profdata/llvm-profdata.cpp182
1 files changed, 158 insertions, 24 deletions
diff --git a/gnu/llvm/tools/llvm-profdata/llvm-profdata.cpp b/gnu/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 1a0b9e127bb..c25cbc2b64d 100644
--- a/gnu/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/gnu/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -123,6 +123,47 @@ static void handleMergeWriterError(Error E, StringRef WhenceFile = "",
}
}
+namespace {
+/// A remapper from original symbol names to new symbol names based on a file
+/// containing a list of mappings from old name to new name.
+class SymbolRemapper {
+ std::unique_ptr<MemoryBuffer> File;
+ DenseMap<StringRef, StringRef> RemappingTable;
+
+public:
+ /// Build a SymbolRemapper from a file containing a list of old/new symbols.
+ static std::unique_ptr<SymbolRemapper> create(StringRef InputFile) {
+ auto BufOrError = MemoryBuffer::getFileOrSTDIN(InputFile);
+ if (!BufOrError)
+ exitWithErrorCode(BufOrError.getError(), InputFile);
+
+ auto Remapper = llvm::make_unique<SymbolRemapper>();
+ Remapper->File = std::move(BufOrError.get());
+
+ for (line_iterator LineIt(*Remapper->File, /*SkipBlanks=*/true, '#');
+ !LineIt.is_at_eof(); ++LineIt) {
+ std::pair<StringRef, StringRef> Parts = LineIt->split(' ');
+ if (Parts.first.empty() || Parts.second.empty() ||
+ Parts.second.count(' ')) {
+ exitWithError("unexpected line in remapping file",
+ (InputFile + ":" + Twine(LineIt.line_number())).str(),
+ "expected 'old_symbol new_symbol'");
+ }
+ Remapper->RemappingTable.insert(Parts);
+ }
+ return Remapper;
+ }
+
+ /// Attempt to map the given old symbol into a new symbol.
+ ///
+ /// \return The new symbol, or \p Name if no such symbol was found.
+ StringRef operator()(StringRef Name) {
+ StringRef New = RemappingTable.lookup(Name);
+ return New.empty() ? Name : New;
+ }
+};
+}
+
struct WeightedFile {
std::string Filename;
uint64_t Weight;
@@ -161,7 +202,8 @@ static bool isFatalError(instrprof_error IPE) {
}
/// Load an input into a writer context.
-static void loadInput(const WeightedFile &Input, WriterContext *WC) {
+static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
+ WriterContext *WC) {
std::unique_lock<std::mutex> CtxGuard{WC->Lock};
// If there's a pending hard error, don't do more work.
@@ -192,6 +234,8 @@ static void loadInput(const WeightedFile &Input, WriterContext *WC) {
}
for (auto &I : *Reader) {
+ if (Remapper)
+ I.Name = (*Remapper)(I.Name);
const StringRef FuncName = I.Name;
bool Reported = false;
WC->Writer.addRecord(std::move(I), Input.Weight, [&](Error E) {
@@ -236,6 +280,7 @@ static void mergeWriterContexts(WriterContext *Dst, WriterContext *Src) {
}
static void mergeInstrProfile(const WeightedFileVector &Inputs,
+ SymbolRemapper *Remapper,
StringRef OutputFilename,
ProfileFormat OutputFormat, bool OutputSparse,
unsigned NumThreads) {
@@ -267,14 +312,14 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
if (NumThreads == 1) {
for (const auto &Input : Inputs)
- loadInput(Input, Contexts[0].get());
+ loadInput(Input, Remapper, Contexts[0].get());
} else {
ThreadPool Pool(NumThreads);
// Load the inputs in parallel (N/NumThreads serial steps).
unsigned Ctx = 0;
for (const auto &Input : Inputs) {
- Pool.async(loadInput, Input, Contexts[Ctx].get());
+ Pool.async(loadInput, Input, Remapper, Contexts[Ctx].get());
Ctx = (Ctx + 1) % NumThreads;
}
Pool.wait();
@@ -322,11 +367,43 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
}
}
+/// Make a copy of the given function samples with all symbol names remapped
+/// by the provided symbol remapper.
+static sampleprof::FunctionSamples
+remapSamples(const sampleprof::FunctionSamples &Samples,
+ SymbolRemapper &Remapper, sampleprof_error &Error) {
+ sampleprof::FunctionSamples Result;
+ Result.setName(Remapper(Samples.getName()));
+ Result.addTotalSamples(Samples.getTotalSamples());
+ Result.addHeadSamples(Samples.getHeadSamples());
+ for (const auto &BodySample : Samples.getBodySamples()) {
+ Result.addBodySamples(BodySample.first.LineOffset,
+ BodySample.first.Discriminator,
+ BodySample.second.getSamples());
+ for (const auto &Target : BodySample.second.getCallTargets()) {
+ Result.addCalledTargetSamples(BodySample.first.LineOffset,
+ BodySample.first.Discriminator,
+ Remapper(Target.first()), Target.second);
+ }
+ }
+ for (const auto &CallsiteSamples : Samples.getCallsiteSamples()) {
+ sampleprof::FunctionSamplesMap &Target =
+ Result.functionSamplesAt(CallsiteSamples.first);
+ for (const auto &Callsite : CallsiteSamples.second) {
+ sampleprof::FunctionSamples Remapped =
+ remapSamples(Callsite.second, Remapper, Error);
+ MergeResult(Error, Target[Remapped.getName()].merge(Remapped));
+ }
+ }
+ return Result;
+}
+
static sampleprof::SampleProfileFormat FormatMap[] = {
sampleprof::SPF_None, sampleprof::SPF_Text, sampleprof::SPF_Compact_Binary,
sampleprof::SPF_GCC, sampleprof::SPF_Binary};
static void mergeSampleProfile(const WeightedFileVector &Inputs,
+ SymbolRemapper *Remapper,
StringRef OutputFilename,
ProfileFormat OutputFormat) {
using namespace sampleprof;
@@ -357,9 +434,13 @@ static void mergeSampleProfile(const WeightedFileVector &Inputs,
for (StringMap<FunctionSamples>::iterator I = Profiles.begin(),
E = Profiles.end();
I != E; ++I) {
- StringRef FName = I->first();
- FunctionSamples &Samples = I->second;
- sampleprof_error Result = ProfileMap[FName].merge(Samples, Input.Weight);
+ sampleprof_error Result = sampleprof_error::success;
+ FunctionSamples Remapped =
+ Remapper ? remapSamples(I->second, *Remapper, Result)
+ : FunctionSamples();
+ FunctionSamples &Samples = Remapper ? Remapped : I->second;
+ StringRef FName = Samples.getName();
+ MergeResult(Result, ProfileMap[FName].merge(Samples, Input.Weight));
if (Result != sampleprof_error::success) {
std::error_code EC = make_error_code(Result);
handleMergeWriterError(errorCodeToError(EC), Input.Filename, FName);
@@ -461,6 +542,10 @@ static int merge_main(int argc, const char *argv[]) {
cl::opt<bool> DumpInputFileList(
"dump-input-file-list", cl::init(false), cl::Hidden,
cl::desc("Dump the list of input files and their weights, then exit"));
+ cl::opt<std::string> RemappingFile("remapping-file", cl::value_desc("file"),
+ cl::desc("Symbol remapping file"));
+ cl::alias RemappingFileA("r", cl::desc("Alias for --remapping-file"),
+ cl::aliasopt(RemappingFile));
cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
cl::init("-"), cl::Required,
cl::desc("Output file"));
@@ -509,11 +594,16 @@ static int merge_main(int argc, const char *argv[]) {
return 0;
}
+ std::unique_ptr<SymbolRemapper> Remapper;
+ if (!RemappingFile.empty())
+ Remapper = SymbolRemapper::create(RemappingFile);
+
if (ProfileKind == instr)
- mergeInstrProfile(WeightedInputs, OutputFilename, OutputFormat,
- OutputSparse, NumThreads);
+ mergeInstrProfile(WeightedInputs, Remapper.get(), OutputFilename,
+ OutputFormat, OutputSparse, NumThreads);
else
- mergeSampleProfile(WeightedInputs, OutputFilename, OutputFormat);
+ mergeSampleProfile(WeightedInputs, Remapper.get(), OutputFilename,
+ OutputFormat);
return 0;
}
@@ -543,13 +633,21 @@ static void traverseAllValueSites(const InstrProfRecord &Func, uint32_t VK,
Stats.ValueSitesHistogram.resize(NV, 0);
Stats.ValueSitesHistogram[NV - 1]++;
}
+
+ uint64_t SiteSum = 0;
+ for (uint32_t V = 0; V < NV; V++)
+ SiteSum += VD[V].Count;
+ if (SiteSum == 0)
+ SiteSum = 1;
+
for (uint32_t V = 0; V < NV; V++) {
- OS << "\t[ " << I << ", ";
+ OS << "\t[ " << format("%2u", I) << ", ";
if (Symtab == nullptr)
- OS << VD[V].Value;
+ OS << format("%4u", VD[V].Value);
else
OS << Symtab->getFuncName(VD[V].Value);
- OS << ", " << VD[V].Count << " ]\n";
+ OS << ", " << format("%10" PRId64, VD[V].Count) << " ] ("
+ << format("%.2f%%", (VD[V].Count * 100.0 / SiteSum)) << ")\n";
}
}
}
@@ -572,9 +670,9 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
uint32_t TopN, bool ShowIndirectCallTargets,
bool ShowMemOPSizes, bool ShowDetailedSummary,
std::vector<uint32_t> DetailedSummaryCutoffs,
- bool ShowAllFunctions,
- const std::string &ShowFunction, bool TextFormat,
- raw_fd_ostream &OS) {
+ bool ShowAllFunctions, uint64_t ValueCutoff,
+ bool OnlyListBelow, const std::string &ShowFunction,
+ bool TextFormat, raw_fd_ostream &OS) {
auto ReaderOrErr = InstrProfReader::create(Filename);
std::vector<uint32_t> Cutoffs = std::move(DetailedSummaryCutoffs);
if (ShowDetailedSummary && Cutoffs.empty()) {
@@ -587,6 +685,7 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
auto Reader = std::move(ReaderOrErr.get());
bool IsIRInstr = Reader->isIRLevelProfile();
size_t ShownFunctions = 0;
+ size_t BelowCutoffFunctions = 0;
int NumVPKind = IPVK_Last - IPVK_First + 1;
std::vector<ValueSitesStats> VPStats(NumVPKind);
@@ -600,12 +699,21 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
decltype(MinCmp)>
HottestFuncs(MinCmp);
+ if (!TextFormat && OnlyListBelow) {
+ OS << "The list of functions with the maximum counter less than "
+ << ValueCutoff << ":\n";
+ }
+
+ // Add marker so that IR-level instrumentation round-trips properly.
+ if (TextFormat && IsIRInstr)
+ OS << ":ir\n";
+
for (const auto &Func : *Reader) {
bool Show =
ShowAllFunctions || (!ShowFunction.empty() &&
Func.Name.find(ShowFunction) != Func.Name.npos);
- bool doTextFormatDump = (Show && ShowCounts && TextFormat);
+ bool doTextFormatDump = (Show && TextFormat);
if (doTextFormatDump) {
InstrProfSymtab &Symtab = Reader->getSymtab();
@@ -617,11 +725,24 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
assert(Func.Counts.size() > 0 && "function missing entry counter");
Builder.addRecord(Func);
- if (TopN) {
- uint64_t FuncMax = 0;
- for (size_t I = 0, E = Func.Counts.size(); I < E; ++I)
- FuncMax = std::max(FuncMax, Func.Counts[I]);
+ uint64_t FuncMax = 0;
+ uint64_t FuncSum = 0;
+ for (size_t I = 0, E = Func.Counts.size(); I < E; ++I) {
+ FuncMax = std::max(FuncMax, Func.Counts[I]);
+ FuncSum += Func.Counts[I];
+ }
+ if (FuncMax < ValueCutoff) {
+ ++BelowCutoffFunctions;
+ if (OnlyListBelow) {
+ OS << " " << Func.Name << ": (Max = " << FuncMax
+ << " Sum = " << FuncSum << ")\n";
+ }
+ continue;
+ } else if (OnlyListBelow)
+ continue;
+
+ if (TopN) {
if (HottestFuncs.size() == TopN) {
if (HottestFuncs.top().second < FuncMax) {
HottestFuncs.pop();
@@ -632,7 +753,6 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
}
if (Show) {
-
if (!ShownFunctions)
OS << "Counters:\n";
@@ -679,7 +799,7 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
if (Reader->hasError())
exitWithError(Reader->getError(), Filename);
- if (ShowCounts && TextFormat)
+ if (TextFormat)
return 0;
std::unique_ptr<ProfileSummary> PS(Builder.getSummary());
OS << "Instrumentation level: "
@@ -687,6 +807,12 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
if (ShowAllFunctions || !ShowFunction.empty())
OS << "Functions shown: " << ShownFunctions << "\n";
OS << "Total functions: " << PS->getNumFunctions() << "\n";
+ if (ValueCutoff > 0) {
+ OS << "Number of functions with maximum count (< " << ValueCutoff
+ << "): " << BelowCutoffFunctions << "\n";
+ OS << "Number of functions with maximum count (>= " << ValueCutoff
+ << "): " << PS->getNumFunctions() - BelowCutoffFunctions << "\n";
+ }
OS << "Maximum function count: " << PS->getMaxFunctionCount() << "\n";
OS << "Maximum internal block count: " << PS->getMaxInternalCount() << "\n";
@@ -788,7 +914,14 @@ static int show_main(int argc, const char *argv[]) {
cl::opt<uint32_t> TopNFunctions(
"topn", cl::init(0),
cl::desc("Show the list of functions with the largest internal counts"));
-
+ cl::opt<uint32_t> ValueCutoff(
+ "value-cutoff", cl::init(0),
+ cl::desc("Set the count value cutoff. Functions with the maximum count "
+ "less than this value will not be printed out. (Default is 0)"));
+ cl::opt<bool> OnlyListBelow(
+ "list-below-cutoff", cl::init(false),
+ cl::desc("Only output names of functions whose max count values are "
+ "below the cutoff value"));
cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n");
if (OutputFilename.empty())
@@ -808,7 +941,8 @@ static int show_main(int argc, const char *argv[]) {
return showInstrProfile(Filename, ShowCounts, TopNFunctions,
ShowIndirectCallTargets, ShowMemOPSizes,
ShowDetailedSummary, DetailedSummaryCutoffs,
- ShowAllFunctions, ShowFunction, TextFormat, OS);
+ ShowAllFunctions, ValueCutoff, OnlyListBelow,
+ ShowFunction, TextFormat, OS);
else
return showSampleProfile(Filename, ShowCounts, ShowAllFunctions,
ShowFunction, OS);