if (!isless (xa, TWO52))
return x;
x2 = (double)(long)x;
+
Compensate. Floor:
if (x2 > x)
x2 -= 1;
Compensate. Ceil:
if (x2 < x)
x2 += 1;
+
if (HONOR_SIGNED_ZEROS (mode))
return copysign (x2, x);
return x2;
emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
- emit_move_insn (res, tmp);
-
if (HONOR_SIGNED_ZEROS (mode))
- ix86_sse_copysign_to_positive (res, res, force_reg (mode, operand1), mask);
+ {
+ /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
+ if (do_floor && flag_rounding_math)
+ tmp = ix86_expand_sse_fabs (tmp, NULL);
+
+ ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
+ }
+ emit_move_insn (res, tmp);
emit_label (label);
LABEL_NUSES (label) = 1;
return x;
xa = xa + TWO52 - TWO52;
x2 = copysign (xa, x);
+
Compensate. Floor:
if (x2 > x)
x2 -= 1;
Compensate. Ceil:
if (x2 < x)
x2 += 1;
+
if (HONOR_SIGNED_ZEROS (mode))
x2 = copysign (x2, x);
return x2;
emit_insn (gen_rtx_SET (tmp, gen_rtx_AND (mode, one, tmp)));
tmp = expand_simple_binop (mode, do_floor ? MINUS : PLUS,
xa, tmp, NULL_RTX, 0, OPTAB_DIRECT);
- if (!do_floor && HONOR_SIGNED_ZEROS (mode))
- ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
+ if (HONOR_SIGNED_ZEROS (mode))
+ {
+ /* Remove the sign with FE_DOWNWARD, where x - x = -0.0. */
+ if (do_floor && flag_rounding_math)
+ tmp = ix86_expand_sse_fabs (tmp, NULL);
+
+ ix86_sse_copysign_to_positive (tmp, tmp, res, mask);
+ }
emit_move_insn (res, tmp);
emit_label (label);
--- /dev/null
+/* PR target/96793 */
+/* { dg-do run { target sse2_runtime } } */
+/* { dg-require-effective-target fenv } */
+/* { dg-options "-O2 -frounding-math -msse2 -mno-sse4 -mfpmath=sse" } */
+
+#include <fenv.h>
+
+double
+__attribute__((noinline))
+test (double value)
+{
+ return __builtin_floor (value);
+}
+
+int
+main ()
+{
+ double result;
+
+ fesetround (FE_DOWNWARD);
+
+ result = test (0.25);
+
+ if (__builtin_signbit (result) != 0)
+ __builtin_abort ();
+
+ return 0;
+}