This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix handling of non-localized vars and remove_forwarder_block (PR debug/43329)


Hi!

This patch fixes 2 issues:

1) When early inliner inlines some routine and remaps some vars, then later
on they are optimized out and just referenced by DEBUG stmts (so var_ann is
NULL), then normal inliner inlines this function into some other function,
the variables are non-localized.  If we don't want to introduce -g/-g0
code generation differences, we can't do otherwise, unless we stop making
such vars non-localized.  The problem is that we store DECL_ORIGIN of the
var into BLOCK_NONLOCALIZED_VARS, while debug stmts of course reference
the variable that has been remapped during early inlining.  This means
that for many such variables we provide no DW_AT_location nor
DW_AT_const_value, eventhough VTA and var-tracking actually computed its
location.  Fixed by remembering the current variable instead of its origin
in BLOCK_NONLOCALIZED_VARS, and adjusting dwarf2out to cope with such a
change.

2) On the larger testcase I've been wondering why min and this parameters
don't have DEBUG stmts added, when the function is inlined with constant
arguments.  Turns out that they are created, but then during cfg cleanup
they are discarded.  Those 2 DEBUG stmts live in a basic block that
cfg cleanup considers to be a forwarder block (it disregards debug stmts),
and when removing this forwarder block the code wants to move over the debug
stmts after labels of next bb if it has just a single predecessor.
In this case it has just one, but as the single_pred_p test is done
after moving in new incoming edges from the forwarder block, it fails.
And after fixing it I've noticed that it moves/copies over just the first
DEBUG stmt, but possibly many times, so the patch fixes that too.

Bootstrapped/regtested on x86_64-linux and i686-linux.  Even in non-inline
heavy code like cc1 the amount of vars with DW_AT_location attribute
grew from ~ 260000 to ~ 320000.  Ok for trunk?

2010-03-11  Jakub Jelinek  <jakub@redhat.com>

	PR debug/43329
	* tree-inline.c (remap_decls): Put old_var rather than origin_var
	into *nonlocalized_list vector.
	* dwarf2out.c (gen_formal_parameter_die): Call decl_ultimate_origin
	even if origin is non-NULL.
	(gen_variable_die): Likewise.
	(process_scope_var): Don't change origin.
	(gen_decl_die): Likewise.
	* tree-cfgcleanup.c (remove_forwarder_block): Check single_pred_p
	before adding new edges instead of after it, fix moving over
	debug stmts.

	* gcc.dg/guality/pr43329-1.c: New test.

