aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-sccvn.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-ssa-sccvn.c')
-rw-r--r--gcc/tree-ssa-sccvn.c122
1 files changed, 65 insertions, 57 deletions
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 8a4af91..934ae40 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1224,8 +1224,8 @@ vn_reference_fold_indirect (vec<vn_reference_op_s> *ops,
/* The only thing we have to do is from &OBJ.foo.bar add the offset
from .foo.bar to the preceding MEM_REF offset and replace the
address with &OBJ. */
- addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (op->op0, 0),
- &addr_offset);
+ addr_base = get_addr_base_and_unit_offset_1 (TREE_OPERAND (op->op0, 0),
+ &addr_offset, vn_valueize);
gcc_checking_assert (addr_base && TREE_CODE (addr_base) != MEM_REF);
if (addr_base != TREE_OPERAND (op->op0, 0))
{
@@ -1282,8 +1282,9 @@ vn_reference_maybe_forwprop_address (vec<vn_reference_op_s> *ops,
poly_int64 addr_offset;
addr = gimple_assign_rhs1 (def_stmt);
- addr_base = get_addr_base_and_unit_offset (TREE_OPERAND (addr, 0),
- &addr_offset);
+ addr_base = get_addr_base_and_unit_offset_1 (TREE_OPERAND (addr, 0),
+ &addr_offset,
+ vn_valueize);
/* If that didn't work because the address isn't invariant propagate
the reference tree from the address operation in case the current
dereference isn't offsetted. */
@@ -2419,7 +2420,7 @@ public:
};
/* Global RPO state for access from hooks. */
-static rpo_elim *rpo_avail;
+static eliminate_dom_walker *rpo_avail;
basic_block vn_context_bb;
/* Return true if BASE1 and BASE2 can be adjusted so they have the
@@ -3223,8 +3224,10 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
return NULL;
}
- /* 6) For memcpy copies translate the reference through them if
- the copy kills ref. */
+ /* 6) For memcpy copies translate the reference through them if the copy
+ kills ref. But we cannot (easily) do this translation if the memcpy is
+ a storage order barrier, i.e. is equivalent to a VIEW_CONVERT_EXPR that
+ can modify the storage order of objects (see storage_order_barrier_p). */
else if (data->vn_walk_kind == VN_WALKREWRITE
&& is_gimple_reg_type (vr->type)
/* ??? Handle BCOPY as well. */
@@ -3274,6 +3277,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
}
if (TREE_CODE (lhs) == ADDR_EXPR)
{
+ if (AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (lhs)))
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_TYPE (lhs))))
+ return (void *)-1;
tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (lhs, 0),
&lhs_offset);
if (!tem)
@@ -3302,6 +3308,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
rhs = vn_valueize (rhs);
if (TREE_CODE (rhs) == ADDR_EXPR)
{
+ if (AGGREGATE_TYPE_P (TREE_TYPE (TREE_TYPE (rhs)))
+ && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_TYPE (rhs))))
+ return (void *)-1;
tree tem = get_addr_base_and_unit_offset (TREE_OPERAND (rhs, 0),
&rhs_offset);
if (!tem)
@@ -3592,6 +3601,7 @@ vn_reference_insert (tree op, tree result, tree vuse, tree vdef)
vr1->vuse = vuse_ssa_val (vuse);
vr1->operands = valueize_shared_reference_ops_from_ref (op, &tem).copy ();
vr1->type = TREE_TYPE (op);
+ vr1->punned = 0;
ao_ref op_ref;
ao_ref_init (&op_ref, op);
vr1->set = ao_ref_alias_set (&op_ref);
@@ -3651,6 +3661,7 @@ vn_reference_insert_pieces (tree vuse, alias_set_type set,
vr1->vuse = vuse_ssa_val (vuse);
vr1->operands = valueize_refs (operands);
vr1->type = type;
+ vr1->punned = 0;
vr1->set = set;
vr1->base_set = base_set;
vr1->hashcode = vn_reference_compute_hash (vr1);
@@ -4471,6 +4482,8 @@ set_ssa_val_to (tree from, tree to)
vn_ssa_aux_t from_info = VN_INFO (from);
tree currval = from_info->valnum; // SSA_VAL (from)
poly_int64 toff, coff;
+ bool curr_undefined = false;
+ bool curr_invariant = false;
/* The only thing we allow as value numbers are ssa_names
and invariants. So assert that here. We don't allow VN_TOP
@@ -4513,9 +4526,9 @@ set_ssa_val_to (tree from, tree to)
}
return false;
}
- bool curr_invariant = is_gimple_min_invariant (currval);
- bool curr_undefined = (TREE_CODE (currval) == SSA_NAME
- && ssa_undefined_value_p (currval, false));
+ curr_invariant = is_gimple_min_invariant (currval);
+ curr_undefined = (TREE_CODE (currval) == SSA_NAME
+ && ssa_undefined_value_p (currval, false));
if (currval != VN_TOP
&& !curr_invariant
&& !curr_undefined
@@ -4570,9 +4583,8 @@ set_and_exit:
&& !operand_equal_p (currval, to, 0)
/* Different undefined SSA names are not actually different. See
PR82320 for a testcase were we'd otherwise not terminate iteration. */
- && !(TREE_CODE (currval) == SSA_NAME
+ && !(curr_undefined
&& TREE_CODE (to) == SSA_NAME
- && ssa_undefined_value_p (currval, false)
&& ssa_undefined_value_p (to, false))
/* ??? For addresses involving volatile objects or types operand_equal_p
does not reliably detect ADDR_EXPRs as equal. We know we are only
@@ -4584,6 +4596,22 @@ set_and_exit:
== get_addr_base_and_unit_offset (TREE_OPERAND (to, 0), &toff))
&& known_eq (coff, toff)))
{
+ if (to != from
+ && currval != VN_TOP
+ && !curr_undefined
+ /* We do not want to allow lattice transitions from one value
+ to another since that may lead to not terminating iteration
+ (see PR95049). Since there's no convenient way to check
+ for the allowed transition of VAL -> PHI (loop entry value,
+ same on two PHIs, to same PHI result) we restrict the check
+ to invariants. */
+ && curr_invariant
+ && is_gimple_min_invariant (to))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " forced VARYING");
+ to = from;
+ }
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, " (changed)\n");
from_info->valnum = to;
@@ -4866,6 +4894,7 @@ visit_reference_op_call (tree lhs, gcall *stmt)
them here. */
vr2->operands = vr1.operands.copy ();
vr2->type = vr1.type;
+ vr2->punned = vr1.punned;
vr2->set = vr1.set;
vr2->base_set = vr1.base_set;
vr2->hashcode = vr1.hashcode;
@@ -4892,10 +4921,11 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
bool changed = false;
tree last_vuse;
tree result;
+ vn_reference_t res;
last_vuse = gimple_vuse (stmt);
result = vn_reference_lookup (op, gimple_vuse (stmt),
- default_vn_walk_kind, NULL, true, &last_vuse);
+ default_vn_walk_kind, &res, true, &last_vuse);
/* We handle type-punning through unions by value-numbering based
on offset and size of the access. Be prepared to handle a
@@ -4917,6 +4947,13 @@ visit_reference_op_load (tree lhs, tree op, gimple *stmt)
gimple_match_op res_op (gimple_match_cond::UNCOND,
VIEW_CONVERT_EXPR, TREE_TYPE (op), result);
result = vn_nary_build_or_lookup (&res_op);
+ if (result
+ && TREE_CODE (result) == SSA_NAME
+ && VN_INFO (result)->needs_insertion)
+ /* Track whether this is the canonical expression for different
+ typed loads. We use that as a stopgap measure for code
+ hoisting when dealing with floating point loads. */
+ res->punned = true;
}
/* When building the conversion fails avoid inserting the reference
@@ -6559,7 +6596,11 @@ eliminate_with_rpo_vn (bitmap inserted_exprs)
{
eliminate_dom_walker walker (CDI_DOMINATORS, inserted_exprs);
+ eliminate_dom_walker *saved_rpo_avail = rpo_avail;
+ rpo_avail = &walker;
walker.walk (cfun->cfg->x_entry_block_ptr);
+ rpo_avail = saved_rpo_avail;
+
return walker.eliminate_cleanup ();
}
@@ -7302,11 +7343,9 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
e->flags &= ~EDGE_DFS_BACK;
int *rpo = XNEWVEC (int, n_basic_blocks_for_fn (fn) - NUM_FIXED_BLOCKS);
+ auto_vec<std::pair<int, int> > toplevel_scc_extents;
int n = rev_post_order_and_mark_dfs_back_seme
- (fn, entry, exit_bbs, !loops_state_satisfies_p (LOOPS_NEED_FIXUP), rpo);
- /* rev_post_order_and_mark_dfs_back_seme fills RPO in reverse order. */
- for (int i = 0; i < n / 2; ++i)
- std::swap (rpo[i], rpo[n-i-1]);
+ (fn, entry, exit_bbs, true, rpo, !iterate ? &toplevel_scc_extents : NULL);
if (!do_region)
BITMAP_FREE (exit_bbs);
@@ -7384,12 +7423,20 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
vn_valueize = rpo_vn_valueize;
/* Initialize the unwind state and edge/BB executable state. */
- bool need_max_rpo_iterate = false;
+ unsigned curr_scc = 0;
for (int i = 0; i < n; ++i)
{
basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]);
rpo_state[i].visited = 0;
rpo_state[i].max_rpo = i;
+ if (!iterate && curr_scc < toplevel_scc_extents.length ())
+ {
+ if (i >= toplevel_scc_extents[curr_scc].first
+ && i <= toplevel_scc_extents[curr_scc].second)
+ rpo_state[i].max_rpo = toplevel_scc_extents[curr_scc].second;
+ if (i == toplevel_scc_extents[curr_scc].second)
+ curr_scc++;
+ }
bb->flags &= ~BB_EXECUTABLE;
bool has_backedges = false;
edge e;
@@ -7401,51 +7448,12 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
e->flags &= ~EDGE_EXECUTABLE;
if (iterate || e == entry || (skip_entry_phis && bb == entry->dest))
continue;
- if (bb_to_rpo[e->src->index] > i)
- {
- rpo_state[i].max_rpo = MAX (rpo_state[i].max_rpo,
- bb_to_rpo[e->src->index]);
- need_max_rpo_iterate = true;
- }
- else
- rpo_state[i].max_rpo
- = MAX (rpo_state[i].max_rpo,
- rpo_state[bb_to_rpo[e->src->index]].max_rpo);
}
rpo_state[i].iterate = iterate && has_backedges;
}
entry->flags |= EDGE_EXECUTABLE;
entry->dest->flags |= BB_EXECUTABLE;
- /* When there are irreducible regions the simplistic max_rpo computation
- above for the case of backedges doesn't work and we need to iterate
- until there are no more changes. */
- unsigned nit = 0;
- while (need_max_rpo_iterate)
- {
- nit++;
- need_max_rpo_iterate = false;
- for (int i = 0; i < n; ++i)
- {
- basic_block bb = BASIC_BLOCK_FOR_FN (fn, rpo[i]);
- edge e;
- edge_iterator ei;
- FOR_EACH_EDGE (e, ei, bb->preds)
- {
- if (e == entry || (skip_entry_phis && bb == entry->dest))
- continue;
- int max_rpo = MAX (rpo_state[i].max_rpo,
- rpo_state[bb_to_rpo[e->src->index]].max_rpo);
- if (rpo_state[i].max_rpo != max_rpo)
- {
- rpo_state[i].max_rpo = max_rpo;
- need_max_rpo_iterate = true;
- }
- }
- }
- }
- statistics_histogram_event (cfun, "RPO max_rpo iterations", nit);
-
/* As heuristic to improve compile-time we handle only the N innermost
loops and the outermost one optimistically. */
if (iterate)