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

Reply via email to