aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-sra.c
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2017-05-02 14:49:55 +0200
committerMartin Jambor <jamborm@gcc.gnu.org>2017-05-02 14:49:55 +0200
commit2bba75411e14cdf1ee67f4ee965665cf6c6c6ea7 (patch)
treedaaf9a73b62e3430dc79e23fa0d3062bcf282693 /gcc/tree-sra.c
parent2bf54d93f159210d0c05a07c655eb847c069365c (diff)
downloadgcc-2bba75411e14cdf1ee67f4ee965665cf6c6c6ea7.zip
gcc-2bba75411e14cdf1ee67f4ee965665cf6c6c6ea7.tar.gz
gcc-2bba75411e14cdf1ee67f4ee965665cf6c6c6ea7.tar.bz2
[PR 78687] Set SRA grp_write lazily
2017-05-02 Martin Jambor <mjambor@suse.cz> PR tree-optimization/78687 * tree-sra.c (access): New field parent. (process_subtree_disqualification): New function. (disqualify_candidate): Call it. (build_accesses_from_assign): Reset write flag if creating an assighnment link. (build_access_subtree): Fill in parent field and also prpagate down grp_write flag. (create_artificial_child_access): New parameter set_grp_write, set grp_write to its value. (propagate_subaccesses_across_link): Also propagate grp_write flag values. (propagate_all_subaccesses): Push the closest parent back to work queue if add_access_to_work_queue returned true. testsuite/ * g++.dg/tree-ssa/pr78687.C: New test. From-SVN: r247497
Diffstat (limited to 'gcc/tree-sra.c')
-rw-r--r--gcc/tree-sra.c91
1 files changed, 78 insertions, 13 deletions
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 0334d06..1606573 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -158,6 +158,10 @@ struct access
the representative. */
struct access *group_representative;
+ /* After access tree has been constructed, this points to the parent of the
+ current access, if there is one. NULL for roots. */
+ struct access *parent;
+
/* If this access has any children (in terms of the definition above), this
points to the first one. */
struct access *first_child;
@@ -690,6 +694,19 @@ static bool constant_decl_p (tree decl)
return VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl);
}
+
+/* Mark LHS of assign links out of ACCESS and its children as written to. */
+
+static void
+process_subtree_disqualification (struct access *access)
+{
+ struct access *child;
+ for (struct assign_link *link = access->first_link; link; link = link->next)
+ link->lacc->grp_write = true;
+ for (child = access->first_child; child; child = child->next_sibling)
+ process_subtree_disqualification (child);
+}
+
/* Remove DECL from candidates for SRA and write REASON to the dump file if
there is one. */
static void
@@ -706,6 +723,13 @@ disqualify_candidate (tree decl, const char *reason)
print_generic_expr (dump_file, decl, 0);
fprintf (dump_file, " - %s\n", reason);
}
+
+ struct access *access = get_first_repr_for_decl (decl);
+ while (access)
+ {
+ process_subtree_disqualification (access);
+ access = access->next_grp;
+ }
}
/* Return true iff the type contains a field or an element which does not allow
@@ -1338,8 +1362,10 @@ build_accesses_from_assign (gimple *stmt)
link->lacc = lacc;
link->racc = racc;
-
add_link_to_rhs (racc, link);
+ /* Let's delay marking the areas as written until propagation of accesses
+ across link. */
+ lacc->write = false;
}
return lacc || racc;
@@ -2252,6 +2278,8 @@ build_access_subtree (struct access **access)
else
last_child->next_sibling = *access;
last_child = *access;
+ (*access)->parent = root;
+ (*access)->grp_write |= root->grp_write;
if (!build_access_subtree (access))
return false;
@@ -2495,13 +2523,15 @@ child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
/* Create a new child access of PARENT, with all properties just like MODEL
except for its offset and with its grp_write false and grp_read true.
- Return the new access or NULL if it cannot be created. Note that this access
- is created long after all splicing and sorting, it's not located in any
- access vector and is automatically a representative of its group. */
+ Return the new access or NULL if it cannot be created. Note that this
+ access is created long after all splicing and sorting, it's not located in
+ any access vector and is automatically a representative of its group. Set
+ the gpr_write flag of the new accesss if SET_GRP_WRITE is true. */
static struct access *
create_artificial_child_access (struct access *parent, struct access *model,
- HOST_WIDE_INT new_offset)
+ HOST_WIDE_INT new_offset,
+ bool set_grp_write)
{
struct access **child;
tree expr = parent->base;
@@ -2523,7 +2553,7 @@ create_artificial_child_access (struct access *parent, struct access *model,
access->offset = new_offset;
access->size = model->size;
access->type = model->type;
- access->grp_write = true;
+ access->grp_write = set_grp_write;
access->grp_read = false;
access->reverse = model->reverse;
@@ -2549,10 +2579,23 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
bool ret = false;
+ /* IF the LHS is still not marked as being written to, we only need to do so
+ if the RHS at this level actually was. */
+ if (!lacc->grp_write &&
+ (racc->grp_write || TREE_CODE (racc->base) == PARM_DECL))
+ {
+ lacc->grp_write = true;
+ ret = true;
+ }
+
if (is_gimple_reg_type (lacc->type)
|| lacc->grp_unscalarizable_region
|| racc->grp_unscalarizable_region)
- return false;
+ {
+ ret |= !lacc->grp_write;
+ lacc->grp_write = true;
+ return ret;
+ }
if (is_gimple_reg_type (racc->type))
{
@@ -2572,7 +2615,7 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
lacc->grp_no_warning = true;
}
}
- return false;
+ return ret;
}
for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
@@ -2581,23 +2624,37 @@ propagate_subaccesses_across_link (struct access *lacc, struct access *racc)
HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
if (rchild->grp_unscalarizable_region)
- continue;
+ {
+ lacc->grp_write = true;
+ continue;
+ }
if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
&new_acc))
{
if (new_acc)
{
+ if (!new_acc->grp_write
+ && (lacc->grp_write || rchild->grp_write))
+ {
+ new_acc ->grp_write = true;
+ ret = true;
+ }
+
rchild->grp_hint = 1;
new_acc->grp_hint |= new_acc->grp_read;
if (rchild->first_child)
ret |= propagate_subaccesses_across_link (new_acc, rchild);
}
+ else
+ lacc->grp_write = true;
continue;
}
rchild->grp_hint = 1;
- new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
+ new_acc = create_artificial_child_access (lacc, rchild, norm_offset,
+ lacc->grp_write
+ || rchild->grp_write);
if (new_acc)
{
ret = true;
@@ -2628,9 +2685,17 @@ propagate_all_subaccesses (void)
if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
continue;
lacc = lacc->group_representative;
- if (propagate_subaccesses_across_link (lacc, racc)
- && lacc->first_link)
- add_access_to_work_queue (lacc);
+ if (propagate_subaccesses_across_link (lacc, racc))
+ do
+ {
+ if (lacc->first_link)
+ {
+ add_access_to_work_queue (lacc);
+ break;
+ }
+ lacc = lacc->parent;
+ }
+ while (lacc);
}
}
}