diff options
author | Jakub Jelinek <jakub@redhat.com> | 2022-12-06 10:23:55 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2022-12-06 10:23:55 +0100 |
commit | 0525a7fad2a5b1d933a9662c11aa074b38cfa3d5 (patch) | |
tree | f3c1a4d33a99178060ac3e5e793608f6df62f0dc /gcc | |
parent | 9f80367e539839fff1df2c85fc2640638199fc9e (diff) | |
download | gcc-0525a7fad2a5b1d933a9662c11aa074b38cfa3d5.zip gcc-0525a7fad2a5b1d933a9662c11aa074b38cfa3d5.tar.gz gcc-0525a7fad2a5b1d933a9662c11aa074b38cfa3d5.tar.bz2 |
range-op-float: Fix up ICE in lower_bound [PR107975]
According to https://gcc.gnu.org/pipermail/gcc-regression/2022-December/077258.html
my patch caused some ICEs, e.g. the following testcase ICEs.
The problem is that lower_bound and upper_bound methods on a france assert
that the range isn't VR_NAN or VR_UNDEFINED.
All the op1_range/op2_range methods already return early if lhs.undefined_p,
but the other cases (when lhs is VR_NAN or the other opN is VR_NAN or
VR_UNDEFINED) aren't. float_binary_op_range_finish will DTRT for those
cases already.
2022-12-06 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/107975
* range-op-float.cc (foperator_mult::op1_range,
foperator_div::op1_range, foperator_div::op2_range): Just
return float_binary_op_range_finish result if lhs is known
NAN, or the other operand is known NAN or UNDEFINED.
* gcc.dg/pr107975.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/range-op-float.cc | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr107975.c | 15 |
2 files changed, 21 insertions, 0 deletions
diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index e9455a9..ac57c8a 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -2146,6 +2146,8 @@ public: bool ret = rdiv.fold_range (r, type, lhs, op2); if (ret == false) return false; + if (lhs.known_isnan () || op2.known_isnan () || op2.undefined_p ()) + return float_binary_op_range_finish (ret, r, type, lhs); const REAL_VALUE_TYPE &lhs_lb = lhs.lower_bound (); const REAL_VALUE_TYPE &lhs_ub = lhs.upper_bound (); const REAL_VALUE_TYPE &op2_lb = op2.lower_bound (); @@ -2296,6 +2298,8 @@ public: bool ret = fop_mult.fold_range (r, type, lhs, op2); if (!ret) return ret; + if (lhs.known_isnan () || op2.known_isnan () || op2.undefined_p ()) + return float_binary_op_range_finish (ret, r, type, lhs); const REAL_VALUE_TYPE &lhs_lb = lhs.lower_bound (); const REAL_VALUE_TYPE &lhs_ub = lhs.upper_bound (); const REAL_VALUE_TYPE &op2_lb = op2.lower_bound (); @@ -2325,6 +2329,8 @@ public: bool ret = fold_range (r, type, op1, lhs); if (!ret) return ret; + if (lhs.known_isnan () || op1.known_isnan () || op1.undefined_p ()) + return float_binary_op_range_finish (ret, r, type, lhs); const REAL_VALUE_TYPE &lhs_lb = lhs.lower_bound (); const REAL_VALUE_TYPE &lhs_ub = lhs.upper_bound (); const REAL_VALUE_TYPE &op1_lb = op1.lower_bound (); diff --git a/gcc/testsuite/gcc.dg/pr107975.c b/gcc/testsuite/gcc.dg/pr107975.c new file mode 100644 index 0000000..7710f6f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr107975.c @@ -0,0 +1,15 @@ +/* PR tree-optimization/107975 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-add-options ieee } */ + +double +foo (double x, double y) +{ + if (x == 42.0) + return 1.0; + double r = x * y; + if (!__builtin_isnan (r)) + __builtin_unreachable (); + return r; +} |