diff options
-rw-r--r-- | gcc/range-op-float.cc | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr110755.c | 29 |
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 +} |