https://gcc.gnu.org/g:fb0ef8d42a46561e8ec8cb2fa49eebfb56c60a27
commit r17-5243-gfb0ef8d42a46561e8ec8cb2fa49eebfb56c60a27 Author: Sun, Qin <[email protected]> Date: Thu Oct 15 13:54:39 2026 +0800 i386: Fold MINP*/MAXP* builtins only if flag_trapping_math is unset ix86_gimple_fold_builtin folds all-ones-mask MINP*/MAXP* builtins to `a < b ? a : b` when optimizing, which drops {SAE}. Since x86 sets DE for denormal operands, {SAE} should be preserved, so we should enable the folding only if flag_trapping_math is unset. PR target/127648 gcc/ChangeLog: * config/i386/i386.cc (ix86_gimple_fold_builtin): Disable the folding on flag_trapping_math. gcc/testsuite/ChangeLog: * gcc.target/i386/pr127648.c: New test. Diff: --- gcc/config/i386/i386.cc | 2 +- gcc/testsuite/gcc.target/i386/pr127648.c | 71 ++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 136c339c8cab..c3548e5d65ae 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -20444,7 +20444,7 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi) else if (tree_to_uhwi (arg4) != 8) /* Invalid round argument. */ break; - else if (HONOR_NANS (arg0)) + else if (HONOR_NANS (arg0) || flag_trapping_math) /* Lowering to comparison would raise exceptions which shouldn't be raised. */ break; diff --git a/gcc/testsuite/gcc.target/i386/pr127648.c b/gcc/testsuite/gcc.target/i386/pr127648.c new file mode 100644 index 000000000000..d0f2915b33fd --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr127648.c @@ -0,0 +1,71 @@ +/* PR target/127648 */ +/* { dg-do run } */ +/* { dg-options "-O3 -mavx512f -ffinite-math-only -save-temps" } */ +/* { dg-require-effective-target avx512f } */ +/* { dg-final { scan-assembler-times "vminps\[ \\t\]+\{sae\}\[^\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+\[^\n\]*%zmm\[0-9\]+" 1 } } */ + +#include "avx512f-check.h" + +static unsigned +rd_mxcsr (void) +{ + unsigned m; + __asm__ __volatile__ ("stmxcsr %0" : "=m" (m) : : "memory"); + return m; +} + +static void +wr_mxcsr (unsigned m) +{ + __asm__ __volatile__ ("ldmxcsr %0" : : "m" (m) : "memory"); +} + +/* -> __builtin_ia32_minps512_mask (a, b, s, -1, 8): all-ones write mask, + round argument 8 == _MM_FROUND_NO_EXC, which suppresses all exception + flags. -ffinite-math-only must not drop the {sae}. */ +__attribute__((noinline)) +static __m512 +f (__m512 a, __m512 b, __m512 s) +{ + return _mm512_mask_min_round_ps (s, (__mmask16) -1, a, b, _MM_FROUND_NO_EXC); +} + +/* volatile so nothing can constant-propagate the operands into f. */ +static volatile unsigned denorm_bits = 0x00000001u; /* 0x1p-149f: DENORMAL, FINITE */ +static volatile float one = 1.0f; +static volatile float zero = 0.0f; + +static void +avx512f_test (void) +{ + union { unsigned u; float f; } cv; + float av[16], bv[16], sv[16]; + __m512 a, b, s, r; + unsigned m; + int i; + + cv.u = denorm_bits; + for (i = 0; i < 16; i++) + { + av[i] = cv.f; + bv[i] = one; + sv[i] = zero; + } + a = _mm512_loadu_ps (av); + b = _mm512_loadu_ps (bv); + s = _mm512_loadu_ps (sv); + + wr_mxcsr (0x1f80u); /* All exceptions masked, all flags clear, FTZ=DAZ=0. */ + r = f (a, b, s); + m = rd_mxcsr (); + + /* {sae} must leave the denormal flag (DE, bit 1) clear. */ + if ((m >> 1) & 1u) + abort (); + + /* And the value must still be min (0x1p-149f, 1.0f) == 0x1p-149f. */ + _mm512_storeu_ps (sv, r); + cv.f = sv[0]; + if (cv.u != 0x00000001u) + abort (); +}
