aboutsummaryrefslogtreecommitdiff
path: root/gcc/match.pd
diff options
context:
space:
mode:
authorYury Gribov <tetra2005@gmail.com>2017-08-04 20:29:12 +0000
committerYury Gribov <ygribov@gcc.gnu.org>2017-08-04 20:29:12 +0000
commitc779bea5b977aa3df19c965c4866c6c20ad258c8 (patch)
tree1d204f2e5879f51d432b6570c00672fc37d7a27d /gcc/match.pd
parente52341f1613a7589425d6eba31a6d5e0500465bd (diff)
downloadgcc-c779bea5b977aa3df19c965c4866c6c20ad258c8.zip
gcc-c779bea5b977aa3df19c965c4866c6c20ad258c8.tar.gz
gcc-c779bea5b977aa3df19c965c4866c6c20ad258c8.tar.bz2
Remove useless floating point casts in comparisons.
2017-08-04 Yury Gribov <tetra2005@gmail.com> PR tree-optimization/57371 gcc/ * match.pd: New pattern. gcc/testsuite/ * c-c++-common/pr57371-1.c: New test. * c-c++-common/pr57371-2.c: New test. * c-c++-common/pr57371-3.c: New test. * c-c++-common/pr57371-4.c: New test. * gcc.dg/pr57371-5.c: New test. From-SVN: r250877
Diffstat (limited to 'gcc/match.pd')
-rw-r--r--gcc/match.pd74
1 files changed, 74 insertions, 0 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index e98db52..0e36f46 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2899,6 +2899,80 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (! HONOR_NANS (@0))
(cmp @0 @1))))))
+/* Optimize various special cases of (FTYPE) N CMP CST. */
+(for cmp (lt le eq ne ge gt)
+ icmp (le le eq ne ge ge)
+ (simplify
+ (cmp (float @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);
+ 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. qNaNs are ok in == or != context.
+ TODO: relax under -fno-trapping-math or
+ -fno-signaling-nans. */
+ bool exception_p
+ = real_isnan (cst) && (cst->signalling
+ || (cmp != EQ_EXPR || cmp != NE_EXPR));
+ /* INT?_MIN is power-of-two so it takes
+ only one mantissa bit. */
+ bool signed_p = isign == SIGNED;
+ bool itype_fits_ftype_p
+ = TYPE_PRECISION (itype) - signed_p <= significand_size (fmt);
+ }
+ /* TODO: allow non-fitting itype and SNaNs when
+ -fno-trapping-math. */
+ (if (itype_fits_ftype_p && ! exception_p)
+ (with
+ {
+ 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_VALUE_TYPE icst;
+ if (cmp == GT_EXPR || cmp == GE_EXPR)
+ real_ceil (&icst, fmt, cst);
+ else if (cmp == LT_EXPR || cmp == LE_EXPR)
+ real_floor (&icst, fmt, cst);
+ else
+ real_trunc (&icst, fmt, cst);
+
+ bool cst_int_p = real_identical (&icst, cst);
+
+ bool overflow_p = false;
+ wide_int icst_val
+ = real_to_integer (&icst, &overflow_p, TYPE_PRECISION (itype));
+ }
+ (switch
+ /* Optimize cases when CST is outside of ITYPE's range. */
+ (if (real_compare (LT_EXPR, cst, &imin))
+ { constant_boolean_node (cmp == GT_EXPR || cmp == GE_EXPR || cmp == NE_EXPR,
+ type); })
+ (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
+ (FTYPE) N == CST -> 0
+ (FTYPE) N != CST -> 1. */
+ (if (cmp == EQ_EXPR || cmp == NE_EXPR)
+ { constant_boolean_node (cmp == NE_EXPR, type); })
+ /* Otherwise replace with sensible integer constant. */
+ (with
+ {
+ gcc_checking_assert (!overflow_p);
+ }
+ (icmp @0 { wide_int_to_tree (itype, icst_val); })))))))))
+
/* Fold A /[ex] B CMP C to A CMP B * C. */
(for cmp (eq ne)
(simplify