https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99497

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Simplified:
#include <x86intrin.h>

void
print128 (__m128 var)
{
  float val[4];
  __builtin_memcpy (val, &var, sizeof(val));
  __builtin_printf ("%f %f %f %f \n", val[0], val[1], val[2], val[3]);
}

int
main ()
{
  __m128 a = _mm_set_ss (__builtin_nanf (""));
  __m128 b = _mm_set_ss (2.0f);
  __m128 c = _mm_max_ss (a, b);
  __m128 d = _mm_max_ss (b, a);
  print128 (c);
  print128 (d);
  return 0;
}

The RTL SMAX etc. ops are defined as:
/* Minimum and maximum values of two operands.  We need both signed and
   unsigned forms.  (We cannot use MIN for SMIN because it conflicts
   with a macro of the same name.)   The signed variants should be used
   with floating point.  Further, if both operands are zeros, or if either
   operand is NaN, then it is unspecified which of the two operands is
   returned as the result.  */

DEF_RTL_EXPR(SMIN, "smin", "ee", RTX_COMM_ARITH)
DEF_RTL_EXPR(SMAX, "smax", "ee", RTX_COMM_ARITH)
DEF_RTL_EXPR(UMIN, "umin", "ee", RTX_COMM_ARITH)
DEF_RTL_EXPR(UMAX, "umax", "ee", RTX_COMM_ARITH)

So, if _mm*_{min,max}_ss has the same requirement on what exactly should be
returned when both operands are zero or if either operand is NaN, then we
probably need to use an UNSPEC unless -ffast-math tells us NaNs won't appear or
sign of zero doesn't matter.

Reply via email to