From 9b054b08813d37586d6765fd087b0fc85dc94daf Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 13 Oct 2015 07:34:41 +0000 Subject: [PATCH] To... To: gcc-patches@gcc.gnu.org Subject: Add an extra pow rule to match.pd From: Richard Sandiford Gcc: private.sent --text follows this line-- Simplify pow(|x|,y) and pow(-x,y) to pow(x,y) if y is an even integer. At the moment this duplicates a case in fold_builtin_pow, but an upcoming patch will move all the fold_builtin_pow rules to match.pd. I'm doing this one early to fix a regression in builtin-10.c for soft-float ARM. gcc/ * real.h (real_isinteger): Declare. * real.c (real_isinteger): New function. * match.pd: Simplify pow(|x|,y) and pow(-x,y) to pow(x,y) if y is an even integer. From-SVN: r228750 --- gcc/ChangeLog | 7 +++++++ gcc/match.pd | 17 ++++++++++++----- gcc/real.c | 18 ++++++++++++++++++ gcc/real.h | 3 ++- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a865043..9fcea29 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2015-10-13 Richard Sandiford + + * real.h (real_isinteger): Declare. + * real.c (real_isinteger): New function. + * match.pd: Simplify pow(|x|,y) and pow(-x,y) to pow(x,y) + if y is an even integer. + 2015-10-11 Jan Hubicka revert: diff --git a/gcc/match.pd b/gcc/match.pd index b02dd03..6714796 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -309,12 +309,19 @@ along with GCC; see the file COPYING3. If not see && TYPE_OVERFLOW_UNDEFINED (type)) @0))) -/* Simplify cos (-x) -> cos (x). */ (for op (negate abs) -(for coss (COS COSH) - (simplify - (coss (op @0)) - (coss @0)))) + /* Simplify cos(-x) and cos(|x|) -> cos(x). Similarly for cosh. */ + (for coss (COS COSH) + (simplify + (coss (op @0)) + (coss @0))) + /* Simplify pow(-x, y) and pow(|x|,y) -> pow(x,y) if y is an even integer. */ + (for pows (POW) + (simplify + (pows (op @0) REAL_CST@1) + (with { HOST_WIDE_INT n; } + (if (real_isinteger (&TREE_REAL_CST (@1), &n) && (n & 1) == 0) + (pows @0 @1)))))) /* X % Y is smaller than Y. */ (for cmp (lt ge) diff --git a/gcc/real.c b/gcc/real.c index f633ffd..85ac83d 100644 --- a/gcc/real.c +++ b/gcc/real.c @@ -4997,6 +4997,24 @@ real_isinteger (const REAL_VALUE_TYPE *c, machine_mode mode) return real_identical (c, &cint); } +/* Check whether C is an integer that fits in a HOST_WIDE_INT, + storing it in *INT_OUT if so. */ + +bool +real_isinteger (const REAL_VALUE_TYPE *c, HOST_WIDE_INT *int_out) +{ + REAL_VALUE_TYPE cint; + + HOST_WIDE_INT n = real_to_integer (c); + real_from_integer (&cint, VOIDmode, n, SIGNED); + if (real_identical (c, &cint)) + { + *int_out = n; + return true; + } + return false; +} + /* Write into BUF the maximum representable finite floating-point number, (1 - b**-p) * b**emax for a given FP format FMT as a hex float string. LEN is the size of BUF, and the buffer must be large diff --git a/gcc/real.h b/gcc/real.h index 706859b..e65b526 100644 --- a/gcc/real.h +++ b/gcc/real.h @@ -467,7 +467,8 @@ extern void real_round (REAL_VALUE_TYPE *, machine_mode, extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); /* Check whether the real constant value given is an integer. */ -extern bool real_isinteger (const REAL_VALUE_TYPE *c, machine_mode mode); +extern bool real_isinteger (const REAL_VALUE_TYPE *, machine_mode); +extern bool real_isinteger (const REAL_VALUE_TYPE *, HOST_WIDE_INT *); /* Write into BUF the maximum representable finite floating-point number, (1 - b**-p) * b**emax for a given FP format FMT as a hex -- 2.7.4