--- gcc/tree-inline.c.jj	2010-02-23 17:50:50.000000000 +0100
+++ gcc/tree-inline.c	2010-03-11 17:04:26.000000000 +0100
@@ -533,7 +533,6 @@ remap_decls (tree decls, VEC(tree,gc) **
   for (old_var = decls; old_var; old_var = TREE_CHAIN (old_var))
     {
       tree new_var;
-      tree origin_var = DECL_ORIGIN (old_var);
 
       if (can_be_nonlocal (old_var, id))
 	{
@@ -545,7 +544,7 @@ remap_decls (tree decls, VEC(tree,gc) **
 	  if ((!optimize || debug_info_level > DINFO_LEVEL_TERSE)
 	      && !DECL_IGNORED_P (old_var)
 	      && nonlocalized_list)
-	    VEC_safe_push (tree, gc, *nonlocalized_list, origin_var);
+	    VEC_safe_push (tree, gc, *nonlocalized_list, old_var);
 	  continue;
 	}
 
@@ -563,7 +562,7 @@ remap_decls (tree decls, VEC(tree,gc) **
 	  if ((!optimize || debug_info_level > DINFO_LEVEL_TERSE)
 	      && !DECL_IGNORED_P (old_var)
 	      && nonlocalized_list)
-	    VEC_safe_push (tree, gc, *nonlocalized_list, origin_var);
+	    VEC_safe_push (tree, gc, *nonlocalized_list, old_var);
 	}
       else
 	{
--- gcc/dwarf2out.c.jj	2010-03-10 19:17:24.000000000 +0100
+++ gcc/dwarf2out.c	2010-03-11 17:20:41.000000000 +0100
@@ -17382,14 +17382,16 @@ gen_formal_parameter_die (tree node, tre
 			  dw_die_ref context_die)
 {
   tree node_or_origin = node ? node : origin;
+  tree ultimate_origin;
   dw_die_ref parm_die
     = new_die (DW_TAG_formal_parameter, context_die, node);
 
   switch (TREE_CODE_CLASS (TREE_CODE (node_or_origin)))
     {
     case tcc_declaration:
-      if (!origin)
-        origin = decl_ultimate_origin (node);
+      ultimate_origin = decl_ultimate_origin (node_or_origin);
+      if (node || ultimate_origin)
+	origin = ultimate_origin;
       if (origin != NULL)
 	add_abstract_origin_attribute (parm_die, origin);
       else
@@ -18106,15 +18108,16 @@ gen_variable_die (tree decl, tree origin
   HOST_WIDE_INT off;
   tree com_decl;
   tree decl_or_origin = decl ? decl : origin;
+  tree ultimate_origin;
   dw_die_ref var_die;
   dw_die_ref old_die = decl ? lookup_decl_die (decl) : NULL;
   dw_die_ref origin_die;
   int declaration = (DECL_EXTERNAL (decl_or_origin)
 		     || class_or_namespace_scope_p (context_die));
 
-  if (!origin)
-    origin = decl_ultimate_origin (decl);
-
+  ultimate_origin = decl_ultimate_origin (decl_or_origin);
+  if (decl || ultimate_origin)
+    origin = ultimate_origin;
   com_decl = fortran_common (decl_or_origin, &off);
 
   /* Symbol in common gets emitted as a child of the common block, in the form
@@ -19160,10 +19163,6 @@ process_scope_var (tree stmt, tree decl,
 {
   dw_die_ref die;
   tree decl_or_origin = decl ? decl : origin;
-  tree ultimate_origin = origin ? decl_ultimate_origin (origin) : NULL;
-
-  if (ultimate_origin)
-    origin = ultimate_origin;
 
   if (TREE_CODE (decl_or_origin) == FUNCTION_DECL)
     die = lookup_decl_die (decl_or_origin);
@@ -19435,7 +19434,7 @@ static void
 gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
 {
   tree decl_or_origin = decl ? decl : origin;
-  tree class_origin = NULL;
+  tree class_origin = NULL, ultimate_origin;
 
   if (DECL_P (decl_or_origin) && DECL_IGNORED_P (decl_or_origin))
     return;
@@ -19481,7 +19480,9 @@ gen_decl_die (tree decl, tree origin, dw
 
       /* If we're emitting a clone, emit info for the abstract instance.  */
       if (origin || DECL_ORIGIN (decl) != decl)
-	dwarf2out_abstract_function (origin ? origin : DECL_ABSTRACT_ORIGIN (decl));
+	dwarf2out_abstract_function (origin
+				     ? DECL_ORIGIN (origin)
+				     : DECL_ABSTRACT_ORIGIN (decl));
 
       /* If we're emitting an out-of-line copy of an inline function,
 	 emit info for the abstract instance and set up to refer to it.  */
@@ -19580,9 +19581,9 @@ gen_decl_die (tree decl, tree origin, dw
 	 complicated because of the possibility that the VAR_DECL really
 	 represents an inlined instance of a formal parameter for an inline
 	 function.  */
-      if (!origin)
-        origin = decl_ultimate_origin (decl);
-      if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL)
+      ultimate_origin = decl_ultimate_origin (decl_or_origin);
+      if (ultimate_origin != NULL_TREE
+	  && TREE_CODE (ultimate_origin) == PARM_DECL)
 	gen_formal_parameter_die (decl, origin,
 				  true /* Emit name attribute.  */,
 				  context_die);
--- gcc/tree-cfgcleanup.c.jj	2010-02-27 11:26:01.000000000 +0100
+++ gcc/tree-cfgcleanup.c	2010-03-11 17:04:26.000000000 +0100
@@ -376,6 +376,7 @@ remove_forwarder_block (basic_block bb)
   gimple label;
   edge_iterator ei;
   gimple_stmt_iterator gsi, gsi_to;
+  bool can_move_debug_stmts;
 
   /* We check for infinite loops already in tree_forwarder_block_p.
      However it may happen that the infinite loop is created
@@ -424,6 +425,8 @@ remove_forwarder_block (basic_block bb)
 	}
     }
 
+  can_move_debug_stmts = single_pred_p (dest);
+
   /* Redirect the edges.  */
   for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
     {
@@ -480,15 +483,16 @@ remove_forwarder_block (basic_block bb)
 
   /* Move debug statements if the destination has just a single
      predecessor.  */
-  if (single_pred_p (dest))
+  if (can_move_debug_stmts)
     {
       gsi_to = gsi_after_labels (dest);
       for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); )
 	{
-	  if (!is_gimple_debug (gsi_stmt (gsi)))
+	  gimple debug = gsi_stmt (gsi);
+	  if (!is_gimple_debug (debug))
 	    break;
 	  gsi_remove (&gsi, false);
-	  gsi_insert_before (&gsi_to, label, GSI_SAME_STMT);
+	  gsi_insert_before (&gsi_to, debug, GSI_SAME_STMT);
 	}
     }
 
--- gcc/testsuite/gcc.dg/guality/pr43329-1.c.jj	2010-03-11 17:04:26.000000000 +0100
+++ gcc/testsuite/gcc.dg/guality/pr43329-1.c	2010-03-11 17:04:26.000000000 +0100
@@ -0,0 +1,50 @@
+/* PR debug/43329 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+static inline void
+foo (int argx)
+{
+  int varx = argx;
+  __asm__ volatile ("nop");			/* { dg-final { gdb-test 10 "argx" "25" } } */
+  __asm__ volatile ("nop" : : "g" (varx));	/* { dg-final { gdb-test 10 "varx" "25" } } */
+}
+
+int i;
+
+__attribute__((noinline))
+void baz (int x)
+{
+  asm volatile ("" : : "r" (x) : "memory");
+}
+
+static inline void
+bar (void)
+{
+  foo (25);
+  i = i + 2;
+  i = i * 2;
+  i = i - 4;
+  baz (i);
+  i = i * 2;
+  i = i >> 1;
+  i = i << 6;
+  baz (i);
+  i = i + 2;
+  i = i * 2;
+  i = i - 4;
+  baz (i);
+  i = i * 2;
+  i = i >> 6;
+  i = i << 1;
+  baz (i);
+}
+
+int
+main (void)
+{
+  __asm__ volatile ("" : "=r" (i) : "0" (0));
+  bar ();
+  bar ();
+  return i;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]