https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127648
Bug ID: 127648
Summary: wrong code at -O{1,2,3} with AVX-512 min/max under
`-ffinite-math-only`
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: kyuwoncho18 at gmail dot com
Target Milestone: ---
Created attachment 65714
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65714&action=edit
reproduction code
### Reproduction
#include <stdio.h>
#include <immintrin.h>
static inline unsigned rd_mxcsr (void)
{
unsigned m;
__asm__ __volatile__ ("stmxcsr %0" : "=m" (m) : : "memory");
return m;
}
static inline 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 (suppress all exceptions). */
__attribute__((noinline))
__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 no compiler can constant-propagate the operands into f */
static volatile unsigned denorm_bits = 0x00000001u; /* 0x1p-149f: DENORMAL,
and FINITE */
static volatile float one = 1.0f;
static volatile float zero = 0.0f;
int main (void)
{
union { unsigned u; float f; } cv, rv;
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 ();
_mm512_storeu_ps (sv, r);
rv.f = sv[0];
printf ("DE=%u IE=%u r0=0x%08x\n", (m >> 1) & 1u, m & 1u, rv.u);
return 0;
}
With the -mavx512f -ffinite-math-only flags, the PoC prints diverged with
optimization.
The DE (Denormal) flag is set only with -O{*} but not with -O0.
godbolt: https://gcc.godbolt.org/z/zbYjY5s7e