re PR rtl-optimization/44214 (Compiler does not optimize vector divide with -frecipro...
authorBill Schmidt <wschmidt@linux.vnet.ibm.com>
Fri, 20 Apr 2012 14:19:13 +0000 (14:19 +0000)
committerWilliam Schmidt <wschmidt@gcc.gnu.org>
Fri, 20 Apr 2012 14:19:13 +0000 (14:19 +0000)
gcc:

2012-04-20  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

PR rtl-optimization/44214
* fold-const.c (exact_inverse): New function.
(fold_binary_loc): Fold vector and complex division by constant into
multiply by recripocal with flag_reciprocal_math; fold vector division
by constant into multiply by reciprocal with exact inverse.

gcc/testsuite:

2012-04-20  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

PR rtl-optimization/44214
* gcc.dg/pr44214-1.c: New test.
* gcc.dg/pr44214-2.c: Likewise.
* gcc.dg/pr44214-3.c: Likewise.

From-SVN: r186625

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr44214-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr44214-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr44214-3.c [new file with mode: 0644]

index 557968c3a353cd0659c9d5eabb23a01446b8e0ea..0a3eda63c1acef8f721f45af2f9a58ceaaee19cd 100644 (file)
@@ -1,3 +1,11 @@
+2012-04-20  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
+
+       PR rtl-optimization/44214
+       * fold-const.c (exact_inverse): New function.
+       (fold_binary_loc): Fold vector and complex division by constant into
+       multiply by recripocal with flag_reciprocal_math; fold vector division
+       by constant into multiply by reciprocal with exact inverse.
+
 2012-04-20  Jan Hubicka  <jh@suse.cz>
 
        * lto-symtab.c (lto_cgraph_replace_node): Merge needed instead of force flags.
index 8aceb733e7d14cc8cf9723423ebc378ef30e8d81..fa75fdbec360c3b9a57626cef1b6ab7e5187dd80 100644 (file)
@@ -9693,6 +9693,48 @@ fold_addr_of_array_ref_difference (location_t loc, tree type,
   return NULL_TREE;
 }
 
+/* If the real or vector real constant CST of type TYPE has an exact
+   inverse, return it, else return NULL.  */
+
+static tree
+exact_inverse (tree type, tree cst)
+{
+  REAL_VALUE_TYPE r;
+  tree unit_type, *elts;
+  enum machine_mode mode;
+  unsigned vec_nelts, i;
+
+  switch (TREE_CODE (cst))
+    {
+    case REAL_CST:
+      r = TREE_REAL_CST (cst);
+
+      if (exact_real_inverse (TYPE_MODE (type), &r))
+       return build_real (type, r);
+
+      return NULL_TREE;
+
+    case VECTOR_CST:
+      vec_nelts = VECTOR_CST_NELTS (cst);
+      elts = XALLOCAVEC (tree, vec_nelts);
+      unit_type = TREE_TYPE (type);
+      mode = TYPE_MODE (unit_type);
+
+      for (i = 0; i < vec_nelts; i++)
+       {
+         r = TREE_REAL_CST (VECTOR_CST_ELT (cst, i));
+         if (!exact_real_inverse (mode, &r))
+           return NULL_TREE;
+         elts[i] = build_real (unit_type, r);
+       }
+
+      return build_vector (type, elts);
+
+    default:
+      return NULL_TREE;
+    }
+}
+
 /* Fold a binary expression of code CODE and type TYPE with operands
    OP0 and OP1.  LOC is the location of the resulting expression.
    Return the folded expression if folding is successful.  Otherwise,
@@ -11734,23 +11776,24 @@ fold_binary_loc (location_t loc,
         so only do this if -freciprocal-math.  We can actually
         always safely do it if ARG1 is a power of two, but it's hard to
         tell if it is or not in a portable manner.  */
-      if (TREE_CODE (arg1) == REAL_CST)
+      if (optimize
+         && (TREE_CODE (arg1) == REAL_CST
+             || (TREE_CODE (arg1) == COMPLEX_CST
+                 && COMPLEX_FLOAT_TYPE_P (TREE_TYPE (arg1)))
+             || (TREE_CODE (arg1) == VECTOR_CST
+                 && VECTOR_FLOAT_TYPE_P (TREE_TYPE (arg1)))))
        {
          if (flag_reciprocal_math
-             && 0 != (tem = const_binop (code, build_real (type, dconst1),
-                                         arg1)))
+             && 0 != (tem = const_binop (code, build_one_cst (type), arg1)))
            return fold_build2_loc (loc, MULT_EXPR, type, arg0, tem);
-         /* Find the reciprocal if optimizing and the result is exact.  */
-         if (optimize)
+         /* Find the reciprocal if optimizing and the result is exact.
+            TODO: Complex reciprocal not implemented.  */
+         if (TREE_CODE (arg1) != COMPLEX_CST)
            {
-             REAL_VALUE_TYPE r;
-             r = TREE_REAL_CST (arg1);
-             if (exact_real_inverse (TYPE_MODE(TREE_TYPE(arg0)), &r))
-               {
-                 tem = build_real (type, r);
-                 return fold_build2_loc (loc, MULT_EXPR, type,
-                                     fold_convert_loc (loc, type, arg0), tem);
-               }
+             tree inverse = exact_inverse (TREE_TYPE (arg0), arg1);
+
+             if (inverse)
+               return fold_build2_loc (loc, MULT_EXPR, type, arg0, inverse);
            }
        }
       /* Convert A/B/C to A/(B*C).  */
