Doh! Wrong patch...
> -----Original Message-----
> From: Roger Sayle <[email protected]>
> Sent: 10 July 2026 17:48
> To: 'GCC Patches' <[email protected]>; 'Jeffrey Law'
> <[email protected]>; 'Andrea Pinski'
> <[email protected]>
> Subject: [PATCH v3] PR tree-opt/57371: Improved comparison of integers to FP
> constants.
>
>
> Hi Jeff and Andrea,
>
> Now that Eikash's patch for PR tree-opt/125385 is in the tree, I've updated my
> (float)i == 4.0f patch against the current mainline.
>
> The full technical description is in my post 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
> and my recent ping (which contained some more context) is at
> https://gcc.gnu.org/pipermail/gcc-patches/2026-June/720287.html
>
> Eikash's patch/optimization is cool, and obsoletes all the ranger related
> pieces of
> my original patch. Thanks Eikash and Andrea.
>
> 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?
>
>
> 2026-07-10 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 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 again,
> Roger
> --
>
> > -----Original Message-----
> > From: Andrea Pinski <[email protected]>
> > Sent: 19 June 2026 07:32
> > To: Andrew Pinski <[email protected]>
> > Cc: Roger Sayle <[email protected]>; GCC Patches <gcc-
> > [email protected]>; Jeffrey Law <[email protected]>
> > Subject: Re: [PATCH] PR tree-opt/57371: Improved comparison of
> > integers to FP constants.
> >
> > On Mon, Jun 15, 2026 at 1:21 AM Andrew Pinski <[email protected]> wrote:
> > >
> > >
> > >
> > > On Mon, Jun 15, 2026, 1:09 AM Roger Sayle
> > > <[email protected]>
> > wrote:
> > >>
> > >>
> > >> 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/
> > >> 11
> > >> 8 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.
> > >
> > >
> > > Hmm, I have someone working on a related patch and this will conflict.
> > > We are changing (cmp (convert int) (float_cst)) to use the ranger
> > > and adding a
> > new function to the format helper to check if the range of the integer
> > can fit into the floating point exactly.
> > > The person working on this should be posting today or tomorrow.
> > > Since I helped with that patch I can review this one too.
> >
> > See https://gcc.gnu.org/pipermail/gcc-patches/2026-June/720633.html .
> > I do know there is some overlap between the 2 patches.
> > Like for an example in your patch you do:
> > ```
> >
> > + 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); }
> > ``
> >
> > While Eikansh does:
> >
> > +#if GIMPLE
> > + int_range_max vr;
> > + if (!value_ok
> > + && gimple_match_range_of_expr (vr, @0, @2)) value_ok =
> > +fmt.can_represent_integral_value_p (&vr); #endif
> >
> > And then can_represent_integral_value_p calls range_fits_type_p which
> > is basically what you do here (but better):
> > + 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);
> >
> >
> >
> >
> > >
> > > Thanks,
> > > Andrea
> > >
> > >
> > >>
> > >> 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 1d0ed62a82f..b4e3a56aeb5 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -7020,6 +7020,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 8c0c3edba17..25e1cbf911f 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -173,6 +173,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 tree_code combine_comparisons (enum tree_code, enum tree_code,
diff --git a/gcc/match.pd b/gcc/match.pd
index 7da15cc4cdc..91f09532a81 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -7730,6 +7730,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))));
bool itype_ok = fmt.can_represent_integral_type_p (itype);
bool value_ok = itype_ok;
@@ -7747,10 +7748,12 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
&& gimple_match_range_of_expr (vr, @0, @2))
value_ok = fmt.can_represent_range_value_p (&vr);
#endif
+ /* Conversion may raise FPE_INEXACT with -ftrapping-math. */
+ if (flag_trapping_math && !value_ok)
+ exception_p = true;
}
- /* TODO: allow non-fitting itype and SNaNs when
- -fno-trapping-math. */
- (if (value_ok && ! exception_p)
+
+ (if (! exception_p)
(with
{
signop isign = TYPE_SIGN (itype);
@@ -7775,7 +7778,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
@@ -7789,21 +7792,23 @@ 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,
+ and it is safe to do so. */
+ (if (cst_int_p
+ && fold_cmp_float_cst_p (imin_val, imax_val, 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 (imin_val, imax_val, 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" } } */