def warn_profile_data_unprofiled : Warning<
"no profile data available for file \"%0\"">,
InGroup<ProfileInstrUnprofiled>;
-def warn_profile_data_misexpect : Warning<
- "Potential performance regression from use of __builtin_expect(): "
- "Annotation was correct on %0 of profiled executions.">,
- BackendInfo,
- InGroup<MisExpect>,
- DefaultIgnore;
+
} // end of instrumentation issue category
}
def ProfileInstrMissing : DiagGroup<"profile-instr-missing">;
def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">;
def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">;
-def MisExpect : DiagGroup<"misexpect">;
// AddressSanitizer frontend instrumentation remarks.
def SanitizeAddressRemarks : DiagGroup<"sanitize-address">;
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
-#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangStandard.h"
#include "clang/Basic/SourceManager.h"
bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D);
/// Specialized handler for unsupported backend feature diagnostic.
void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D);
- /// Specialized handler for misexpect warnings.
- /// Note that misexpect remarks are emitted through ORE
- void MisExpectDiagHandler(const llvm::DiagnosticInfoMisExpect &D);
/// Specialized handlers for optimization remarks.
/// Note that these handlers only accept remarks and they always handle
/// them.
<< Filename << Line << Column;
}
-void BackendConsumer::MisExpectDiagHandler(
- const llvm::DiagnosticInfoMisExpect &D) {
- StringRef Filename;
- unsigned Line, Column;
- bool BadDebugInfo = false;
- FullSourceLoc Loc =
- getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
-
- Diags.Report(Loc, diag::warn_profile_data_misexpect) << D.getMsg().str();
-
- if (BadDebugInfo)
- // If we were not able to translate the file:line:col information
- // back to a SourceLocation, at least emit a note stating that
- // we could not translate this location. This can happen in the
- // case of #line directives.
- Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
- << Filename << Line << Column;
-}
-
void BackendConsumer::EmitOptimizationMessage(
const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) {
// We only support warnings and remarks.
case llvm::DK_Unsupported:
UnsupportedDiagHandler(cast<DiagnosticInfoUnsupported>(DI));
return;
- case llvm::DK_MisExpect:
- MisExpectDiagHandler(cast<DiagnosticInfoMisExpect>(DI));
- return;
default:
// Plugin IDs are not bound to any value as they are set dynamically.
ComputeDiagRemarkID(Severity, backend_plugin, DiagID);
}
}
- if (Diags.isIgnored(diag::warn_profile_data_misexpect, SourceLocation()))
- Res.FrontendOpts.LLVMArgs.push_back("-pgo-warn-misexpect");
-
LangOpts.FunctionAlignment =
getLastArgIntValue(Args, OPT_function_alignment, 0, Diags);
+++ /dev/null
-bar
-# Func Hash:
-11262309464
-# Num Counters:
-2
-# Counter Values:
-200000
-2
-
+++ /dev/null
-bar
-# Func Hash:
-45795613684824
-# Num Counters:
-2
-# Counter Values:
-200000
-0
-
+++ /dev/null
-main
-# Func Hash:
-79676873694057560
-# Num Counters:
-5
-# Counter Values:
-1
-20
-20000
-20000
-20000
-
+++ /dev/null
-main
-# Func Hash:
-8712453512413296413
-# Num Counters:
-9
-# Counter Values:
-1
-20000
-20000
-4066
-11889
-0
-0
-4045
-0
-
+++ /dev/null
-main
-# Func Hash:
-1965403898329309329
-# Num Counters:
-9
-# Counter Values:
-1
-20
-20000
-20000
-12
-26
-0
-0
-19962
-
+++ /dev/null
-// Test that misexpect emits no warning when prediction is correct
-
-// RUN: llvm-profdata merge %S/Inputs/misexpect-branch.proftext -o %t.profdata
-// RUN: %clang_cc1 %s -O2 -o - -disable-llvm-passes -emit-llvm -fprofile-instrument-use-path=%t.profdata -verify -Wmisexpect
-
-// expected-no-diagnostics
-#define likely(x) __builtin_expect(!!(x), 1)
-#define unlikely(x) __builtin_expect(!!(x), 0)
-
-int foo(int);
-int baz(int);
-int buzz();
-
-const int inner_loop = 100;
-const int outer_loop = 2000;
-
-int bar() {
- int rando = buzz();
- int x = 0;
- if (unlikely(rando % (outer_loop * inner_loop) == 0)) {
- x = baz(rando);
- } else {
- x = foo(50);
- }
- return x;
-}
+++ /dev/null
-// Test that misexpect emits no warning when condition is not a compile-time constant
-
-// RUN: llvm-profdata merge %S/Inputs/misexpect-branch-nonconst-expect-arg.proftext -o %t.profdata
-// RUN: %clang_cc1 %s -O2 -o - -disable-llvm-passes -emit-llvm -fprofile-instrument-use-path=%t.profdata -verify -Wmisexpect
-
-// expected-no-diagnostics
-int foo(int);
-int baz(int);
-int buzz();
-
-const int inner_loop = 100;
-const int outer_loop = 2000;
-
-int bar() {
- int rando = buzz();
- int x = 0;
- if (__builtin_expect(rando % (outer_loop * inner_loop) == 0, buzz())) {
- x = baz(rando);
- } else {
- x = foo(50);
- }
- return x;
-}
+++ /dev/null
-// Test that misexpect emits no warning when prediction is correct
-
-// RUN: llvm-profdata merge %S/Inputs/misexpect-branch.proftext -o %t.profdata
-// RUN: %clang_cc1 %s -O2 -o - -disable-llvm-passes -emit-llvm -fprofile-instrument-use-path=%t.profdata -verify -Wmisexpect
-
-// expected-no-diagnostics
-#define unpredictable(x) __builtin_unpredictable(!!(x))
-
-int foo(int);
-int baz(int);
-int buzz();
-
-const int inner_loop = 100;
-const int outer_loop = 2000;
-
-int bar() {
- int rando = buzz();
- int x = 0;
- if (unpredictable(rando % (outer_loop * inner_loop) == 0)) {
- x = baz(rando);
- } else {
- x = foo(50);
- }
- return x;
-}
+++ /dev/null
-// Test that misexpect detects mis-annotated branches
-
-// RUN: llvm-profdata merge %S/Inputs/misexpect-branch.proftext -o %t.profdata
-// RUN: %clang_cc1 %s -O2 -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata -verify=imprecise -Wmisexpect
-// RUN: %clang_cc1 %s -O2 -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata -verify=exact -Wmisexpect -debug-info-kind=line-tables-only
-// RUN: %clang_cc1 %s -O2 -o - -disable-llvm-passes -emit-llvm -fprofile-instrument-use-path=%t.profdata -verify=foo
-
-// foo-no-diagnostics
-#define likely(x) __builtin_expect(!!(x), 1)
-#define unlikely(x) __builtin_expect(!!(x), 0)
-
-int foo(int);
-int baz(int);
-int buzz();
-
-const int inner_loop = 100;
-const int outer_loop = 2000;
-
-int bar() { // imprecise-warning-re {{Potential performance regression from use of __builtin_expect(): Annotation was correct on {{.+}}% ({{[0-9]+ / [0-9]+}}) of profiled executions.}}
- int rando = buzz();
- int x = 0;
- if (likely(rando % (outer_loop * inner_loop) == 0)) { // exact-warning-re {{Potential performance regression from use of __builtin_expect(): Annotation was correct on {{.+}}% ({{[0-9]+ / [0-9]+}}) of profiled executions.}}
- x = baz(rando);
- } else {
- x = foo(50);
- }
- return x;
-}
+++ /dev/null
-// Test that misexpect detects mis-annotated switch statements for default case
-
-// RUN: llvm-profdata merge %S/Inputs/misexpect-switch-default.proftext -o %t.profdata
-// RUN: %clang_cc1 %s -O2 -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata -verify -Wmisexpect -debug-info-kind=line-tables-only
-
-int sum(int *buff, int size);
-int random_sample(int *buff, int size);
-int rand();
-void init_arry();
-
-const int inner_loop = 1000;
-const int outer_loop = 20;
-const int arry_size = 25;
-
-int arry[arry_size] = {0};
-
-int main() {
- init_arry();
- int val = 0;
- int j;
- for (j = 0; j < outer_loop * inner_loop; ++j) {
- unsigned condition = rand() % 5;
- switch (__builtin_expect(condition, 6)) { // expected-warning-re {{Potential performance regression from use of __builtin_expect(): Annotation was correct on {{.+}}% ({{[0-9]+ / [0-9]+}}) of profiled executions.}}
- case 0:
- val += sum(arry, arry_size);
- break;
- case 1:
- case 2:
- case 3:
- break;
- case 4:
- val += random_sample(arry, arry_size);
- break;
- default:
- __builtin_unreachable();
- } // end switch
- } // end outer_loop
-
- return 0;
-}
+++ /dev/null
-// Test that misexpect emits no warning when switch condition is non-const
-
-// RUN: llvm-profdata merge %S/Inputs/misexpect-switch.proftext -o %t.profdata
-// RUN: %clang_cc1 %s -O2 -o - -disable-llvm-passes -emit-llvm -fprofile-instrument-use-path=%t.profdata -verify -Wmisexpect
-
-// expected-no-diagnostics
-int sum(int *buff, int size);
-int random_sample(int *buff, int size);
-int rand();
-void init_arry();
-
-const int inner_loop = 1000;
-const int outer_loop = 20;
-const int arry_size = 25;
-
-int arry[arry_size] = {0};
-
-int main() {
- init_arry();
- int val = 0;
-
- int j, k;
- for (j = 0; j < outer_loop; ++j) {
- for (k = 0; k < inner_loop; ++k) {
- unsigned condition = rand() % 10000;
- switch (__builtin_expect(condition, rand())) {
- case 0:
- val += sum(arry, arry_size);
- break;
- case 1:
- case 2:
- case 3:
- case 4:
- val += random_sample(arry, arry_size);
- break;
- default:
- __builtin_unreachable();
- } // end switch
- } // end inner_loop
- } // end outer_loop
-
- return 0;
-}
+++ /dev/null
-// Test that misexpect emits no warning when there is only one switch case
-
-// RUN: llvm-profdata merge %S/Inputs/misexpect-switch-default-only.proftext -o %t.profdata
-// RUN: %clang_cc1 %s -O2 -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata -verify -Wmisexpect -debug-info-kind=line-tables-only
-
-// expected-no-diagnostics
-int sum(int *buff, int size);
-int random_sample(int *buff, int size);
-int rand();
-void init_arry();
-
-const int inner_loop = 1000;
-const int outer_loop = 20;
-const int arry_size = 25;
-
-int arry[arry_size] = {0};
-
-int main() {
- init_arry();
- int val = 0;
-
- int j, k;
- for (j = 0; j < outer_loop; ++j) {
- for (k = 0; k < inner_loop; ++k) {
- unsigned condition = rand() % 10000;
- switch (__builtin_expect(condition, 0)) {
- default:
- val += random_sample(arry, arry_size);
- break;
- }; // end switch
- } // end inner_loop
- } // end outer_loop
-
- return 0;
-}
+++ /dev/null
-// Test that misexpect detects mis-annotated switch statements
-
-// RUN: llvm-profdata merge %S/Inputs/misexpect-switch.proftext -o %t.profdata
-// RUN: %clang_cc1 %s -O2 -o - -emit-llvm -fprofile-instrument-use-path=%t.profdata -verify -Wmisexpect -debug-info-kind=line-tables-only
-
-int sum(int *buff, int size);
-int random_sample(int *buff, int size);
-int rand();
-void init_arry();
-
-const int inner_loop = 1000;
-const int outer_loop = 20;
-const int arry_size = 25;
-
-int arry[arry_size] = {0};
-
-int main() {
- init_arry();
- int val = 0;
-
- int j, k;
- for (j = 0; j < outer_loop; ++j) {
- for (k = 0; k < inner_loop; ++k) {
- unsigned condition = rand() % 10000;
- switch (__builtin_expect(condition, 0)) { // expected-warning-re {{Potential performance regression from use of __builtin_expect(): Annotation was correct on {{.+}}% ({{[0-9]+ / [0-9]+}}) of profiled executions.}}
- case 0:
- val += sum(arry, arry_size);
- break;
- case 1:
- case 2:
- case 3:
- break;
- default:
- val += random_sample(arry, arry_size);
- break;
- } // end switch
- } // end inner_loop
- } // end outer_loop
-
- return 0;
-}