tree-ssa-reassoc.c (find_insert_point): New function.
authorEaswaran Raman <eraman@gcc.gnu.org>
Sat, 18 May 2013 01:35:04 +0000 (01:35 +0000)
committerEaswaran Raman <eraman@gcc.gnu.org>
Sat, 18 May 2013 01:35:04 +0000 (01:35 +0000)
2013-05-17   Easwaran Raman  <eraman@google.com>

        * tree-ssa-reassoc.c (find_insert_point): New function.
        (insert_stmt_after): Likewise.
        (get_def_stmt): Likewise.
        (ensure_ops_are_available): Likewise.
        (not_dominated_by): Likewise.
        (rewrite_expr_tree): Do not move statements beyond what is
        necessary. Remove call to swap_ops_for_binary_stmt...
        (reassociate_bb): ... and move it here.
        (build_and_add_sum): Assign UIDs for new statements.
        (linearize_expr): Likewise.
        (do_reassoc): Renumber gimple statement UIDs.

testsuite/ChangeLog:

2013-05-17   Easwaran Raman  <eraman@google.com>

        * gcc.dg/tree-ssa/reassoc-28.c: New testcase.

From-SVN: r199048

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c [new file with mode: 0644]
gcc/tree-ssa-reassoc.c

index 5cc09ae4dddcbfe73a81d9f95175df3adb63d5ef..4536e6279a138265e65e80cc5b5467b1c75272d0 100644 (file)
@@ -1,3 +1,17 @@
+2013-05-17   Easwaran Raman  <eraman@google.com>
+
+       * tree-ssa-reassoc.c (find_insert_point): New function.
+       (insert_stmt_after): Likewise.
+       (get_def_stmt): Likewise.
+       (ensure_ops_are_available): Likewise.
+       (not_dominated_by): Likewise.
+       (rewrite_expr_tree): Do not move statements beyond what is
+       necessary. Remove call to swap_ops_for_binary_stmt...
+       (reassociate_bb): ... and move it here.
+       (build_and_add_sum): Assign UIDs for new statements.
+       (linearize_expr): Likewise.
+       (do_reassoc): Renumber gimple statement UIDs.
+
 2013-05-17  Jan Hubicka  <jh@suse.cz>
 
        * lto-symtab.c (lto_symtab_merge_cgraph_nodes): Resolve cross module
 
        * Makefile.in (tree-switch-conversion.o): Depend on $(OPTABS_H).
 
+>>>>>>> .r199043
 2013-05-16  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/driver-i386.c (host_detect_local_cpu): Determine
index ec5cbde7329991765b9ed6d35053cd141ed9c539..6fd1b2ed3a680fd282371d4263fb270ce9a8ac8e 100644 (file)
@@ -1,3 +1,7 @@
+2013-05-17   Easwaran Raman  <eraman@google.com>
+
+       * gcc.dg/tree-ssa/reassoc-28.c: New testcase.
+
 2013-05-17  Marc Glisse  <marc.glisse@inria.fr>
 
        PR testsuite/57313
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c
new file mode 100644 (file)
index 0000000..3d10b49
--- /dev/null
@@ -0,0 +1,37 @@
+/* { dg-do run} */
+/* { dg-options "-O2 -fdump-tree-reassoc1-details" } */
+
+#define LENGTH 4
+void abort (void);
+unsigned
+__attribute__ ((noinline))  foo (unsigned char *buf, int n)
+{
+ unsigned sum = 0, i = 0;
+ do {
+   sum +=(buf)[n-1];
+   /* Split the BB to test statements are correctly moved to
+      satisfy dependences.  */
+   if (n > LENGTH)
+     i++;
+   sum += buf[n-2];
+   sum += buf[n-3];
+   sum += buf[n-4];
+   n = n-4;
+ } while (n > 0);
+
+ return sum + i;
+}
+
+unsigned char a[] = {1, 1, 1, 1};
+
+int main() {
+  int sum = foo (a, LENGTH);
+  if (sum != 4)
+    abort ();
+  return 0;
+}
+
+/* Verify one stmt has been moved to another BB to ensure correct dependences.  */
+/* { dg-final { scan-tree-dump-times "to a different BB" 1 "reassoc1"} }*/
+/* { dg-final { scan-tree-dump-times "within same BB" 2 "reassoc1"} }*/
+/* { dg-final { cleanup-tree-dump "reassoc1" } } */
index 4fc19cb551eda29a067b2f656903ed6a03e3ff99..29c9dff2868b68732820e431ecfa248159b836e6 100644 (file)
@@ -1166,6 +1166,7 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
       && (!op2def || gimple_nop_p (op2def)))
     {
       gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
+      gimple_set_uid (sum, gimple_uid (gsi_stmt (gsi)));
       gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
     }
   else if ((!op1def || gimple_nop_p (op1def))
@@ -1175,6 +1176,7 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
       if (gimple_code (op2def) == GIMPLE_PHI)
        {
          gsi = gsi_after_labels (gimple_bb (op2def));
+          gimple_set_uid (sum, gimple_uid (gsi_stmt (gsi)));
          gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
        }
       else
@@ -1182,6 +1184,7 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
          if (!stmt_ends_bb_p (op2def))
            {
              gsi = gsi_for_stmt (op2def);
+              gimple_set_uid (sum, gimple_uid (op2def));
              gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
            }
          else
@@ -1200,6 +1203,7 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
       if (gimple_code (op1def) == GIMPLE_PHI)
        {
          gsi = gsi_after_labels (gimple_bb (op1def));
+          gimple_set_uid (sum, gimple_uid (op1def));
          gsi_insert_before (&gsi, sum, GSI_NEW_STMT);
        }
       else
@@ -1207,6 +1211,7 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode)
          if (!stmt_ends_bb_p (op1def))
            {
              gsi = gsi_for_stmt (op1def);
+              gimple_set_uid (sum, gimple_uid (op1def));
              gsi_insert_after (&gsi, sum, GSI_NEW_STMT);
            }
          else
