diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 493f74f47b7..c4865775f62 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2012-04-27 Tom de Vries + + PR tree-optimization/51879 + * tree-ssa-sccvn.h (struct vn_reference_s): Add result_vdef field. + * tree-ssa-sccvn.c (mark_use_processed): New function, factored out + of ... + (defs_to_varying): ... here. Don't set use_processed. + (visit_reference_op_call): Handle gimple_vdef. + Handle case that lhs is NULL_TREE. + (visit_use): Use mark_use_processed. Handle calls with side-effect + using visit_reference_op_call. + 2012-04-26 Richard Sandiford * sched-deps.c (fixup_sched_groups): Rename to... diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index ddb1ba6640e..e9e6bfa7c70 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2525,6 +2525,30 @@ set_ssa_val_to (tree from, tree to) return false; } +/* Mark as processed all the definitions in the defining stmt of USE, or + the USE itself. */ + +static void +mark_use_processed (tree use) +{ + ssa_op_iter iter; + def_operand_p defp; + gimple stmt = SSA_NAME_DEF_STMT (use); + + if (SSA_NAME_IS_DEFAULT_DEF (use) || gimple_code (stmt) == GIMPLE_PHI) + { + VN_INFO (use)->use_processed = true; + return; + } + + FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_ALL_DEFS) + { + tree def = DEF_FROM_PTR (defp); + + VN_INFO (def)->use_processed = true; + } +} + /* Set all definitions in STMT to value number to themselves. Return true if a value number changed. */ @@ -2538,8 +2562,6 @@ defs_to_varying (gimple stmt) FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_ALL_DEFS) { tree def = DEF_FROM_PTR (defp); - - VN_INFO (def)->use_processed = true; changed |= set_ssa_val_to (def, def); } return changed; @@ -2598,27 +2620,41 @@ visit_reference_op_call (tree lhs, gimple stmt) { bool changed = false; struct vn_reference_s vr1; - tree result; + vn_reference_t vnresult = NULL; tree vuse = gimple_vuse (stmt); + tree vdef = gimple_vdef (stmt); vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE; vr1.operands = valueize_shared_reference_ops_from_call (stmt); vr1.type = gimple_expr_type (stmt); vr1.set = 0; vr1.hashcode = vn_reference_compute_hash (&vr1); - result = vn_reference_lookup_1 (&vr1, NULL); - if (result) + vn_reference_lookup_1 (&vr1, &vnresult); + + if (vnresult) { - changed = set_ssa_val_to (lhs, result); - if (TREE_CODE (result) == SSA_NAME - && VN_INFO (result)->has_constants) - VN_INFO (lhs)->has_constants = true; + if (vnresult->result_vdef) + changed |= set_ssa_val_to (vdef, vnresult->result_vdef); + + if (!vnresult->result && lhs) + vnresult->result = lhs; + + if (vnresult->result && lhs) + { + changed |= set_ssa_val_to (lhs, vnresult->result); + + if (VN_INFO (vnresult->result)->has_constants) + VN_INFO (lhs)->has_constants = true; + } } else { void **slot; vn_reference_t vr2; - changed = set_ssa_val_to (lhs, lhs); + if (vdef) + changed |= set_ssa_val_to (vdef, vdef); + if (lhs) + changed |= set_ssa_val_to (lhs, lhs); vr2 = (vn_reference_t) pool_alloc (current_info->references_pool); vr2->vuse = vr1.vuse; vr2->operands = valueize_refs (create_reference_ops_from_call (stmt)); @@ -2626,6 +2662,7 @@ visit_reference_op_call (tree lhs, gimple stmt) vr2->set = vr1.set; vr2->hashcode = vr1.hashcode; vr2->result = lhs; + vr2->result_vdef = vdef; slot = htab_find_slot_with_hash (current_info->references, vr2, vr2->hashcode, INSERT); if (*slot) @@ -2795,7 +2832,6 @@ visit_reference_op_store (tree lhs, tree op, gimple stmt) going to valueize the references in-place. */ if ((vdef = gimple_vdef (stmt))) { - VN_INFO (vdef)->use_processed = true; changed |= set_ssa_val_to (vdef, vdef); } @@ -2817,7 +2853,6 @@ visit_reference_op_store (tree lhs, tree op, gimple stmt) def = gimple_vdef (stmt); use = gimple_vuse (stmt); - VN_INFO (def)->use_processed = true; changed |= set_ssa_val_to (def, SSA_VAL (use)); } @@ -3167,7 +3202,7 @@ visit_use (tree use) bool changed = false; gimple stmt = SSA_NAME_DEF_STMT (use); - VN_INFO (use)->use_processed = true; + mark_use_processed (use); gcc_assert (!SSA_NAME_IN_FREE_LIST (use)); if (dump_file && (dump_flags & TDF_DETAILS) @@ -3186,8 +3221,7 @@ visit_use (tree use) { if (gimple_code (stmt) == GIMPLE_PHI) changed = visit_phi (stmt); - else if (!gimple_has_lhs (stmt) - || gimple_has_volatile_ops (stmt)) + else if (gimple_has_volatile_ops (stmt)) changed = defs_to_varying (stmt); else if (is_gimple_assign (stmt)) { @@ -3349,34 +3383,44 @@ visit_use (tree use) /* ??? We could try to simplify calls. */ - if (stmt_has_constants (stmt) - && TREE_CODE (lhs) == SSA_NAME) - VN_INFO (lhs)->has_constants = true; - else if (TREE_CODE (lhs) == SSA_NAME) + if (lhs && TREE_CODE (lhs) == SSA_NAME) { - /* We reset expr and constantness here because we may - have been value numbering optimistically, and - iterating. They may become non-constant in this case, - even if they were optimistically constant. */ - VN_INFO (lhs)->has_constants = false; - VN_INFO (lhs)->expr = NULL_TREE; + if (stmt_has_constants (stmt)) + VN_INFO (lhs)->has_constants = true; + else + { + /* We reset expr and constantness here because we may + have been value numbering optimistically, and + iterating. They may become non-constant in this case, + even if they were optimistically constant. */ + VN_INFO (lhs)->has_constants = false; + VN_INFO (lhs)->expr = NULL_TREE; + } + + if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) + { + changed = defs_to_varying (stmt); + goto done; + } } - if (TREE_CODE (lhs) == SSA_NAME - && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) - changed = defs_to_varying (stmt); /* ??? We should handle stores from calls. */ - else if (TREE_CODE (lhs) == SSA_NAME) + if (!gimple_call_internal_p (stmt) + && (gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST) + /* If the call has side effects, subsequent calls won't have + the same incoming vuse, so it's save to assume + equality. */ + || gimple_has_side_effects (stmt)) + && ((lhs && TREE_CODE (lhs) == SSA_NAME) + || (!lhs && gimple_vdef (stmt)))) { - if (!gimple_call_internal_p (stmt) - && gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST)) - changed = visit_reference_op_call (lhs, stmt); - else - changed = defs_to_varying (stmt); + changed = visit_reference_op_call (lhs, stmt); } else changed = defs_to_varying (stmt); } + else + changed = defs_to_varying (stmt); } done: return changed; diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h index b37b084413d..a4f294f0788 100644 --- a/gcc/tree-ssa-sccvn.h +++ b/gcc/tree-ssa-sccvn.h @@ -110,6 +110,7 @@ typedef struct vn_reference_s tree type; VEC (vn_reference_op_s, heap) *operands; tree result; + tree result_vdef; } *vn_reference_t; typedef const struct vn_reference_s *const_vn_reference_t;