On Thu, Jun 25, 2026 at 10:41 PM Eikansh Gupta <[email protected]> wrote: > > When integer operands are converted to a floating-point type before a > comparison, the existing fold only checks whether the whole integer type > is exactly representable. Use SSA range information as a fallback so > range-limited values, such as those masked to [0, 255], can be compared > directly as integers. Apply the same range-aware exactness check to > integer-to-float comparisons against real constants. > > PR tree-optimization/125385 > > gcc/ChangeLog: > > * match.pd ((FTYPE) N CMP (FTYPE) M): Use range information > to decide whether integer operands are exactly representable. > ((FTYPE) N CMP CST): Likewise. > * real.cc: Include backend.h and vr-values.h. > (format_helper::can_represent_range_value_p): New function. > * real.h (format_helper::can_represent_range_value_p): Declare. > * tree-core.h (class irange): Forward declare. > > gcc/testsuite/ChangeLog: > > * gcc.dg/tree-ssa/pr125385.c: New test.
Ok. Pushed as https://gcc.gnu.org/pipermail/gcc-cvs/2026-June/456401.html . Thanks, Andrea > > Signed-off-by: Eikansh Gupta <[email protected]> > --- > gcc/match.pd | 41 ++++++++++-- > gcc/real.cc | 24 +++++++ > gcc/real.h | 1 + > gcc/testsuite/gcc.dg/tree-ssa/pr125385.c | 82 ++++++++++++++++++++++++ > gcc/tree-core.h | 1 + > 5 files changed, 142 insertions(+), 7 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr125385.c > > diff --git a/gcc/match.pd b/gcc/match.pd > index 8c410c2f3b3..5e1659896ae 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -7610,7 +7610,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (for cmp (lt le eq ne ge gt unordered ordered unlt unle ungt unge uneq ltgt) > icmp (lt le eq ne ge gt unordered ordered lt le gt ge eq ne) > (simplify > - (cmp (float@0 @1) (float @2)) > + (cmp (float@0 @1) (float@3 @2)) > (if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (@0)) > && ! DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@0))) > (with > @@ -7618,11 +7618,21 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@0)))); > tree type1 = TREE_TYPE (@1); > bool type1_signed_p = TYPE_SIGN (type1) == SIGNED; > + bool type1_ok = fmt.can_represent_integral_type_p (type1); > tree type2 = TREE_TYPE (@2); > bool type2_signed_p = TYPE_SIGN (type2) == SIGNED; > + bool type2_ok = fmt.can_represent_integral_type_p (type2); > +#if GIMPLE > + int_range_max vr1, vr2; > + if (!type1_ok > + && gimple_match_range_of_expr (vr1, @1, @0)) > + type1_ok = fmt.can_represent_range_value_p (&vr1); > + if (!type2_ok > + && gimple_match_range_of_expr (vr2, @2, @3)) > + type2_ok = fmt.can_represent_range_value_p (&vr2); > +#endif > } > - (if (fmt.can_represent_integral_type_p (type1) > - && fmt.can_represent_integral_type_p (type2)) > + (if (type1_ok && type2_ok) > (if (cmp == ORDERED_EXPR || cmp == UNORDERED_EXPR) > { constant_boolean_node (cmp == ORDERED_EXPR, type); } > (if (TYPE_PRECISION (type1) > TYPE_PRECISION (type2) > @@ -7639,13 +7649,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (for cmp (lt le eq ne ge gt) > icmp (le le eq ne ge ge) > (simplify > - (cmp (float @0) REAL_CST@1) > + (cmp (float@2 @0) REAL_CST@1) > (if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (@1)) > && ! DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@1))) > (with > { > tree itype = TREE_TYPE (@0); > format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@1)))); > + bool itype_ok = fmt.can_represent_integral_type_p (itype); > + bool value_ok = itype_ok; > const REAL_VALUE_TYPE *cst = TREE_REAL_CST_PTR (@1); > /* Be careful to preserve any potential exceptions due to NaNs. > qNaNs are ok in == or != context. */ > @@ -7654,16 +7666,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > && ((cmp != EQ_EXPR && cmp != NE_EXPR) > || (cst->signalling > && HONOR_SNANS (TREE_TYPE (@1)))); > +#if GIMPLE > + int_range_max vr; > + if (!value_ok > + && gimple_match_range_of_expr (vr, @0, @2)) > + value_ok = fmt.can_represent_range_value_p (&vr); > +#endif > } > /* TODO: allow non-fitting itype and SNaNs when > -fno-trapping-math. */ > - (if (fmt.can_represent_integral_type_p (itype) && ! exception_p) > + (if (value_ok && ! exception_p) > (with > { > signop isign = TYPE_SIGN (itype); > + wide_int imin_val = wi::min_value (itype); > + wide_int imax_val = wi::max_value (itype); > +#if GIMPLE > + if (!itype_ok) > + { > + imin_val = vr.lower_bound (); > + imax_val = vr.upper_bound (); > + } > +#endif > REAL_VALUE_TYPE imin, imax; > - real_from_integer (&imin, fmt, wi::min_value (itype), isign); > - real_from_integer (&imax, fmt, wi::max_value (itype), isign); > + real_from_integer (&imin, fmt, imin_val, isign); > + real_from_integer (&imax, fmt, imax_val, isign); > > REAL_VALUE_TYPE icst; > if (cmp == GT_EXPR || cmp == GE_EXPR) > diff --git a/gcc/real.cc b/gcc/real.cc > index 4c017cb878d..29cb6a1edd2 100644 > --- a/gcc/real.cc > +++ b/gcc/real.cc > @@ -22,9 +22,13 @@ > #include "config.h" > #include "system.h" > #include "coretypes.h" > +#include "bitmap.h" > +#include "function.h" > #include "tm.h" > #include "rtl.h" > #include "tree.h" > +#include "value-range.h" > +#include "vr-values.h" > #include "realmpfr.h" > #include "dfp.h" > > @@ -5512,6 +5516,26 @@ bool format_helper::can_represent_integral_type_p > (tree type) const > return TYPE_PRECISION (type) - signed_p <= significand_size (*this); > } > > +/* True if all values in integer range *VR can be represented by this > + floating-point type exactly. */ > + > +bool > +format_helper::can_represent_range_value_p (const irange *vr) const > +{ > + gcc_assert (!decimal_p ()); > + > + if (vr->undefined_p () || vr->varying_p ()) > + return false; > + > + tree type = vr->type (); > + unsigned precision = significand_size (*this); > + > + if (TYPE_SIGN (type) == SIGNED) > + precision++; > + > + return range_fits_type_p (vr, precision, TYPE_SIGN (type)); > +} > + > /* True if mode M has a NaN representation and > the treatment of NaN operands is important. */ > > diff --git a/gcc/real.h b/gcc/real.h > index dc39c32d85f..e9ddcf5e171 100644 > --- a/gcc/real.h > +++ b/gcc/real.h > @@ -223,6 +223,7 @@ public: > > bool decimal_p () const { return m_format && m_format->b == 10; } > bool can_represent_integral_type_p (tree type) const; > + bool can_represent_range_value_p (const class irange *) const; > > private: > const real_format *m_format; > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr125385.c > b/gcc/testsuite/gcc.dg/tree-ssa/pr125385.c > new file mode 100644 > index 00000000000..630fa58d23e > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr125385.c > @@ -0,0 +1,82 @@ > +/* PR tree-optimization/125385 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -fdump-tree-optimized" } */ > + > +int > +f_lt (int a, int b) > +{ > + a &= 0xff; > + b &= 0xff; > + return (float) a < (float) b; > +} > + > +int > +f_le (int a, int b) > +{ > + a &= 0xff; > + b &= 0xff; > + return (float) a <= (float) b; > +} > + > +int > +f_eq (int a, int b) > +{ > + a &= 0xff; > + b &= 0xff; > + return (float) a == (float) b; > +} > + > +int > +f_ne (int a, int b) > +{ > + a &= 0xff; > + b &= 0xff; > + return (float) a != (float) b; > +} > + > +int > +f_ge (int a, int b) > +{ > + a &= 0xff; > + b &= 0xff; > + return (float) a >= (float) b; > +} > + > +int > +f_gt (int a, int b) > +{ > + a &= 0xff; > + b &= 0xff; > + return (float) a > (float) b; > +} > + > +int > +f_signed_range (int a, int b) > +{ > + a = (a & 0xff) - 128; > + b = (b & 0xff) - 128; > + return (float) a < (float) b; > +} > + > +int > +f_cst (int a) > +{ > + a &= 0xff; > + return (float) a < 42.0f; > +} > + > +int > +f_cst_fractional (int a) > +{ > + a &= 0xff; > + return (float) a < 42.5f; > +} > + > +int > +f_cst_outside_type (int a) > +{ > + a &= 0xff; > + return (float) a < 2147483648.0f; > +} > + > +/* { dg-final { scan-tree-dump-not "\\(float\\)" "optimized" } } */ > diff --git a/gcc/tree-core.h b/gcc/tree-core.h > index 09c07c5c129..c9232c16fec 100644 > --- a/gcc/tree-core.h > +++ b/gcc/tree-core.h > @@ -34,6 +34,7 @@ struct real_value; > struct fixed_value; > struct ptr_info_def; > struct die_struct; > +class irange; > > > /*--------------------------------------------------------------------------- > -- > 2.34.1 >
