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 ();
+}

Reply via email to