X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-ssa-forwprop.c;h=bbce3304c4eca1987670c6da582e63c15bdd2c72;hb=0f32121ec043f5e041215644603c7ee5759f9bb0;hp=c3e7d432528627fca812e1e53638ef264fdb6020;hpb=dd277d48c6583b9ac3a360761cf4484f021c9f0b;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index c3e7d432528..bbce3304c4e 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -186,8 +186,7 @@ get_prop_dest_stmt (tree name, tree *final_name_p) return NULL; /* If this is not a trivial copy, we found it. */ - if (!gimple_assign_copy_p (use_stmt) - || TREE_CODE (gimple_assign_lhs (use_stmt)) != SSA_NAME + if (!gimple_assign_ssa_name_copy_p (use_stmt) || gimple_assign_rhs1 (use_stmt) != name) break; @@ -225,12 +224,11 @@ get_prop_source_stmt (tree name, bool single_use_only, bool *single_use_p) } /* If name is defined by a PHI node or is the default def, bail out. */ - if (gimple_code (def_stmt) != GIMPLE_ASSIGN) + if (!is_gimple_assign (def_stmt)) return NULL; - /* If name is not a simple copy destination, we found it. */ - if (!gimple_assign_copy_p (def_stmt) - || TREE_CODE (gimple_assign_rhs1 (def_stmt)) != SSA_NAME) + /* If def_stmt is not a simple copy, we possibly found it. */ + if (!gimple_assign_ssa_name_copy_p (def_stmt)) { tree rhs; @@ -266,6 +264,7 @@ can_propagate_from (gimple def_stmt) ssa_op_iter iter; gcc_assert (is_gimple_assign (def_stmt)); + /* If the rhs has side-effects we cannot propagate from it. */ if (gimple_has_volatile_ops (def_stmt)) return false; @@ -276,8 +275,8 @@ can_propagate_from (gimple def_stmt) return false; /* Constants can be always propagated. */ - if (is_gimple_min_invariant - (rhs_to_tree (TREE_TYPE (gimple_assign_lhs (def_stmt)), def_stmt))) + if (gimple_assign_single_p (def_stmt) + && is_gimple_min_invariant (gimple_assign_rhs1 (def_stmt))) return true; /* We cannot propagate ssa names that occur in abnormal phi nodes. */ @@ -289,14 +288,14 @@ can_propagate_from (gimple def_stmt) then we can not apply optimizations as some targets require function pointers to be canonicalized and in this case this optimization could eliminate a necessary canonicalization. */ - if (is_gimple_assign (def_stmt) - && (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt)))) + if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))) { tree rhs = gimple_assign_rhs1 (def_stmt); if (POINTER_TYPE_P (TREE_TYPE (rhs)) && TREE_CODE (TREE_TYPE (TREE_TYPE (rhs))) == FUNCTION_TYPE) return false; } + return true; } @@ -668,7 +667,8 @@ forward_propagate_addr_into_variable_array_index (tree offset, tunit)) != NULL_TREE) { gimple offset_def2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (offset_def)); - if (gimple_assign_rhs_code (offset_def2) == MULT_EXPR + if (is_gimple_assign (offset_def2) + && gimple_assign_rhs_code (offset_def2) == MULT_EXPR && TREE_CODE (gimple_assign_rhs2 (offset_def2)) == INTEGER_CST && tree_int_cst_equal (gimple_assign_rhs2 (offset_def2), tunit)) { @@ -717,6 +717,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, tree *rhsp, *lhsp; gimple use_stmt = gsi_stmt (*use_stmt_gsi); enum tree_code rhs_code; + bool res = true; gcc_assert (TREE_CODE (def_rhs) == ADDR_EXPR); @@ -739,7 +740,11 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, address which we cannot do in a single statement. */ if (!single_use_p || (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (def_rhs)) - && !is_gimple_min_invariant (def_rhs))) + && (!is_gimple_min_invariant (def_rhs) + || (INTEGRAL_TYPE_P (TREE_TYPE (lhs)) + && POINTER_TYPE_P (TREE_TYPE (def_rhs)) + && (TYPE_PRECISION (TREE_TYPE (lhs)) + > TYPE_PRECISION (TREE_TYPE (def_rhs))))))) return forward_propagate_addr_expr (lhs, def_rhs); gimple_assign_set_rhs1 (use_stmt, unshare_expr (def_rhs)); @@ -760,19 +765,26 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, /* Now see if the LHS node is an INDIRECT_REF using NAME. If so, propagate the ADDR_EXPR into the use of NAME and fold the result. */ if (TREE_CODE (lhs) == INDIRECT_REF - && TREE_OPERAND (lhs, 0) == name - && may_propagate_address_into_dereference (def_rhs, lhs) - && (lhsp != gimple_assign_lhs_ptr (use_stmt) - || useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (def_rhs, 0)), - TREE_TYPE (rhs)))) + && TREE_OPERAND (lhs, 0) == name) { - *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0)); - fold_stmt_inplace (use_stmt); - tidy_after_forward_propagate_addr (use_stmt); + if (may_propagate_address_into_dereference (def_rhs, lhs) + && (lhsp != gimple_assign_lhs_ptr (use_stmt) + || useless_type_conversion_p + (TREE_TYPE (TREE_OPERAND (def_rhs, 0)), TREE_TYPE (rhs)))) + { + *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0)); + fold_stmt_inplace (use_stmt); + tidy_after_forward_propagate_addr (use_stmt); - /* Continue propagating into the RHS if this was not the only use. */ - if (single_use_p) - return true; + /* Continue propagating into the RHS if this was not the only use. */ + if (single_use_p) + return true; + } + else + /* We can have a struct assignment dereferencing our name twice. + Note that we didn't propagate into the lhs to not falsely + claim we did when propagating into the rhs. */ + res = false; } /* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR @@ -792,7 +804,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, *rhsp = unshare_expr (TREE_OPERAND (def_rhs, 0)); fold_stmt_inplace (use_stmt); tidy_after_forward_propagate_addr (use_stmt); - return true; + return res; } /* Now see if the RHS node is an INDIRECT_REF using NAME. If so, @@ -823,7 +835,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, true, GSI_NEW_STMT); gimple_assign_set_rhs1 (use_stmt, new_rhs); tidy_after_forward_propagate_addr (use_stmt); - return true; + return res; } /* If the defining rhs comes from an indirect reference, then do not convert into a VIEW_CONVERT_EXPR. */ @@ -837,7 +849,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, *rhsp = new_rhs; fold_stmt_inplace (use_stmt); tidy_after_forward_propagate_addr (use_stmt); - return true; + return res; } } @@ -862,12 +874,22 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, of the elements in X into &x[C1 + C2/element size]. */ if (TREE_CODE (rhs2) == INTEGER_CST) { - tree new_rhs = maybe_fold_stmt_addition (gimple_expr_type (use_stmt), + tree new_rhs = maybe_fold_stmt_addition (gimple_location (use_stmt), + TREE_TYPE (def_rhs), def_rhs, rhs2); if (new_rhs) { - gimple_assign_set_rhs_from_tree (use_stmt_gsi, - unshare_expr (new_rhs)); + tree type = TREE_TYPE (gimple_assign_lhs (use_stmt)); + new_rhs = unshare_expr (new_rhs); + if (!useless_type_conversion_p (type, TREE_TYPE (new_rhs))) + { + if (!is_gimple_min_invariant (new_rhs)) + new_rhs = force_gimple_operand_gsi (use_stmt_gsi, new_rhs, + true, NULL_TREE, + true, GSI_SAME_STMT); + new_rhs = fold_convert (type, new_rhs); + } + gimple_assign_set_rhs_from_tree (use_stmt_gsi, new_rhs); use_stmt = gsi_stmt (*use_stmt_gsi); update_stmt (use_stmt); tidy_after_forward_propagate_addr (use_stmt); @@ -930,19 +952,17 @@ forward_propagate_addr_expr (tree name, tree rhs) { gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt); - push_stmt_changes (&use_stmt); result = forward_propagate_addr_expr_1 (name, rhs, &gsi, single_use_p); /* If the use has moved to a different statement adjust - the update machinery. */ + the update machinery for the old statement too. */ if (use_stmt != gsi_stmt (gsi)) { - pop_stmt_changes (&use_stmt); - use_stmt = gsi_stmt (gsi); update_stmt (use_stmt); + use_stmt = gsi_stmt (gsi); } - else - pop_stmt_changes (&use_stmt); + + update_stmt (use_stmt); } all &= result; @@ -950,9 +970,8 @@ forward_propagate_addr_expr (tree name, tree rhs) use_rhs = gimple_assign_rhs1 (use_stmt); if (result && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME - && (TREE_CODE (use_rhs) == SSA_NAME - || (CONVERT_EXPR_P (use_rhs) - && TREE_CODE (TREE_OPERAND (use_rhs, 0)) == SSA_NAME))) + && TREE_CODE (use_rhs) == SSA_NAME + && has_zero_uses (gimple_assign_lhs (use_stmt))) { gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt); release_defs (use_stmt); @@ -1255,6 +1274,15 @@ tree_ssa_forward_propagate_single_use_vars (void) else gsi_next (&gsi); } + else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR + && is_gimple_min_invariant (rhs)) + { + /* Make sure to fold &a[0] + off_1 here. */ + fold_stmt_inplace (stmt); + update_stmt (stmt); + if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) + gsi_next (&gsi); + } else if ((gimple_assign_rhs_code (stmt) == BIT_NOT_EXPR || gimple_assign_rhs_code (stmt) == NEGATE_EXPR) && TREE_CODE (rhs) == SSA_NAME) @@ -1325,7 +1353,7 @@ tree_ssa_forward_propagate_single_use_vars (void) static bool gate_forwprop (void) { - return 1; + return flag_tree_forwprop; } struct gimple_opt_pass pass_forwprop =