From: Jakub Jelinek Date: Fri, 20 Sep 2024 07:14:29 +0000 (+0200) Subject: i386: Fix up _mm_min_ss etc. handling of zeros and NaNs [PR116738] X-Git-Tag: releases/gcc-12.5.0~114 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f44314ec26af041cf9e5c794ba341435cc1b7c62;p=thirdparty%2Fgcc.git i386: Fix up _mm_min_ss etc. handling of zeros and NaNs [PR116738] min/max patterns for intrinsics which on x86 result in the second input operand if the two operands are both zeros or one or both of them are a NaN shouldn't use SMIN/SMAX RTL, because that is similarly to MIN_EXPR/MAX_EXPR undefined what will be the result in those cases. The following patch adds an expander which uses either a new pattern with UNSPEC_IEEE_M{AX,IN} or use the S{MIN,MAX} representation of the same. 2024-09-20 Uros Bizjak Jakub Jelinek PR target/116738 * config/i386/subst.md (mask_scalar_operand_arg34, mask_scalar_expand_op3, round_saeonly_scalar_mask_arg3): New subst attributes. * config/i386/sse.md (_vm3): Change from define_insn to define_expand, rename the old define_insn to ... (*_vm3): ... this. (_ieee_vm3): New define_insn. * gcc.target/i386/sse-pr116738.c: New test. (cherry picked from commit 624d3af025e820ede7ec4334f7a2d5d4731c99a9) --- diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 09b308e03c7..d65ad5f1736 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -2866,7 +2866,27 @@ (const_string "*"))) (set_attr "mode" "")]) -(define_insn "_vm3" +(define_expand "_vm3" + [(set (match_operand:VFH_128 0 "register_operand") + (vec_merge:VFH_128 + (smaxmin:VFH_128 + (match_operand:VFH_128 1 "register_operand") + (match_operand:VFH_128 2 "nonimmediate_operand")) + (match_dup 1) + (const_int 1)))] + "TARGET_SSE" +{ + if (!flag_finite_math_only || flag_signed_zeros) + { + emit_insn (gen__ieee_vm3 + (operands[0], operands[1], operands[2] + + )); + DONE; + } +}) + +(define_insn "*_vm3" [(set (match_operand:VFH_128 0 "register_operand" "=x,v") (vec_merge:VFH_128 (smaxmin:VFH_128 @@ -2884,6 +2904,25 @@ (set_attr "prefix" "") (set_attr "mode" "")]) +(define_insn "_ieee_vm3" + [(set (match_operand:VFH_128 0 "register_operand" "=x,v") + (vec_merge:VFH_128 + (unspec:VFH_128 + [(match_operand:VFH_128 1 "register_operand" "0,v") + (match_operand:VFH_128 2 "nonimmediate_operand" "xm,")] + IEEE_MAXMIN) + (match_dup 1) + (const_int 1)))] + "TARGET_SSE" + "@ + \t{%2, %0|%0, %2} + v\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "noavx,avx") + (set_attr "type" "sse") + (set_attr "btver2_sse_attr" "maxmin") + (set_attr "prefix" "") + (set_attr "mode" "")]) + (define_mode_attr addsub_cst [(V4DF "5") (V2DF "1") (V4SF "5") (V8SF "85")]) diff --git a/gcc/config/i386/subst.md b/gcc/config/i386/subst.md index bb86f82905f..6302097c53c 100644 --- a/gcc/config/i386/subst.md +++ b/gcc/config/i386/subst.md @@ -344,6 +344,8 @@ (define_subst_attr "mask_scalarcz_operand4" "mask_scalarcz" "" "%{%5%}%N4") (define_subst_attr "mask_scalar4_dest_false_dep_for_glc_cond" "mask_scalar" "1" "operands[4] == CONST0_RTX(mode)") (define_subst_attr "mask_scalarc_dest_false_dep_for_glc_cond" "mask_scalarc" "1" "operands[3] == CONST0_RTX(V8HFmode)") +(define_subst_attr "mask_scalar_operand_arg34" "mask_scalar" "" ", operands[3], operands[4]") +(define_subst_attr "mask_scalar_expand_op3" "mask_scalar" "3" "5") (define_subst "mask_scalar" [(set (match_operand:SUBST_V 0) @@ -451,6 +453,7 @@ (define_subst_attr "round_saeonly_scalar_constraint" "round_saeonly_scalar" "vm" "v") (define_subst_attr "round_saeonly_scalar_prefix" "round_saeonly_scalar" "vex" "evex") (define_subst_attr "round_saeonly_scalar_nimm_predicate" "round_saeonly_scalar" "nonimmediate_operand" "register_operand") +(define_subst_attr "round_saeonly_scalar_mask_arg3" "round_saeonly_scalar" "" ", operands[]") (define_subst "round_saeonly_scalar" [(set (match_operand:SUBST_V 0) diff --git a/gcc/testsuite/gcc.target/i386/sse-pr116738.c b/gcc/testsuite/gcc.target/i386/sse-pr116738.c new file mode 100644 index 00000000000..5b31bf24748 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/sse-pr116738.c @@ -0,0 +1,28 @@ +/* PR target/116738 */ +/* { dg-do run } */ +/* { dg-options "-O2 -msse" } */ +/* { dg-require-effective-target sse } */ + +#include "sse-check.h" + +static inline float +clamp (float f) +{ + __m128 v = _mm_set_ss (f); + __m128 zero = _mm_setzero_ps (); + __m128 greatest = _mm_set_ss (__FLT_MAX__); + v = _mm_min_ss (v, greatest); + v = _mm_max_ss (v, zero); + return _mm_cvtss_f32 (v); +} + +static void +sse_test (void) +{ + float f = clamp (-0.0f); + if (f != 0.0f || __builtin_signbitf (f)) + abort (); + f = clamp (__builtin_nanf ("")); + if (__builtin_isnanf (f) || f != __FLT_MAX__) + abort (); +}