Fix PR tree-optimization/20703 Fix PR tree-optimization/20725
authorDaniel Berlin <dberlin@dberlin.org>
Mon, 4 Apr 2005 19:02:16 +0000 (19:02 +0000)
committerDaniel Berlin <dberlin@gcc.gnu.org>
Mon, 4 Apr 2005 19:02:16 +0000 (19:02 +0000)
2005-04-02  Daniel Berlin  <dberlin@dberlin.org>
    Diego Novillo <dnovillo@redhat.com>

Fix PR tree-optimization/20703
Fix PR tree-optimization/20725

* tree-ssa-pre.c (phi_translate): Handle tcc_comparison.
(create_expression_by_pieces): Ditto.
(valid_in_set): Ditto. Also handle tcc_declaration.
(find_or_generate_expression): Handle comparison class.
(insert_into_preds_of_block): Ditto.
(insert_aux): Ditto.
(create_value_expr_from): Handle comparison class, recursively
handle reference nodes.
(compute_avail): Handle comparison classes, rewrite a little cleaner.
(execute_pre): Fix spacing.
(do_fre): Renamed to execute_fre.

Co-Authored-By: Diego Novillo <dnovillo@redhat.com>
From-SVN: r97567

gcc/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-2.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-3.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-4.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-6.c
gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c [new file with mode: 0644]
gcc/tree-ssa-pre.c

index fd38d96..5c4716f 100644 (file)
@@ -1,3 +1,21 @@
+2005-04-02  Daniel Berlin  <dberlin@dberlin.org>
+           Diego Novillo <dnovillo@redhat.com>
+           
+       Fix PR tree-optimization/20703
+       Fix PR tree-optimization/20725
+       
+       * tree-ssa-pre.c (phi_translate): Handle tcc_comparison.
+       (create_expression_by_pieces): Ditto.
+       (valid_in_set): Ditto. Also handle tcc_declaration.
+       (find_or_generate_expression): Handle comparison class.
+       (insert_into_preds_of_block): Ditto.
+       (insert_aux): Ditto.
+       (create_value_expr_from): Handle comparison class, recursively
+       handle reference nodes.
+       (compute_avail): Handle comparison classes, rewrite a little cleaner.
+       (execute_pre): Fix spacing.
+       (do_fre): Renamed to execute_fre.
+
 2005-04-04  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * doc/invoke.texi (SPARC options): Document that
index a2fc435..3bdd204 100644 (file)
@@ -17,5 +17,5 @@ int main(int argc, char **argv)
 }
 /* We should eliminate one evaluation of b + c along the main path, 
    causing one reload. */
-/* { dg-final { scan-tree-dump-times "Eliminated:1" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
 /* { dg-final { cleanup-tree-dump "pre" } } */
index 3a11078..6df2611 100644 (file)
@@ -17,5 +17,5 @@ int motion_test1(int data, int data_0, int data_3, int v)
 }
 /* We should eliminate one computation of data_0 + data_3 along the 
    main path, causing one reload. */
-/* { dg-final { scan-tree-dump-times "Eliminated:1" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
 /* { dg-final { cleanup-tree-dump "pre" } } */
index 6952bc6..3925f75 100644 (file)
@@ -11,5 +11,5 @@ unsigned foo1 (unsigned a, unsigned b)
   return j + k;
 }
 /* We should eliminate both 4*b and 4*a from the main body of the loop */
-/* { dg-final { scan-tree-dump-times "Eliminated:2" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"} } */
 /* { dg-final { cleanup-tree-dump "pre" } } */
index acb7f5a..6f4c2f3 100644 (file)
@@ -11,5 +11,5 @@ int main(void)
 }
 /* We should eliminate the x+1 computation from this routine, replacing
    it with a phi of 3, 4 */
-/* { dg-final { scan-tree-dump-times "Eliminated:1" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
 /* { dg-final { cleanup-tree-dump "pre" } } */
index c3f79c2..8756944 100644 (file)
@@ -12,5 +12,5 @@ foo (int i)
 }
 /* We should detect that a+b is the same along both edges, and replace it with
    5  */
-/* { dg-final { scan-tree-dump-times "Constified:1" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-times "Constified: 1" 1 "pre"} } */
 /* { dg-final { cleanup-tree-dump "pre" } } */
index 39b0e83..a639e9d 100644 (file)
@@ -10,5 +10,5 @@ int main(int x)
 }
 /* We should eliminate one evaluation of x + 1 along the x = 2 path,
    causing one elimination.  */
