Message ID | 20221010060050.3741173-1-aurelien@aurel32.net |
---|---|
State | New |
Headers | show |
Series | [v3] Avoid undefined behaviour in ibm128 implementation of llroundl (BZ #29488) | expand |
On Mon, 10 Oct 2022 at 19:01, Aurelien Jarno <aurelien@aurel32.net> wrote: > Detecting an overflow edge case depended on signed overflow of a long > long. Replace the additions and the overflow checks by > __builtin_add_overflow(). > This certainly looks better than my fix, thanks! Cheers, mwh > sysdeps/ieee754/ldbl-128ibm/s_llroundl.c | 21 +++++++++------------ > 1 file changed, 9 insertions(+), 12 deletions(-) > > This patch is based on the original patch from Michael Hudson-Doyle, > using __builtin_add_overflow() as suggested by Florian Weimer > > It passes all tests on ppc64el with gcc 12 with both -O2 and -O3. > > diff --git a/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c > b/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c > index d85154e73a..d8c0de1faf 100644 > --- a/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c > +++ b/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c > @@ -66,38 +66,35 @@ __llroundl (long double x) > /* Peg at max/min values, assuming that the above conversions do so. > Strictly speaking, we can return anything for values that > overflow, > but this is more useful. */ > - res = hi + lo; > - > - /* This is just sign(hi) == sign(lo) && sign(res) != sign(hi). */ > - if (__glibc_unlikely (((~(hi ^ lo) & (res ^ hi)) < 0))) > + if (__glibc_unlikely (__builtin_add_overflow (hi, lo, &res))) > goto overflow; > > xh -= lo; > ldbl_canonicalize (&xh, &xl); > > - hi = res; > if (xh > 0.5) > { > - res += 1; > + if (__glibc_unlikely (__builtin_add_overflow (res, 1, &res))) > + goto overflow; > } > else if (xh == 0.5) > { > if (xl > 0.0 || (xl == 0.0 && res >= 0)) > - res += 1; > + if (__glibc_unlikely (__builtin_add_overflow (res, 1, &res))) > + goto overflow; > } > else if (-xh > 0.5) > { > - res -= 1; > + if (__glibc_unlikely (__builtin_add_overflow (res, -1, &res))) > + goto overflow; > } > else if (-xh == 0.5) > { > if (xl < 0.0 || (xl == 0.0 && res <= 0)) > - res -= 1; > + if (__glibc_unlikely (__builtin_add_overflow (res, -1, &res))) > + goto overflow; > } > > - if (__glibc_unlikely (((~(hi ^ (res - hi)) & (res ^ hi)) < 0))) > - goto overflow; > - > return res; > } > else > -- > 2.35.1 > >
Ping. Tulio (as powerpc machine maintainer) or Joseph (as math component maintainer), could you please have a look at this patch? On 2022-10-10 08:00, Aurelien Jarno wrote: > Detecting an overflow edge case depended on signed overflow of a long > long. Replace the additions and the overflow checks by > __builtin_add_overflow(). > --- > sysdeps/ieee754/ldbl-128ibm/s_llroundl.c | 21 +++++++++------------ > 1 file changed, 9 insertions(+), 12 deletions(-) > > This patch is based on the original patch from Michael Hudson-Doyle, > using __builtin_add_overflow() as suggested by Florian Weimer > > It passes all tests on ppc64el with gcc 12 with both -O2 and -O3. > > diff --git a/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c b/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c > index d85154e73a..d8c0de1faf 100644 > --- a/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c > +++ b/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c > @@ -66,38 +66,35 @@ __llroundl (long double x) > /* Peg at max/min values, assuming that the above conversions do so. > Strictly speaking, we can return anything for values that overflow, > but this is more useful. */ > - res = hi + lo; > - > - /* This is just sign(hi) == sign(lo) && sign(res) != sign(hi). */ > - if (__glibc_unlikely (((~(hi ^ lo) & (res ^ hi)) < 0))) > + if (__glibc_unlikely (__builtin_add_overflow (hi, lo, &res))) > goto overflow; > > xh -= lo; > ldbl_canonicalize (&xh, &xl); > > - hi = res; > if (xh > 0.5) > { > - res += 1; > + if (__glibc_unlikely (__builtin_add_overflow (res, 1, &res))) > + goto overflow; > } > else if (xh == 0.5) > { > if (xl > 0.0 || (xl == 0.0 && res >= 0)) > - res += 1; > + if (__glibc_unlikely (__builtin_add_overflow (res, 1, &res))) > + goto overflow; > } > else if (-xh > 0.5) > { > - res -= 1; > + if (__glibc_unlikely (__builtin_add_overflow (res, -1, &res))) > + goto overflow; > } > else if (-xh == 0.5) > { > if (xl < 0.0 || (xl == 0.0 && res <= 0)) > - res -= 1; > + if (__glibc_unlikely (__builtin_add_overflow (res, -1, &res))) > + goto overflow; > } > > - if (__glibc_unlikely (((~(hi ^ (res - hi)) & (res ^ hi)) < 0))) > - goto overflow; > - > return res; > } > else > -- > 2.35.1 > >
Aurelien Jarno <aurelien@aurel32.net> writes: > Ping. Tulio (as powerpc machine maintainer) or Joseph (as math component > maintainer), could you please have a look at this patch? I apologize for taking so long to review this. LGTM. Reviewed-by: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c b/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c index d85154e73a..d8c0de1faf 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_llroundl.c @@ -66,38 +66,35 @@ __llroundl (long double x) /* Peg at max/min values, assuming that the above conversions do so. Strictly speaking, we can return anything for values that overflow, but this is more useful. */ - res = hi + lo; - - /* This is just sign(hi) == sign(lo) && sign(res) != sign(hi). */ - if (__glibc_unlikely (((~(hi ^ lo) & (res ^ hi)) < 0))) + if (__glibc_unlikely (__builtin_add_overflow (hi, lo, &res))) goto overflow; xh -= lo; ldbl_canonicalize (&xh, &xl); - hi = res; if (xh > 0.5) { - res += 1; + if (__glibc_unlikely (__builtin_add_overflow (res, 1, &res))) + goto overflow; } else if (xh == 0.5) { if (xl > 0.0 || (xl == 0.0 && res >= 0)) - res += 1; + if (__glibc_unlikely (__builtin_add_overflow (res, 1, &res))) + goto overflow; } else if (-xh > 0.5) { - res -= 1; + if (__glibc_unlikely (__builtin_add_overflow (res, -1, &res))) + goto overflow; } else if (-xh == 0.5) { if (xl < 0.0 || (xl == 0.0 && res <= 0)) - res -= 1; + if (__glibc_unlikely (__builtin_add_overflow (res, -1, &res))) + goto overflow; } - if (__glibc_unlikely (((~(hi ^ (res - hi)) & (res ^ hi)) < 0))) - goto overflow; - return res; } else