tree-cfg.c (tree_can_merge_blocks_p): Allow phi nodes in the merged block.
authorZdenek Dvorak <dvorakz@suse.cz>
Tue, 17 May 2005 19:55:53 +0000 (21:55 +0200)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Tue, 17 May 2005 19:55:53 +0000 (19:55 +0000)
* tree-cfg.c (tree_can_merge_blocks_p): Allow phi nodes in the
merged block.
(replace_uses_by): New function.
(tree_merge_blocks): Eliminate the phi nodes in the merged block.
* tree-flow.h (fold_stmt_inplace): Declare.
* tree-ssa-ccp.c (fold_stmt_inplace): New function.
* tree-ssa-dom.c (tree_ssa_dominator_optimize): Update dominance
info after cfg cleanup.

From-SVN: r99850

gcc/ChangeLog
gcc/tree-cfg.c
gcc/tree-flow.h
gcc/tree-ssa-ccp.c
gcc/tree-ssa-dom.c

index 85483143181da2b61b4da34a880927796e3b8f86..141be32fece47d5538b4800ab8fa63ffcd84f47c 100644 (file)
@@ -1,3 +1,14 @@
+2005-05-17  Zdenek Dvorak  <dvorakz@suse.cz>
+
+       * tree-cfg.c (tree_can_merge_blocks_p): Allow phi nodes in the
+       merged block.
+       (replace_uses_by): New function.
+       (tree_merge_blocks): Eliminate the phi nodes in the merged block.
+       * tree-flow.h (fold_stmt_inplace): Declare.
+       * tree-ssa-ccp.c (fold_stmt_inplace): New function.
+       * tree-ssa-dom.c (tree_ssa_dominator_optimize): Update dominance
+       info after cfg cleanup.
+
 2005-05-17  Zdenek Dvorak  <dvorakz@suse.cz>
 
        * cfgloop.h (just_once_each_iteration_p): Declaration changed.
 2005-05-17  Zdenek Dvorak  <dvorakz@suse.cz>
 
        * cfgloop.h (just_once_each_iteration_p): Declaration changed.
index be7e0f53dbb461670d40b4add16750348e4ff28f..4beb0e74290b7708c7e4cce741e6bf41a3fe5569 100644 (file)
@@ -1261,6 +1261,7 @@ tree_can_merge_blocks_p (basic_block a, basic_block b)
 {
   tree stmt;
   block_stmt_iterator bsi;
 {
   tree stmt;
   block_stmt_iterator bsi;
+  tree phi;
 
   if (!single_succ_p (a))
     return false;
 
   if (!single_succ_p (a))
     return false;
@@ -1288,9 +1289,19 @@ tree_can_merge_blocks_p (basic_block a, basic_block b)
       && DECL_NONLOCAL (LABEL_EXPR_LABEL (stmt)))
     return false;
 
       && DECL_NONLOCAL (LABEL_EXPR_LABEL (stmt)))
     return false;
 
-  /* There may be no PHI nodes at the start of B.  */
-  if (phi_nodes (b))
-    return false;
+  /* It must be possible to eliminate all phi nodes in B.  If ssa form
+     is not up-to-date, we cannot eliminate any phis.  */
+  phi = phi_nodes (b);
+  if (phi)
+    {
+      if (need_ssa_update_p ())
+       return false;
+
+      for (; phi; phi = PHI_CHAIN (phi))
+       if (!is_gimple_reg (PHI_RESULT (phi))
+           && !may_propagate_copy (PHI_RESULT (phi), PHI_ARG_DEF (phi, 0)))
+         return false;
+    }
 
   /* Do not remove user labels.  */
   for (bsi = bsi_start (b); !bsi_end_p (bsi); bsi_next (&bsi))
 
   /* Do not remove user labels.  */
   for (bsi = bsi_start (b); !bsi_end_p (bsi); bsi_next (&bsi))
@@ -1310,6 +1321,55 @@ tree_can_merge_blocks_p (basic_block a, basic_block b)
   return true;
 }
 
   return true;
 }
 
+/* Replaces all uses of NAME by VAL.  */
+
+static void
+replace_uses_by (tree name, tree val)
+{
+  imm_use_iterator imm_iter;
+  use_operand_p use;
+  tree stmt;
+  edge e;
+  unsigned i;
+  VEC(tree,heap) *stmts = VEC_alloc (tree, heap, 20);
+
+  FOR_EACH_IMM_USE_SAFE (use, imm_iter, name)
+    {
+      stmt = USE_STMT (use);
+
+      SET_USE (use, val);
+
+      if (TREE_CODE (stmt) == PHI_NODE)
+       {
+         e = PHI_ARG_EDGE (stmt, PHI_ARG_INDEX_FROM_USE (use));
+         if (e->flags & EDGE_ABNORMAL)
+           {
+             /* This can only occur for virtual operands, since
+                for the real ones SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
+                would prevent replacement.  */
+             gcc_assert (!is_gimple_reg (name));
+             SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val) = 1;
+           }
+       }
+      else
+       VEC_safe_push (tree, heap, stmts, stmt);
+    }
+  /* We do not update the statements in the loop above.  Consider
+     x = w * w;
+
+     If we performed the update in the first loop, the statement
+     would be rescanned after first occurence of w is replaced,
+     the new uses would be placed to the beginning of the list,
+     and we would never process them.  */
+  for (i = 0; VEC_iterate (tree, stmts, i, stmt); i++)
+    {
+      fold_stmt_inplace (stmt);
+      update_stmt (stmt);
+    }
+
+  VEC_free (tree, heap, stmts);
+}
 
 /* Merge block B into block A.  */
 
 
 /* Merge block B into block A.  */
 
