Presumably due to -fno-strict-aliasing, gcc doesn't know that the
stores through vdata do not alter the value of tk->tkr_mono.shift. So
e.g. in the loop normalizing vdata->monotonic_time_snsec, gcc reloads
tk->tkr_mono.shift and recomputes the ((u64)NSEC_PER_SEC) <<
tk->tkr_mono.shift constant. While that loop is usually never entered,
so the constant is only used once, we might as well make the generated
code a little smaller and microscopically faster when we do enter the
loop. So make a local copy of shift and use that.

Do not do the assignment in the declaration, because there's another
shift operation (1 << vclock_mode) before we get to use the shift
variable, and there's no point in having gcc load it to some non-%ecx
register, or, on 32 bit, immediately spill it.

As a bonus, two awkward line breaks vanish. bloat-o-meter:

Function                                     old     new   delta
update_vsyscall                              480     398     -82 (i386)
update_vsyscall                              304     281     -23 (x86_64)

Signed-off-by: Rasmus Villemoes <[email protected]>
---
Other tricks are possible (reuse the initial monotonic_time
computation for the _coarse version, maybe alias
vdata->wall_time{,_coarse}_sec via a union (and rearrange to make sure
both are in the same cache line as their nsec buddy)), but I'm not
sure even this one is worth it.

arch/x86/entry/vsyscall/vsyscall_gtod.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/arch/x86/entry/vsyscall/vsyscall_gtod.c 
b/arch/x86/entry/vsyscall/vsyscall_gtod.c
index e1216dd95c04..550447a43a50 100644
--- a/arch/x86/entry/vsyscall/vsyscall_gtod.c
+++ b/arch/x86/entry/vsyscall/vsyscall_gtod.c
@@ -31,6 +31,7 @@ void update_vsyscall(struct timekeeper *tk)
 {
        int vclock_mode = tk->tkr_mono.clock->archdata.vclock_mode;
        struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data;
+       int shift;
 
        /* Mark the new vclock used. */
        BUILD_BUG_ON(VCLOCK_MAX >= 32);
@@ -43,7 +44,7 @@ void update_vsyscall(struct timekeeper *tk)
        vdata->cycle_last       = tk->tkr_mono.cycle_last;
        vdata->mask             = tk->tkr_mono.mask;
        vdata->mult             = tk->tkr_mono.mult;
-       vdata->shift            = tk->tkr_mono.shift;
+       vdata->shift = shift    = tk->tkr_mono.shift;
 
        vdata->wall_time_sec            = tk->xtime_sec;
        vdata->wall_time_snsec          = tk->tkr_mono.xtime_nsec;
@@ -52,17 +53,15 @@ void update_vsyscall(struct timekeeper *tk)
                                        + tk->wall_to_monotonic.tv_sec;
        vdata->monotonic_time_snsec     = tk->tkr_mono.xtime_nsec
                                        + ((u64)tk->wall_to_monotonic.tv_nsec
-                                               << tk->tkr_mono.shift);
-       while (vdata->monotonic_time_snsec >=
-                                       (((u64)NSEC_PER_SEC) << 
tk->tkr_mono.shift)) {
-               vdata->monotonic_time_snsec -=
-                                       ((u64)NSEC_PER_SEC) << 
tk->tkr_mono.shift;
+                                               << shift);
+       while (vdata->monotonic_time_snsec >= (((u64)NSEC_PER_SEC) << shift)) {
+               vdata->monotonic_time_snsec -= ((u64)NSEC_PER_SEC) << shift;
                vdata->monotonic_time_sec++;
        }
 
        vdata->wall_time_coarse_sec     = tk->xtime_sec;
        vdata->wall_time_coarse_nsec    = (long)(tk->tkr_mono.xtime_nsec >>
-                                                tk->tkr_mono.shift);
+                                                shift);
 
        vdata->monotonic_time_coarse_sec =
                vdata->wall_time_coarse_sec + tk->wall_to_monotonic.tv_sec;
-- 
2.15.1

Reply via email to