X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-ssa-ccp.c;h=ac544d3e2beae59091d935fa0edba1c6f333f801;hb=0b24c2581da7243b803e58b11bb1adc9fecac900;hp=738606fad0234751c3aa437c580c2964119c9d8d;hpb=3064bb7bdf4b3e57842207a7cfbb72d686ace48a;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 738606fad02..ac544d3e2be 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -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 Adapted to GIMPLE trees by Diego Novillo @@ -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)