summaryrefslogtreecommitdiff
path: root/gcc/tree-sra.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-sra.c')
-rw-r--r--gcc/tree-sra.c102
1 files changed, 60 insertions, 42 deletions
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 3922c22d824..67001a64564 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -144,7 +144,9 @@ struct access
points to the first one. */
struct access *first_child;
- /* Pointer to the next sibling in the access tree as described above. */
+ /* In intraprocedural SRA, pointer to the next sibling in the access tree as
+ described above. In IPA-SRA this is a pointer to the next access
+ belonging to the same group (having the same representative). */
struct access *next_sibling;
/* Pointers to the first and last element in the linked list of assign
@@ -1231,7 +1233,6 @@ build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset,
case UNION_TYPE:
case QUAL_UNION_TYPE:
case RECORD_TYPE:
- /* Some ADA records are half-unions, treat all of them the same. */
for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
{
HOST_WIDE_INT pos, size;
@@ -1242,7 +1243,10 @@ build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset,
pos = int_bit_position (fld);
gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
- size = tree_low_cst (DECL_SIZE (fld), 1);
+ tr_size = DECL_SIZE (fld);
+ if (!tr_size || !host_integerp (tr_size, 1))
+ continue;
+ size = tree_low_cst (tr_size, 1);
if (pos > offset || (pos + size) <= offset)
continue;
@@ -1300,7 +1304,8 @@ build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset,
/* Construct an expression that would reference a part of aggregate *EXPR of
type TYPE at the given OFFSET of the type EXP_TYPE. If EXPR is NULL, the
function only determines whether it can build such a reference without
- actually doing it.
+ actually doing it, otherwise, the tree it points to is unshared first and
+ then used as a base for furhter sub-references.
FIXME: Eventually this should be replaced with
maybe_fold_offset_to_reference() from tree-ssa-ccp.c but that requires a
@@ -1313,6 +1318,9 @@ build_ref_for_offset (tree *expr, tree type, HOST_WIDE_INT offset,
{
location_t loc = expr ? EXPR_LOCATION (*expr) : UNKNOWN_LOCATION;
+ if (expr)
+ *expr = unshare_expr (*expr);
+
if (allow_ptr && POINTER_TYPE_P (type))
{
type = TREE_TYPE (type);
@@ -1755,7 +1763,7 @@ create_artificial_child_access (struct access *parent, struct access *model,
access but LACC is not, change the type of the latter, if possible. */
static bool
-propagate_subacesses_accross_link (struct access *lacc, struct access *racc)
+propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
{
struct access *rchild;
HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
@@ -1796,7 +1804,7 @@ propagate_subacesses_accross_link (struct access *lacc, struct access *racc)
rchild->grp_hint = 1;
new_acc->grp_hint |= new_acc->grp_read;
if (rchild->first_child)
- ret |= propagate_subacesses_accross_link (new_acc, rchild);
+ ret |= propagate_subaccesses_across_link (new_acc, rchild);
}
continue;
}
@@ -1814,7 +1822,7 @@ propagate_subacesses_accross_link (struct access *lacc, struct access *racc)
{
ret = true;
if (racc->first_child)
- propagate_subacesses_accross_link (new_acc, rchild);
+ propagate_subaccesses_across_link (new_acc, rchild);
}
}
@@ -1840,7 +1848,7 @@ propagate_all_subaccesses (void)
if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
continue;
lacc = lacc->group_representative;
- if (propagate_subacesses_accross_link (lacc, racc)
+ if (propagate_subaccesses_across_link (lacc, racc)
&& lacc->first_link)
add_access_to_work_queue (lacc);
}
@@ -1956,7 +1964,7 @@ generate_subtree_copies (struct access *access, tree agg,
{
do
{
- tree expr = unshare_expr (agg);
+ tree expr = agg;
if (chunk_size && access->offset >= start_offset + chunk_size)
return;
@@ -2231,7 +2239,7 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
rhs = unshare_expr (lacc->expr);
else
{
- rhs = unshare_expr (top_racc->base);
+ rhs = top_racc->base;
repl_found = build_ref_for_offset (&rhs,
TREE_TYPE (top_racc->base),
offset, lacc->type, false);
@@ -2368,7 +2376,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
&& !access_has_children_p (lacc))
{
- tree expr = unshare_expr (lhs);
+ tree expr = lhs;
if (build_ref_for_offset (&expr, TREE_TYPE (lhs), 0,
TREE_TYPE (rhs), false))
{
@@ -2379,7 +2387,7 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
&& !access_has_children_p (racc))
{
- tree expr = unshare_expr (rhs);
+ tree expr = rhs;
if (build_ref_for_offset (&expr, TREE_TYPE (rhs), 0,
TREE_TYPE (lhs), false))
rhs = expr;
@@ -2812,33 +2820,34 @@ analyze_modified_params (VEC (access_p, heap) *representatives)
for (i = 0; i < func_param_count; i++)
{
- struct access *repr = VEC_index (access_p, representatives, i);
- VEC (access_p, heap) *access_vec;
- int j, access_count;
- tree parm;
+ struct access *repr;
- if (!repr || no_accesses_p (repr))
- continue;
- parm = repr->base;
- if (!POINTER_TYPE_P (TREE_TYPE (parm))
- || repr->grp_maybe_modified)
- continue;
-
- access_vec = get_base_access_vector (parm);
- access_count = VEC_length (access_p, access_vec);
- for (j = 0; j < access_count; j++)
+ for (repr = VEC_index (access_p, representatives, i);
+ repr;
+ repr = repr->next_grp)
{
struct access *access;
+ bitmap visited;
ao_ref ar;
- /* All accesses are read ones, otherwise grp_maybe_modified would be
- trivially set. */
- access = VEC_index (access_p, access_vec, j);
- ao_ref_init (&ar, access->expr);
- walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
- mark_maybe_modified, repr, NULL);
- if (repr->grp_maybe_modified)
- break;
+ if (no_accesses_p (repr))
+ continue;
+ if (!POINTER_TYPE_P (TREE_TYPE (repr->base))
+ || repr->grp_maybe_modified)
+ continue;
+
+ ao_ref_init (&ar, repr->expr);
+ visited = BITMAP_ALLOC (NULL);
+ for (access = repr; access; access = access->next_sibling)
+ {
+ /* All accesses are read ones, otherwise grp_maybe_modified would
+ be trivially set. */
+ walk_aliased_vdefs (&ar, gimple_vuse (access->stmt),
+ mark_maybe_modified, repr, &visited);
+ if (repr->grp_maybe_modified)
+ break;
+ }
+ BITMAP_FREE (visited);
}
}
}
@@ -3007,24 +3016,30 @@ static struct access *
unmodified_by_ref_scalar_representative (tree parm)
{
int i, access_count;
- struct access *access;
+ struct access *repr;
VEC (access_p, heap) *access_vec;
access_vec = get_base_access_vector (parm);
gcc_assert (access_vec);
- access_count = VEC_length (access_p, access_vec);
+ repr = VEC_index (access_p, access_vec, 0);
+ if (repr->write)
+ return NULL;
+ repr->group_representative = repr;
- for (i = 0; i < access_count; i++)
+ access_count = VEC_length (access_p, access_vec);
+ for (i = 1; i < access_count; i++)
{
- access = VEC_index (access_p, access_vec, i);
+ struct access *access = VEC_index (access_p, access_vec, i);
if (access->write)
return NULL;
+ access->group_representative = repr;
+ access->next_sibling = repr->next_sibling;
+ repr->next_sibling = access;
}
- access = VEC_index (access_p, access_vec, 0);
- access->grp_read = 1;
- access->grp_scalar_ptr = 1;
- return access;
+ repr->grp_read = 1;
+ repr->grp_scalar_ptr = 1;
+ return repr;
}
/* Sort collected accesses for parameter PARM, identify representatives for
@@ -3079,6 +3094,9 @@ splice_param_accesses (tree parm, bool *ro_grp)
return NULL;
modification |= ac2->write;
+ ac2->group_representative = access;
+ ac2->next_sibling = access->next_sibling;
+ access->next_sibling = ac2;
j++;
}