@@ -366,6 +366,8 @@ (define_subst_attr "mask_scalar_operand4
(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>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)
@@ -473,6 +475,7 @@ (define_subst_attr "round_saeonly_scalar
(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[<mask_scalar_expand_op3>]")
(define_subst "round_saeonly_scalar"
[(set (match_operand:SUBST_V 0)
@@ -3333,7 +3333,27 @@ (define_insn "*ieee_<ieee_maxmin><mode>3
(const_string "*")))
(set_attr "mode" "<ssescalarmode>")])
-(define_insn "<sse>_vm<code><mode>3<mask_scalar_name><round_saeonly_scalar_name>"
+(define_expand "<sse>_vm<code><mode>3<mask_scalar_name><round_saeonly_scalar_name>"
+ [(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_<sse>_ieee_vm<maxmin_float><mode>3<mask_scalar_name><round_saeonly_scalar_name>
+ (operands[0], operands[1], operands[2]
+ <mask_scalar_operand_arg34>
+ <round_saeonly_scalar_mask_arg3>));
+ DONE;
+ }
+})
+
+(define_insn "*<sse>_vm<code><mode>3<mask_scalar_name><round_saeonly_scalar_name>"
[(set (match_operand:VFH_128 0 "register_operand" "=x,v")
(vec_merge:VFH_128
(smaxmin:VFH_128
@@ -3348,6 +3368,25 @@ (define_insn "<sse>_vm<code><mode>3<mask
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sse")
(set_attr "btver2_sse_attr" "maxmin")
+ (set_attr "prefix" "<round_saeonly_scalar_prefix>")
+ (set_attr "mode" "<ssescalarmode>")])
+
+(define_insn "<sse>_ieee_vm<ieee_maxmin><mode>3<mask_scalar_name><round_saeonly_scalar_name>"
+ [(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,<round_saeonly_scalar_constraint>")]
+ IEEE_MAXMIN)
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE"
+ "@
+ <ieee_maxmin><ssescalarmodesuffix>\t{%2, %0|%0, %<iptr>2}
+ v<ieee_maxmin><ssescalarmodesuffix>\t{<round_saeonly_scalar_mask_op3>%2, %1, %0<mask_scalar_operand3>|%0<mask_scalar_operand3>, %1, %<iptr>2<round_saeonly_scalar_mask_op3>}"
+ [(set_attr "isa" "noavx,avx")
+ (set_attr "type" "sse")
+ (set_attr "btver2_sse_attr" "maxmin")
(set_attr "prefix" "<round_saeonly_scalar_prefix>")
(set_attr "mode" "<ssescalarmode>")])
@@ -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 ();
+}