Skip to content

Build with SSE2 & fpmath=sse on x86 - #25362

Open
marc-mabe wants to merge 1 commit into
php:masterfrom
marc-mabe:fpmath_sse
Open

marc-mabe wants to merge 1 commit into
php:masterfrom
marc-mabe:fpmath_sse

Conversation

@marc-mabe

Copy link
Copy Markdown
Contributor

SSE2 is part of the x86-64 baseline, but optional on 32-bit x86, where GCC targets i686 by default. Such builds miss the SSE2 code paths and compute doubles on the x87 unit.

x87 registers have a 15-bit exponent that zend_init_fpu() cannot clamp, so subnormal results are rounded twice and can be one ULP off:

$a = 5.678650331314532e-158;
$b = 2.3715405351663569e-153;
var_dump($a * $b);
// x87:                1.34671494457485E-310
// SSE2 and 64-bit:    1.3467149445748E-310  (correctly rounded)

The new PHP_CHECK_SSE2 macro in build/php.m4, called from the platform-specific compile settings in configure.ac, prepends to CFLAGS and CXXFLAGS on x86 targets:

  • -msse2 if supported and not enabled by default;
  • -mfpmath=sse if SSE2 is enabled and doubles do not use it by default. Clang does this by itself; GCC needs the flag.

Configure warns but builds without SSE2 if the build machine cannot run SSE2 code. When cross compiling, -msse2 is added without that check.

The resulting build requires SSE2. Pass CFLAGS=-mno-sse2 to build without SSE2.

phpize builds do not call the macro, but an extension can call PHP_CHECK_SSE2 from its config.m4.

SSE2 is part of the x86-64 baseline, but optional on 32-bit x86, where
GCC targets i686 by default. Such builds miss the __SSE2__ code paths and
compute doubles on the x87 unit.

x87 registers have a 15-bit exponent that zend_init_fpu() cannot clamp,
so subnormal results are rounded twice and can be one ULP off:

    $a = 5.678650331314532e-158;
    $b = 2.3715405351663569e-153;
    var_dump($a * $b);
    // x87:                1.34671494457485E-310
    // SSE2 and 64-bit:    1.3467149445748E-310  (correctly rounded)

The new PHP_CHECK_SSE2 macro in build/php.m4, called from the
platform-specific compile settings in configure.ac, prepends to CFLAGS
and CXXFLAGS on x86 targets:

 - -msse2 if supported and not enabled by default;
 - -mfpmath=sse if SSE2 is enabled and doubles do not use it by default.
   Clang does this by itself; GCC needs the flag.

Configure warns but builds without SSE2 if the build machine cannot run
SSE2 code. When cross compiling, -msse2 is added without that check.

The resulting build requires SSE2. Pass CFLAGS=-mno-sse2 to build without
SSE2.

phpize builds do not call the macro, but an extension can call
PHP_CHECK_SSE2 from its config.m4.

@Sjord Sjord left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mailing list post: https://news-web.php.net/php.internals/133038

Perhaps this also needs a NEWS entry.

@@ -0,0 +1,25 @@
--TEST--
Float multiplication and division with subnormal results are correctly rounded
--DESCRIPTION--

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this test needs a skip guard if someone builds with CFLAGS=-mno-sse2?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test is designed like others ( e.g. gh14140.phpt does for -ffp-contract=off). If you build with -mno-sse2, failing this test is the expected result, and there’s no way to detect it from a phpt without adding test-only API.

@TimWolla
TimWolla requested a review from petk November 11, 2026 11:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants