aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/range-op-float.cc18
-rw-r--r--gcc/testsuite/gcc.dg/pr110755.c29
2 files changed, 47 insertions, 0 deletions
diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 238a326..a8d39cf 100644
--- a/gcc/range-op-float.cc
+++ b/gcc/range-op-float.cc
@@ -324,6 +324,24 @@ frange_arithmetic (enum tree_code code, tree type,
bool inexact = real_arithmetic (&value, code, &op1, &op2);
real_convert (&result, mode, &value);
+ /* When rounding towards negative infinity, x + (-x) and
+ x - x is -0 rather than +0 real_arithmetic computes.
+ So, when we are looking for lower bound (inf is negative),
+ use -0 rather than +0. */
+ if (flag_rounding_math
+ && (code == PLUS_EXPR || code == MINUS_EXPR)
+ && !inexact
+ && real_iszero (&result)
+ && !real_isneg (&result)
+ && real_isneg (&inf))
+ {
+ REAL_VALUE_TYPE op2a = op2;
+ if (code == PLUS_EXPR)
+ op2a.sign ^= 1;
+ if (real_isneg (&op1) == real_isneg (&op2a) && real_equal (&op1, &op2a))
+ result.sign = 1;
+ }
+
// Be extra careful if there may be discrepancies between the
// compile and runtime results.
bool round = false;
diff --git a/gcc/testsuite/gcc.dg/pr110755.c b/gcc/testsuite/gcc.dg/pr110755.c
new file mode 100644
index 0000000..c3bfaa6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr110755.c
@@ -0,0 +1,29 @@
+/* PR tree-optimization/110755 */
+/* { dg-do run } */
+/* { dg-require-effective-target fenv } */
+/* { dg-require-effective-target hard_float } */
+/* { dg-options "-O2 -frounding-math" } */
+
+#include <fenv.h>
+
+__attribute__((noipa)) float
+foo (float x)
+{
+ if (x > 0.0)
+ {
+ x += 0x1p+23;
+ x -= 0x1p+23;
+ x = __builtin_fabsf (x);
+ }
+ return x;
+}
+
+int
+main ()
+{
+#ifdef FE_DOWNWARD
+ fesetround (FE_DOWNWARD);
+ if (__builtin_signbit (foo (0.5)))
+ __builtin_abort ();
+#endif
+}