return acc && acc->first_child;
}
+/* Return true iff ACC is (partly) covered by at least one replacement. */
+
+static bool
+access_has_replacements_p (struct access *acc)
+{
+ struct access *child;
+ if (acc->grp_to_be_replaced)
+ return true;
+ for (child = acc->first_child; child; child = child->next_sibling)
+ if (access_has_replacements_p (child))
+ return true;
+ return false;
+}
+
/* Return a vector of pointers to accesses for the variable given in BASE or
NULL if there is none. */
&& (root->grp_scalar_write || root->grp_assignment_write))))
{
bool new_integer_type;
- if (TREE_CODE (root->type) == ENUMERAL_TYPE)
+ /* Always create access replacements that cover the whole access.
+ For integral types this means the precision has to match.
+ Avoid assumptions based on the integral type kind, too. */
+ if (INTEGRAL_TYPE_P (root->type)
+ && (TREE_CODE (root->type) != INTEGER_TYPE
+ || TYPE_PRECISION (root->type) != root->size)
+ /* But leave bitfield accesses alone. */
+ && (root->offset % BITS_PER_UNIT) == 0)
{
tree rt = root->type;
- root->type = build_nonstandard_integer_type (TYPE_PRECISION (rt),
+ root->type = build_nonstandard_integer_type (root->size,
TYPE_UNSIGNED (rt));
+ root->expr = build_ref_for_offset (UNKNOWN_LOCATION,
+ root->base, root->offset,
+ root->type, NULL, false);
new_integer_type = true;
}
else
force_gimple_rhs = true;
sra_stats.exprs++;
}
+ else if (racc
+ && !racc->grp_unscalarized_data
+ && TREE_CODE (lhs) == SSA_NAME
+ && !access_has_replacements_p (racc))
+ {
+ rhs = get_repl_default_def_ssa_name (racc);
+ modify_this_stmt = true;
+ sra_stats.exprs++;
+ }
if (modify_this_stmt)
{
generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
gsi, true, true, loc);
sra_stats.separate_lhs_rhs_handling++;
+
+ /* This gimplification must be done after generate_subtree_copies,
+ lest we insert the subtree copies in the middle of the gimplified
+ sequence. */
+ if (force_gimple_rhs)
+ rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
+ true, GSI_SAME_STMT);
+ if (gimple_assign_rhs1 (*stmt) != rhs)
+ {
+ modify_this_stmt = true;
+ gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
+ gcc_assert (*stmt == gsi_stmt (orig_gsi));
+ }
+
+ return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
}
else
{
}
else
{
- if (racc)
+ if (access_has_children_p (racc)
+ && !racc->grp_unscalarized_data)
{
- if (!racc->grp_to_be_replaced && !racc->grp_unscalarized_data)
+ if (dump_file)
{
- if (dump_file)
- {
- fprintf (dump_file, "Removing load: ");
- print_gimple_stmt (dump_file, *stmt, 0, 0);
- }
-
- if (TREE_CODE (lhs) == SSA_NAME)
- {
- rhs = get_repl_default_def_ssa_name (racc);
- if (!useless_type_conversion_p (TREE_TYPE (lhs),
- TREE_TYPE (rhs)))
- rhs = fold_build1_loc (loc, VIEW_CONVERT_EXPR,
- TREE_TYPE (lhs), rhs);
- }
- else
- {
- if (racc->first_child)
- generate_subtree_copies (racc->first_child, lhs,
- racc->offset, 0, 0, gsi,
- false, false, loc);
-
- gcc_assert (*stmt == gsi_stmt (*gsi));
- unlink_stmt_vdef (*stmt);
- gsi_remove (gsi, true);
- sra_stats.deleted++;
- return SRA_AM_REMOVED;
- }
+ fprintf (dump_file, "Removing load: ");
+ print_gimple_stmt (dump_file, *stmt, 0, 0);
}
- else if (racc->first_child)
- generate_subtree_copies (racc->first_child, lhs, racc->offset,
- 0, 0, gsi, false, true, loc);
+ generate_subtree_copies (racc->first_child, lhs,
+ racc->offset, 0, 0, gsi,
+ false, false, loc);
+ gcc_assert (*stmt == gsi_stmt (*gsi));
+ unlink_stmt_vdef (*stmt);
+ gsi_remove (gsi, true);
+ sra_stats.deleted++;
+ return SRA_AM_REMOVED;
}
+ /* Restore the aggregate RHS from its components so the
+ prevailing aggregate copy does the right thing. */
+ if (access_has_children_p (racc))
+ generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
+ gsi, false, false, loc);
+ /* Re-load the components of the aggregate copy destination.
+ But use the RHS aggregate to load from to expose more
+ optimization opportunities. */
if (access_has_children_p (lacc))
generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
0, 0, gsi, true, true, loc);
}
- }
- /* This gimplification must be done after generate_subtree_copies, lest we
- insert the subtree copies in the middle of the gimplified sequence. */
- if (force_gimple_rhs)
- rhs = force_gimple_operand_gsi (&orig_gsi, rhs, true, NULL_TREE,
- true, GSI_SAME_STMT);
- if (gimple_assign_rhs1 (*stmt) != rhs)
- {
- modify_this_stmt = true;
- gimple_assign_set_rhs_from_tree (&orig_gsi, rhs);
- gcc_assert (*stmt == gsi_stmt (orig_gsi));
+ return SRA_AM_NONE;
}
-
- return modify_this_stmt ? SRA_AM_MODIFIED : SRA_AM_NONE;
}
/* Traverse the function body and all modifications as decided in