@@ -2841,6 +2846,135 @@ swap_ops_for_binary_stmt (vec<operand_entry_t> ops,
     }
 }
 
+/* Determine if stmt A is not dominated by stmt B. If A and B are in
+   same basic block, then A's UID has to be less than B. If they are
+   in different BB's, then A's BB must not be dominated by B's BB.  */
+
+static inline bool
+not_dominated_by (gimple a, gimple b)
+{
+  basic_block bb_a, bb_b;
+  bb_a = gimple_bb (a);
+  bb_b = gimple_bb (b);
+  return ((bb_a == bb_b && gimple_uid (a)  < gimple_uid (b))
+          || (bb_a != bb_b
+              && !dominated_by_p (CDI_DOMINATORS, bb_a, bb_b)));
+
+}
+
+/* Find the statement after which STMT must be moved so that the
+   dependency from DEP_STMT to STMT is maintained.  */
+
+static gimple
+find_insert_point (gimple stmt, gimple dep_stmt)
+{
+  gimple insert_stmt = stmt;
+  if (dep_stmt == NULL)
+    return stmt;
+  if (not_dominated_by (insert_stmt, dep_stmt))
+    insert_stmt = dep_stmt;
+  return insert_stmt;
+}
+
+/* Insert STMT after INSERT_POINT.  */
+
+static void
+insert_stmt_after (gimple stmt, gimple insert_point)
+{
+  imm_use_iterator iter;
+  tree lhs;
+  gimple use_stmt;
+  gimple_stmt_iterator gsistmt = gsi_for_stmt (stmt), gsi_insert;
+  basic_block insert_bb = gimple_bb (insert_point);
+  bool insert_bb_different = (insert_bb != gimple_bb (stmt));
+  lhs = gimple_assign_lhs (stmt);
+  /* If there are any debug uses of LHS, reset them.  */
+  FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
+    {
+      if (is_gimple_debug (use_stmt)
+          && not_dominated_by (use_stmt, insert_point))
+        {
+          gimple_debug_bind_reset_value (use_stmt);
+          update_stmt (use_stmt);
+        }
+    }
+  /* If INSERT_STMT is a phi node, then do not insert just after that statement.
+     Instead, find the first non-label gimple statement in BB and insert before
+     that.  */
+  if (gimple_code (insert_point) == GIMPLE_PHI)
+    {
+      gsi_insert = gsi_after_labels (insert_bb);
+      gsi_move_before (&gsistmt, &gsi_insert);
+    }
+  /* Statements marked for throw can not be in the middle of a basic block. So
+     we can not insert a statement (not marked for throw) immediately after.  */
+  else if (stmt_ends_bb_p (insert_point))
+    {
+      edge succ_edge = find_fallthru_edge (insert_bb->succs);
+      insert_bb = succ_edge->dest;
+      insert_bb_different = (insert_bb != gimple_bb (stmt));
+      /* Insert STMT at the beginning of the successor basic block.  */
+      gsi_insert = gsi_after_labels (insert_bb);
+      gsi_move_before (&gsistmt, &gsi_insert);
+    }
+  else
+    {
+      gsi_insert = gsi_for_stmt (insert_point);
+      gsi_move_after (&gsistmt, &gsi_insert);
+    }
+  /* Set the UID of STMT to that of INSERT_POINT so that subsequent comparisons
+     of UIDs to determine dominance within a basic block works.  */
+  gimple_set_uid (stmt, gimple_uid (insert_point));
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "Moved stmt ");
+      print_gimple_stmt (dump_file, stmt, 0, 0);
+      fprintf (dump_file, " %s to satisfy dependences\n",
+               insert_bb_different ? "to a different BB" : "within same BB");
+    }
+
+}
+
+/* If OP is a SSA variable and is not the default definition, return the
+   gimple statement that defines OP. Else return NULL.  */
+
+static inline gimple
+get_def_stmt (tree op)
+{
+  if (TREE_CODE (op) == SSA_NAME
+      && !SSA_NAME_IS_DEFAULT_DEF (op))
+    return SSA_NAME_DEF_STMT (op);
+  else
+    return NULL;
+}
+
+/* Ensure that operands in the OPS vector are available for STMT and all
+   gimple statements on which STMT depends.  */
+
+static void
+ensure_ops_are_available (gimple stmt, vec<operand_entry_t> ops, int opindex)
+{
+  unsigned int len = ops.length ();
+  gimple insert_stmt = stmt;
+  gimple dep_stmts[2];
+  dep_stmts[0] = get_def_stmt (ops[opindex]->op);
+  if (len - opindex == 2)
+    {
+      dep_stmts[1] = get_def_stmt (ops[opindex + 1]->op);
+    }
+  else
+    {
+      gimple stmt1 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt));
+      ensure_ops_are_available (stmt1, ops, opindex + 1);
+      dep_stmts[1] = stmt1;
+    }
+  for (int i = 0; i < 2; i++)
+    insert_stmt = find_insert_point (insert_stmt, dep_stmts[i]);
+
+  if (insert_stmt != stmt)
+    insert_stmt_after (stmt, insert_stmt);
+}
+
 /* Recursively rewrite our linearized statements so that the operators
    match those in OPS[OPINDEX], putting the computation in rank
    order.  */
