Skip to contentSkip to conversation

musl: Use FENV_ACCESS pragma instead of maytrap exception behavior

PATCH New Khem Raj 1 participant 3 messages Nov 11

lore
Share & tools
lore

Khem Raj

author
#0 lore raw

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
deleted file mode 100644
index dfff81299b..0000000000
@@ -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
index b53b4be84c..0be24b22f1 100644
@@ -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"
author
#1 lore raw

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
new file mode 100644
index 0000000000..f87f9752e2
@@ -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
index 0be24b22f1..ff8a08337c 100644
@@ -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"
author
#2 lore raw

PATCH 3/3 libc-test: Re-enable yn test

In reply to Khem Raj

its 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
index 96ff279fa6..814d7bcb64 100644
@@ -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;
--}