re PR tree-optimization/63586 (x+x+x+x -> 4*x in gimple)
authorKugan Vivekanandarajah <kuganv@linaro.org>
Wed, 18 May 2016 00:58:45 +0000 (00:58 +0000)
committerKugan Vivekanandarajah <kugan@gcc.gnu.org>
Wed, 18 May 2016 00:58:45 +0000 (00:58 +0000)
gcc/testsuite/ChangeLog:

2016-05-17  Kugan Vivekanandarajah  <kuganv@linaro.org>

PR middle-end/63586
* gcc.dg/tree-ssa/pr63586-2.c: New test.
* gcc.dg/tree-ssa/pr63586.c: New test.
* gcc.dg/tree-ssa/reassoc-14.c: Adjust multiplication count.

gcc/ChangeLog:

2016-05-17  Kugan Vivekanandarajah  <kuganv@linaro.org>

PR middle-end/63586
* tree-ssa-reassoc.c (transform_add_to_multiply): New.
(reassociate_bb): Call transform_add_to_multiply.

From-SVN: r236356

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/reassoc-14.c
gcc/tree-ssa-reassoc.c

index 1404d22cc46852c6f77666c2e66fcd6aed631794..2f294c89fdf60e5f698f887eb5266cfb543e298e 100644 (file)
@@ -1,3 +1,9 @@
+2016-05-17  Kugan Vivekanandarajah  <kuganv@linaro.org>
+
+       PR middle-end/63586
+       * tree-ssa-reassoc.c (transform_add_to_multiply): New.
+       (reassociate_bb): Call transform_add_to_multiply.
+
 2016-05-17  Kugan Vivekanandarajah  <kuganv@linaro.org>
 
        * config/aarch64/aarch64.c (all_extensions): Removed unused static variable.
index e803bd634348e3a527edd82efda9dc5d912579ee..87fd63a1d77a8f62e6221df723aa5b123331e3f4 100644 (file)
@@ -1,3 +1,10 @@
+2016-05-17  Kugan Vivekanandarajah  <kuganv@linaro.org>
+
+       PR middle-end/63586
+       * gcc.dg/tree-ssa/pr63586-2.c: New test.
+       * gcc.dg/tree-ssa/pr63586.c: New test.
+       * gcc.dg/tree-ssa/reassoc-14.c: Adjust multiplication count.
+
 2016-05-17  Nathan Sidwell  <nathan@acm.org>
 
        * gcc.c-torture/execute/20030222-1.c: Skip on ptx.
index 62802d16ed30fafc3d80eab72cb7503d10f452ae..16ebc86133fac199d90a761679756219b7272b64 100644 (file)
@@ -19,6 +19,7 @@ unsigned int test2 (unsigned int x, unsigned int y, unsigned int z,
   return tmp1 + tmp2 + tmp3;
 }
 
-/* There should be one multiplication left in test1 and three in test2.  */
+/* There should be two multiplication left in test1 (inculding one generated
+   when converting addition to multiplication) and three in test2.  */
 
-/* { dg-final { scan-tree-dump-times "\\\*" 4 "reassoc1" } } */
+/* { dg-final { scan-tree-dump-times "\\\*" 5 "reassoc1" } } */
index 740897756bd59a59c115e64d0fb9a2153510622c..3b5f36bf1e45c5ef7c9a5f7205394a002a99a72c 100644 (file)
@@ -1756,6 +1756,82 @@ eliminate_redundant_comparison (enum tree_code opcode,
   return false;
 }
 
+/* Transform repeated addition of same values into multiply with
+   constant.  */
+static bool
+transform_add_to_multiply (gimple *stmt, vec<operand_entry *> *ops)
+{
+  operand_entry *oe;
+  tree op = NULL_TREE;
+  int j;
+  int i, start = -1, end = 0, count = 0;
+  vec<std::pair <int, int> > indxs = vNULL;
+  bool changed = false;
+
+  if (!INTEGRAL_TYPE_P (TREE_TYPE ((*ops)[0]->op))
+      && !flag_unsafe_math_optimizations)
+    return false;
+
+  /* Look for repeated operands.  */
+  FOR_EACH_VEC_ELT (*ops, i, oe)
+    {
+      if (start == -1)
+       {
+         count = 1;
+         op = oe->op;
+         start = i;
+       }
+      else if (operand_equal_p (oe->op, op, 0))
+       {
+         count++;
+         end = i;
+       }
+      else
+       {
+         if (count > 1)
+           indxs.safe_push (std::make_pair (start, end));
+         count = 1;
+         op = oe->op;
+         start = i;
+       }
+    }
+
+  if (count > 1)
+    indxs.safe_push (std::make_pair (start, end));
+
+  for (j = indxs.length () - 1; j >= 0; --j)
+    {
+      /* Convert repeated operand addition to multiplication.  */
+      start = indxs[j].first;
+      end = indxs[j].second;
+      op = (*ops)[start]->op;
+      count = end - start + 1;
+      for (i = end; i >= start; --i)
+       ops->unordered_remove (i);
+      tree tmp = make_ssa_name (TREE_TYPE (op));
+      tree cst = build_int_cst (integer_type_node, count);
+      gimple *def_stmt = SSA_NAME_DEF_STMT (op);
+      gassign *mul_stmt
+       = gimple_build_assign (tmp, MULT_EXPR,
+                              op, fold_convert (TREE_TYPE (op), cst));
+      if (gimple_code (def_stmt) == GIMPLE_NOP
+         || gimple_bb (stmt) != gimple_bb (def_stmt))
+       {
+         gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+         gimple_set_uid (mul_stmt, gimple_uid (stmt));
+         gsi_insert_before (&gsi, mul_stmt, GSI_NEW_STMT);
+       }
+      else
+       insert_stmt_after (mul_stmt, def_stmt);
+      gimple_set_visited (mul_stmt, true);
+      add_to_ops_vec (ops, tmp);
+      changed = true;
+    }
+
+  return changed;
+}
+
+
 /* Perform various identities and other optimizations on the list of
    operand entries, stored in OPS.  The tree code for the binary
    operation between all the operands is OPCODE.  */
@@ -5110,6 +5186,10 @@ reassociate_bb (basic_block bb)
                  optimize_ops_list (rhs_code, &ops);
                }
 
+             if (rhs_code == PLUS_EXPR
+                 && transform_add_to_multiply (stmt, &ops))
+               ops.qsort (sort_by_operand_rank);
+
              if (rhs_code == BIT_IOR_EXPR || rhs_code == BIT_AND_EXPR)
                {
                  if (is_vector)