diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5f3c8ac13d6..fcd9f5c6fdc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2012-10-26 Martin Jambor + + 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 * config/i386/i386.c (insn_is_function_arg) : Add check on CALL diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 5acb6125079..65b5ef59e15 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -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