Factor out division by squares and remove division around comparisons (1/2)

Message ID 67e59ce0-12c4-cc34-00f9-edd02d2d341e@foss.arm.com
State New
Headers show

Commit Message

Jackson Woodruff Aug. 10, 2017, 2:10 p.m.
And have now attached that patch.

Jackson


On 08/10/2017 03:09 PM, Jackson Woodruff wrote:
> Hi all,
>
> The patch implements the division opitmizations discussed in
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71026 .
>
> The implemented change differs slightly from the
> proposed one in that we re-associate:
>
>     C / x comparison 0.0 -> x comparison' 0.0
>
> Where C is any constant and comparison' is changed as
> appropriate if C is negative.
>
> The implementations also removes the division from:
>
>     x / C comparison 0.0 -> x comparison' 0.0
>
> Where again, comparison' is changed as appropriate if C is
> negative.
>
> We also change the association of
>
>      x / (y * C) -> (x / C) / y
>
> If C is a constant. All of the above require
> -funsafe-math-optimizations.
>
> We also change:
>
>   x / (- y) -> (-x) / y
>
> Which requires -fno-trapping-math.
>
> Bootstrapped and regtested (with part 2 of this patch) on aarch64.
>
> OK for trunk?
>
> (Apologies if the recipients in the 'to' field received this twice,
> I accidentally sent this from an email gcc-patches doesn't accept)
>
> Jackson
>
> gcc/
>
> 2017-08-03  Jackson Woodruff  <jackson.woodruff@arm.com>
>
>     PR 71026/tree-optimization
>     * match.pd: New patterns.
>
>
> gcc/testsuite
>
> 2017-08-03  Jackson Woodruff  <jackson.woodruff@arm.com>
>
>     PR 71026/tree-optimization
>     * gcc.dg/associate_comparison_1.c: New.
>     * gcc.dg/associate_division_2.c: New.
>

Comments

Joseph Myers Aug. 10, 2017, 10:03 p.m. | #1
On Thu, 10 Aug 2017, Jackson Woodruff wrote:

> > We also change:
> > 
> >   x / (- y) -> (-x) / y
> > 
> > Which requires -fno-trapping-math.

I don't see why that requires -fno-trapping-math.  The exceptions should 
be identical from both variants, as should the result, as far as defined 
by C or IEEE 754 (it's possible it might affect the sign of a NaN result 
on some architectures, but only where that sign is unspecified in C and 
IEEE 754 terms, so such a change is OK).

Patch

diff --git a/gcc/match.pd b/gcc/match.pd
index e98db52af84946cf579c6434e06d450713a47162..7abfd11601a956ecb59c945256c9f30dc0b6f6c9 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -342,16 +342,42 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (negate @0)))
 
 (if (flag_reciprocal_math)
- /* Convert (A/B)/C to A/(B*C)  */
+ /* Convert (A/B)/C to A/(B*C) where B is not a constant.  */
  (simplify
   (rdiv (rdiv:s @0 @1) @2)
-   (rdiv @0 (mult @1 @2)))
+   (if (TREE_CODE (@1) != REAL_CST)
+    (rdiv @0 (mult @1 @2))))
+
+ /* Simplify x / (C * y) to (x / C) / y where C is a constant.  */
+ (simplify
+  (rdiv @0
+   (mult @1 REAL_CST@2))
+  (rdiv (rdiv @0 @2) @1))
 
  /* Convert A/(B/C) to (A/B)*C  */
  (simplify
   (rdiv @0 (rdiv:s @1 @2))
    (mult (rdiv @0 @1) @2)))
 
+(if (!flag_trapping_math)
+  /* Simplify x / (- y) to -x / y.  */
+  (simplify
+    (rdiv @0 (negate @1))
+    (rdiv (negate @0) @1)))
+
+(if (flag_unsafe_math_optimizations)
+  /* Simplify (C / x op 0.0) to x op 0.0 for C > 0.  */
+  (for op (lt le gt ge)
+	   neg_op (gt ge lt le)
+    (simplify
+      (op (rdiv REAL_CST@0 @1) real_zerop@2)
+      (switch
+       (if (!real_equal (TREE_REAL_CST_PTR (@0), &dconst0)
+	    && !REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
+	(op @1 @2))
+       (if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@0)))
+	(neg_op @1 @2))))))
+
 /* Optimize (X & (-A)) / A where A is a power of 2, to X >> log2(A) */
 (for div (trunc_div ceil_div floor_div round_div exact_div)
  (simplify
@@ -3446,6 +3472,21 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (if (!HONOR_SNANS (type))
    @0))
 
+ /* Simplify (x * C1) cmp C2 -> x cmp C2 / C1
+    and simplify (x / C1) cmp C2 -> x cmp C2 * C1.  */
+ (for cmp (lt le gt ge)
+      neg_cmp (gt ge lt le)
+  (for op (mult rdiv)
+       inv_op (rdiv mult)
+      (simplify
+       (cmp (op @0 REAL_CST@1) REAL_CST@2)
+       (switch
+	(if (!real_equal (TREE_REAL_CST_PTR (@1), &dconst0)
+	     && !REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1)))
+	 (cmp @0 (inv_op @2 @1)))
+	(if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (@1)))
+	 (neg_cmp @0 (inv_op @2 @1)))))))
+
  /* Simplify sqrt(x) * sqrt(y) -> sqrt(x*y).  */
  (for root (SQRT CBRT)
   (simplify
diff --git a/gcc/testsuite/gcc.dg/associate_comparison_1.c b/gcc/testsuite/gcc.dg/associate_comparison_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..c12e5cfb2a8388068fa1731cc2305f9fe5139fd6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/associate_comparison_1.c
@@ -0,0 +1,17 @@ 
+/* { dg-do compile } */
+/* { dg-options "-funsafe-math-optimizations -fdump-tree-optimized" } */
+
+int
+lt_cmp (float x, float y)
+{
+  return x / 2 <= 0;
+}
+
+int
+inv_cmp (float x, float y)
+{
+  return 5 / x >= 0;
+}
+
+
+/* { dg-final { scan-tree-dump-not " / " "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/associate_division_2.c b/gcc/testsuite/gcc.dg/associate_division_2.c
new file mode 100644
index 0000000000000000000000000000000000000000..1f9c1741ce980f1148016e37399134aa8a619b1d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/associate_division_2.c
@@ -0,0 +1,13 @@ 
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-optimized" } */
+
+float
+neg_mov (float w, float x, float *y, float *z)
+{
+  *z = x / (- w);
+  *y = 3 / w;
+
+  return 5 / w;
+}
+
+/* { dg-final { scan-tree-dump-times " / " 1 "optimized" } } */