musl: Use FENV_ACCESS pragma instead of maytrap exception behavior
PATCH 1/3 musl: Use FENV_ACCESS pragma instead of maytrap exception behavior
Upstream review [1] asked whether the real problem is a missing #pragma STDC FENV_ACCESS ON in the affected sources. It is: with the pragma in expm1.c, expm1f.c, hypot.c and hypotf.c, clang stops speculating the floating point operations that raise the spurious exceptions, and libc-test math/expm1, expm1f, hypot, hypotf and sinh pass.
Tested natively on aarch64 with clang 23.1.3 and gcc 14.2 for generic, cortex-a57, cortex-a72 and neoverse-n1: those tests now pass with both compilers, and gcc builds are unchanged. The remaining clang only math failure, yn, comes from fma contraction and is already deleted from the libc-test ptest.
Replace the configure flag with the source change.
[1] https://www.openwall.com/lists/musl/2026/10/28/2
AI-Generated: Uses Claude Code
--- ...p-exception-behavior-maytrap-when-su.patch | 46 ------------ ..._ACCESS-in-expm1-expm1f-hypot-and-hy.patch | 73 +++++++++++++++++++ meta/recipes-core/musl/musl_git.bb | 2 +- 3 files changed, 74 insertions(+), 47 deletions(-) delete mode 100644 meta/recipes-core/musl/musl/0004-configure-use-ffp-exception-behavior-maytrap-when-su.patch create mode 100644 meta/recipes-core/musl/musl/0004-math-enable-FENV_ACCESS-in-expm1-expm1f-hypot-and-hy.patch
meta/recipes-core/musl/musl/0004-configure-use-ffp-exception-behavior-maytrap-when-su.patch deleted +0 -46
@@ -1,46 +0,0 @@ -From fe310a5e2fe6be3c28f800bde383d7df5aac4b49 Mon Sep 17 00:00:00 2001 -From: Khem Raj <[email protected]> -Date: Sun, 25 Oct 2026 21:54:26 -0700 -Subject: [PATCH] configure: use -ffp-exception-behavior=maytrap when supported - -The math library relies on floating point exception flags being raised -exactly as the C code would raise them. GCC keeps that by default -(-ftrapping-math), but clang assumes floating point exceptions are never -inspected unless told otherwise, and may then evaluate both arms of a -branch and select the result. Built with clang 23 for aarch64, expm1() -computes both y*2.0*0x1p1023 and y*twopk for the k < 0 || k > 56 case -and picks one with fcsel, so the unused multiply raises a spurious -OVERFLOW. libc-test's math/expm1, expm1f, hypot, hypotf and sinh fail -because of that. - --ffp-exception-behavior=maytrap tells clang to avoid transformations -that raise exceptions the original code would not raise. GCC does not -accept the option, so tryflag leaves GCC builds unchanged. - -Upstream-Status: Submitted [https://www.openwall.com/lists/musl/2026/10/28/1] -Signed-off-by: Khem Raj <[email protected]> ---- - configure | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/configure b/configure -index bc9fbe48..7e1e1b72 100755 ---- a/configure -+++ b/configure -@@ -355,6 +355,16 @@ tryflag CFLAGS_C99FSE -fexcess-precision=standard \ - || { test "$ARCH" = i386 && tryflag CFLAGS_C99FSE -ffloat-store ; } - tryflag CFLAGS_C99FSE -frounding-math - -+# -+# The math library relies on floating point exception flags being -+# raised exactly as the C code would raise them. GCC does not move -+# floating point operations that may trap across branches by default -+# (-ftrapping-math), but clang assumes exceptions are never inspected -+# unless told otherwise, and may then evaluate both sides of a branch, -+# raising spurious exceptions (e.g. OVERFLOW from expm1, hypot, sinh). -+# -+tryflag CFLAGS_C99FSE -ffp-exception-behavior=maytrap -+ - # - # Semantically we want to insist that our sources follow the - # C rules for type-based aliasing, but most if not all real-world
meta/recipes-core/musl/musl/0004-math-enable-FENV_ACCESS-in-expm1-expm1f-hypot-and-hy.patch new file +73 -0
73 lines not on this page · raw message
meta/recipes-core/musl/musl_git.bb +1 -1
@@ -14,7 +14,7 @@ SRC_URI = "git://git.musl-libc.org/musl;branch=master \ file://0001-Make-dynamic-linker-a-relative-symlink-to-libc.patch \ file://0002-ldso-Use-syslibdir-and-libdir-as-default-pathes-to-l.patch \ file://0003-tools-version.sh-fall-back-to-VERSION-when-git-descr.patch \ - file://0004-configure-use-ffp-exception-behavior-maytrap-when-su.patch \ + file://0004-math-enable-FENV_ACCESS-in-expm1-expm1f-hypot-and-hy.patch \ " PROVIDES += "virtual/libc virtual/libiconv virtual/libintl virtual/crypt"
PATCH 2/3 musl: Disable FP contraction in yn
clang contracts a*b+c into fma by default, unlike GCC in ISO C mode. That changes the rounding of the yn() forward recurrence, and libc-test math/yn fails with a 3.2 ulp error when musl is built with clang. Turn contraction off in jn.c with #pragma STDC FP_CONTRACT OFF.
Tested natively on aarch64 with clang 23.1.3 and gcc 14.2 for generic, cortex-a57, cortex-a72 and neoverse-n1: math/yn passes with both compilers.
AI-Generated: Uses Claude Code
--- ...-math-disable-FP-contraction-in-jn.c.patch | 34 +++++++++++++++++++ meta/recipes-core/musl/musl_git.bb | 1 + 2 files changed, 35 insertions(+) create mode 100644 meta/recipes-core/musl/musl/0005-math-disable-FP-contraction-in-jn.c.patch
meta/recipes-core/musl/musl/0005-math-disable-FP-contraction-in-jn.c.patch new file +34 -0
@@ -0,0 +1,34 @@ +From 3c36c2969dc3bea32d7e465428f7b2c78787de77 Mon Sep 17 00:00:00 2001 +From: Khem Raj <[email protected]> +Date: Tue, 10 Nov 2026 20:13:06 -0800 +Subject: [PATCH] math: disable FP contraction in jn.c + +GCC does not contract floating point expressions in ISO C mode +(-std=c99), but clang contracts a*b+c into fma by default. In yn() +that turns the forward recurrence b = (2.0*i/x)*b - a into an fma, +which changes its rounding. Built with clang 23 for aarch64, +libc-test's math/yn then fails with + + yn(6, 0x1.8c5db097f7442p-1) want -0x1.6dbc18f9d5ddep+13 + got -0x1.6dbc18f9d5de1p+13, ulperr -3.219 + +Turn contraction off for this file, as GCC builds already have it. + +Upstream-Status: Submitted [https://www.openwall.com/lists/musl/2026/11/11/4] +Signed-off-by: Khem Raj <[email protected]> +--- + src/math/jn.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/math/jn.c b/src/math/jn.c +index 4878a54..b077f02 100644 +--- a/src/math/jn.c ++++ b/src/math/jn.c +@@ -35,6 +35,7 @@ + */ + + #include "libm.h" ++#pragma STDC FP_CONTRACT OFF + + static const double invsqrtpi = 5.64189583547756279280e-01; /* 0x3FE20DD7, 0x50429B6D */ +
meta/recipes-core/musl/musl_git.bb +1 -0
@@ -15,6 +15,7 @@ SRC_URI = "git://git.musl-libc.org/musl;branch=master \ file://0002-ldso-Use-syslibdir-and-libdir-as-default-pathes-to-l.patch \ file://0003-tools-version.sh-fall-back-to-VERSION-when-git-descr.patch \ file://0004-math-enable-FENV_ACCESS-in-expm1-expm1f-hypot-and-hy.patch \ + file://0005-math-disable-FP-contraction-in-jn.c.patch \ " PROVIDES += "virtual/libc virtual/libiconv virtual/libintl virtual/crypt"
PATCH 3/3 libc-test: Re-enable yn test
In reply to Khem Rajits now fixed in musl
--- .../0001-math-Delete-failing-tests.patch | 51 ------------------- 1 file changed, 51 deletions(-)
meta/recipes-core/musl/libc-test/0001-math-Delete-failing-tests.patch +0 -51
@@ -15,13 +15,11 @@ Signed-off-by: Khem Raj <[email protected]> src/math/fmaf.c | 47 -------------------------------------------- src/math/fmal.c | 52 ------------------------------------------------- src/math/powf.c | 47 -------------------------------------------- - src/math/yn.c | 43 ---------------------------------------- 5 files changed, 236 deletions(-) delete mode 100644 src/math/fma.c delete mode 100644 src/math/fmaf.c delete mode 100644 src/math/fmal.c delete mode 100644 src/math/powf.c - delete mode 100644 src/math/yn.c diff --git a/src/math/fma.c b/src/math/fma.c deleted file mode 100644
@@ -240,52 +238,3 @@ index 4778c2f..0000000 - } - return !!err; -} -diff --git a/src/math/yn.c b/src/math/yn.c -deleted file mode 100644 -index 244dbb8..0000000 ---- a/src/math/yn.c -+++ /dev/null -@@ -1,43 +0,0 @@ --#define _XOPEN_SOURCE 700 --#include <stdint.h> --#include <stdio.h> --#include "mtest.h" -- --static struct di_d t[] = { --#include "sanity/yn.h" --#include "special/yn.h" --}; -- --int main(void) --{ -- #pragma STDC FENV_ACCESS ON -- double y; -- float d; -- int e, i, err = 0; -- struct di_d *p; -- -- for (i = 0; i < sizeof t/sizeof *t; i++) { -- p = t + i; -- -- if (p->r < 0) -- continue; -- fesetround(p->r); -- feclearexcept(FE_ALL_EXCEPT); -- y = yn(p->i, p->x); -- e = fetestexcept(INEXACT|INVALID|DIVBYZERO|UNDERFLOW|OVERFLOW); -- -- if (!checkexcept(e, p->e, p->r)) { -- printf("%s:%d: bad fp exception: %s yn(%lld, %a)=%a, want %s", -- p->file, p->line, rstr(p->r), p->i, p->x, p->y, estr(p->e)); -- printf(" got %s\n", estr(e)); -- err++; -- } -- d = ulperr(y, p->y, p->dy); -- if ((!(p->x < 0) && !checkulp(d, p->r)) || (p->x < 0 && !isnan(y) && y != -inf)) { -- printf("%s:%d: %s yn(%lld, %a) want %a got %a, ulperr %.3f = %a + %a\n", -- p->file, p->line, rstr(p->r), p->i, p->x, p->y, y, d, d-p->dy, p->dy); -- err++; -- } -- } -- return !!err; --}