From fe33f943054b93af8b965ce6564b8713b0979a21 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 14 Jun 2024 23:11:05 -0700 Subject: [PATCH] timespec-add,timespec-sub: tune MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * lib/timespec-add.c (timespec_add): * lib/timespec-sub.c (timespec_sub): Simplify by detecting overflow when the two overflow bits of the underlying operation differ. This avoids some gotos and labels and conditional branches; GCC 14 x86-64 now generates just one conditional branch for the resulting code. Idea stolen from my recent changes to the glibc manual’s time chapter. * modules/timespec-add (Depends-on): * modules/timespec-sub (Depends-on): Add stdbool. --- ChangeLog | 13 +++++++++++++ lib/timespec-add.c | 30 +++++++++--------------------- lib/timespec-sub.c | 29 +++++++++-------------------- modules/timespec-add | 1 + modules/timespec-sub | 1 + 5 files changed, 33 insertions(+), 41 deletions(-) diff --git a/ChangeLog b/ChangeLog index 12b392648d..93266c7e23 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2024-06-14 Paul Eggert + + timespec-add,timespec-sub: tune + * lib/timespec-add.c (timespec_add): + * lib/timespec-sub.c (timespec_sub): + Simplify by detecting overflow when the two overflow bits of the + underlying operation differ. This avoids some gotos and labels + and conditional branches; GCC 14 x86-64 now generates just one + conditional branch for the resulting code. Idea stolen from + my recent changes to the glibc manual’s time chapter. + * modules/timespec-add (Depends-on): + * modules/timespec-sub (Depends-on): Add stdbool. + 2024-06-14 Collin Funk gnulib-tool.py: Simplify joining paths. diff --git a/lib/timespec-add.c b/lib/timespec-add.c index e10c19842c..5068318711 100644 --- a/lib/timespec-add.c +++ b/lib/timespec-add.c @@ -29,34 +29,22 @@ struct timespec timespec_add (struct timespec a, struct timespec b) { - time_t rs = a.tv_sec; - time_t bs = b.tv_sec; - int ns = a.tv_nsec + b.tv_nsec; - int nsd = ns - TIMESPEC_HZ; - int rns = ns; - - if (0 <= nsd) - { - rns = nsd; - time_t bs1; - if (!ckd_add (&bs1, bs, 1)) - bs = bs1; - else if (rs < 0) - rs++; - else - goto high_overflow; - } - - if (ckd_add (&rs, rs, bs)) + int nssum = a.tv_nsec + b.tv_nsec; + int carry = TIMESPEC_HZ <= nssum; + time_t rs; + int rns; + bool v = ckd_add (&rs, a.tv_sec, b.tv_sec); + if (v == ckd_add (&rs, rs, carry)) + rns = nssum - TIMESPEC_HZ * carry; + else { - if (bs < 0) + if ((TYPE_MINIMUM (time_t) + TYPE_MAXIMUM (time_t)) / 2 < rs) { rs = TYPE_MINIMUM (time_t); rns = 0; } else { - high_overflow: rs = TYPE_MAXIMUM (time_t); rns = TIMESPEC_HZ - 1; } diff --git a/lib/timespec-sub.c b/lib/timespec-sub.c index 315cc63836..f6d948780e 100644 --- a/lib/timespec-sub.c +++ b/lib/timespec-sub.c @@ -30,28 +30,17 @@ struct timespec timespec_sub (struct timespec a, struct timespec b) { - time_t rs = a.tv_sec; - time_t bs = b.tv_sec; - int ns = a.tv_nsec - b.tv_nsec; - int rns = ns; - - if (ns < 0) - { - rns = ns + TIMESPEC_HZ; - time_t bs1; - if (!ckd_add (&bs1, bs, 1)) - bs = bs1; - else if (- TYPE_SIGNED (time_t) < rs) - rs--; - else - goto low_overflow; - } - - if (ckd_sub (&rs, rs, bs)) + int nsdiff = a.tv_nsec - b.tv_nsec; + bool borrow = nsdiff < 0; + time_t rs; + int rns; + bool v = ckd_sub (&rs, a.tv_sec, b.tv_sec); + if (v == ckd_sub (&rs, rs, borrow)) + rns = nsdiff + TIMESPEC_HZ * borrow; + else { - if (0 < bs) + if ((TYPE_MINIMUM (time_t) + TYPE_MAXIMUM (time_t)) / 2 < rs) { - low_overflow: rs = TYPE_MINIMUM (time_t); rns = 0; } diff --git a/modules/timespec-add b/modules/timespec-add index 45daf6e26b..d509f3019e 100644 --- a/modules/timespec-add +++ b/modules/timespec-add @@ -7,6 +7,7 @@ lib/timespec-add.c Depends-on: c99 intprops +stdbool stdckdint timespec diff --git a/modules/timespec-sub b/modules/timespec-sub index d7316a5c9c..1fd2309ae4 100644 --- a/modules/timespec-sub +++ b/modules/timespec-sub @@ -7,6 +7,7 @@ lib/timespec-sub.c Depends-on: c99 intprops +stdbool stdckdint timespec -- 2.39.5