OSDN Git Service

* tree-ssa-ccp.c (insert_clobber_before_stack_restore): Recurse on copy
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-ccp.c
index 738606f..ac544d3 100644 (file)
@@ -1,6 +1,6 @@
 /* Conditional constant propagation pass for the GNU compiler.
    Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011, 2012 Free Software Foundation, Inc.
+   2010, 2011, 2012, 2013 Free Software Foundation, Inc.
    Adapted from original RTL SSA-CCP by Daniel Berlin <dberlin@dberlin.org>
    Adapted to GIMPLE trees by Diego Novillo <dnovillo@redhat.com>
 
@@ -409,7 +409,8 @@ valid_lattice_transition (prop_value_t old_val, prop_value_t new_val)
 
   /* Now both lattice values are CONSTANT.  */
 
-  /* Allow transitioning from &x to &x & ~3.  */
+  /* Allow transitioning from PHI <&x, not executable> == &x
+     to PHI <&x, &y> == common alignment.  */
   if (TREE_CODE (old_val.value) != INTEGER_CST
       && TREE_CODE (new_val.value) == INTEGER_CST)
     return true;
@@ -652,14 +653,20 @@ likely_value (gimple stmt)
             the undefined operand may be promoted.  */
          return UNDEFINED;
 
+       case ADDR_EXPR:
+         /* If any part of an address is UNDEFINED, like the index
+            of an ARRAY_EXPR, then treat the result as UNDEFINED.  */
+         return UNDEFINED;
+
        default:
          ;
        }
     }
   /* If there was an UNDEFINED operand but the result may be not UNDEFINED
-     fall back to VARYING even if there were CONSTANT operands.  */
+     fall back to CONSTANT.  During iteration UNDEFINED may still drop
+     to CONSTANT.  */
   if (has_undefined_operand)
-    return VARYING;
+    return CONSTANT;
 
   /* We do not consider virtual operands here -- load from read-only
      memory may have only VARYING virtual operands, but still be
@@ -1368,6 +1375,10 @@ bit_value_unop (enum tree_code code, tree type, tree rhs)
   prop_value_t rval = get_value_for_expr (rhs, true);
   double_int value, mask;
   prop_value_t val;
+
+  if (rval.lattice_val == UNDEFINED)
+    return rval;
+
   gcc_assert ((rval.lattice_val == CONSTANT
               && TREE_CODE (rval.value) == INTEGER_CST)
              || double_int_minus_one_p (rval.mask));
@@ -1399,6 +1410,16 @@ bit_value_binop (enum tree_code code, tree type, tree rhs1, tree rhs2)
   prop_value_t r2val = get_value_for_expr (rhs2, true);
   double_int value, mask;
   prop_value_t val;
+
+  if (r1val.lattice_val == UNDEFINED
+      || r2val.lattice_val == UNDEFINED)
+    {
+      val.lattice_val = VARYING;
+      val.value = NULL_TREE;
+      val.mask = double_int_minus_one;
+      return val;
+    }
+
   gcc_assert ((r1val.lattice_val == CONSTANT
               && TREE_CODE (r1val.value) == INTEGER_CST)
              || double_int_minus_one_p (r1val.mask));
@@ -1567,7 +1588,6 @@ evaluate_stmt (gimple stmt)
       && !is_constant)
     {
       enum gimple_code code = gimple_code (stmt);
-      tree fndecl;
       val.lattice_val = VARYING;
       val.value = NULL_TREE;
       val.mask = double_int_minus_one;
@@ -1614,10 +1634,9 @@ evaluate_stmt (gimple stmt)
              || POINTER_TYPE_P (TREE_TYPE (rhs1)))
            val = bit_value_binop (code, TREE_TYPE (rhs1), rhs1, rhs2);
        }
-      else if (code == GIMPLE_CALL
-              && (fndecl = gimple_call_fndecl (stmt))
-              && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+      else if (gimple_call_builtin_class_p (stmt, BUILT_IN_NORMAL))
        {
+         tree fndecl = gimple_call_fndecl (stmt);
          switch (DECL_FUNCTION_CODE (fndecl))
            {
            case BUILT_IN_MALLOC:
@@ -1725,6 +1744,9 @@ insert_clobber_before_stack_restore (tree saved_val, tree var, htab_t *visited)
        insert_clobber_before_stack_restore (gimple_phi_result (stmt), var,
                                             visited);
       }
+    else if (gimple_assign_ssa_name_copy_p (stmt))
+      insert_clobber_before_stack_restore (gimple_assign_lhs (stmt), var,
+                                          visited);
     else
       gcc_assert (is_gimple_debug (stmt));
 }
@@ -1749,23 +1771,25 @@ gsi_prev_dom_bb_nondebug (gimple_stmt_iterator *i)
 }
 
 /* Find a BUILT_IN_STACK_SAVE dominating gsi_stmt (I), and insert
-   a clobber of VAR before each matching BUILT_IN_STACK_RESTORE.  */
+   a clobber of VAR before each matching BUILT_IN_STACK_RESTORE.
+
+   It is possible that BUILT_IN_STACK_SAVE cannot be find in a dominator when a
+   previous pass (such as DOM) duplicated it along multiple paths to a BB.  In
+   that case the function gives up without inserting the clobbers.  */
 
 static void
 insert_clobbers_for_var (gimple_stmt_iterator i, tree var)
 {
-  bool save_found;
   gimple stmt;
   tree saved_val;
   htab_t visited = NULL;
 
-  for (save_found = false; !gsi_end_p (i); gsi_prev_dom_bb_nondebug (&i))
+  for (; !gsi_end_p (i); gsi_prev_dom_bb_nondebug (&i))
     {
       stmt = gsi_stmt (i);
 
       if (!gimple_call_builtin_p (stmt, BUILT_IN_STACK_SAVE))
        continue;
-      save_found = true;
 
       saved_val = gimple_call_lhs (stmt);
       if (saved_val == NULL_TREE)
@@ -1777,7 +1801,6 @@ insert_clobbers_for_var (gimple_stmt_iterator i, tree var)
 
   if (visited != NULL)
     htab_delete (visited);
-  gcc_assert (save_found);
 }
 
 /* Detects a __builtin_alloca_with_align with constant size argument.  Declares
@@ -2273,7 +2296,7 @@ optimize_stdarg_builtin (gimple call)
     case BUILT_IN_VA_START:
       if (!va_list_simple_ptr
          || targetm.expand_builtin_va_start != NULL
-          || builtin_decl_explicit_p (BUILT_IN_NEXT_ARG))
+         || !builtin_decl_explicit_p (BUILT_IN_NEXT_ARG))
        return NULL_TREE;
 
       if (gimple_call_num_args (call) != 2)