Index: gcc/gcc/tree-ssa-phiprop.c |
diff --git a/gcc/gcc/tree-ssa-phiprop.c b/gcc/gcc/tree-ssa-phiprop.c |
index 1b9c6fa85b5abf8b2ddcd25db8c91baeea46d07c..fcd1d23bac8f08e5436c25a72b19047be21edd4b 100644 |
--- a/gcc/gcc/tree-ssa-phiprop.c |
+++ b/gcc/gcc/tree-ssa-phiprop.c |
@@ -90,12 +90,12 @@ along with GCC; see the file COPYING3. If not see |
/* Structure to keep track of the value of a dereferenced PHI result |
- and the set of virtual operands used for that dereference. */ |
+ and the virtual operand used for that dereference. */ |
struct phiprop_d |
{ |
tree value; |
- gimple vop_stmt; |
+ tree vuse; |
}; |
/* Verify if the value recorded for NAME in PHIVN is still valid at |
@@ -104,34 +104,27 @@ struct phiprop_d |
static bool |
phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb) |
{ |
- gimple vop_stmt = phivn[SSA_NAME_VERSION (name)].vop_stmt; |
- ssa_op_iter ui; |
- tree vuse; |
+ tree vuse = phivn[SSA_NAME_VERSION (name)].vuse; |
+ gimple use_stmt; |
+ imm_use_iterator ui2; |
+ bool ok = true; |
- /* The def stmts of all virtual uses need to be post-dominated |
- by bb. */ |
- FOR_EACH_SSA_TREE_OPERAND (vuse, vop_stmt, ui, SSA_OP_VUSE) |
- { |
- gimple use_stmt; |
- imm_use_iterator ui2; |
- bool ok = true; |
+ /* The def stmts of the virtual uses need to be dominated by bb. */ |
+ gcc_assert (vuse != NULL_TREE); |
- FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse) |
+ FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse) |
+ { |
+ /* If BB does not dominate a VDEF, the value is invalid. */ |
+ if ((gimple_vdef (use_stmt) != NULL_TREE |
+ || gimple_code (use_stmt) == GIMPLE_PHI) |
+ && !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb)) |
{ |
- /* If BB does not dominate a VDEF, the value is invalid. */ |
- if ((!ZERO_SSA_OPERANDS (use_stmt, SSA_OP_VDEF) |
- || gimple_code (use_stmt) == GIMPLE_PHI) |
- && !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb)) |
- { |
- ok = false; |
- BREAK_FROM_IMM_USE_STMT (ui2); |
- } |
+ ok = false; |
+ BREAK_FROM_IMM_USE_STMT (ui2); |
} |
- if (!ok) |
- return false; |
} |
- return true; |
+ return ok; |
} |
/* Insert a new phi node for the dereference of PHI at basic_block |
@@ -154,25 +147,45 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt, |
res = gimple_assign_lhs (use_stmt); |
SSA_NAME_DEF_STMT (res) = new_phi = create_phi_node (res, bb); |
+ if (dump_file && (dump_flags & TDF_DETAILS)) |
+ { |
+ fprintf (dump_file, "Inserting PHI for result of load "); |
+ print_gimple_stmt (dump_file, use_stmt, 0, 0); |
+ } |
+ |
/* Add PHI arguments for each edge inserting loads of the |
addressable operands. */ |
FOR_EACH_EDGE (e, ei, bb->preds) |
{ |
tree old_arg, new_var; |
gimple tmp; |
+ source_location locus; |
old_arg = PHI_ARG_DEF_FROM_EDGE (phi, e); |
+ locus = gimple_phi_arg_location_from_edge (phi, e); |
while (TREE_CODE (old_arg) == SSA_NAME |
&& (SSA_NAME_VERSION (old_arg) >= n |
|| phivn[SSA_NAME_VERSION (old_arg)].value == NULL_TREE)) |
{ |
gimple def_stmt = SSA_NAME_DEF_STMT (old_arg); |
old_arg = gimple_assign_rhs1 (def_stmt); |
+ locus = gimple_location (def_stmt); |
} |
if (TREE_CODE (old_arg) == SSA_NAME) |
- /* Reuse a formerly created dereference. */ |
- new_var = phivn[SSA_NAME_VERSION (old_arg)].value; |
+ { |
+ if (dump_file && (dump_flags & TDF_DETAILS)) |
+ { |
+ fprintf (dump_file, " for edge defining "); |
+ print_generic_expr (dump_file, PHI_ARG_DEF_FROM_EDGE (phi, e), 0); |
+ fprintf (dump_file, " reusing PHI result "); |
+ print_generic_expr (dump_file, |
+ phivn[SSA_NAME_VERSION (old_arg)].value, 0); |
+ fprintf (dump_file, "\n"); |
+ } |
+ /* Reuse a formerly created dereference. */ |
+ new_var = phivn[SSA_NAME_VERSION (old_arg)].value; |
+ } |
else |
{ |
gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR); |
@@ -186,18 +199,28 @@ phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt, |
add_referenced_var (new_var); |
new_var = make_ssa_name (new_var, tmp); |
gimple_assign_set_lhs (tmp, new_var); |
+ gimple_set_location (tmp, locus); |
gsi_insert_on_edge (e, tmp); |
- |
update_stmt (tmp); |
- mark_symbols_for_renaming (tmp); |
+ |
+ if (dump_file && (dump_flags & TDF_DETAILS)) |
+ { |
+ fprintf (dump_file, " for edge defining "); |
+ print_generic_expr (dump_file, PHI_ARG_DEF_FROM_EDGE (phi, e), 0); |
+ fprintf (dump_file, " inserting load "); |
+ print_gimple_stmt (dump_file, tmp, 0, 0); |
+ } |
} |
- add_phi_arg (new_phi, new_var, e); |
+ add_phi_arg (new_phi, new_var, e, locus); |
} |
update_stmt (new_phi); |
+ if (dump_file && (dump_flags & TDF_DETAILS)) |
+ print_gimple_stmt (dump_file, new_phi, 0, 0); |
+ |
return res; |
} |
@@ -228,8 +251,7 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn, |
ssa_op_iter i; |
bool phi_inserted; |
- if (MTAG_P (SSA_NAME_VAR (ptr)) |
- || !POINTER_TYPE_P (TREE_TYPE (ptr)) |
+ if (!POINTER_TYPE_P (TREE_TYPE (ptr)) |
|| !is_gimple_reg_type (TREE_TYPE (TREE_TYPE (ptr)))) |
return false; |
@@ -254,6 +276,7 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn, |
/* Avoid to have to decay *&a to a[0] later. */ |
|| !is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (arg, 0)))) |
&& !(TREE_CODE (arg) == SSA_NAME |
+ && SSA_NAME_VERSION (arg) < n |
&& phivn[SSA_NAME_VERSION (arg)].value != NULL_TREE |
&& phivn_valid_p (phivn, arg, bb))) |
return false; |
@@ -270,29 +293,27 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn, |
phi_inserted = false; |
FOR_EACH_IMM_USE_STMT (use_stmt, ui, ptr) |
{ |
- ssa_op_iter ui2; |
+ gimple def_stmt; |
tree vuse; |
/* Check whether this is a load of *ptr. */ |
if (!(is_gimple_assign (use_stmt) |
- && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME |
+ && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME |
&& gimple_assign_rhs_code (use_stmt) == INDIRECT_REF |
&& TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == ptr |
/* We cannot replace a load that may throw or is volatile. */ |
&& !stmt_can_throw_internal (use_stmt))) |
continue; |
- /* Check if we can move the loads. The def stmts of all virtual uses |
- need to be post-dominated by bb. */ |
- FOR_EACH_SSA_TREE_OPERAND (vuse, use_stmt, ui2, SSA_OP_VUSE) |
- { |
- gimple def_stmt = SSA_NAME_DEF_STMT (vuse); |
- if (!SSA_NAME_IS_DEFAULT_DEF (vuse) |
- && (gimple_bb (def_stmt) == bb |
- || !dominated_by_p (CDI_DOMINATORS, |
- bb, gimple_bb (def_stmt)))) |
- goto next; |
- } |
+ /* Check if we can move the loads. The def stmt of the virtual use |
+ needs to be in a different basic block dominating bb. */ |
+ vuse = gimple_vuse (use_stmt); |
+ def_stmt = SSA_NAME_DEF_STMT (vuse); |
+ if (!SSA_NAME_IS_DEFAULT_DEF (vuse) |
+ && (gimple_bb (def_stmt) == bb |
+ || !dominated_by_p (CDI_DOMINATORS, |
+ bb, gimple_bb (def_stmt)))) |
+ goto next; |
/* Found a proper dereference. Insert a phi node if this |
is the first load transformation. */ |
@@ -302,7 +323,7 @@ propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn, |
/* Remember the value we created for *ptr. */ |
phivn[SSA_NAME_VERSION (ptr)].value = res; |
- phivn[SSA_NAME_VERSION (ptr)].vop_stmt = use_stmt; |
+ phivn[SSA_NAME_VERSION (ptr)].vuse = vuse; |
/* Remove old stmt. The phi is taken care of by DCE, if we |
want to delete it here we also have to delete all intermediate |
@@ -327,41 +348,35 @@ next:; |
return phi_inserted; |
} |
-/* Helper walking the dominator tree starting from BB and processing |
- phi nodes with global data PHIVN and N. */ |
- |
-static bool |
-tree_ssa_phiprop_1 (basic_block bb, struct phiprop_d *phivn, size_t n) |
-{ |
- bool did_something = false; |
- basic_block son; |
- gimple_stmt_iterator gsi; |
- |
- for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
- did_something |= propagate_with_phi (bb, gsi_stmt (gsi), phivn, n); |
- |
- for (son = first_dom_son (CDI_DOMINATORS, bb); |
- son; |
- son = next_dom_son (CDI_DOMINATORS, son)) |
- did_something |= tree_ssa_phiprop_1 (son, phivn, n); |
- |
- return did_something; |
-} |
- |
/* Main entry for phiprop pass. */ |
static unsigned int |
tree_ssa_phiprop (void) |
{ |
+ VEC(basic_block, heap) *bbs; |
struct phiprop_d *phivn; |
+ bool did_something = false; |
+ basic_block bb; |
+ gimple_stmt_iterator gsi; |
+ unsigned i; |
+ size_t n; |
calculate_dominance_info (CDI_DOMINATORS); |
- phivn = XCNEWVEC (struct phiprop_d, num_ssa_names); |
+ n = num_ssa_names; |
+ phivn = XCNEWVEC (struct phiprop_d, n); |
+ |
+ /* Walk the dominator tree in preorder. */ |
+ bbs = get_all_dominated_blocks (CDI_DOMINATORS, |
+ single_succ (ENTRY_BLOCK_PTR)); |
+ for (i = 0; VEC_iterate (basic_block, bbs, i, bb); ++i) |
+ for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) |
+ did_something |= propagate_with_phi (bb, gsi_stmt (gsi), phivn, n); |
- if (tree_ssa_phiprop_1 (ENTRY_BLOCK_PTR, phivn, num_ssa_names)) |
+ if (did_something) |
gsi_commit_edge_inserts (); |
+ VEC_free (basic_block, heap, bbs); |
free (phivn); |
return 0; |
@@ -370,10 +385,10 @@ tree_ssa_phiprop (void) |
static bool |
gate_phiprop (void) |
{ |
- return 1; |
+ return flag_tree_phiprop; |
} |
-struct gimple_opt_pass pass_phiprop = |
+struct gimple_opt_pass pass_phiprop = |
{ |
{ |
GIMPLE_PASS, |