re PR debug/54971 (SRA pessimizes debug info by not creating debug stmts for fields...
authorMartin Jambor <mjambor@suse.cz>
Fri, 26 Oct 2012 16:13:00 +0000 (18:13 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Fri, 26 Oct 2012 16:13:00 +0000 (18:13 +0200)
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

gcc/ChangeLog
gcc/tree-sra.c

index 5f3c8ac13d63a9c5c16baf4662f8f69b171405cf..fcd9f5c6fdc606cc5aec30eff4afd0df04329b5b 100644 (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
index 5acb61250795b0da92bb88c667071585b37758c9..65b5ef59e151c9344c249f64baa292c762eb7a3b 100644 (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