[llvm-profdata] Improve error messaging when merging mismatched profile data
authorNathan Slingerland <slingn@gmail.com>
Tue, 17 Nov 2015 22:08:53 +0000 (22:08 +0000)
committerNathan Slingerland <slingn@gmail.com>
Tue, 17 Nov 2015 22:08:53 +0000 (22:08 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253384 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ProfileData/InstrProf.cpp
test/tools/llvm-profdata/count-mismatch.proftext
tools/llvm-profdata/llvm-profdata.cpp

index ef7b19b2882099b899a097de2fa15c4cfb48a958..2dd0f916c6d25955071b6d341932f9cc452607fb 100644 (file)
@@ -51,13 +51,13 @@ class InstrProfErrorCategoryType : public std::error_category {
     case instrprof_error::unknown_function:
       return "No profile data available for function";
     case instrprof_error::hash_mismatch:
-      return "Function hash mismatch";
+      return "Function control flow change detected (hash mismatch)";
     case instrprof_error::count_mismatch:
-      return "Function count mismatch";
+      return "Function basic block count change detected (counter mismatch)";
     case instrprof_error::counter_overflow:
       return "Counter overflow";
     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.");
   }
index 1a2e73fbffdb76a682c141dca6048f6ce4ad8d8c..b42b11dbcf9ddcb95b1c2c7bf514c90af22de4fc 100644 (file)
@@ -14,7 +14,8 @@ foo
 
 # The hash matches, but we can't combine these because the number of
 # 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
 1024
 3
index 1cd47dd5e84c248cb883474f6c7c2866e1fe7d57..f8499c30f66ac1e28655159a00612d80e9d588f2 100644 (file)
@@ -27,6 +27,8 @@
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
 
+#include <set>
+
 using namespace llvm;
 
 static void exitWithError(const Twine &Message,
@@ -41,7 +43,8 @@ static void exitWithError(const Twine &Message,
   ::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()) {
     instrprof_error instrError = static_cast<instrprof_error>(Error.value());
     if (instrError == instrprof_error::unrecognized_format) {
@@ -57,6 +60,32 @@ namespace {
     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,
                               StringRef OutputFilename) {
   if (OutputFilename.compare("-") == 0)
@@ -68,15 +97,20 @@ static void mergeInstrProfile(const cl::list<std::string> &Inputs,
     exitWithErrorCode(EC, OutputFilename);
 
   InstrProfWriter Writer;
+  std::set<std::error_code> WriterErrorCodes;
   for (const auto &Filename : Inputs) {
     auto ReaderOrErr = InstrProfReader::create(Filename);
     if (std::error_code ec = ReaderOrErr.getError())
       exitWithErrorCode(ec, Filename);
 
     auto Reader = std::move(ReaderOrErr.get());
-    for (auto &I : *Reader)
-      if (std::error_code EC = Writer.addRecord(std::move(I)))
-        errs() << Filename << ": " << I.Name << ": " << EC.message() << "\n";
+    for (auto &I : *Reader) {
+      if (std::error_code EC = Writer.addRecord(std::move(I))) {
+        // Only show hint the first time an error occurs.
+        bool firstTime = WriterErrorCodes.insert(EC).second;
+        handleMergeWriterError(EC, Filename, I.Name, firstTime);
+      }
+    }
     if (Reader->hasError())
       exitWithErrorCode(Reader->getError(), Filename);
   }