https://gcc.gnu.org/g:8351875a5e2c52492198e3959a42b0934b89694f

commit r17-1931-g8351875a5e2c52492198e3959a42b0934b89694f
Author: Eikansh Gupta <[email protected]>
Date:   Fri Jun 26 11:10:43 2026 +0530

    tree-optimization: Use ranges for int-float comparisons [PR125385]
    
    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.
    
    Signed-off-by: Eikansh Gupta <[email protected]>

Diff:
---
 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(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index 615ce9b19639..62f191cefba0 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 4c017cb878d7..29cb6a1edd2b 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 dc39c32d85f0..e9ddcf5e1717 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 000000000000..630fa58d23e7
--- /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 6992a5acf81e..918e077af1b3 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;
 
 
 /*---------------------------------------------------------------------------

Reply via email to