mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-20 13:41:30 +00:00
tracing: Process constants for (un)likely() profiler
When running the likely/unlikely profiler, one of the results did not look accurate. It noted that the unlikely() in link_path_walk() was 100% incorrect. When I added a trace_printk() to see what was happening there, it became 80% correct! Looking deeper into what whas happening, I found that gcc split that if statement into two paths. One where the if statement became a constant, the other path a variable. The other path had the if statement always hit (making the unlikely there, always false), but since the #define unlikely() has: #define unlikely() (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) Where constants are ignored by the branch profiler, the "constant" path made by the compiler was ignored, even though it was hit 80% of the time. By just passing the constant value to the __branch_check__() function and tracing it out of line (as always correct, as likely/unlikely isn't a factor for constants), then we get back the accurate readings of branches that were optimized by gcc causing part of the execution to become constant. Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
parent
6496bb72bf
commit
d45ae1f704
2 changed files with 13 additions and 7 deletions
|
@ -107,12 +107,13 @@ struct ftrace_branch_data {
|
||||||
*/
|
*/
|
||||||
#if defined(CONFIG_TRACE_BRANCH_PROFILING) \
|
#if defined(CONFIG_TRACE_BRANCH_PROFILING) \
|
||||||
&& !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__)
|
&& !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__)
|
||||||
void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
|
void ftrace_likely_update(struct ftrace_branch_data *f, int val,
|
||||||
|
int expect, int is_constant);
|
||||||
|
|
||||||
#define likely_notrace(x) __builtin_expect(!!(x), 1)
|
#define likely_notrace(x) __builtin_expect(!!(x), 1)
|
||||||
#define unlikely_notrace(x) __builtin_expect(!!(x), 0)
|
#define unlikely_notrace(x) __builtin_expect(!!(x), 0)
|
||||||
|
|
||||||
#define __branch_check__(x, expect) ({ \
|
#define __branch_check__(x, expect, is_constant) ({ \
|
||||||
int ______r; \
|
int ______r; \
|
||||||
static struct ftrace_branch_data \
|
static struct ftrace_branch_data \
|
||||||
__attribute__((__aligned__(4))) \
|
__attribute__((__aligned__(4))) \
|
||||||
|
@ -122,8 +123,9 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
|
||||||
.file = __FILE__, \
|
.file = __FILE__, \
|
||||||
.line = __LINE__, \
|
.line = __LINE__, \
|
||||||
}; \
|
}; \
|
||||||
______r = likely_notrace(x); \
|
______r = __builtin_expect(!!(x), expect); \
|
||||||
ftrace_likely_update(&______f, ______r, expect); \
|
ftrace_likely_update(&______f, ______r, \
|
||||||
|
expect, is_constant); \
|
||||||
______r; \
|
______r; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -133,10 +135,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
|
||||||
* written by Daniel Walker.
|
* written by Daniel Walker.
|
||||||
*/
|
*/
|
||||||
# ifndef likely
|
# ifndef likely
|
||||||
# define likely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1))
|
# define likely(x) (__branch_check__(x, 1, __builtin_constant_p(x)))
|
||||||
# endif
|
# endif
|
||||||
# ifndef unlikely
|
# ifndef unlikely
|
||||||
# define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0))
|
# define unlikely(x) (__branch_check__(x, 0, __builtin_constant_p(x)))
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#ifdef CONFIG_PROFILE_ALL_BRANCHES
|
#ifdef CONFIG_PROFILE_ALL_BRANCHES
|
||||||
|
|
|
@ -200,8 +200,12 @@ void trace_likely_condition(struct ftrace_branch_data *f, int val, int expect)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BRANCH_TRACER */
|
#endif /* CONFIG_BRANCH_TRACER */
|
||||||
|
|
||||||
void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect)
|
void ftrace_likely_update(struct ftrace_branch_data *f, int val,
|
||||||
|
int expect, int is_constant)
|
||||||
{
|
{
|
||||||
|
/* A constant is always correct */
|
||||||
|
if (is_constant)
|
||||||
|
val = expect;
|
||||||
/*
|
/*
|
||||||
* I would love to have a trace point here instead, but the
|
* I would love to have a trace point here instead, but the
|
||||||
* trace point code is so inundated with unlikely and likely
|
* trace point code is so inundated with unlikely and likely
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue