+2016-08-15 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/72867
+ * config/i386/sse.md (<code><mode>3<mask_name><round_saeonly_name>):
+ Emit ieee_<ieee_maxmin><mode>3<mask_name><round_saeonly_name>
+ for !flag_finite_math_only or flag_signed_zeros.
+ (*<code><mode>3<mask_name><round_saeonly_name>): Rename from
+ *<code><mode>3_finite<mask_name><round_saeonly_name>. Do not
+ depend on flag_finite_math_only.
+ (ieee_<ieee_maxmin><mode>3<mask_name><round_saeonly_name>):
+ New insn pattern.
+ (*<code><mode>3<mask_name><round_saeonly_name>): Remove.
+ (*ieee_smin<mode>3): Ditto.
+ (*ieee_smax<mode>3): Ditto.
+ * config/i386/mmx.md (mmx_<code>v2sf3): Emit
+ mmx_ieee_<ieee_maxmin>v2sf3 for !flag_finite_math_only or
+ flag_signed_zeros.
+ (*mmx_<code>v2sf3): Rename from *mmx_<code>v2sf3_finite. Do not
+ depend on flag_finite_math_only.
+ (mmx_ieee_<ieee_maxmin>v2sf3): New insn pattern.
+ (*mmx_<code>v2sf3): Remove.
+ * config/i386/subst.md (round_saeonly_mask_arg3): New subst attribute.
+ * config/i386/i386.c (ix86_expand_sse_fp_mimnax): Check
+ flag_signed_zeros instead of !flag_unsafe_math_optimizations.
+
2016-08-15 Segher Boessenkool <segher@kernel.crashing.org>
PR rtl-optimization/73650
/* We want to check HONOR_NANS and HONOR_SIGNED_ZEROS here,
but MODE may be a vector mode and thus not appropriate. */
- if (!flag_finite_math_only || !flag_unsafe_math_optimizations)
+ if (!flag_finite_math_only || flag_signed_zeros)
{
int u = is_min ? UNSPEC_IEEE_MIN : UNSPEC_IEEE_MAX;
rtvec v;
(umax "maxu") (umin "minu")])
(define_code_attr maxmin_float [(smax "max") (smin "min")])
+(define_int_iterator IEEE_MAXMIN
+ [UNSPEC_IEEE_MAX
+ UNSPEC_IEEE_MIN])
+
+(define_int_attr ieee_maxmin
+ [(UNSPEC_IEEE_MAX "max")
+ (UNSPEC_IEEE_MIN "min")])
+
;; Mapping of logic operators
(define_code_iterator any_logic [and ior xor])
(define_code_iterator any_or [ior xor])
;; Their operands are not commutative, and thus they may be used in the
;; presence of -0.0 and NaN.
-(define_int_iterator IEEE_MAXMIN
- [UNSPEC_IEEE_MAX
- UNSPEC_IEEE_MIN])
-
-(define_int_attr ieee_maxmin
- [(UNSPEC_IEEE_MAX "max")
- (UNSPEC_IEEE_MIN "min")])
-
(define_insn "*ieee_s<ieee_maxmin><mode>3"
[(set (match_operand:MODEF 0 "register_operand" "=x,v")
(unspec:MODEF
(set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
-;; ??? For !flag_finite_math_only, the representation with SMIN/SMAX
-;; isn't really correct, as those rtl operators aren't defined when
-;; applied to NaNs. Hopefully the optimizers won't get too smart on us.
-
(define_expand "mmx_<code>v2sf3"
[(set (match_operand:V2SF 0 "register_operand")
(smaxmin:V2SF
(match_operand:V2SF 2 "nonimmediate_operand")))]
"TARGET_3DNOW"
{
- if (!flag_finite_math_only)
- operands[1] = force_reg (V2SFmode, operands[1]);
- ix86_fixup_binary_operands_no_copy (<CODE>, V2SFmode, operands);
+ if (!flag_finite_math_only || flag_signed_zeros)
+ {
+ operands[1] = force_reg (V2SFmode, operands[1]);
+ emit_insn (gen_mmx_ieee_<maxmin_float>v2sf3
+ (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ else
+ ix86_fixup_binary_operands_no_copy (<CODE>, V2SFmode, operands);
})
-(define_insn "*mmx_<code>v2sf3_finite"
+;; These versions of the min/max patterns are intentionally ignorant of
+;; their behavior wrt -0.0 and NaN (via the commutative operand mark).
+;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator
+;; are undefined in this condition, we're certain this is correct.
+
+(define_insn "*mmx_<code>v2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=y")
(smaxmin:V2SF
(match_operand:V2SF 1 "nonimmediate_operand" "%0")
(match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
- "TARGET_3DNOW && flag_finite_math_only
- && ix86_binary_operator_ok (<CODE>, V2SFmode, operands)"
+ "TARGET_3DNOW && ix86_binary_operator_ok (<CODE>, V2SFmode, operands)"
"pf<maxmin_float>\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxadd")
(set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
-(define_insn "*mmx_<code>v2sf3"
+;; These versions of the min/max patterns implement exactly the operations
+;; min = (op1 < op2 ? op1 : op2)
+;; max = (!(op1 < op2) ? op1 : op2)
+;; Their operands are not commutative, and thus they may be used in the
+;; presence of -0.0 and NaN.
+
+(define_insn "mmx_ieee_<ieee_maxmin>v2sf3"
[(set (match_operand:V2SF 0 "register_operand" "=y")
- (smaxmin:V2SF
- (match_operand:V2SF 1 "register_operand" "0")
- (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
+ (unspec:V2SF
+ [(match_operand:V2SF 1 "register_operand" "0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
+ IEEE_MAXMIN))]
"TARGET_3DNOW"
- "pf<maxmin_float>\t{%2, %0|%0, %2}"
+ "pf<ieee_maxmin>\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxadd")
(set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(set_attr "prefix" "orig,vex")
(set_attr "mode" "SF")])
-;; ??? For !flag_finite_math_only, the representation with SMIN/SMAX
-;; isn't really correct, as those rtl operators aren't defined when
-;; applied to NaNs. Hopefully the optimizers won't get too smart on us.
-
(define_expand "<code><mode>3<mask_name><round_saeonly_name>"
[(set (match_operand:VF 0 "register_operand")
(smaxmin:VF
(match_operand:VF 2 "<round_saeonly_nimm_predicate>")))]
"TARGET_SSE && <mask_mode512bit_condition> && <round_saeonly_mode512bit_condition>"
{
- if (!flag_finite_math_only)
- operands[1] = force_reg (<MODE>mode, operands[1]);
- ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);
+ if (!flag_finite_math_only || flag_signed_zeros)
+ {
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+ emit_insn (gen_ieee_<maxmin_float><mode>3<mask_name><round_saeonly_name>
+ (operands[0], operands[1], operands[2]
+ <mask_operand_arg34>
+ <round_saeonly_mask_arg3>));
+ DONE;
+ }
+ else
+ ix86_fixup_binary_operands_no_copy (<CODE>, <MODE>mode, operands);
})
-(define_insn "*<code><mode>3_finite<mask_name><round_saeonly_name>"
+;; These versions of the min/max patterns are intentionally ignorant of
+;; their behavior wrt -0.0 and NaN (via the commutative operand mark).
+;; Since both the tree-level MAX_EXPR and the rtl-level SMAX operator
+;; are undefined in this condition, we're certain this is correct.
+
+(define_insn "*<code><mode>3<mask_name><round_saeonly_name>"
[(set (match_operand:VF 0 "register_operand" "=x,v")
(smaxmin:VF
(match_operand:VF 1 "<round_saeonly_nimm_predicate>" "%0,v")
(match_operand:VF 2 "<round_saeonly_nimm_predicate>" "xBm,<round_saeonly_constraint>")))]
- "TARGET_SSE && flag_finite_math_only
- && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)
+ "TARGET_SSE && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)
&& <mask_mode512bit_condition> && <round_saeonly_mode512bit_condition>"
"@
<maxmin_float><ssemodesuffix>\t{%2, %0|%0, %2}
(set_attr "prefix" "<mask_prefix3>")
(set_attr "mode" "<MODE>")])
-(define_insn "*<code><mode>3<mask_name><round_saeonly_name>"
+;; These versions of the min/max patterns implement exactly the operations
+;; min = (op1 < op2 ? op1 : op2)
+;; max = (!(op1 < op2) ? op1 : op2)
+;; Their operands are not commutative, and thus they may be used in the
+;; presence of -0.0 and NaN.
+
+(define_insn "ieee_<ieee_maxmin><mode>3<mask_name><round_saeonly_name>"
[(set (match_operand:VF 0 "register_operand" "=x,v")
- (smaxmin:VF
- (match_operand:VF 1 "register_operand" "0,v")
- (match_operand:VF 2 "<round_saeonly_nimm_predicate>" "xBm,<round_saeonly_constraint>")))]
- "TARGET_SSE && !flag_finite_math_only
+ (unspec:VF
+ [(match_operand:VF 1 "register_operand" "0,v")
+ (match_operand:VF 2 "<round_saeonly_nimm_predicate>" "xBm,<round_saeonly_constraint>")]
+ IEEE_MAXMIN))]
+ "TARGET_SSE
&& <mask_mode512bit_condition> && <round_saeonly_mode512bit_condition>"
"@
- <maxmin_float><ssemodesuffix>\t{%2, %0|%0, %2}
- v<maxmin_float><ssemodesuffix>\t{<round_saeonly_mask_op3>%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %2<round_saeonly_mask_op3>}"
+ <ieee_maxmin><ssemodesuffix>\t{%2, %0|%0, %2}
+ v<ieee_maxmin><ssemodesuffix>\t{<round_saeonly_mask_op3>%2, %1, %0<mask_operand3>|%0<mask_operand3>, %1, %2<round_saeonly_mask_op3>}"
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sseadd")
(set_attr "btver2_sse_attr" "maxmin")
(set_attr "prefix" "<round_saeonly_prefix>")
(set_attr "mode" "<ssescalarmode>")])
-;; These versions of the min/max patterns implement exactly the operations
-;; min = (op1 < op2 ? op1 : op2)
-;; max = (!(op1 < op2) ? op1 : op2)
-;; Their operands are not commutative, and thus they may be used in the
-;; presence of -0.0 and NaN.
-
-(define_insn "*ieee_smin<mode>3"
- [(set (match_operand:VF 0 "register_operand" "=x,v")
- (unspec:VF
- [(match_operand:VF 1 "register_operand" "0,v")
- (match_operand:VF 2 "vector_operand" "xBm,vm")]
- UNSPEC_IEEE_MIN))]
- "TARGET_SSE"
- "@
- min<ssemodesuffix>\t{%2, %0|%0, %2}
- vmin<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "isa" "noavx,avx")
- (set_attr "type" "sseadd")
- (set_attr "prefix" "orig,vex")
- (set_attr "mode" "<MODE>")])
-
-(define_insn "*ieee_smax<mode>3"
- [(set (match_operand:VF 0 "register_operand" "=x,v")
- (unspec:VF
- [(match_operand:VF 1 "register_operand" "0,v")
- (match_operand:VF 2 "vector_operand" "xBm,vm")]
- UNSPEC_IEEE_MAX))]
- "TARGET_SSE"
- "@
- max<ssemodesuffix>\t{%2, %0|%0, %2}
- vmax<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "isa" "noavx,avx")
- (set_attr "type" "sseadd")
- (set_attr "prefix" "orig,vex")
- (set_attr "mode" "<MODE>")])
-
(define_insn "avx_addsubv4df3"
[(set (match_operand:V4DF 0 "register_operand" "=x")
(vec_merge:V4DF
(define_subst_attr "round_saeonly_mask_op4" "round_saeonly" "" "<round_saeonly_mask_operand4>")
(define_subst_attr "round_saeonly_mask_scalar_merge_op4" "round_saeonly" "" "<round_saeonly_mask_scalar_merge_operand4>")
(define_subst_attr "round_saeonly_sd_mask_op5" "round_saeonly" "" "<round_saeonly_sd_mask_operand5>")
+(define_subst_attr "round_saeonly_mask_arg3" "round_saeonly" "" ", operands[<mask_expand_op3>]")
(define_subst_attr "round_saeonly_constraint" "round_saeonly" "vm" "v")
(define_subst_attr "round_saeonly_constraint2" "round_saeonly" "m" "v")
(define_subst_attr "round_saeonly_nimm_predicate" "round_saeonly" "vector_operand" "register_operand")
+2016-08-15 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/72867
+ * gcc.target/i386/pr72867.c: New test.
+
2016-08-16 Eric Botcazou <ebotcazou@adacore.com>
* c-c++-common/dump-ada-spec-5.c: New test.
--- /dev/null
+/* PR target/72867 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+/* { dg-require-effective-target sse } */
+
+#include "sse-check.h"
+#include <xmmintrin.h>
+
+static void
+sse_test (void)
+{
+ float nan = __builtin_nanf ("");
+
+ __m128 x = _mm_min_ps(_mm_set1_ps(nan), _mm_set1_ps(1.0f));
+
+ if (x[0] != 1.0f)
+ abort ();
+
+ x = _mm_min_ps(_mm_set1_ps(1.f), _mm_set1_ps(nan));
+
+ if (!__builtin_isnan (x[0]))
+ abort ();
+}