mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-19 03:38:26 +00:00
[llvm-profdata] Improve error messaging when merging mismatched profile data
Summary: This change tries to make the root cause of instrumented profile data merge failures clearer. Previous: $ llvm-profdata merge test_0.profraw test_1.profraw -o test_merged.profdata test_1.profraw: foo: Function count mismatch test_1.profraw: bar: Function count mismatch test_1.profraw: baz: Function count mismatch ... Changed: $ llvm-profdata merge test_0.profraw test_1.profraw -o test_merged.profdata test_1.profraw: foo: Function basic block count change detected (counter mismatch) Make sure that all profile data to be merged is generated from the same binary. test_1.profraw: bar: Function basic block count change detected (counter mismatch) test_1.profraw: baz: Function basic block count change detected (counter mismatch) ... Reviewers: dnovillo, davidxl, bogner Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D14739 llvm-svn: 253384
This commit is contained in:
parent
f43318e7eb
commit
9c743e7e7f
@ -51,13 +51,13 @@ class InstrProfErrorCategoryType : public std::error_category {
|
|||||||
case instrprof_error::unknown_function:
|
case instrprof_error::unknown_function:
|
||||||
return "No profile data available for function";
|
return "No profile data available for function";
|
||||||
case instrprof_error::hash_mismatch:
|
case instrprof_error::hash_mismatch:
|
||||||
return "Function hash mismatch";
|
return "Function control flow change detected (hash mismatch)";
|
||||||
case instrprof_error::count_mismatch:
|
case instrprof_error::count_mismatch:
|
||||||
return "Function count mismatch";
|
return "Function basic block count change detected (counter mismatch)";
|
||||||
case instrprof_error::counter_overflow:
|
case instrprof_error::counter_overflow:
|
||||||
return "Counter overflow";
|
return "Counter overflow";
|
||||||
case instrprof_error::value_site_count_mismatch:
|
case instrprof_error::value_site_count_mismatch:
|
||||||
return "Function's value site counts mismatch";
|
return "Function value site count change detected (counter mismatch)";
|
||||||
}
|
}
|
||||||
llvm_unreachable("A value of instrprof_error has no message.");
|
llvm_unreachable("A value of instrprof_error has no message.");
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,8 @@ foo
|
|||||||
|
|
||||||
# The hash matches, but we can't combine these because the number of
|
# The hash matches, but we can't combine these because the number of
|
||||||
# counters differs.
|
# counters differs.
|
||||||
# MERGE_ERRS: count-mismatch.proftext: foo: Function count mismatch
|
# MERGE_ERRS: count-mismatch.proftext: foo: Function basic block count change detected (counter mismatch)
|
||||||
|
# MERGE_ERRS: Make sure that all profile data to be merged is generated from the same binary.
|
||||||
foo
|
foo
|
||||||
1024
|
1024
|
||||||
3
|
3
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
#include "llvm/Support/Signals.h"
|
#include "llvm/Support/Signals.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
static void exitWithError(const Twine &Message,
|
static void exitWithError(const Twine &Message,
|
||||||
@ -41,7 +43,8 @@ static void exitWithError(const Twine &Message,
|
|||||||
::exit(1);
|
::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exitWithErrorCode(const std::error_code &Error, StringRef Whence = "") {
|
static void exitWithErrorCode(const std::error_code &Error,
|
||||||
|
StringRef Whence = "") {
|
||||||
if (Error.category() == instrprof_category()) {
|
if (Error.category() == instrprof_category()) {
|
||||||
instrprof_error instrError = static_cast<instrprof_error>(Error.value());
|
instrprof_error instrError = static_cast<instrprof_error>(Error.value());
|
||||||
if (instrError == instrprof_error::unrecognized_format) {
|
if (instrError == instrprof_error::unrecognized_format) {
|
||||||
@ -57,6 +60,32 @@ namespace {
|
|||||||
enum ProfileKinds { instr, sample };
|
enum ProfileKinds { instr, sample };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handleMergeWriterError(std::error_code &Error,
|
||||||
|
StringRef WhenceFile = "",
|
||||||
|
StringRef WhenceFunction = "",
|
||||||
|
bool ShowHint = true)
|
||||||
|
{
|
||||||
|
if (!WhenceFile.empty())
|
||||||
|
errs() << WhenceFile << ": ";
|
||||||
|
if (!WhenceFunction.empty())
|
||||||
|
errs() << WhenceFunction << ": ";
|
||||||
|
errs() << Error.message() << "\n";
|
||||||
|
|
||||||
|
if (ShowHint) {
|
||||||
|
StringRef Hint = "";
|
||||||
|
if (Error.category() == instrprof_category()) {
|
||||||
|
instrprof_error instrError = static_cast<instrprof_error>(Error.value());
|
||||||
|
if (instrError == instrprof_error::count_mismatch) {
|
||||||
|
Hint = "Make sure that all profile data to be merged is generated " \
|
||||||
|
"from the same binary.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Hint.empty())
|
||||||
|
errs() << Hint << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void mergeInstrProfile(const cl::list<std::string> &Inputs,
|
static void mergeInstrProfile(const cl::list<std::string> &Inputs,
|
||||||
StringRef OutputFilename) {
|
StringRef OutputFilename) {
|
||||||
if (OutputFilename.compare("-") == 0)
|
if (OutputFilename.compare("-") == 0)
|
||||||
@ -68,15 +97,20 @@ static void mergeInstrProfile(const cl::list<std::string> &Inputs,
|
|||||||
exitWithErrorCode(EC, OutputFilename);
|
exitWithErrorCode(EC, OutputFilename);
|
||||||
|
|
||||||
InstrProfWriter Writer;
|
InstrProfWriter Writer;
|
||||||
|
std::set<std::error_code> WriterErrorCodes;
|
||||||
for (const auto &Filename : Inputs) {
|
for (const auto &Filename : Inputs) {
|
||||||
auto ReaderOrErr = InstrProfReader::create(Filename);
|
auto ReaderOrErr = InstrProfReader::create(Filename);
|
||||||
if (std::error_code ec = ReaderOrErr.getError())
|
if (std::error_code ec = ReaderOrErr.getError())
|
||||||
exitWithErrorCode(ec, Filename);
|
exitWithErrorCode(ec, Filename);
|
||||||
|
|
||||||
auto Reader = std::move(ReaderOrErr.get());
|
auto Reader = std::move(ReaderOrErr.get());
|
||||||
for (auto &I : *Reader)
|
for (auto &I : *Reader) {
|
||||||
if (std::error_code EC = Writer.addRecord(std::move(I)))
|
if (std::error_code EC = Writer.addRecord(std::move(I))) {
|
||||||
errs() << Filename << ": " << I.Name << ": " << EC.message() << "\n";
|
// Only show hint the first time an error occurs.
|
||||||
|
bool firstTime = WriterErrorCodes.insert(EC).second;
|
||||||
|
handleMergeWriterError(EC, Filename, I.Name, firstTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (Reader->hasError())
|
if (Reader->hasError())
|
||||||
exitWithErrorCode(Reader->getError(), Filename);
|
exitWithErrorCode(Reader->getError(), Filename);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user