===================================================================
@@ -14394,11 +14394,11 @@
if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
&& !flag_trapping_math)
{
- if (!TARGET_ROUND && optimize_insn_for_size_p ())
- FAIL;
if (TARGET_ROUND)
emit_insn (gen_sse4_1_round<mode>2
(operands[0], operands[1], GEN_INT (ROUND_MXCSR)));
+ else if (optimize_insn_for_size_p ())
+ FAIL;
else
ix86_expand_rint (operand0, operand1);
}
@@ -14431,7 +14431,12 @@
if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
&& !flag_trapping_math && !flag_rounding_math)
{
- if (TARGET_64BIT || (<MODE>mode != DFmode))
+ if (TARGET_ROUND)
+ {
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+ ix86_expand_round_sse4 (operands[0], operands[1]);
+ }
+ else if (TARGET_64BIT || (<MODE>mode != DFmode))
ix86_expand_round (operands[0], operands[1]);
else
ix86_expand_rounddf_32 (operands[0], operands[1]);
@@ -14663,14 +14668,13 @@
&& !flag_trapping_math)"
{
if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
- && !flag_trapping_math
- && (TARGET_ROUND || optimize_insn_for_speed_p ()))
+ && !flag_trapping_math)
{
- if (!TARGET_ROUND && optimize_insn_for_size_p ())
- FAIL;
if (TARGET_ROUND)
emit_insn (gen_sse4_1_round<mode>2
(operands[0], operands[1], GEN_INT (ROUND_FLOOR)));
+ else if (optimize_insn_for_size_p ())
+ FAIL;
else if (TARGET_64BIT || (<MODE>mode != DFmode))
ix86_expand_floorceil (operand0, operand1, true);
else
@@ -14922,8 +14926,7 @@
&& !flag_trapping_math)"
{
if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
- && !flag_trapping_math
- && (TARGET_ROUND || optimize_insn_for_speed_p ()))
+ && !flag_trapping_math)
{
if (TARGET_ROUND)
emit_insn (gen_sse4_1_round<mode>2
@@ -15179,8 +15182,7 @@
&& !flag_trapping_math)"
{
if (SSE_FLOAT_MODE_P (<MODE>mode) && TARGET_SSE_MATH
- && !flag_trapping_math
- && (TARGET_ROUND || optimize_insn_for_speed_p ()))
+ && !flag_trapping_math)
{
if (TARGET_ROUND)
emit_insn (gen_sse4_1_round<mode>2
===================================================================
@@ -174,6 +174,7 @@ extern void ix86_expand_lfloorceil (rtx, rtx, bool
extern void ix86_expand_rint (rtx, rtx);
extern void ix86_expand_floorceil (rtx, rtx, bool);
extern void ix86_expand_floorceildf_32 (rtx, rtx, bool);
+extern void ix86_expand_round_sse4 (rtx, rtx);
extern void ix86_expand_round (rtx, rtx);
extern void ix86_expand_rounddf_32 (rtx, rtx);
extern void ix86_expand_trunc (rtx, rtx);
===================================================================
@@ -32676,6 +32676,52 @@ ix86_expand_round (rtx operand0, rtx operand1)
emit_move_insn (operand0, res);
}
+
+/* Expand SSE sequence for computing round
+ from OP1 storing into OP0 using sse4 round insn. */
+void
+ix86_expand_round_sse4 (rtx op0, rtx op1)
+{
+ enum machine_mode mode = GET_MODE (op0);
+ rtx e1, e2, e3, res, half, mask;
+ const struct real_format *fmt;
+ REAL_VALUE_TYPE pred_half, half_minus_pred_half;
+ rtx (*gen_round) (rtx, rtx, rtx);
+
+ switch (mode)
+ {
+ case SFmode:
+ gen_round = gen_sse4_1_roundsf2;
+ break;
+ case DFmode:
+ gen_round = gen_sse4_1_rounddf2;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ /* e1 = fabs(op1) */
+ e1 = ix86_expand_sse_fabs (op1, &mask);
+
+ /* load nextafter (0.5, 0.0) */
+ fmt = REAL_MODE_FORMAT (mode);
+ real_2expN (&half_minus_pred_half, -(fmt->p) - 1, mode);
+ REAL_ARITHMETIC (pred_half, MINUS_EXPR, dconsthalf, half_minus_pred_half);
+
+ /* e2 = e1 + 0.5 */
+ half = force_reg (mode, const_double_from_real_value (pred_half, mode));
+ e2 = expand_simple_binop (mode, PLUS, e1, half, NULL_RTX, 0, OPTAB_DIRECT);
+
+ /* e3 = trunc(e2) */
+ e3 = gen_reg_rtx (mode);
+ emit_insn (gen_round (e3, e2, GEN_INT (ROUND_TRUNC)));
+
+ /* res = copysign (e3, op1) */
+ res = gen_reg_rtx (mode);
+ ix86_sse_copysign_to_positive (res, e3, op1, mask);
+
+ emit_move_insn (op0, res);
+}
/* Table of valid machine attributes. */