On Mon, Sep 19, 2022 at 9:59 AM Aldy Hernandez <al...@redhat.com> wrote: > > ISTM that a specifically nonnegative range should not contain -NAN, > otherwise signbit_p() would return false, because we'd be unsure of the > sign. > > Do y'all agree?
what tree_expr_nonnegative_p actually means isn't 100% clear. For REAL_CST it actually looks at the sign-bit but we have (simplify /* copysign(x,y) -> fabs(x) if y is nonnegative. */ (COPYSIGN_ALL @0 tree_expr_nonnegative_p@1) (abs @0)) is abs (@0) OK for sNaNs and -NaN/+NaN? And we have /* Convert abs[u] (X) where X is nonnegative -> (X). */ (simplify (abs tree_expr_nonnegative_p@0) @0) where at least sNaN -> qNaN would be dropped? And of course (simplify /* signbit(x) -> 0 if x is nonnegative. */ (SIGNBIT tree_expr_nonnegative_p@0) { integer_zero_node; }) that is, is tree_expr_nonnegative_p actually tree_expr_sign or does tree_expr_nonnegative (x) mean x >= (typeof(X)) 0 or !(x < (typeof(X))0)? That said, 'set_nonnegative' could be interpreted to be without NaNs? Richard. > PR 68097/tree-optimization > > gcc/ChangeLog: > > * value-range.cc (frange::set_nonnegative): Set +NAN. > (range_tests_signed_zeros): New test. > * value-range.h (frange::update_nan): New overload to set NAN sign. > --- > gcc/value-range.cc | 9 +++++++++ > gcc/value-range.h | 14 ++++++++++++++ > 2 files changed, 23 insertions(+) > > diff --git a/gcc/value-range.cc b/gcc/value-range.cc > index 67d5d7fa90f..e432ec8b525 100644 > --- a/gcc/value-range.cc > +++ b/gcc/value-range.cc > @@ -752,6 +752,10 @@ void > frange::set_nonnegative (tree type) > { > set (type, dconst0, dconstinf); > + > + // Set +NAN as the only possibility. > + if (HONOR_NANS (type)) > + update_nan (/*sign=*/0); > } > > // Here we copy between any two irange's. The ranges can be legacy or > @@ -3800,6 +3804,11 @@ range_tests_signed_zeros () > r1.update_nan (); > r0.intersect (r1); > ASSERT_TRUE (r0.known_isnan ()); > + > + r0.set_nonnegative (float_type_node); > + ASSERT_TRUE (r0.signbit_p (signbit) && !signbit); > + if (HONOR_NANS (float_type_node)) > + ASSERT_TRUE (r0.maybe_isnan ()); > } > > static void > diff --git a/gcc/value-range.h b/gcc/value-range.h > index 3a401f3e4e2..5b261d4f46a 100644 > --- a/gcc/value-range.h > +++ b/gcc/value-range.h > @@ -312,6 +312,7 @@ public: > const REAL_VALUE_TYPE &lower_bound () const; > const REAL_VALUE_TYPE &upper_bound () const; > void update_nan (); > + void update_nan (bool sign); > void clear_nan (); > > // fpclassify like API > @@ -1098,6 +1099,19 @@ frange::update_nan () > verify_range (); > } > > +// Like above, but set the sign of the NAN. > + > +inline void > +frange::update_nan (bool sign) > +{ > + gcc_checking_assert (!undefined_p ()); > + m_pos_nan = !sign; > + m_neg_nan = sign; > + normalize_kind (); > + if (flag_checking) > + verify_range (); > +} > + > // Clear the NAN bit and adjust the range. > > inline void > -- > 2.37.1 >