To...
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 13 Oct 2015 07:34:41 +0000 (07:34 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 13 Oct 2015 07:34:41 +0000 (07:34 +0000)
To: gcc-patches@gcc.gnu.org
Subject: Add an extra pow rule to match.pd
From: Richard Sandiford <richard.sandiford@arm.com>
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
gcc/match.pd
gcc/real.c
gcc/real.h

index a8650439eef6e3b1fc77b31a80ae298992175916..9fcea2965a79fd8f4fc2a83bd684cd11f78ee464 100644 (file)
@@ -1,3 +1,10 @@
+2015-10-13  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * 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  <hubicka@ucw.cz>
 
        revert:
index b02dd03430d0d71fac989da16c7cf0f552dc5b4f..6714796943e38bb2051afe65cb76420733ce1518 100644 (file)
@@ -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)
index f633ffd2e88fb9afb6c60136e3355463f46fa062..85ac83d3fdca5163d4764fb4065400c4717bb4da 100644 (file)
@@ -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
index 706859b6c64dadfb491bc43e3f985a25dcf5a926..e65b5263e11add52d08ddfd936abf1e3a459d698 100644 (file)
@@ -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