aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/compiler.h
diff options
context:
space:
mode:
authorSteven Rostedt (VMware) <rostedt@goodmis.org>2017-01-17 12:29:35 -0500
committerSteven Rostedt (VMware) <rostedt@goodmis.org>2017-01-17 15:13:05 -0500
commitd45ae1f7041ac52ade6c5ec76d96bbed765d67aa (patch)
tree902c94fd3caee27e8812eebb0591d10243fcb871 /include/linux/compiler.h
parent6496bb72bf20c1c7e4d6be44dfa663163e709116 (diff)
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>
Diffstat (limited to 'include/linux/compiler.h')
-rw-r--r--include/linux/compiler.h14
1 files changed, 8 insertions, 6 deletions
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index cf0fa5d86059..bbbe1570de1c 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -107,12 +107,13 @@ struct ftrace_branch_data {
107 */ 107 */
108#if defined(CONFIG_TRACE_BRANCH_PROFILING) \ 108#if defined(CONFIG_TRACE_BRANCH_PROFILING) \
109 && !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__) 109 && !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__)
110void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); 110void ftrace_likely_update(struct ftrace_branch_data *f, int val,
111 int expect, int is_constant);
111 112
112#define likely_notrace(x) __builtin_expect(!!(x), 1) 113#define likely_notrace(x) __builtin_expect(!!(x), 1)
113#define unlikely_notrace(x) __builtin_expect(!!(x), 0) 114#define unlikely_notrace(x) __builtin_expect(!!(x), 0)
114 115
115#define __branch_check__(x, expect) ({ \ 116#define __branch_check__(x, expect, is_constant) ({ \
116 int ______r; \ 117 int ______r; \
117 static struct ftrace_branch_data \ 118 static struct ftrace_branch_data \
118 __attribute__((__aligned__(4))) \ 119 __attribute__((__aligned__(4))) \
@@ -122,8 +123,9 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
122 .file = __FILE__, \ 123 .file = __FILE__, \
123 .line = __LINE__, \ 124 .line = __LINE__, \
124 }; \ 125 }; \
125 ______r = likely_notrace(x); \ 126 ______r = __builtin_expect(!!(x), expect); \
126 ftrace_likely_update(&______f, ______r, expect); \ 127 ftrace_likely_update(&______f, ______r, \
128 expect, is_constant); \
127 ______r; \ 129 ______r; \
128 }) 130 })
129 131
@@ -133,10 +135,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
133 * written by Daniel Walker. 135 * written by Daniel Walker.
134 */ 136 */
135# ifndef likely 137# ifndef likely
136# define likely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1)) 138# define likely(x) (__branch_check__(x, 1, __builtin_constant_p(x)))
137# endif 139# endif
138# ifndef unlikely 140# ifndef unlikely
139# define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) 141# define unlikely(x) (__branch_check__(x, 0, __builtin_constant_p(x)))
140# endif 142# endif
141 143
142#ifdef CONFIG_PROFILE_ALL_BRANCHES 144#ifdef CONFIG_PROFILE_ALL_BRANCHES