re PR debug/54971 (SRA pessimizes debug info by not creating debug stmts for fields without replacements)

2012-10-26  Martin Jambor  <mjambor@suse.cz>

	PR debug/54971
	* tree-sra.c (struct access): New flag grp_to_be_debug_replaced.
	(dump_access): Dump the new flag.
	(analyze_access_subtree): Set the new flag when appropriate.
	(create_access_replacement): Handle debug replacements differently.
	(generate_subtree_copies): Handle the grp_to_be_debug_replaced flag.
	(init_subtree_with_zero): Likewise.
	(sra_modify_expr): Likewise.
	(load_assign_lhs_subreplacements): Likewise.
	(sra_modify_assign): Likewise.

From-SVN: r192848
This commit is contained in:
Martin Jambor 2012-10-26 18:13:00 +02:00 committed by Martin Jambor
parent a4bbf9102b
commit be384c1080
2 changed files with 166 additions and 14 deletions

View File

@ -1,3 +1,16 @@
2012-10-26 Martin Jambor <mjambor@suse.cz>
PR debug/54971
* tree-sra.c (struct access): New flag grp_to_be_debug_replaced.
(dump_access): Dump the new flag.
(analyze_access_subtree): Set the new flag when appropriate.
(create_access_replacement): Handle debug replacements differently.
(generate_subtree_copies): Handle the grp_to_be_debug_replaced flag.
(init_subtree_with_zero): Likewise.
(sra_modify_expr): Likewise.
(load_assign_lhs_subreplacements): Likewise.
(sra_modify_assign): Likewise.
2012-10-23 Yuri Rumyantsev <ysrumyan@gmail.com>
* config/i386/i386.c (insn_is_function_arg) : Add check on CALL

View File

@ -227,6 +227,10 @@ struct access
/* Set when a scalar replacement should be created for this variable. */
unsigned grp_to_be_replaced : 1;
/* Set when we want a replacement for the sole purpose of having it in
generated debug statements. */
unsigned grp_to_be_debug_replaced : 1;
/* Should TREE_NO_WARNING of a replacement be set? */
unsigned grp_no_warning : 1;
@ -390,7 +394,7 @@ dump_access (FILE *f, struct access *access, bool grp)
"grp_hint = %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_to_be_debug_replaced = %d, grp_maybe_modified = %d, "
"grp_not_necessarilly_dereferenced = %d\n",
access->grp_read, access->grp_write, access->grp_assignment_read,
access->grp_assignment_write, access->grp_scalar_read,
@ -398,7 +402,7 @@ dump_access (FILE *f, struct access *access, bool grp)
access->grp_hint, 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_to_be_debug_replaced, access->grp_maybe_modified,
access->grp_not_necessarilly_dereferenced);
else
fprintf (f, ", write = %d, grp_total_scalarization = %d, "
@ -1528,6 +1532,43 @@ build_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
gsi, insert_after);
}
/* Attempt to build a memory reference that we could but into a gimple
debug_bind statement. Similar to build_ref_for_model but punts if it has to
create statements and return s NULL instead. This function also ignores
alignment issues and so its results should never end up in non-debug
statements. */
static tree
build_debug_ref_for_model (location_t loc, tree base, HOST_WIDE_INT offset,
struct access *model)
{
HOST_WIDE_INT base_offset;
tree off;
if (TREE_CODE (model->expr) == COMPONENT_REF
&& DECL_BIT_FIELD (TREE_OPERAND (model->expr, 1)))
return NULL_TREE;
base = get_addr_base_and_unit_offset (base, &base_offset);
if (!base)
return NULL_TREE;
if (TREE_CODE (base) == MEM_REF)
{
off = build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)),
base_offset + offset / BITS_PER_UNIT);
off = int_const_binop (PLUS_EXPR, TREE_OPERAND (base, 1), off);
base = unshare_expr (TREE_OPERAND (base, 0));
}
else
{
off = build_int_cst (reference_alias_ptr_type (base),
base_offset + offset / BITS_PER_UNIT);
base = build_fold_addr_expr (unshare_expr (base));
}
return fold_build2_loc (loc, MEM_REF, model->type, base, off);
}
/* Construct a memory reference consisting of component_refs and array_refs to
a part of an aggregate *RES (which is of type TYPE). The requested part
should have type EXP_TYPE at be the given OFFSET. This function might not
@ -1861,7 +1902,13 @@ create_access_replacement (struct access *access)
{
tree repl;
repl = create_tmp_var (access->type, "SR");
if (access->grp_to_be_debug_replaced)
{
repl = create_tmp_var_raw (access->type, NULL);
DECL_CONTEXT (repl) = current_function_decl;
}
else
repl = create_tmp_var (access->type, "SR");
if (TREE_CODE (access->type) == COMPLEX_TYPE
|| TREE_CODE (access->type) == VECTOR_TYPE)
{
@ -1930,12 +1977,22 @@ create_access_replacement (struct access *access)
if (dump_file)
{
fprintf (dump_file, "Created a replacement for ");
print_generic_expr (dump_file, access->base, 0);
fprintf (dump_file, " offset: %u, size: %u: ",
(unsigned) access->offset, (unsigned) access->size);
print_generic_expr (dump_file, repl, 0);
fprintf (dump_file, "\n");
if (access->grp_to_be_debug_replaced)
{
fprintf (dump_file, "Created a debug-only replacement for ");
print_generic_expr (dump_file, access->base, 0);
fprintf (dump_file, " offset: %u, size: %u\n",
(unsigned) access->offset, (unsigned) access->size);
}
else
{
fprintf (dump_file, "Created a replacement for ");
print_generic_expr (dump_file, access->base, 0);
fprintf (dump_file, " offset: %u, size: %u: ",
(unsigned) access->offset, (unsigned) access->size);
print_generic_expr (dump_file, repl, 0);
fprintf (dump_file, "\n");
}
}
sra_stats.replacements++;
@ -2144,6 +2201,23 @@ analyze_access_subtree (struct access *root, struct access *parent,
}
else
{
if (MAY_HAVE_DEBUG_STMTS && allow_replacements
&& scalar && !root->first_child
&& (root->grp_scalar_write || root->grp_assignment_write))
{
gcc_checking_assert (!root->grp_scalar_read
&& !root->grp_assignment_read);
root->grp_to_be_debug_replaced = 1;
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Marking ");
print_generic_expr (dump_file, root->base, 0);
fprintf (dump_file, " offset: %u, size: %u ",
(unsigned) root->offset, (unsigned) root->size);
fprintf (dump_file, " to be replaced with debug statements.\n");
}
}
if (covered_to < limit)
hole = true;
if (scalar)
@ -2504,6 +2578,22 @@ generate_subtree_copies (struct access *access, tree agg,
update_stmt (stmt);
sra_stats.subtree_copies++;
}
else if (write
&& access->grp_to_be_debug_replaced
&& (chunk_size == 0
|| access->offset + access->size > start_offset))
{
gimple ds;
tree drhs = build_debug_ref_for_model (loc, agg,
access->offset - top_offset,
access);
ds = gimple_build_debug_bind (get_access_replacement (access),
drhs, gsi_stmt (*gsi));
if (insert_after)
gsi_insert_after (gsi, ds, GSI_NEW_STMT);
else
gsi_insert_before (gsi, ds, GSI_SAME_STMT);
}
if (access->first_child)
generate_subtree_copies (access->first_child, agg, top_offset,
@ -2540,6 +2630,16 @@ init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
update_stmt (stmt);
gimple_set_location (stmt, loc);
}
else if (access->grp_to_be_debug_replaced)
{
gimple ds = gimple_build_debug_bind (get_access_replacement (access),
build_zero_cst (access->type),
gsi_stmt (*gsi));
if (insert_after)
gsi_insert_after (gsi, ds, GSI_NEW_STMT);
else
gsi_insert_before (gsi, ds, GSI_SAME_STMT);
}
for (child = access->first_child; child; child = child->next_sibling)
init_subtree_with_zero (child, gsi, insert_after, loc);
@ -2646,6 +2746,13 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write)
*expr = repl;
sra_stats.exprs++;
}
else if (write && access->grp_to_be_debug_replaced)
{
gimple ds = gimple_build_debug_bind (get_access_replacement (access),
NULL_TREE,
gsi_stmt (*gsi));
gsi_insert_after (gsi, ds, GSI_NEW_STMT);
}
if (access->first_child)
{
@ -2721,10 +2828,11 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
location_t loc = gimple_location (gsi_stmt (*old_gsi));
for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling)
{
HOST_WIDE_INT offset = lacc->offset - left_offset + top_racc->offset;
if (lacc->grp_to_be_replaced)
{
struct access *racc;
HOST_WIDE_INT offset = lacc->offset - left_offset + top_racc->offset;
gimple stmt;
tree rhs;
@ -2764,10 +2872,34 @@ load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
update_stmt (stmt);
sra_stats.subreplacements++;
}
else if (*refreshed == SRA_UDH_NONE
&& lacc->grp_read && !lacc->grp_covered)
*refreshed = handle_unscalarized_data_in_subtree (top_racc,
old_gsi);
else
{
if (*refreshed == SRA_UDH_NONE
&& lacc->grp_read && !lacc->grp_covered)
*refreshed = handle_unscalarized_data_in_subtree (top_racc,
old_gsi);
if (lacc && lacc->grp_to_be_debug_replaced)
{
gimple ds;
tree drhs;
struct access *racc = find_access_in_subtree (top_racc, offset,
lacc->size);
if (racc && racc->grp_to_be_replaced)
drhs = get_access_replacement (racc);
else if (*refreshed == SRA_UDH_LEFT)
drhs = build_debug_ref_for_model (loc, lacc->base, lacc->offset,
lacc);
else if (*refreshed == SRA_UDH_RIGHT)
drhs = build_debug_ref_for_model (loc, top_racc->base, offset,
lacc);
else
drhs = NULL_TREE;
ds = gimple_build_debug_bind (get_access_replacement (lacc),
drhs, gsi_stmt (*old_gsi));
gsi_insert_after (new_gsi, ds, GSI_NEW_STMT);
}
}
if (lacc->first_child)
load_assign_lhs_subreplacements (lacc, top_racc, left_offset,
@ -2982,6 +3114,13 @@ sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi)
}
}
if (lacc && lacc->grp_to_be_debug_replaced)
{
gimple ds = gimple_build_debug_bind (get_access_replacement (lacc),
unshare_expr (rhs), *stmt);
gsi_insert_before (gsi, ds, GSI_SAME_STMT);
}
/* From this point on, the function deals with assignments in between
aggregates when at least one has scalar reductions of some of its
components. There are three possible scenarios: Both the LHS and RHS have