OSDN Git Service

2005-06-25 Thomas Koenig <Thomas.Koenig@online.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-forwprop.c
index f65df57..d5db4a8 100644 (file)
@@ -15,14 +15,13 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "errors.h"
 #include "ggc.h"
 #include "tree.h"
 #include "rtl.h"
@@ -45,7 +44,7 @@ Boston, MA 02111-1307, USA.  */
    code.  One day we'll want to generalize this code.
 
    One class of common cases we handle is forward propagating a single use
-   variale into a COND_EXPR.  
+   variable into a COND_EXPR.  
 
      bb0:
        x = a COND b;
@@ -146,6 +145,11 @@ Boston, MA 02111-1307, USA.  */
 
    This will (of course) be extended as other needs arise.  */
 
+
+/* Set to true if we delete EH edges during the optimization.  */
+static bool cfg_changed;
+
+
 /* Given an SSA_NAME VAR, return true if and only if VAR is defined by
    a comparison.  */
 
@@ -434,6 +438,25 @@ forward_propagate_into_cond (tree cond_expr)
     }
 }
 
+/* We've just substituted an ADDR_EXPR into stmt.  Update all the 
+   relevant data structures to match.  */
+
+static void
+tidy_after_forward_propagate_addr (tree stmt)
+{
+  mark_new_vars_to_rename (stmt);
+
+  /* We may have turned a trapping insn into a non-trapping insn.  */
+  if (maybe_clean_or_replace_eh_stmt (stmt, stmt)
+      && tree_purge_dead_eh_edges (bb_for_stmt (stmt)))
+    cfg_changed = true;
+
+  if (TREE_CODE (TREE_OPERAND (stmt, 1)) == ADDR_EXPR)
+     recompute_tree_invarant_for_addr_expr (TREE_OPERAND (stmt, 1));
+
+  update_stmt (stmt);
+}
+
 /* STMT defines LHS which is contains the address of the 0th element
    in an array.  USE_STMT uses LHS to compute the address of an
    arbitrary element within the array.  The (variable) byte offset
@@ -498,9 +521,8 @@ forward_propagate_addr_into_variable_array_index (tree offset, tree lhs,
 
   /* That should have created gimple, so there is no need to
      record information to undo the propagation.  */
-  fold_stmt (bsi_stmt_ptr (bsi_for_stmt (use_stmt)));
-  mark_new_vars_to_rename (use_stmt);
-  update_stmt (use_stmt);
+  fold_stmt_inplace (use_stmt);
+  tidy_after_forward_propagate_addr (use_stmt);
   return true;
 }
 
@@ -537,12 +559,8 @@ forward_propagate_addr_expr (tree stmt)
   if (bb_for_stmt (use_stmt)->loop_depth > stmt_loop_depth)
     return false;
 
-  /* If the two statements belong to different EH regions, then there
-     is nothing we can or should try to do.  */
-  if (lookup_stmt_eh_region (use_stmt) != lookup_stmt_eh_region (stmt))
-    return false;
-
-  /* Strip away any outer COMPONENT_REF/ARRAY_REF nodes from the LHS.  */
+  /* Strip away any outer COMPONENT_REF/ARRAY_REF nodes from the LHS. 
+     ADDR_EXPR will not appear on the LHS.  */
   lhs = TREE_OPERAND (use_stmt, 0);
   while (TREE_CODE (lhs) == COMPONENT_REF || TREE_CODE (lhs) == ARRAY_REF)
     lhs = TREE_OPERAND (lhs, 0);
@@ -554,9 +572,8 @@ forward_propagate_addr_expr (tree stmt)
       /* This should always succeed in creating gimple, so there is
         no need to save enough state to undo this propagation.  */
       TREE_OPERAND (lhs, 0) = unshare_expr (TREE_OPERAND (stmt, 1));
-      fold_stmt (bsi_stmt_ptr (bsi_for_stmt (use_stmt)));
-      mark_new_vars_to_rename (use_stmt);
-      update_stmt (use_stmt);
+      fold_stmt_inplace (use_stmt);
+      tidy_after_forward_propagate_addr (use_stmt);
       return true;
     }
 
@@ -570,14 +587,16 @@ forward_propagate_addr_expr (tree stmt)
   if (TREE_CODE (lhs) == SSA_NAME && TREE_OPERAND (use_stmt, 1) == name)
     {
       TREE_OPERAND (use_stmt, 1) = unshare_expr (TREE_OPERAND (stmt, 1));
-      mark_new_vars_to_rename (use_stmt);
-      update_stmt (use_stmt);
+      tidy_after_forward_propagate_addr (use_stmt);
       return true;
     }
 
-  /* Strip away any outer COMPONENT_REF/ARRAY_REF nodes from the RHS.  */
+  /* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
+     nodes from the RHS.  */
   rhs = TREE_OPERAND (use_stmt, 1);
-  while (TREE_CODE (rhs) == COMPONENT_REF || TREE_CODE (rhs) == ARRAY_REF)
+  while (TREE_CODE (rhs) == COMPONENT_REF
+        || TREE_CODE (rhs) == ARRAY_REF
+        || TREE_CODE (rhs) == ADDR_EXPR)
     rhs = TREE_OPERAND (rhs, 0);
 
   /* Now see if the RHS node is an INDIRECT_REF using NAME.  If so, 
@@ -587,9 +606,8 @@ forward_propagate_addr_expr (tree stmt)
       /* This should always succeed in creating gimple, so there is
          no need to save enough state to undo this propagation.  */
       TREE_OPERAND (rhs, 0) = unshare_expr (TREE_OPERAND (stmt, 1));
-      fold_stmt (bsi_stmt_ptr (bsi_for_stmt (use_stmt)));
-      mark_new_vars_to_rename (use_stmt);
-      update_stmt (use_stmt);
+      fold_stmt_inplace (use_stmt);
+      tidy_after_forward_propagate_addr (use_stmt);
       return true;
     }
 
@@ -619,10 +637,9 @@ forward_propagate_addr_expr (tree stmt)
       /* If folding succeeds, then we have just exposed new variables
         in USE_STMT which will need to be renamed.  If folding fails,
         then we need to put everything back the way it was.  */
-      if (fold_stmt (bsi_stmt_ptr (bsi_for_stmt (use_stmt))))
+      if (fold_stmt_inplace (use_stmt))
        {
-         mark_new_vars_to_rename (use_stmt);
-         update_stmt (use_stmt);
+         tidy_after_forward_propagate_addr (use_stmt);
          return true;
        }
       else
@@ -670,6 +687,8 @@ tree_ssa_forward_propagate_single_use_vars (void)
 {
   basic_block bb;
 
+  cfg_changed = false;
+
   FOR_EACH_BB (bb)
     {
       block_stmt_iterator bsi;
@@ -699,6 +718,9 @@ tree_ssa_forward_propagate_single_use_vars (void)
            bsi_next (&bsi);
        }
     }
+
+  if (cfg_changed)
+    cleanup_tree_cfg ();
 }