Canonicalize constant multiplies in division
authorWilco Dijkstra <wdijkstr@arm.com>
Thu, 16 Nov 2017 11:54:49 +0000 (11:54 +0000)
committerWilco Dijkstra <wilco@gcc.gnu.org>
Thu, 16 Nov 2017 11:54:49 +0000 (11:54 +0000)
This patch implements some of the optimizations discussed in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71026.

Canonicalize x / (C1 * y) into (x * C2) / y.

This moves constant multiplies out of the RHS of a division in order
to allow further simplifications (such as (C1 * x) / (C2 * y) ->
(C3 * x) / y) and to enable more reciprocal CSEs.

2017-11-16  Wilco Dijkstra  <wdijkstr@arm.com>
    Jackson Woodruff  <jackson.woodruff@arm.com>

    gcc/
PR tree-optimization/71026
* match.pd: Canonicalize constant multiplies in division.

    gcc/testsuite/
PR tree-optimization/71026
* gcc.dg/cse_recip.c: New test.

Co-Authored-By: Jackson Woodruff <jackson.woodruff@arm.com>
From-SVN: r254816

gcc/ChangeLog
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/cse_recip.c [new file with mode: 0644]

index f9a429369d6a869bdf2df735adcf4591a34cc297..aaaa6389856d64f5a4db8ad327d5f9d5e0ffd0c1 100644 (file)
@@ -1,3 +1,9 @@
+2017-11-16  Wilco Dijkstra  <wdijkstr@arm.com>
+           Jackson Woodruff  <jackson.woodruff@arm.com>
+
+       PR tree-optimization/71026
+       * match.pd: Canonicalize constant multiplies in division.
+
 2017-11-16  Wilco Dijkstra  <wdijkstr@arm.com>
 
        * opts.c (default_options_table): Add OPT_fomit_frame_pointer entry.
index 2557f08ad35e69d51e6a985886a1a33dd9d6fce4..0e21a0d8d8ff478c122a199d4b4a93f701d6466a 100644 (file)
@@ -344,10 +344,18 @@ 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). */
  (simplify
   (rdiv (rdiv:s @0 @1) @2)
-   (rdiv @0 (mult @1 @2)))
+  (rdiv @0 (mult @1 @2)))
+
+ /* Canonicalize x / (C1 * y) to (x * C2) / y.  */
+ (simplify
+  (rdiv @0 (mult:s @1 REAL_CST@2))
+  (with
+   { tree tem = const_binop (RDIV_EXPR, type, build_one_cst (type), @2); }
+   (if (tem)
+    (rdiv (mult @0 { tem; } ) @1))))
 
  /* Convert A/(B/C) to (A/B)*C  */
  (simplify
@@ -633,15 +641,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (if (tem)
      (rdiv { tem; } @1)))))
 
-/* Convert C1/(X*C2) into (C1/C2)/X  */
-(simplify
- (rdiv REAL_CST@0 (mult @1 REAL_CST@2))
-  (if (flag_reciprocal_math)
-   (with
-    { tree tem = const_binop (RDIV_EXPR, type, @0, @2); }
-    (if (tem)
-     (rdiv { tem; } @1)))))
-
 /* Simplify ~X & X as zero.  */
 (simplify
  (bit_and:c (convert? @0) (convert? (bit_not @0)))
index 2c3e979ce95dc19dc17a85ba0b7cc9e8cc417af3..57bdc1c5ccc3c101e2e6122a3bc319a8301f3186 100644 (file)
@@ -1,3 +1,9 @@
+2017-11-16  Wilco Dijkstra  <wdijkstr@arm.com>
+           Jackson Woodruff  <jackson.woodruff@arm.com>
+
+       PR tree-optimization/71026
+       * gcc.dg/cse_recip.c: New test.
+
 2017-11-16  Wilco Dijkstra  <wdijkstr@arm.com>
 
        * gcc.target/aarch64/lr_free_2.c: Fix test.
diff --git a/gcc/testsuite/gcc.dg/cse_recip.c b/gcc/testsuite/gcc.dg/cse_recip.c
new file mode 100644 (file)
index 0000000..88cba99
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-optimized-raw" } */
+
+void
+cse_recip (float x, float y, float *a)
+{
+  a[0] = y / (5 * x);
+  a[1] = y / (3 * x);
+  a[2] = y / x;
+}
+
+/* { dg-final { scan-tree-dump-times "rdiv_expr" 1 "optimized" } } */