]> granicus.if.org Git - clang/commitdiff
CodeGen: Improve warnings about uninstrumented files when profiling
authorJustin Bogner <mail@justinbogner.com>
Thu, 26 Jun 2014 01:45:07 +0000 (01:45 +0000)
committerJustin Bogner <mail@justinbogner.com>
Thu, 26 Jun 2014 01:45:07 +0000 (01:45 +0000)
Improve the warning when building with -fprofile-instr-use and a file
appears not to have been profiled at all. This keys on whether a
function is defined in the main file or not to avoid false negatives
when one includes a header with functions that have been profiled.

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

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/CodeGenPGO.cpp
lib/CodeGen/CodeGenPGO.h
test/Profile/Inputs/c-unprofiled.proftext [new file with mode: 0644]
test/Profile/Inputs/profiled_header.h [new file with mode: 0644]
test/Profile/c-unprofiled.c [new file with mode: 0644]

index db924a589085c37f96746a61952f57ec630214fb..3d10fcfef06114686cd291bf601fab0d20fa38d1 100644 (file)
@@ -707,3 +707,4 @@ def BackendOptimizationRemarkAnalysis : DiagGroup<"pass-analysis">;
 
 // Instrumentation based profiling warnings.
 def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">;
+def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">;
index c691921fa1341144827bacf9cf2c8bb4c1c90536..9be3d8543a4bc600d7c1298a89e1ef5a0ca8388d 100644 (file)
@@ -7178,6 +7178,10 @@ def warn_profile_data_out_of_date : Warning<
   "profile data may be out of date: of %0 function%s0, %1 %plural{1:has|:have}1"
   " no data and %2 %plural{1:has|:have}2 mismatched data that will be ignored">,
   InGroup<ProfileInstrOutOfDate>;
+def warn_profile_data_unprofiled : Warning<
+  "no profile data available for file \"%0\"">,
+  InGroup<ProfileInstrUnprofiled>;
+
 } // end of instrumentation issue category
 
 } // end of sema component.
index f1b899f49f5c3ee635fdc1428db08e684d1d232d..d172b45c682a5797e9f9c17c9bab294d96cbc0be 100644 (file)
@@ -314,6 +314,19 @@ void CodeGenModule::clear() {
   DeferredDeclsToEmit.clear();
 }
 
+void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags,
+                                       StringRef MainFile) {
+  if (!hasDiagnostics())
+    return;
+  if (VisitedInMainFile > 0 && VisitedInMainFile == MissingInMainFile) {
+    if (MainFile.empty())
+      MainFile = "<stdin>";
+    Diags.Report(diag::warn_profile_data_unprofiled) << MainFile;
+  } else
+    Diags.Report(diag::warn_profile_data_out_of_date) << Visited << Missing
+                                                      << Mismatched;
+}
+
 void CodeGenModule::Release() {
   EmitDeferred();
   applyReplacements();
@@ -327,9 +340,8 @@ void CodeGenModule::Release() {
   if (getCodeGenOpts().ProfileInstrGenerate)
     if (llvm::Function *PGOInit = CodeGenPGO::emitInitialization(*this))
       AddGlobalCtor(PGOInit, 0);
-  if (PGOReader && PGOStats.isOutOfDate())
-    getDiags().Report(diag::warn_profile_data_out_of_date)
-        << PGOStats.Visited << PGOStats.Missing << PGOStats.Mismatched;
+  if (PGOReader && PGOStats.hasDiagnostics())
+    PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName);
   EmitCtorList(GlobalCtors, "llvm.global_ctors");
   EmitCtorList(GlobalDtors, "llvm.global_dtors");
   EmitGlobalAnnotations();
index 6cb4fc17c5e3df1dc8daf830dcb75f8eb8ab2644..d96b34eee6288a7e4981c6e982cbf3b8a8764476 100644 (file)
@@ -218,12 +218,36 @@ struct ARCEntrypoints {
 };
 
 /// This class records statistics on instrumentation based profiling.
-struct InstrProfStats {
-  InstrProfStats() : Visited(0), Missing(0), Mismatched(0) {}
-  bool isOutOfDate() { return Missing || Mismatched; }
+class InstrProfStats {
+  uint32_t VisitedInMainFile;
+  uint32_t MissingInMainFile;
   uint32_t Visited;
   uint32_t Missing;
   uint32_t Mismatched;
+
+public:
+  InstrProfStats()
+      : VisitedInMainFile(0), MissingInMainFile(0), Visited(0), Missing(0),
+        Mismatched(0) {}
+  /// Record that we've visited a function and whether or not that function was
+  /// in the main source file.
+  void addVisited(bool MainFile) {
+    if (MainFile)
+      ++VisitedInMainFile;
+    ++Visited;
+  }
+  /// Record that a function we've visited has no profile data.
+  void addMissing(bool MainFile) {
+    if (MainFile)
+      ++MissingInMainFile;
+    ++Missing;
+  }
+  /// Record that a function we've visited has mismatched profile data.
+  void addMismatched(bool MainFile) { ++Mismatched; }
+  /// Whether or not the stats we've gathered indicate any potential problems.
+  bool hasDiagnostics() { return Missing || Mismatched; }
+  /// Report potential problems we've found to \c Diags.
+  void reportDiagnostics(DiagnosticsEngine &Diags, StringRef MainFile);
 };
 
 /// This class organizes the cross-function state that is used while generating
index 22534b828ee55dd30a50c01e35580fec37e013d2..b233e3c7d75e3b1851510d9ab3e2befc764ee86d 100644 (file)
@@ -837,7 +837,8 @@ void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
     emitCounterVariables();
   }
   if (PGOReader) {
-    loadRegionCounts(PGOReader);
+    SourceManager &SM = CGM.getContext().getSourceManager();
+    loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
     computeRegionCounts(D);
     applyFunctionAttributes(PGOReader, Fn);
   }
@@ -912,16 +913,17 @@ void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter) {
   Builder.CreateStore(Count, Addr);
 }
 
-void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader) {
-  CGM.getPGOStats().Visited++;
+void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
+                                  bool IsInMainFile) {
+  CGM.getPGOStats().addVisited(IsInMainFile);
   RegionCounts.reset(new std::vector<uint64_t>);
   uint64_t Hash;
   if (PGOReader->getFunctionCounts(getFuncName(), Hash, *RegionCounts)) {
-    CGM.getPGOStats().Missing++;
+    CGM.getPGOStats().addMissing(IsInMainFile);
     RegionCounts.reset();
   } else if (Hash != FunctionHash ||
              RegionCounts->size() != NumRegionCounters) {
-    CGM.getPGOStats().Mismatched++;
+    CGM.getPGOStats().addMismatched(IsInMainFile);
     RegionCounts.reset();
   }
 }
index c4348085882d1d24812dae6612da06c0289a6e2f..2f4aa660bea31da81f4681a26d3c875ba837c9d5 100644 (file)
@@ -118,7 +118,8 @@ private:
   void computeRegionCounts(const Decl *D);
   void applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
                                llvm::Function *Fn);
-  void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader);
+  void loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
+                        bool IsInMainFile);
   void emitCounterVariables();
   llvm::GlobalVariable *buildDataVar();
 
diff --git a/test/Profile/Inputs/c-unprofiled.proftext b/test/Profile/Inputs/c-unprofiled.proftext
new file mode 100644 (file)
index 0000000..d2ef7ae
--- /dev/null
@@ -0,0 +1,10 @@
+function_in_header
+10
+2
+1
+0
+
+main
+0
+1
+1
diff --git a/test/Profile/Inputs/profiled_header.h b/test/Profile/Inputs/profiled_header.h
new file mode 100644 (file)
index 0000000..fa649d4
--- /dev/null
@@ -0,0 +1,3 @@
+void function_in_header(int i) {
+  if (i) {}
+}
diff --git a/test/Profile/c-unprofiled.c b/test/Profile/c-unprofiled.c
new file mode 100644 (file)
index 0000000..275cd2d
--- /dev/null
@@ -0,0 +1,26 @@
+// Test that unprofiled files are recognized. Here, we have two functions in the
+// profile, main() and function_in_header, but we use the profile on a file that
+// has the profile-less some_unprofiled_function so that the only profiled code
+// in #included in a header.
+
+// FIXME: It would be nice to use -verify here instead of FileCheck, but -verify
+// doesn't play well with warnings that have no line number.
+
+// RUN: llvm-profdata merge %S/Inputs/c-unprofiled.proftext -o %t.profdata
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-unprofiled.c -I %S/Inputs/ %s -o /dev/null -emit-llvm -fprofile-instr-use=%t.profdata -Wprofile-instr-unprofiled 2>&1 | FileCheck %s
+
+// CHECK: warning: no profile data available for file "c-unprofiled.c"
+
+#include "profiled_header.h"
+
+#ifdef GENERATE_OUTDATED_DATA
+int main(int argc, const char *argv[]) {
+  function_in_header(0);
+  return 0;
+}
+#else
+void some_unprofiled_function(int i) {
+  if (i)
+    function_in_header(i);
+}
+#endif