diff options
author | Yury Gribov <tetra2005@gmail.com> | 2017-08-04 20:29:12 +0000 |
---|---|---|
committer | Yury Gribov <ygribov@gcc.gnu.org> | 2017-08-04 20:29:12 +0000 |
commit | c779bea5b977aa3df19c965c4866c6c20ad258c8 (patch) | |
tree | 1d204f2e5879f51d432b6570c00672fc37d7a27d /gcc/match.pd | |
parent | e52341f1613a7589425d6eba31a6d5e0500465bd (diff) | |
download | gcc-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.pd | 74 |
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 |