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
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">;
"not a Doxygen trailing comment">, InGroup<Documentation>, 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<ProfileInstrOutOfDate>;
+} // end of instrumentation issue category
+
} // end of sema component.
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();
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 {
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
return *RRData;
}
+ InstrProfStats &getPGOStats() {
+ return PGOStats;
+ }
+
PGOProfileData *getPGOData() const {
return PGOData;
}
}
void CodeGenPGO::loadRegionCounts(PGOProfileData *PGOData) {
+ CGM.getPGOStats().Visited++;
RegionCounts.reset(new std::vector<uint64_t>);
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() {
// 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;
#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();