OSDN Git Service

2007-10-15 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-forwprop.c
index 29ee888..047d057 100644 (file)
@@ -1,11 +1,11 @@
 /* Forward propagation of expressions for single use variables.
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -14,9 +14,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 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, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -238,6 +237,14 @@ can_propagate_from (tree def_stmt)
 {
   tree rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
 
+  /* If the rhs has side-effects we cannot propagate from it.  */
+  if (TREE_SIDE_EFFECTS (rhs))
+    return false;
+
+  /* If the rhs is a load we cannot propagate from it.  */
+  if (REFERENCE_CLASS_P (rhs))
+    return false;
+
   /* We cannot propagate ssa names that occur in abnormal phi nodes.  */
   switch (TREE_CODE_LENGTH (TREE_CODE (rhs)))
     {
@@ -327,46 +334,16 @@ combine_cond_expr_cond (enum tree_code code, tree type,
   /* Require that we got a boolean type out if we put one in.  */
   gcc_assert (TREE_CODE (TREE_TYPE (t)) == TREE_CODE (type));
 
-  /* For (bool)x use x != 0.  */
-  if (TREE_CODE (t) == NOP_EXPR
-      && TREE_TYPE (t) == boolean_type_node)
-    {
-      tree top0 = TREE_OPERAND (t, 0);
-      t = build2 (NE_EXPR, type,
-                 top0, build_int_cst (TREE_TYPE (top0), 0));
-    }
-  /* For !x use x == 0.  */
-  else if (TREE_CODE (t) == TRUTH_NOT_EXPR)
-    {
-      tree top0 = TREE_OPERAND (t, 0);
-      t = build2 (EQ_EXPR, type,
-                 top0, build_int_cst (TREE_TYPE (top0), 0));
-    }
-  /* For cmp ? 1 : 0 use cmp.  */
-  else if (TREE_CODE (t) == COND_EXPR
-          && COMPARISON_CLASS_P (TREE_OPERAND (t, 0))
-          && integer_onep (TREE_OPERAND (t, 1))
-          && integer_zerop (TREE_OPERAND (t, 2)))
-    {
-      tree top0 = TREE_OPERAND (t, 0);
-      t = build2 (TREE_CODE (top0), type,
-                 TREE_OPERAND (top0, 0), TREE_OPERAND (top0, 1));
-    }
+  /* Canonicalize the combined condition for use in a COND_EXPR.  */
+  t = canonicalize_cond_expr_cond (t);
 
   /* Bail out if we required an invariant but didn't get one.  */
-  if (invariant_only
-      && !is_gimple_min_invariant (t))
+  if (!t
+      || (invariant_only
+         && !is_gimple_min_invariant (t)))
     return NULL_TREE;
 
-  /* A valid conditional for a COND_EXPR is either a gimple value
-     or a comparison with two gimple value operands.  */
-  if (is_gimple_val (t)
-      || (COMPARISON_CLASS_P (t)
-         && is_gimple_val (TREE_OPERAND (t, 0))
-         && is_gimple_val (TREE_OPERAND (t, 1))))
-    return t;
-
-  return NULL_TREE;
+  return t;
 }
 
 /* Propagate from the ssa name definition statements of COND_EXPR
@@ -382,8 +359,8 @@ forward_propagate_into_cond (tree cond_expr, tree stmt)
   do {
     tree tmp = NULL_TREE;
     tree cond = COND_EXPR_COND (cond_expr);
-    tree name, def_stmt, rhs;
-    bool single_use_p;
+    tree name, def_stmt, rhs0 = NULL_TREE, rhs1 = NULL_TREE;
+    bool single_use0_p = false, single_use1_p = false;
 
     /* We can do tree combining on SSA_NAME and comparison expressions.  */
     if (COMPARISON_CLASS_P (cond)
@@ -392,15 +369,15 @@ forward_propagate_into_cond (tree cond_expr, tree stmt)
        /* For comparisons use the first operand, that is likely to
           simplify comparisons against constants.  */
        name = TREE_OPERAND (cond, 0);
-       def_stmt = get_prop_source_stmt (name, false, &single_use_p);
+       def_stmt = get_prop_source_stmt (name, false, &single_use0_p);
        if (def_stmt != NULL_TREE
            && can_propagate_from (def_stmt))
          {
            tree op1 = TREE_OPERAND (cond, 1);
-           rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+           rhs0 = GIMPLE_STMT_OPERAND (def_stmt, 1);
            tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
-                                         fold_convert (TREE_TYPE (op1), rhs),
-                                         op1, !single_use_p);
+                                         fold_convert (TREE_TYPE (op1), rhs0),
+                                         op1, !single_use0_p);
          }
        /* If that wasn't successful, try the second operand.  */
        if (tmp == NULL_TREE
@@ -408,17 +385,25 @@ forward_propagate_into_cond (tree cond_expr, tree stmt)
          {
            tree op0 = TREE_OPERAND (cond, 0);
            name = TREE_OPERAND (cond, 1);
-           def_stmt = get_prop_source_stmt (name, false, &single_use_p);
+           def_stmt = get_prop_source_stmt (name, false, &single_use1_p);
            if (def_stmt == NULL_TREE
                || !can_propagate_from (def_stmt))
              return did_something;
 
-           rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
+           rhs1 = GIMPLE_STMT_OPERAND (def_stmt, 1);
            tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
                                          op0,
-                                         fold_convert (TREE_TYPE (op0), rhs),
-                                         !single_use_p);
+                                         fold_convert (TREE_TYPE (op0), rhs1),
+                                         !single_use1_p);
          }