-/* { dg-final { scan-tree-dump-times "Eliminated:1" 1 "pre"} } */
+/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */
 /* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-7.c
new file mode 100644 (file)
index 0000000..642c36c
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */ 
+/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-pre-stats" } */
+int
+foo (int *array)
+{
+    if (array[1] != 0)
+          return array[1];
+      return 0;
+}
+/* We should eliminate one address calculation, and one load.  */
+/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c
new file mode 100644 (file)
index 0000000..f8e1921
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */ 
+/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-pre-stats" } */
+struct s {
+      int *n;
+};
+
+int
+foo (unsigned int i, struct s *array)
+{
+  int *p = array[i].n;
+  if (p)
+    {
+      int *q = array[i].n;
+      if (p != q)
+       return 1;
+    }
+  return 0;
+}
+/* We should eliminate two address calculations, one cast, and one load.  */
+/* { dg-final { scan-tree-dump-times "Eliminated: 4" 1 "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
index 5593c00..6ca0b0a 100644 (file)
@@ -871,6 +871,7 @@ phi_translate (tree expr, value_set_t set, basic_block pred,
       return NULL;
 
     case tcc_binary:
+    case tcc_comparison:
       {
        tree oldop1 = TREE_OPERAND (expr, 0);
        tree oldop2 = TREE_OPERAND (expr, 1);
@@ -1057,6 +1058,7 @@ valid_in_set (value_set_t set, tree expr)
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_binary:
+    case tcc_comparison:
       {
        tree op1 = TREE_OPERAND (expr, 0);
        tree op2 = TREE_OPERAND (expr, 1);
@@ -1077,6 +1079,10 @@ valid_in_set (value_set_t set, tree expr)
       gcc_assert (TREE_CODE (expr) == SSA_NAME);
       return true;
 
+    case tcc_declaration:
+      /* VAR_DECL and PARM_DECL are never anticipatable.  */
+      return false;
+
     default:
       /* No other cases should be encountered.  */
       gcc_unreachable (); 
@@ -1284,6 +1290,7 @@ find_or_generate_expression (basic_block block, tree expr, tree stmts)
       genop = VALUE_HANDLE_EXPR_SET (expr)->head->expr;
       gcc_assert (UNARY_CLASS_P (genop)
                  || BINARY_CLASS_P (genop)
+                 || COMPARISON_CLASS_P (genop)
                  || REFERENCE_CLASS_P (genop));
       genop = create_expression_by_pieces (block, genop, stmts);
     }
@@ -1315,6 +1322,7 @@ create_expression_by_pieces (basic_block block, tree expr, tree stmts)
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
     case tcc_binary:
