statement? This flag is propagated down the access tree. */
unsigned grp_assignment_read : 1;
+ /* Does this group contain a write access that comes from an assignment
+ statement? This flag is propagated down the access tree. */
+ unsigned grp_assignment_write : 1;
+
/* Other passes of the analysis use this bit to make function
analyze_access_subtree create scalar replacements for this group if
possible. */
if (grp)
fprintf (f, ", grp_write = %d, total_scalarization = %d, "
"grp_read = %d, grp_hint = %d, grp_assignment_read = %d,"
- "grp_covered = %d, grp_unscalarizable_region = %d, "
- "grp_unscalarized_data = %d, grp_partial_lhs = %d, "
- "grp_to_be_replaced = %d, grp_maybe_modified = %d, "
+ "grp_assignment_write = %d, grp_covered = %d, "
+ "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
+ "grp_partial_lhs = %d, grp_to_be_replaced = %d, "
+ "grp_maybe_modified = %d, "
"grp_not_necessarilly_dereferenced = %d\n",
access->grp_write, access->total_scalarization,
access->grp_read, access->grp_hint, access->grp_assignment_read,
- access->grp_covered, access->grp_unscalarizable_region,
- access->grp_unscalarized_data, access->grp_partial_lhs,
- access->grp_to_be_replaced, access->grp_maybe_modified,
+ access->grp_assignment_write, access->grp_covered,
+ access->grp_unscalarizable_region, access->grp_unscalarized_data,
+ access->grp_partial_lhs, access->grp_to_be_replaced,
+ access->grp_maybe_modified,
access->grp_not_necessarilly_dereferenced);
else
fprintf (f, ", write = %d, total_scalarization = %d, "
racc = build_access_from_expr_1 (rhs, stmt, false);
lacc = build_access_from_expr_1 (lhs, stmt, true);
+ if (lacc)
+ lacc->grp_assignment_write = 1;
+
if (racc)
{
racc->grp_assignment_read = 1;
bool grp_write = access->write;
bool grp_read = !access->write;
bool grp_assignment_read = access->grp_assignment_read;
+ bool grp_assignment_write = access->grp_assignment_write;
bool multiple_reads = false;
bool total_scalarization = access->total_scalarization;
bool grp_partial_lhs = access->grp_partial_lhs;
grp_read = true;
}
grp_assignment_read |= ac2->grp_assignment_read;
+ grp_assignment_write |= ac2->grp_assignment_write;
grp_partial_lhs |= ac2->grp_partial_lhs;
unscalarizable_region |= ac2->grp_unscalarizable_region;
total_scalarization |= ac2->total_scalarization;
access->grp_write = grp_write;
access->grp_read = grp_read;
access->grp_assignment_read = grp_assignment_read;
+ access->grp_assignment_write = grp_assignment_write;
access->grp_hint = multiple_reads || total_scalarization;
access->grp_partial_lhs = grp_partial_lhs;
access->grp_unscalarizable_region = unscalarizable_region;
return false;
}
-enum mark_read_status { SRA_MR_NOT_READ, SRA_MR_READ, SRA_MR_ASSIGN_READ};
+enum mark_rw_status { SRA_MRRW_NOTHING, SRA_MRRW_DIRECT, SRA_MRRW_ASSIGN};
/* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set all
sorts of access flags appropriately along the way, notably always set
grp_read and grp_assign_read according to MARK_READ and grp_write when
- MARK_WRITE is true. */
+ MARK_WRITE is true.
+
+ Creating a replacement for a scalar access is considered beneficial if its
+ grp_hint is set (this means we are either attempting total scalarization or
+ there is more than one direct read access) or according to the following
+ table:
+
+ Access written to individually (once or more times)
+ |
+ | Parent written to in an assignment statement
+ | |
+ | | Access read individually _once_
+ | | |
+ | | | Parent read in an assignment statement
+ | | | |
+ | | | | Scalarize Comment
+-----------------------------------------------------------------------------
+ 0 0 0 0 No access for the scalar
+ 0 0 0 1 No access for the scalar
+ 0 0 1 0 No Single read - won't help
+ 0 0 1 1 No The same case
+ 0 1 0 0 No access for the scalar
+ 0 1 0 1 No access for the scalar
+ 0 1 1 0 Yes s = *g; return s.i;
+ 0 1 1 1 Yes The same case as above
+ 1 0 0 0 No Won't help
+ 1 0 0 1 Yes s.i = 1; *g = s;
+ 1 0 1 0 Yes s.i = 5; g = s.i;
+ 1 0 1 1 Yes The same case as above
+ 1 1 0 0 No Won't help.
+ 1 1 0 1 Yes s.i = 1; *g = s;
+ 1 1 1 0 Yes s = *g; return s.i;
+ 1 1 1 1 Yes Any of the above yeses */
static bool
analyze_access_subtree (struct access *root, bool allow_replacements,
- enum mark_read_status mark_read, bool mark_write)
+ enum mark_rw_status mark_read,
+ enum mark_rw_status mark_write)
{
struct access *child;
HOST_WIDE_INT limit = root->offset + root->size;
bool scalar = is_gimple_reg_type (root->type);
bool hole = false, sth_created = false;
bool direct_read = root->grp_read;
+ bool direct_write = root->grp_write;
- if (mark_read == SRA_MR_ASSIGN_READ)
+ if (root->grp_assignment_read)
+ mark_read = SRA_MRRW_ASSIGN;
+ else if (mark_read == SRA_MRRW_ASSIGN)
{
root->grp_read = 1;
root->grp_assignment_read = 1;
}
- if (mark_read == SRA_MR_READ)
+ else if (mark_read == SRA_MRRW_DIRECT)
root->grp_read = 1;
- else if (root->grp_assignment_read)
- mark_read = SRA_MR_ASSIGN_READ;
else if (root->grp_read)
- mark_read = SRA_MR_READ;
+ mark_read = SRA_MRRW_DIRECT;
- if (mark_write)
- root->grp_write = true;
+ if (root->grp_assignment_write)
+ mark_write = SRA_MRRW_ASSIGN;
+ else if (mark_write == SRA_MRRW_ASSIGN)
+ {
+ root->grp_write = 1;
+ root->grp_assignment_write = 1;
+ }
+ else if (mark_write == SRA_MRRW_DIRECT)
+ root->grp_write = 1;
else if (root->grp_write)
- mark_write = true;
+ mark_write = SRA_MRRW_DIRECT;
if (root->grp_unscalarizable_region)
allow_replacements = false;
if (allow_replacements && scalar && !root->first_child
&& (root->grp_hint
- || (root->grp_write && (direct_read || root->grp_assignment_read))))
+ || ((direct_write || root->grp_assignment_write)
+ && (direct_read || root->grp_assignment_read))))
{
if (dump_file && (dump_flags & TDF_DETAILS))
{
while (access)
{
- if (analyze_access_subtree (access, true, SRA_MR_NOT_READ, false))
+ if (analyze_access_subtree (access, true,
+ SRA_MRRW_NOTHING, SRA_MRRW_NOTHING))
ret = true;
access = access->next_grp;
}