[glibc/release/2.43/master] math: Fix fma alignment when exponent difference is exactly 64 (BZ 34183)
Adhemerval Zanella via Glibc-cvs <[email protected]> Thu, 28 May 2026 16:21:07 +0000 (GMT)
| Newsgroups | gmane.comp.lib.glibc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=a47b5b2b3eee486c4bea0df65af775296a13f09d commit a47b5b2b3eee486c4bea0df65af775296a13f09d Author: Adhemerval Zanella <[email protected]> Date: Wed May 27 16:48:19 2026 -0300 math: Fix fma alignment when exponent difference is exactly 64 (BZ 34183) When d (the exponent difference between z and x*y) is exactly 64, the alignment path shifts z left by 64 bits via (zhi = nz.m, zlo = 0) and decrements d to 0, then takes the inner 'if (d < 64)' branch which evaluates 'rhi << (64 - d)' with d == 0. A shift by 64 of a 64-bit value is UB in C. Add the explicit 'if (d == 0)' empty branch (present in the original musl implementation). Checked on x86_64-linux-gnu with --disable-multi-arch and arm-linux-gnueabihf. Reviewed-by: H.J. Lu <[email protected]> (cherry picked from commit 1e7935ae87550323021876f3099bb04aeadd8491) Diff: --- math/auto-libm-test-in | 2 ++ math/auto-libm-test-out-fma | 25 +++++++++++++++++++++++++ sysdeps/ieee754/dbl-64/s_fma.c | 5 ++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/math/auto-libm-test-in b/math/auto-libm-test-in index 2001baa605..82f0aface8 100644 --- a/math/auto-libm-test-in +++ b/math/auto-libm-test-in @@ -6483,6 +6483,8 @@ fma 0x1.000002p-126 -0x1.000002p-26 0x1p103 fma 0x1.000002p-126 0x1.000002p-26 -0x1p103 fma 0x1.000002p-126 -0x1.000002p-26 -0x1p103 +fma 0x1.000008p+0 0x1.000008p+0 0x1p+11 + fma 0x1.7fp+13 0x1.0000000000001p+0 0x1.ffep-48 fma 0x1.fffp+0 0x1.0000000000001p+0 -0x1.fffp+0 fma 0x1.0000002p+0 0x1.ffffffcp-1 0x1p-300 diff --git a/math/auto-libm-test-out-fma b/math/auto-libm-test-out-fma index 438fcb61da..ba1fdc7472 100644 --- a/math/auto-libm-test-out-fma +++ b/math/auto-libm-test-out-fma @@ -13364,6 +13364,31 @@ fma 0x1.000002p-126 -0x1.000002p-26 -0x1p103 = fma tonearest ibm128 0x4.000008p-128 -0x4.000008p-28 -0x8p+100 : -0x8p+100 : inexact = fma towardzero ibm128 0x4.000008p-128 -0x4.000008p-28 -0x8p+100 : -0x8p+100 : inexact = fma upward ibm128 0x4.000008p-128 -0x4.000008p-28 -0x8p+100 : -0x8p+100 : inexact +fma 0x1.000008p+0 0x1.000008p+0 0x1p+11 += fma downward binary32 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.01p+8 : inexact += fma tonearest binary32 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.01p+8 : inexact += fma towardzero binary32 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.01p+8 : inexact += fma upward binary32 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.01001p+8 : inexact += fma downward binary64 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001p+8 : inexact += fma tonearest binary64 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001p+8 : inexact += fma towardzero binary64 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001p+8 : inexact += fma upward binary64 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000008p+8 : inexact += fma downward intel96 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma tonearest intel96 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma towardzero intel96 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma upward intel96 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma downward m68k96 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma tonearest m68k96 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma towardzero m68k96 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma upward m68k96 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma downward binary128 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma tonearest binary128 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma towardzero binary128 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma upward binary128 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma downward ibm128 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma tonearest ibm128 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma towardzero ibm128 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : += fma upward ibm128 0x1.000008p+0 0x1.000008p+0 0x8p+8 : 0x8.0100001000004p+8 : fma 0x1.7fp+13 0x1.0000000000001p+0 0x1.ffep-48 = fma downward binary64 0x2.fep+12 0x1.0000000000001p+0 0x1.ffep-48 : 0x2.fe00000000002p+12 : inexact = fma tonearest binary64 0x2.fep+12 0x1.0000000000001p+0 0x1.ffep-48 : 0x2.fe00000000002p+12 : inexact diff --git a/sysdeps/ieee754/dbl-64/s_fma.c b/sysdeps/ieee754/dbl-64/s_fma.c index d65d505915..b9147ae32c 100644 --- a/sysdeps/ieee754/dbl-64/s_fma.c +++ b/sysdeps/ieee754/dbl-64/s_fma.c @@ -114,7 +114,10 @@ __fma (double x, double y, double z) zhi = nz.m; e = nz.e - 64; d -= 64; - if (d < 64) + if (d == 0) + /* No further shift of r needed; rhi/rlo are unchanged. */ + ; + else if (d < 64) { rlo = rhi << (64 - d) | rlo >> d | !!(rlo << (64 - d)); rhi = rhi >> d;