+       /* If that wasn't successful either, try both operands.  */
+       if (tmp == NULL_TREE
+           && rhs0 != NULL_TREE
+           && rhs1 != NULL_TREE)
+         tmp = combine_cond_expr_cond (TREE_CODE (cond), boolean_type_node,
+                                       rhs0,
+                                       fold_convert (TREE_TYPE (rhs0), rhs1),
+                                       !(single_use0_p && single_use1_p));
       }
     else if (TREE_CODE (cond) == SSA_NAME)
       {
@@ -428,9 +413,9 @@ forward_propagate_into_cond (tree cond_expr, tree stmt)
            || !can_propagate_from (def_stmt))
          return did_something;
 
-       rhs = GIMPLE_STMT_OPERAND (def_stmt, 1);
-       tmp = combine_cond_expr_cond (NE_EXPR, boolean_type_node, rhs,
-                                     build_int_cst (TREE_TYPE (rhs), 0),
+       rhs0 = GIMPLE_STMT_OPERAND (def_stmt, 1);
+       tmp = combine_cond_expr_cond (NE_EXPR, boolean_type_node, rhs0,
+                                     build_int_cst (TREE_TYPE (rhs0), 0),
                                      false);
       }
 
@@ -601,8 +586,8 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, tree use_stmt,
            && rhs == name)
           || ((TREE_CODE (rhs) == NOP_EXPR
                || TREE_CODE (rhs) == CONVERT_EXPR)
-              && tree_ssa_useless_type_conversion_1 (TREE_TYPE (rhs),
-                                                     TREE_TYPE (def_rhs))))
+              && useless_type_conversion_p (TREE_TYPE (rhs),
+                                           TREE_TYPE (def_rhs))))
     return forward_propagate_addr_expr (lhs, def_rhs);
 
   /* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
@@ -670,7 +655,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, tree use_stmt,
       && TREE_CODE (TREE_OPERAND (rhs, 1)) == SSA_NAME
       /* Avoid problems with IVopts creating PLUS_EXPRs with a
         different type than their operands.  */
-      && lang_hooks.types_compatible_p (TREE_TYPE (name), TREE_TYPE (rhs)))
+      && useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (name)))
     {
       bool res;
       
@@ -718,13 +703,6 @@ forward_propagate_addr_expr (tree name, tree rhs)
          continue;
        }
 
-      /* If the use_stmt has side-effects, don't propagate into it.  */
-      if (stmt_ann (use_stmt)->has_volatile_ops)
-       {
-         all = false;
-         continue;
-       }
-
       push_stmt_changes (&use_stmt);
 
       result = forward_propagate_addr_expr_1 (name, rhs, use_stmt,
@@ -1029,8 +1007,7 @@ tree_ssa_forward_propagate_single_use_vars (void)
              did_something = forward_propagate_into_cond (stmt, stmt);
              if (did_something == 2)
                cfg_changed = true;
-             fold_undefer_overflow_warnings (!TREE_NO_WARNING (stmt)
-                                             && did_something, stmt,
+             fold_undefer_overflow_warnings (did_something, stmt,
                                              WARN_STRICT_OVERFLOW_CONDITIONAL);
              bsi_next (&bsi);
            }