index 1cfffd8e7f7ae9bf632fe869d2aaa8d9bf7754f6..e8d4f0dd5453627b3f2563534ea2842de9860831 100644 (file)
@@ -1,3 +1,10 @@
+2012-04-20  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
+
+       PR rtl-optimization/44214
+       * gcc.dg/pr44214-1.c: New test.
+       * gcc.dg/pr44214-2.c: Likewise.
+       * gcc.dg/pr44214-3.c: Likewise.
+
 2012-04-20  Richard Guenther  <rguenther@suse.de>
 
        * g++.dg/torture/20120420-1.C: New testcase.
diff --git a/gcc/testsuite/gcc.dg/pr44214-1.c b/gcc/testsuite/gcc.dg/pr44214-1.c
new file mode 100644 (file)
index 0000000..292ce57
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -freciprocal-math -fdump-tree-ccp1" } */
+
+typedef double v2df __attribute__ ((vector_size (16)));
+
+void do_div (v2df *a, v2df *b)
+{
+  *a = *b / (v2df) { 2.0, 3.0 };
+}
+
+/* Constant folding should multiply *b by the reciprocals of the
+   vector elements.  The fold does not take place for generic
+   vectors until the first CCP pass.  The string " * " occurs 3
+   times:  one multiply and two indirect parameters.  */
+
+/* { dg-final { scan-tree-dump-times " \\\* " 3 "ccp1" } } */
+/* { dg-final { scan-tree-dump-times " / " 0 "ccp1" } } */
+/* { dg-final { cleanup-tree-dump "ccp1" } } */
diff --git a/gcc/testsuite/gcc.dg/pr44214-2.c b/gcc/testsuite/gcc.dg/pr44214-2.c
new file mode 100644 (file)
index 0000000..7e8581a
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -freciprocal-math -fdump-tree-original" } */
+
+void do_div (_Complex double *a, _Complex double *b)
+{
+  *a = *b / (4.0 - 5.0fi);
+}
+
+/* Constant folding should multiply *b by the reciprocal of 4 - 5i
+   = 4/41 + (5/41)i.  */
+
+/* { dg-final { scan-tree-dump-times " \\\* " 1 "original" } } */
+/* { dg-final { scan-tree-dump-times " / " 0 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
diff --git a/gcc/testsuite/gcc.dg/pr44214-3.c b/gcc/testsuite/gcc.dg/pr44214-3.c
new file mode 100644 (file)
index 0000000..46d5ee8
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ccp1" } */
+
+typedef double v2df __attribute__ ((vector_size (16)));
+
+void do_div (v2df *a, v2df *b)
+{
+  *a = *b / (v2df) { 2.0, 2.0 };
+}
+
+/* Since 2.0 has an exact reciprocal, constant folding should multiply *b
+   by the reciprocals of the vector elements.  As a result there should be
+   one vector multiply and zero divides in the optimized code.  The fold
+   does not take place for generic vectors until the first CCP pass.  The
+   string " * " occurs 3 times:  one multiply and two indirect parameters.  */
+
+/* { dg-final { scan-tree-dump-times " \\\* " 3 "ccp1" } } */
+/* { dg-final { scan-tree-dump-times " / " 0 "ccp1" } } */
+/* { dg-final { cleanup-tree-dump "ccp1" } } */