Hi Jeff,
I'd like to ping/progress a patch of mine from July 2024:
https://gcc.gnu.org/pipermail/gcc-patches/2024-July/658482.html
which was initially (positively) reviewed here:
https://gcc.gnu.org/pipermail/gcc-patches/2024-August/659433.html

The original motivation for this patch was Claudiu's issue/analysis at
https://github.com/foss-for-synopsys-dwc-arc-processors/gcc/issues/118
which predicted a dramatic +26% performance improvement on EEMBC's
iirflt01 benchmark.

A quick summary is that GCC currently fails to optimize:
int foo(long long x) { return x == 1.0; }
to use an integral comparison (and avoid a floating point conversion)
because all the values of long long can't be precisely represented
as a (IEEE) double.  This is too strict a condition, as only one
value of a "long long" gets converted to 1.0 (even with overflow
and rounding).

The code review above agreed the implementation itself is reasonable
and both machine and floating-point independent, the challenge is in
writing test cases for the code, which unfortunately must assume a
particular floating point format, and are therefore non-portable.

To respond to Jeff's previous request/question, my preferred
solution is rather than try to add "-mieee" to these new test cases,
which should still pass even without strict IEEE (i.e. NaN) support,
and therefore we should still be testing with -O2 default flags,
but instead it makes sense for various backends to add additional
tests/copies to their gcc.target directories including "-mieee",
"-msoft-float", "-md-float", "-mg-float", "-mfpmath=387" etc. if
they so wish.  A failure of these tests does not indicate an issue
with the implementation, which simply uses the current compile-time
integer to FP (real) conversion support, but that that test hasn't
been ported to the new/native floating point format (say FP8 or FP4).

