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.