@@ -1318,10 +1378,40 @@ tree_merge_blocks (basic_block a, basic_block b)
 {
   block_stmt_iterator bsi;
   tree_stmt_iterator last;
 {
   block_stmt_iterator bsi;
   tree_stmt_iterator last;
+  tree phi;
 
   if (dump_file)
     fprintf (dump_file, "Merging blocks %d and %d\n", a->index, b->index);
 
 
   if (dump_file)
     fprintf (dump_file, "Merging blocks %d and %d\n", a->index, b->index);
 
+  /* Remove the phi nodes.  */
+  bsi = bsi_last (a);
+  for (phi = phi_nodes (b); phi; phi = phi_nodes (b))
+    {
+      tree def = PHI_RESULT (phi), use = PHI_ARG_DEF (phi, 0);
+      tree copy;
+      
+      if (!may_propagate_copy (def, use)
+         /* Propagating pointers might cause the set of vops for statements
+            to be changed, and thus require ssa form update.  */
+         || (is_gimple_reg (def)
+             && POINTER_TYPE_P (TREE_TYPE (def))))
+       {
+         gcc_assert (is_gimple_reg (def));
+
+         /* Note that just emiting the copies is fine -- there is no problem
+            with ordering of phi nodes.  This is because A is the single
+            predecessor of B, therefore results of the phi nodes cannot
+            appear as arguments of the phi nodes.  */
+         copy = build2 (MODIFY_EXPR, void_type_node, def, use);
+         bsi_insert_after (&bsi, copy, BSI_NEW_STMT);
+         SET_PHI_RESULT (phi, NULL_TREE);
+         SSA_NAME_DEF_STMT (def) = copy;
+       }
+      else
+       replace_uses_by (def, use);
+      remove_phi_node (phi, NULL);
+    }
+
   /* Ensure that B follows A.  */
   move_block_after (b, a);
 
   /* Ensure that B follows A.  */
   move_block_after (b, a);
 
index 1bf9d87db16b0ffe829f31b0c209066227d04677..90bef3763f97d38d0cc8b3ee03f27d56b83886f3 100644 (file)
@@ -630,6 +630,7 @@ void set_current_def (tree, tree);
 
 /* In tree-ssa-ccp.c  */
 bool fold_stmt (tree *);
 
 /* In tree-ssa-ccp.c  */
 bool fold_stmt (tree *);
+bool fold_stmt_inplace (tree);
 tree widen_bitfield (tree, tree, tree);
 
 /* In tree-vrp.c  */
 tree widen_bitfield (tree, tree, tree);
 
 /* In tree-vrp.c  */
index 85753bdd764d31044b65d35ddb38c08d4117841e..45472f402ab55f28d4614e34808136ff58681f2e 100644 (file)
@@ -2308,6 +2308,32 @@ fold_stmt (tree *stmt_p)
   return changed;
 }
 
   return changed;
 }
 
+/* Perform the minimal folding on statement STMT.  Only operations like
+   *&x created by constant propagation are handled.  The statement cannot
+   be replaced with a new one.  */
+
+bool
+fold_stmt_inplace (tree stmt)
+{
+  tree old_stmt = stmt, rhs, new_rhs;
+  bool changed = false;
+
+  walk_tree (&stmt, fold_stmt_r, &changed, NULL);
+  gcc_assert (stmt == old_stmt);
+
+  rhs = get_rhs (stmt);
+  if (!rhs || rhs == stmt)
+    return changed;
+
+  new_rhs = fold (rhs);
+  if (new_rhs == rhs)
+    return changed;
+
+  changed |= set_rhs (&stmt, new_rhs);
+  gcc_assert (stmt == old_stmt);
+
+  return changed;
+}
 \f
 /* Convert EXPR into a GIMPLE value suitable for substitution on the
    RHS of an assignment.  Insert the necessary statements before
 \f
 /* Convert EXPR into a GIMPLE value suitable for substitution on the
    RHS of an assignment.  Insert the necessary statements before
index b827494b7dc1236105d1099cfdbf4c1e232218c0..692dd705b2f3868fd88aaa73e677f722b5e2bac6 100644 (file)
@@ -404,6 +404,7 @@ tree_ssa_dominator_optimize (void)
   /* Clean up the CFG so that any forwarder blocks created by loop
      canonicalization are removed.  */
   cleanup_tree_cfg ();
   /* Clean up the CFG so that any forwarder blocks created by loop
      canonicalization are removed.  */
   cleanup_tree_cfg ();
+  calculate_dominance_info (CDI_DOMINATORS);
 
   /* If we prove certain blocks are unreachable, then we want to
      repeat the dominator optimization process as PHI nodes may
 
   /* If we prove certain blocks are unreachable, then we want to
      repeat the dominator optimization process as PHI nodes may