From 859d2b24895e5bfaa52005a48a36236024175bfb Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Tue, 15 Apr 2014 21:22:35 +0000 Subject: [PATCH] CodeGen: Emit warnings for out of date profile data during PGO This adds a warning that triggers when profile data doesn't match for the source that's being compiled with -fprofile-instr-use=. This fires only once per translation unit, as warning on every mismatched function would be quite noisy. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206322 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticGroups.td | 3 +++ include/clang/Basic/DiagnosticSemaKinds.td | 7 +++++++ lib/CodeGen/CodeGenModule.cpp | 3 +++ lib/CodeGen/CodeGenModule.h | 14 ++++++++++++++ lib/CodeGen/CodeGenPGO.cpp | 10 ++++++++-- test/Profile/c-outdated-data.c | 13 ++++++++----- 6 files changed, 43 insertions(+), 7 deletions(-) diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index c21a313386..f707c989fc 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -665,3 +665,6 @@ def BackendInlineAsm : DiagGroup<"inline-asm">; def BackendFrameLargerThan : DiagGroup<"frame-larger-than">; def BackendPlugin : DiagGroup<"backend-plugin">; def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">; + +// Instrumentation based profiling warnings. +def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a1a5f5a892..76b314ead5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -6984,4 +6984,11 @@ def warn_not_a_doxygen_trailing_member_comment : Warning< "not a Doxygen trailing comment">, InGroup, DefaultIgnore; } // end of documentation issue category +let CategoryName = "Instrumentation Issue" in { +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; +} // end of instrumentation issue category + } // end of sema component. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 6ea60ba1c0..d4daaa55c7 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -286,6 +286,9 @@ void CodeGenModule::Release() { if (getCodeGenOpts().ProfileInstrGenerate) if (llvm::Function *PGOInit = CodeGenPGO::emitInitialization(*this)) AddGlobalCtor(PGOInit, 0); + if (PGOData && PGOStats.isOutOfDate()) + getDiags().Report(diag::warn_profile_data_out_of_date) + << PGOStats.Visited << PGOStats.Missing << PGOStats.Mismatched; EmitCtorList(GlobalCtors, "llvm.global_ctors"); EmitCtorList(GlobalDtors, "llvm.global_dtors"); EmitGlobalAnnotations(); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 0d13bdcc2f..f6614dd44b 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -220,6 +220,15 @@ struct ARCEntrypoints { llvm::Constant *clang_arc_use; }; +/// This class records statistics on instrumentation based profiling. +struct InstrProfStats { + InstrProfStats() : Visited(0), Missing(0), Mismatched(0) {} + bool isOutOfDate() { return Missing || Mismatched; } + uint32_t Visited; + uint32_t Missing; + uint32_t Mismatched; +}; + /// CodeGenModule - This class organizes the cross-function state that is used /// while generating LLVM code. class CodeGenModule : public CodeGenTypeCache { @@ -258,6 +267,7 @@ class CodeGenModule : public CodeGenTypeCache { llvm::MDNode *NoObjCARCExceptionsMetadata; RREntrypoints *RRData; PGOProfileData *PGOData; + InstrProfStats PGOStats; // WeakRefReferences - A set of references that have only been seen via // a weakref so far. This is used to remove the weak of the reference if we @@ -483,6 +493,10 @@ public: return *RRData; } + InstrProfStats &getPGOStats() { + return PGOStats; + } + PGOProfileData *getPGOData() const { return PGOData; } diff --git a/lib/CodeGen/CodeGenPGO.cpp b/lib/CodeGen/CodeGenPGO.cpp index 55a09e8db5..c451bef57c 100644 --- a/lib/CodeGen/CodeGenPGO.cpp +++ b/lib/CodeGen/CodeGenPGO.cpp @@ -908,11 +908,17 @@ void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter) { } void CodeGenPGO::loadRegionCounts(PGOProfileData *PGOData) { + CGM.getPGOStats().Visited++; RegionCounts.reset(new std::vector); uint64_t Hash; - if (PGOData->getFunctionCounts(getFuncName(), Hash, *RegionCounts) || - Hash != FunctionHash || RegionCounts->size() != NumRegionCounters) + if (PGOData->getFunctionCounts(getFuncName(), Hash, *RegionCounts)) { + CGM.getPGOStats().Missing++; RegionCounts.reset(); + } else if (Hash != FunctionHash || + RegionCounts->size() != NumRegionCounters) { + CGM.getPGOStats().Mismatched++; + RegionCounts.reset(); + } } void CodeGenPGO::destroyRegionCounters() { diff --git a/test/Profile/c-outdated-data.c b/test/Profile/c-outdated-data.c index fe5a5c75cc..c241005b70 100644 --- a/test/Profile/c-outdated-data.c +++ b/test/Profile/c-outdated-data.c @@ -1,11 +1,11 @@ // Test that outdated data is ignored. -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-outdated-data.c %s -o - -emit-llvm -fprofile-instr-use=%S/Inputs/c-outdated-data.profdata | FileCheck -check-prefix=PGOUSE %s +// 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. -// TODO: We should have a warning or a remark that tells us the profile data was -// discarded, rather than just checking that we fail to add metadata. +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9 -main-file-name c-outdated-data.c %s -o /dev/null -emit-llvm -fprofile-instr-use=%S/Inputs/c-outdated-data.profdata -Wprofile-instr-dropped 2>&1 | FileCheck %s +// CHECK: warning: profile data may be out of date: of 3 functions, 1 has no data and 1 has mismatched data that will be ignored -// PGOUSE-LABEL: @no_usable_data() void no_usable_data() { int i = 0; @@ -14,9 +14,12 @@ void no_usable_data() { #ifdef GENERATE_OUTDATED_DATA if (i) {} #endif +} - // PGOUSE-NOT: br {{.*}} !prof ![0-9]+ +#ifndef GENERATE_OUTDATED_DATA +void no_data() { } +#endif int main(int argc, const char *argv[]) { no_usable_data(); -- 2.40.0