+    case tcc_comparison:
       {
        tree_stmt_iterator tsi;
        tree forced_stmts;
@@ -1466,6 +1474,7 @@ insert_into_preds_of_block (basic_block block, value_set_node_t node,
       bprime = pred->src;
       eprime = avail[bprime->index];
       if (BINARY_CLASS_P (eprime)
+         || COMPARISON_CLASS_P (eprime)
          || UNARY_CLASS_P (eprime))
        {
          builtexpr = create_expression_by_pieces (bprime,
@@ -1579,6 +1588,7 @@ insert_aux (basic_block block)
                   node = node->next)
                {
                  if (BINARY_CLASS_P (node->expr)
+                     || COMPARISON_CLASS_P (node->expr)
                      || UNARY_CLASS_P (node->expr))
                    {
                      tree *avail;
@@ -1767,43 +1777,71 @@ add_to_sets (tree var, tree expr, vuse_optype vuses, bitmap_set_t s1,
 /* Given a unary or binary expression EXPR, create and return a new
    expression with the same structure as EXPR but with its operands
    replaced with the value handles of each of the operands of EXPR.
-   Insert EXPR's operands into the EXP_GEN set for BLOCK.
 
    VUSES represent the virtual use operands associated with EXPR (if
-   any). They are used when computing the hash value for EXPR.  */
+   any). They are used when computing the hash value for EXPR.
+   Insert EXPR's operands into the EXP_GEN set for BLOCK. */
 
 static inline tree
-create_value_expr_from (tree expr, basic_block block, vuse_optype vuses)
+create_value_expr_from (tree expr, basic_block block,
+                       vuse_optype vuses)
+
 {
   int i;
   enum tree_code code = TREE_CODE (expr);
   tree vexpr;
+  alloc_pool pool;
 
   gcc_assert (TREE_CODE_CLASS (code) == tcc_unary
              || TREE_CODE_CLASS (code) == tcc_binary
+             || TREE_CODE_CLASS (code) == tcc_comparison
              || TREE_CODE_CLASS (code) == tcc_reference);
 
   if (TREE_CODE_CLASS (code) == tcc_unary)
-    vexpr = pool_alloc (unary_node_pool);
+    pool = unary_node_pool;
   else if (TREE_CODE_CLASS (code) == tcc_reference)
-    vexpr = pool_alloc (reference_node_pool);
+    pool = reference_node_pool;
   else
-    vexpr = pool_alloc (binary_node_pool);
+    pool = binary_node_pool;
 
+  vexpr = pool_alloc (pool);
   memcpy (vexpr, expr, tree_size (expr));
 
   for (i = 0; i < TREE_CODE_LENGTH (code); i++)
     {
-      tree op = TREE_OPERAND (expr, i);
-      if (op != NULL)
+      tree val, op;
+      
+      op = TREE_OPERAND (expr, i);
+      if (op == NULL_TREE)
+       continue;
+
+      /* If OP is a constant that has overflowed, do not value number
+        this expression.  */
+      if (TREE_CODE_CLASS (TREE_CODE (op)) == tcc_constant
+         && TREE_OVERFLOW (op))
+       {
+         pool_free (pool, vexpr);
+         return NULL;
+       }
+
+      /* Recursively value-numberize reference ops */
+      if (TREE_CODE_CLASS (TREE_CODE (op)) == tcc_reference)
        {
-         tree val = vn_lookup_or_add (op, vuses);
-         if (!is_undefined_value (op))
-           value_insert_into_set (EXP_GEN (block), op);
-         if (TREE_CODE (val) == VALUE_HANDLE)
-           TREE_TYPE (val) = TREE_TYPE (TREE_OPERAND (vexpr, i));
-         TREE_OPERAND (vexpr, i) = val;
+         tree tempop = create_value_expr_from (op, block, vuses);
+         op = tempop ? tempop : op;
+         val = vn_lookup_or_add (op, vuses);
        }
+      else       
+       /* Create a value handle for OP and add it to VEXPR.  */
+       val = vn_lookup_or_add (op, NULL);
+
+      if (!is_undefined_value (op))
+       value_insert_into_set (EXP_GEN (block), op);
+
+      if (TREE_CODE (val) == VALUE_HANDLE)
+       TREE_TYPE (val) = TREE_TYPE (TREE_OPERAND (vexpr, i));
+
+      TREE_OPERAND (vexpr, i) = val;
     }
 
   return vexpr;
@@ -1902,8 +1940,29 @@ compute_avail (void)
              vuse_optype vuses = STMT_VUSE_OPS (stmt);
 
              STRIP_USELESS_TYPE_CONVERSION (rhs);
-             if (TREE_CODE (rhs) == SSA_NAME
-                 || is_gimple_min_invariant (rhs))
+             if (UNARY_CLASS_P (rhs)
+                 || BINARY_CLASS_P (rhs)
+                 || COMPARISON_CLASS_P (rhs)
+                 || REFERENCE_CLASS_P (rhs))
+               {
+                 /* For binary, unary, and reference expressions,
+                    create a duplicate expression with the operands
+                    replaced with the value handles of the original
+                    RHS.  */
+                 tree newt = create_value_expr_from (rhs, block, vuses);
+                 if (newt)
+                   {
+                     add_to_sets (lhs, newt, vuses, TMP_GEN (block),
+                                  AVAIL_OUT (block));
+                     value_insert_into_set (EXP_GEN (block), newt);
+                     continue;
+                   }
+               }
+             else if (TREE_CODE (rhs) == SSA_NAME
+                      || is_gimple_min_invariant (rhs)
+                      || TREE_INVARIANT (rhs)
+                      || TREE_CODE (rhs) == ADDR_EXPR
+                      || DECL_P (rhs))
                {
                  /* Compute a value number for the RHS of the statement
                     and add its value to the AVAIL_OUT set for the block.
@@ -1916,19 +1975,6 @@ compute_avail (void)
                    value_insert_into_set (EXP_GEN (block), rhs);
                  continue;
                }          
-             else if (UNARY_CLASS_P (rhs) || BINARY_CLASS_P (rhs)
-                      || TREE_CODE (rhs) == INDIRECT_REF)
-               {
-                 /* For binary, unary, and reference expressions,
-                    create a duplicate expression with the operands
-                    replaced with the value handles of the original
-                    RHS.  */
-                 tree newt = create_value_expr_from (rhs, block, vuses);
-                 add_to_sets (lhs, newt, vuses, TMP_GEN (block),
-                              AVAIL_OUT (block));
-                 value_insert_into_set (EXP_GEN (block), newt);
-                 continue;
-               }
            }
 
          /* For any other statement that we don't recognize, simply
@@ -2286,10 +2332,10 @@ execute_pre (bool do_fre)
 
   if (dump_file && (dump_flags & TDF_STATS))
     {
-      fprintf (dump_file, "Insertions:%d\n", pre_stats.insertions);
-      fprintf (dump_file, "New PHIs:%d\n", pre_stats.phis);
-      fprintf (dump_file, "Eliminated:%d\n", pre_stats.eliminations);
-      fprintf (dump_file, "Constified:%d\n", pre_stats.constified);
+      fprintf (dump_file, "Insertions: %d\n", pre_stats.insertions);
+      fprintf (dump_file, "New PHIs: %d\n", pre_stats.phis);
+      fprintf (dump_file, "Eliminated: %d\n", pre_stats.eliminations);
+      fprintf (dump_file, "Constified: %d\n", pre_stats.constified);
     }
   
   bsi_commit_edge_inserts ();
@@ -2336,7 +2382,7 @@ struct tree_opt_pass pass_pre =
 /* Gate and execute functions for FRE.  */
 
 static void
-do_fre (void)
+execute_fre (void)
 {
   execute_pre (true);
 }
@@ -2351,7 +2397,7 @@ struct tree_opt_pass pass_fre =
 {
   "fre",                               /* name */
   gate_fre,                            /* gate */
-  do_fre,                              /* execute */
+  execute_fre,                         /* execute */
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */