Hi, the following patch fixes PR 54971 by creating extra for-debug-statements-only declarations for parts of aggregates that are never read and then creates debug bind statements so that the value of the non-used part is accessible from debug info.
Bootstrapped and tested on x86_64-linux without any problems, OK for trunk? Thanks, Martin 2012-10-25 Martin Jambor <mjam...@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. (build_debug_ref_for_model): New function. (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. *** /tmp/HYIEed_tree-sra.c Fri Oct 26 11:11:26 2012 --- gcc/tree-sra.c Fri Oct 26 00:54:18 2012 *************** struct access *** 227,232 **** --- 227,236 ---- /* 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; *************** dump_access (FILE *f, struct access *acc *** 390,396 **** "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_not_necessarilly_dereferenced = %d\n", access->grp_read, access->grp_write, access->grp_assignment_read, access->grp_assignment_write, access->grp_scalar_read, --- 394,400 ---- "grp_hint = %d, grp_covered = %d, " "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, " "grp_partial_lhs = %d, grp_to_be_replaced = %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, *************** dump_access (FILE *f, struct access *acc *** 398,404 **** 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_not_necessarilly_dereferenced); else fprintf (f, ", write = %d, grp_total_scalarization = %d, " --- 402,408 ---- 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_to_be_debug_replaced, access->grp_maybe_modified, access->grp_not_necessarilly_dereferenced); else fprintf (f, ", write = %d, grp_total_scalarization = %d, " *************** build_ref_for_model (location_t loc, tre *** 1528,1533 **** --- 1532,1574 ---- 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 *************** create_access_replacement (struct access *** 1861,1867 **** { tree repl; ! repl = create_tmp_var (access->type, "SR"); if (TREE_CODE (access->type) == COMPLEX_TYPE || TREE_CODE (access->type) == VECTOR_TYPE) { --- 1902,1914 ---- { tree repl; ! 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) { *************** create_access_replacement (struct access *** 1930,1941 **** 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"); } sra_stats.replacements++; --- 1977,1998 ---- if (dump_file) { ! 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++; *************** analyze_access_subtree (struct access *r *** 2144,2149 **** --- 2201,2223 ---- } 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) *************** generate_subtree_copies (struct access * *** 2504,2509 **** --- 2578,2599 ---- 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, *************** init_subtree_with_zero (struct access *a *** 2540,2545 **** --- 2630,2645 ---- 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); *************** sra_modify_expr (tree *expr, gimple_stmt *** 2646,2651 **** --- 2746,2758 ---- *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) { *************** load_assign_lhs_subreplacements (struct *** 2721,2730 **** location_t loc = gimple_location (gsi_stmt (*old_gsi)); for (lacc = lacc->first_child; lacc; lacc = lacc->next_sibling) { if (lacc->grp_to_be_replaced) { struct access *racc; - HOST_WIDE_INT offset = lacc->offset - left_offset + top_racc->offset; gimple stmt; tree rhs; --- 2828,2838 ---- 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; gimple stmt; tree rhs; *************** load_assign_lhs_subreplacements (struct *** 2764,2773 **** 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); if (lacc->first_child) load_assign_lhs_subreplacements (lacc, top_racc, left_offset, --- 2872,2905 ---- 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); ! 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, *************** sra_modify_assign (gimple *stmt, gimple_ *** 2982,2987 **** --- 3114,3126 ---- } } + 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