This patch has been retested on x86_64-pc-linux-gnu with make bootstrap
and make -k check, both with and without --target_board=unix{-m32}
with no new failures.  Ok for mainline (cleaning up any testsuite
wrinkles if/as they're reported)?


2026-06-15  Roger Sayle  <[email protected]>

gcc/ChangeLog
        PR tree-optimization/57371
        * fold-const.cc (fold_cmp_float_cst_p): New helper function.
        * fold-const.h (fold_cmp_float_cst_p): Prototype here.
        * match.pd ((FTYPE) N CMP CST): Use ranger to determine
        whether value is exactly representable by floating point type,
        and check flag_trapping_math if not.  Use the new helper
        fold_cmp_float_cst_p to check that transformation to an integer
        comparison is safe.

gcc/testsuite/ChangeLog
        PR tree-optimization/57371
        * c-c++-common/pr57371-6.c: New test case.
        * c-c++-common/pr57371-7.c: Likewise.
        * c-c++-common/pr57371-8.c: Likewise.
        * c-c++-common/pr57371-9.c: Likewise.
        * c-c++-common/pr57371-10.c: Likewise.


Thanks in advance,
Roger
--

diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 352083e146b..5561145de69 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -7095,6 +7095,92 @@ fold_real_zero_addition_p (const_tree type, const_tree 
arg,
   return negate || (arg && !tree_expr_maybe_real_minus_zero_p (arg));
 }
 
+/* Subroutine of match.pd that determines if it is safe to optimize
+   a floating point comparison of an integer value, known to be between
+   LO and HI, using comparison operator CMP, against the real constant
+   R in floating point type FMT, as the same integer comparison against
+   the integer constant I, with sign ISIGN.
+
+   For example, with IEEE-754, (float)x == 2.0f may replaced with x == 2
+   because the floating point representations of the neighboring integers
+   (float)1 and (float)3 are distinct from 2.0f, having values 1.0f and
+   3.0f respectively.  On the other hand (float)x == 16777220.0f can't
+   be replaced by x == 16777220 as (float)16777221 is also 1677220.0f
+   due to truncation/rounding.
+*/
+bool
+fold_cmp_float_cst_p (wide_int lo, wide_int hi, enum tree_code cmp,
+                     const REAL_VALUE_TYPE *r, format_helper fmt,
+                     wide_int i, signop isign)
+{
+  REAL_VALUE_TYPE raw;
+  REAL_VALUE_TYPE rnd;
+  bool check_im1 = true;
+  bool check_ip1 = true;
+
+  switch (cmp)
+    {
+    case EQ_EXPR:
+    case NE_EXPR:
+      /* Check both i-1 and i+1.  */
+      break;
+
+    case LT_EXPR:
+    case GE_EXPR:
+      /* Only check i-1.  */
+      check_ip1 = false;
+      break;
+
+    case LE_EXPR:
+    case GT_EXPR:
+      /* Only check i+1.  */
+      check_im1 = false;
+      break;
+
+    default:
+      return false;
+    }
+
+    if (flag_rounding_math && i != 0)
+      {
+       real_from_integer (&raw, VOIDmode, i, isign);
+        if (!real_identical (r, &raw))
+         return false;
+      }
+
+    if (check_im1 && wi::gt_p (i, lo, isign))
+      {
+       if (flag_rounding_math)
+         {
+           real_from_integer (&raw, VOIDmode, i - 1, isign);
+           real_convert (&rnd, fmt, &raw);
+           if (!real_identical (&raw, &rnd))
+             return false;
+         }
+       else
+         real_from_integer (&rnd, fmt, i - 1, isign);
+       if (real_identical (r, &rnd))
+         return false;
+      }
+
+    if (check_ip1 && wi::lt_p (i, hi, isign))
+      {
+       if (flag_rounding_math)
+         {
+           real_from_integer (&raw, VOIDmode, i + 1, isign);
+           real_convert (&rnd, fmt, &raw);
+           if (!real_identical (&raw, &rnd))
+             return false;
+         }
+       else
+         real_from_integer (&rnd, fmt, i + 1, isign);
+       if (real_identical (r, &rnd))
+         return false;
+      }
+
+  return true;
+}
+
 /* Subroutine of match.pd that optimizes comparisons of a division by
    a nonzero integer constant against an integer constant, i.e.
    X/C1 op C2.
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index ca464ce60af..8d8c3258979 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -177,6 +177,12 @@ extern bool integer_valued_real_p (tree, int = 0);
 
 extern bool fold_real_zero_addition_p (const_tree, const_tree, const_tree,
                                       int);
+extern bool fold_cmp_float_cst_p (wide_int lo, wide_int hi,
+                                 enum tree_code cmp,
+                                 const REAL_VALUE_TYPE *r,
+                                 format_helper fmt,
+                                 wide_int i, signop isign);
+
 extern tree combine_comparisons (location_t, enum tree_code, enum tree_code,
                                 enum tree_code, tree, tree, tree);
 extern void debug_fold_checksum (const_tree);
diff --git a/gcc/match.pd b/gcc/match.pd
index 8a2de136e7f..6ef445d6247 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -7552,6 +7552,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (with
      {
        tree itype = TREE_TYPE (@0);
+       signop isign = TYPE_SIGN (itype);
        format_helper fmt (REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (@1))));
        const REAL_VALUE_TYPE *cst = TREE_REAL_CST_PTR (@1);
        /* Be careful to preserve any potential exceptions due to NaNs.
@@ -7561,16 +7562,41 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
                          && ((cmp != EQ_EXPR && cmp != NE_EXPR)
                              || (cst->signalling
                                  && HONOR_SNANS (TREE_TYPE (@1))));
+       /* Conversion may raise FPE_INEXACT with -ftrapping-math.  */
+       wide_int hi,lo;
+       bool exact_p;
+#if GIMPLE
+       int_range_max vr0;
+       get_range_query (cfun)->range_of_expr (vr0, @0);
+       if (!vr0.undefined_p ())
+        {
+          lo = vr0.lower_bound ();
+          hi = vr0.upper_bound ();
+          int prec = (isign == SIGNED)
+                     ? MAX (wi::min_precision (hi, SIGNED),
+                            wi::min_precision (lo, SIGNED)) - 1
+                     : wi::min_precision (hi, UNSIGNED);
+          wide_int nz = vr0.get_nonzero_bits ();
+          if (nz != 0)
+            prec -= wi::ctz (nz);
+          exact_p = prec <= significand_size (fmt);
+        }
+       else
+#endif
+       {
+         exact_p = fmt.can_represent_integral_type_p (itype);
+         lo = wi::min_value (itype);
+         hi = wi::max_value (itype);
+       }
+       if (flag_trapping_math && !exact_p)
+        exception_p = true;
      }
-     /* TODO: allow non-fitting itype and SNaNs when
-       -fno-trapping-math.  */
-     (if (fmt.can_represent_integral_type_p (itype) && ! exception_p)
+     (if (! exception_p)
       (with
        {
-        signop isign = TYPE_SIGN (itype);
         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, lo, isign);
+        real_from_integer (&imax, fmt, hi, isign);
 
         REAL_VALUE_TYPE icst;
         if (cmp == GT_EXPR || cmp == GE_EXPR)
@@ -7580,7 +7606,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
         else
           real_trunc (&icst, fmt, cst);
 
-        bool cst_int_p = !real_isnan (cst) && real_identical (&icst, cst);
+        bool cst_int_p = real_isfinite (cst) && real_identical (&icst, cst);
 
         bool overflow_p = false;
         wide_int icst_val
@@ -7594,21 +7620,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        (if (real_compare (GT_EXPR, cst, &imax))
         { constant_boolean_node (cmp == LT_EXPR || cmp == LE_EXPR || cmp == 
NE_EXPR,
                                  type); })
-       /* Remove cast if CST is an integer representable by ITYPE.  */
-       (if (cst_int_p)
-        (cmp @0 { gcc_assert (!overflow_p);
-                  wide_int_to_tree (itype, icst_val); })
-       )
-       /* When CST is fractional, optimize
+       /* When CST is fractional, infinity or NaN, then optimize
            (FTYPE) N == CST -> 0
            (FTYPE) N != CST -> 1.  */
-       (if (cmp == EQ_EXPR || cmp == NE_EXPR)
+       (if (!cst_int_p
+            && (cmp == EQ_EXPR || cmp == NE_EXPR))
         { constant_boolean_node (cmp == NE_EXPR, type); })
+       /* Remove cast if CST is an integer representable by ITYPE.  */
+       (if (cst_int_p
+            && fold_cmp_float_cst_p (lo, hi, cmp, &icst, fmt,
+                                     icst_val, isign))
+        (cmp @0 { wide_int_to_tree (itype, icst_val); })
+       )
        /* Otherwise replace with sensible integer constant.  */
-       (with
-        {
-          gcc_checking_assert (!overflow_p);
-        }
+       (if (!cst_int_p 
+            && fold_cmp_float_cst_p (lo, hi, icmp, &icst, fmt,
+                                     icst_val, isign))
         (icmp @0 { wide_int_to_tree (itype, icst_val); })))))))))
 
 /* Fold A /[ex] B CMP C to A CMP B * C.  */
diff --git a/gcc/testsuite/c-c++-common/pr57371-10.c 
b/gcc/testsuite/c-c++-common/pr57371-10.c
new file mode 100644
index 00000000000..96172767c78
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr57371-10.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fno-trapping-math -frounding-math" 
} */
+
+int foo1 (int a) {
+  return (float) a != 16777222.0f;
+}
+
+int foo2 (unsigned int b) {
+  return (float) b != 16777222.0f;
+}
+
+int foo3 (unsigned long long c) {
+  return (float) c != 16777222.0f;
+}
+
+int foo4 (long long d) {
+  return (float) d != 16777222.0f;
+}
+
+/* { dg-final { scan-tree-dump-times "\\(float\\)" 4 "optimized" } } */
diff --git a/gcc/testsuite/c-c++-common/pr57371-6.c 
b/gcc/testsuite/c-c++-common/pr57371-6.c
new file mode 100644
index 00000000000..3486b94bac8
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr57371-6.c
@@ -0,0 +1,200 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fno-trapping-math" } */
+
+int foo1 (int p) {
+  return (float) p != 0;
+  /* { dg-final { scan-tree-dump "p_\[0-9]\\(D\\) != 0;" "optimized" } } */
+}
+
+int foo2 (unsigned int q) {
+  return (float) q != 0;
+  /* { dg-final { scan-tree-dump "q_\[0-9]\\(D\\) != 0;" "optimized" } } */
+}
+
+int foo3 (long long r) {
+  return (float) r != 0;
+  /* { dg-final { scan-tree-dump "r_\[0-9]\\(D\\) != 0;" "optimized" } } */
+}
+
+int foo4 (unsigned long long s) {
+  return (float) s != 0;
+  /* { dg-final { scan-tree-dump "s_\[0-9]\\(D\\) != 0;" "optimized" } } */
+}
+
+int foo5 (long long t) {
+  return (double) t != 0;
+  /* { dg-final { scan-tree-dump "t_\[0-9]\\(D\\) != 0;" "optimized" } } */
+}
+
+int foo6 (unsigned long long u) {
+  return (double) u != 0;
+  /* { dg-final { scan-tree-dump "u_\[0-9]\\(D\\) != 0;" "optimized" } } */
+}
+
+/* Tests when RHS is within range of integer type.  */
+
+void in_range (unsigned int x)
+{
+  {
+    volatile int in_range_1;
+    in_range_1 = (float) x > 100.0f;
+    /* { dg-final { scan-tree-dump " > 100;" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_2;
+    in_range_2 = (float) x < 200.0f;
+    /* { dg-final { scan-tree-dump " <= 199;" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_3;
+    in_range_3 = (float) x > 300.5f;
+    /* { dg-final { scan-tree-dump " > 300;" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_4;
+    in_range_4 = (float) x < 400.5f;
+    /* { dg-final { scan-tree-dump " <= 400;" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_5;
+    in_range_5 = (float) x == 500.0f;
+    /* { dg-final { scan-tree-dump " == 500;" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_6;
+    in_range_6 = (float) x != 600.0f;
+    /* { dg-final { scan-tree-dump " != 600;" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_7;
+    in_range_7 = (float) x == 700.5f;
+    /* { dg-final { scan-tree-dump "in_range_7 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_8;
+    in_range_8 = (float) x != 800.5f;
+    /* { dg-final { scan-tree-dump "in_range_8 ={v} 1" "optimized" } } */
+  }
+}
+
+/* Tests for cases where RHS is out of range of integer type.  */
+
+void out_range (unsigned int x)
+{
+  {
+    volatile int out_range_1;
+    out_range_1 = (float) x > -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_1 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int out_range_2;
+    out_range_2 = (float) x >= -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_2 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int out_range_3;
+    out_range_3 = (float) x < -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_3 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int out_range_4;
+    out_range_4 = (float) x <= -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_4 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int out_range_5;
+    out_range_5 = (float) x == -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_5 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int out_range_6;
+    out_range_6 = (float) x != -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_6 ={v} 1" "optimized" } } */
+  }
+}
+
+/* Tests with non-finite float consts.  */
+
+void nonfinite (unsigned int x)
+{
+#define INFINITY __builtin_inff ()
+
+  {
+    volatile int nonfinite_1;
+    nonfinite_1 = (float) x > INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_1 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_2;
+    nonfinite_2 = (float) x >= INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_2 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_3;
+    nonfinite_3 = (float) x < INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_3 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_4;
+    nonfinite_4 = (float) x <= INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_4 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_5;
+    nonfinite_5 = (float) x > -INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_5 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_6;
+    nonfinite_6 = (float) x >= -INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_6 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_7;
+    nonfinite_7 = (float) x < -INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_7 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_8;
+    nonfinite_8 = (float) x <= -INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_8 ={v} 0" "optimized" } } */
+  }
+
+#define QNAN __builtin_nanf ("0")
+
+  /* Even for qNaNs, only == and != are quiet.  */
+
+  {
+    volatile int nonfinite_9;
+    nonfinite_9 = (float) x == QNAN;
+    /* { dg-final { scan-tree-dump "nonfinite_9 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_10;
+    nonfinite_10 = (float) x != QNAN;
+    /* { dg-final { scan-tree-dump "nonfinite_10 ={v} 1" "optimized" } } */
+  }
+}
+
+/* { dg-final { scan-tree-dump-not "\\(float\\)" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "\\(double\\)" "optimized" } } */
diff --git a/gcc/testsuite/c-c++-common/pr57371-7.c 
b/gcc/testsuite/c-c++-common/pr57371-7.c
new file mode 100644
index 00000000000..b976eb9b17e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr57371-7.c
@@ -0,0 +1,218 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int foo1 (int a) {
+  a &= 4095;
+  return (float) a != 0.0f;
+  /* { dg-final { scan-tree-dump "a_\[0-9] != 0;" "optimized" } } */
+}
+
+int foo2 (unsigned int b) {
+  b &= 4095;
+  return (float) b != 0.0f;
+  /* { dg-final { scan-tree-dump "b_\[0-9] != 0;" "optimized" } } */
+}
+
+int foo3 (unsigned long long c) {
+  c &= 4095;
+  return (float) c != 0.0f;
+  /* { dg-final { scan-tree-dump "c_\[0-9] != 0;" "optimized" } } */
+}
+
+int foo4 (long long d) {
+  d &= 4095;
+  return (float) d != 0.0f;
+  /* { dg-final { scan-tree-dump "d_\[0-9] != 0;" "optimized" } } */
+}
+
+/* Tests when RHS is within range of integer type.  */
+
+void in_range (unsigned int x)
+{
+  {
+    volatile int in_range_1;
+    x &= 4095;
+    in_range_1 = (float) x > 100.0f;
+    /* { dg-final { scan-tree-dump " > 100" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_2;
+    x &= 4095;
+    in_range_2 = (float) x < 200.0f;
+    /* { dg-final { scan-tree-dump " <= 199" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_3;
+    x &= 4095;
+    in_range_3 = (float) x > 300.5f;
+    /* { dg-final { scan-tree-dump " > 300" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_4;
+    x &= 4095;
+    in_range_4 = (float) x < 400.5f;
+    /* { dg-final { scan-tree-dump " <= 400" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_5;
+    x &= 4095;
+    in_range_5 = (float) x == 500.0f;
+    /* { dg-final { scan-tree-dump " == 500" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_6;
+    x &= 4095;
+    in_range_6 = (float) x != 600.0f;
+    /* { dg-final { scan-tree-dump " != 600" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_7;
+    x &= 4095;
+    in_range_7 = (float) x == 700.5f;
+    /* { dg-final { scan-tree-dump "in_range_7 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int in_range_8;
+    x &= 4095;
+    in_range_8 = (float) x != 800.5f;
+    /* { dg-final { scan-tree-dump "in_range_8 ={v} 1" "optimized" } } */
+  }
+}
+
+/* Tests for cases where RHS is out of range of integer type.  */
+
+void out_range (unsigned int x)
+{
+  {
+    volatile int out_range_1;
+    x &= 4095;
+    out_range_1 = (float) x > -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_1 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int out_range_2;
+    x &= 4095;
+    out_range_2 = (float) x >= -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_2 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int out_range_3;
+    x &= 4095;
+    out_range_3 = (float) x < -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_3 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int out_range_4;
+    x &= 4095;
+    out_range_4 = (float) x <= -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_4 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int out_range_5;
+    x &= 4095;
+    out_range_5 = (float) x == -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_5 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int out_range_6;
+    x &= 4095;
+    out_range_6 = (float) x != -100.5f;
+    /* { dg-final { scan-tree-dump "out_range_6 ={v} 1" "optimized" } } */
+  }
+}
+
+/* Tests with non-finite float consts.  */
+
+void nonfinite (unsigned int x)
+{
+#define INFINITY __builtin_inff ()
+
+  {
+    volatile int nonfinite_1;
+    x &= 4095;
+    nonfinite_1 = (float) x > INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_1 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_2;
+    x &= 4095;
+    nonfinite_2 = (float) x >= INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_2 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_3;
+    x &= 4095;
+    nonfinite_3 = (float) x < INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_3 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_4;
+    x &= 4095;
+    nonfinite_4 = (float) x <= INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_4 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_5;
+    x &= 4095;
+    nonfinite_5 = (float) x > -INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_5 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_6;
+    x &= 4095;
+    nonfinite_6 = (float) x >= -INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_6 ={v} 1" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_7;
+    x &= 4095;
+    nonfinite_7 = (float) x < -INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_7 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_8;
+    x &= 4095;
+    nonfinite_8 = (float) x <= -INFINITY;
+    /* { dg-final { scan-tree-dump "nonfinite_8 ={v} 0" "optimized" } } */
+  }
+
+#define QNAN __builtin_nanf ("0")
+
+  /* Even for qNaNs, only == and != are quiet.  */
+
+  {
+    volatile int nonfinite_9;
+    x &= 4095;
+    nonfinite_9 = (float) x == QNAN;
+    /* { dg-final { scan-tree-dump "nonfinite_9 ={v} 0" "optimized" } } */
+  }
+
+  {
+    volatile int nonfinite_10;
+    x &= 4095;
+    nonfinite_10 = (float) x != QNAN;
+    /* { dg-final { scan-tree-dump "nonfinite_10 ={v} 1" "optimized" } } */
+  }
+}
+
+/* { dg-final { scan-tree-dump-not "\\(float\\)" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "\\(double\\)" "optimized" } } */
diff --git a/gcc/testsuite/c-c++-common/pr57371-8.c 
b/gcc/testsuite/c-c++-common/pr57371-8.c
new file mode 100644
index 00000000000..d0d7eecc9a1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr57371-8.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fno-trapping-math" } */
+
+int foo1 (int a) {
+  return (float) a != 16777220.0f;
+}
+
+int foo2 (unsigned int b) {
+  return (float) b != 16777220.0f;
+}
+
+int foo3 (unsigned long long c) {
+  return (float) c != 16777220.0f;
+}
+
+int foo4 (long long d) {
+  return (float) d != 16777220.0f;
+}
+
+/* { dg-final { scan-tree-dump-times "\\(float\\)" 4 "optimized" } } */
diff --git a/gcc/testsuite/c-c++-common/pr57371-9.c 
b/gcc/testsuite/c-c++-common/pr57371-9.c
new file mode 100644
index 00000000000..32b8cbadfb1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr57371-9.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fno-trapping-math" } */
+
+int foo1 (int a) {
+  return (float) a != 16777222.0f;
+  /* { dg-final { scan-tree-dump "a_\[0-9]\\(D\\) != 16777222;" "optimized" } 
} */
+}
+
+int foo2 (unsigned int b) {
+  return (float) b != 16777222.0f;
+  /* { dg-final { scan-tree-dump "b_\[0-9]\\(D\\) != 16777222;" "optimized" } 
} */
+}
+
+int foo3 (unsigned long long c) {
+  return (float) c != 16777222.0f;
+  /* { dg-final { scan-tree-dump "c_\[0-9]\\(D\\) != 16777222;" "optimized" } 
} */
+}
+
+int foo4 (long long d) {
+  return (float) d != 16777222.0f;
+  /* { dg-final { scan-tree-dump "d_\[0-9]\\(D\\) != 16777222;" "optimized" } 
} */
+}
+
+/* { dg-final { scan-tree-dump-not "\\(float\\)" "optimized" } } */

Reply via email to