@@ -2853,11 +2987,6 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
   tree rhs2 = gimple_assign_rhs2 (stmt);
   operand_entry_t oe;
 
-  /* If we have three operands left, then we want to make sure the ones
-     that get the double binary op are chosen wisely.  */
-  if (opindex + 3 == ops.length ())
-    swap_ops_for_binary_stmt (ops, opindex, stmt);
-
   /* The final recursion case for this function is that you have
      exactly two operations left.
      If we had one exactly one op in the entire list to start with, we
@@ -2903,20 +3032,7 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
     {
       if (!moved)
        {
-         gimple_stmt_iterator gsinow, gsirhs1;
-         gimple stmt1 = stmt, stmt2;
-         unsigned int count;
-
-         gsinow = gsi_for_stmt (stmt);
-         count = ops.length () - opindex - 2;
-         while (count-- != 0)
-           {
-             stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
-             gsirhs1 = gsi_for_stmt (stmt2);
-             gsi_move_before (&gsirhs1, &gsinow);
-             gsi_prev (&gsinow);
-             stmt1 = stmt2;
-           }
+          ensure_ops_are_available (stmt, ops, opindex);
          moved = true;
        }
 
@@ -3128,6 +3244,7 @@ linearize_expr (gimple stmt)
   gsinow = gsi_for_stmt (stmt);
   gsirhs = gsi_for_stmt (binrhs);
   gsi_move_before (&gsirhs, &gsinow);
+  gimple_set_uid (binrhs, gimple_uid (stmt));
 
   gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
   gimple_assign_set_rhs1 (binrhs, gimple_assign_lhs (binlhs));
@@ -4134,7 +4251,16 @@ reassociate_bb (basic_block bb)
                      && ops.length () > 3)
                    rewrite_expr_tree_parallel (stmt, width, ops);
                  else
-                   rewrite_expr_tree (stmt, 0, ops, false);
+                    {
+                      /* When there are three operands left, we want
+                         to make sure the ones that get the double
+                         binary op are chosen wisely.  */
+                      int len = ops.length ();
+                      if (len >= 3)
+                        swap_ops_for_binary_stmt (ops, len - 3, stmt);
+
+                     rewrite_expr_tree (stmt, 0, ops, false);
+                    }
 
                  /* If we combined some repeated factors into a 
                     __builtin_powi call, multiply that result by the
@@ -4195,6 +4321,7 @@ static void
 do_reassoc (void)
 {
   break_up_subtract_bb (ENTRY_BLOCK_PTR);
+  renumber_gimple_stmt_uids ();
   reassociate_bb (EXIT_BLOCK_PTR);
 }