OSDN Git Service

Fix an unwinding bug for functions with dynamic stack frames.
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-ccp.c
index 738606f..4e86b8d 100644 (file)
@@ -657,9 +657,10 @@ likely_value (gimple stmt)
        }
     }
   /* 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 +1369,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 +1404,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));
@@ -1749,23 +1764,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 +1794,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 +2289,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)