Patchwork [PR,debug/46583] don't prune local type decls

login
register
mail settings
Submitter Alexandre Oliva
Date Jan. 19, 2011, 10:24 p.m.
Message ID <or62tkfs5p.fsf@livre.localdomain>
Download mbox | patch
Permalink /patch/79606/
State New
Headers show

Comments

Alexandre Oliva - Jan. 19, 2011, 10:24 p.m.
Ping?

On Nov 24, 2010, Alexandre Oliva <aoliva@redhat.com> wrote:

> Dropping type decls from block locals before inlining affects DECL_UID
> ordering, which may in turn cause -g/-g0 codegen differences.  In the
> given testcase, it's just a -fcompare-debug error, but the test could
> presumably be expanded to trigger actual differences in codegen.

> The problem is that, when we discard a typedef decl from a lexical
> block, and then inline or clone it, we fail to remap it and its
> underlying type at that moment.  We may remap other decls before we even
> get a chance to get to it: if some variable decl uses that type, we'll
> remap the variable before remapping the type, so we've already
> introduced differences.  It would get worse if other significant decls
> stood in between the typedef and the variable decl.

> The problem is further complicated because the decision on whether the
> variable can be nonlocalized depends on whether its type, if needing
> remapping, was already remapped when the time comes to remap the
> variable.  So, if we've removed the typedef from its lexical block and
> there's no intervening use of the type, we won't have remapped it yet,
> and the variable will be kept in the local list.  I'm not sure whether
> this may have additional implications for codegen.

> I'm a bit concerned that the problem might be even more serious:
> discarding random variable declarations might change the order of
> remapping of types, and change which variables are regarded as
> nonlocalized, both of which might have implications to codegen (the
> first one certainly would).

> Now, in C and C++, only local types would have to be remapped in this
> way (global types would reuse the same type AFAIK), and then, if we keep
> local type decls around, we'll remap them before we get to the
> variables, and everything should be fine.  I'm concerned, however, that
> this may not hold for other languages, or maybe even in GNU-extended
> versions of C (nested functions referencing local types of the enclosing
> function come to mind).

> Anyhow, it seems to me that dropping local type decls from lexical
> scopes doesn't buy us much, and even though it is indeed a sledgehammer,
> as richi put it, this fixes the problem, and I can't envision other
> simpler solutions that wouldn't risk running into the problems mentioned
> above, so...

> Regstrapped on x86_64-linux-gnu and i686-pc-linux-gnu.  Ok to install?


> One solution I do envision, which might help, would be to try to figure
> out which types are unused, and discard those.  Say, scan all variables
> within a lexical scope (including nested blocks), deciding which ones
> can be discarded, and then, as we move out of the nesting, we can
> decide, from last to first, which types are unused, and mark as used
> types refereced from retained variables and other types that are used,
> removing those that, when reached during this backward scan, remain
> marked as unused.  Or something along these lines, taking nested
> functions into account, if needed, and anything else I may have missed
> ;-)
Richard Guenther - Jan. 20, 2011, 10:19 a.m.
On Wed, Jan 19, 2011 at 11:24 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
> Ping?
>
> On Nov 24, 2010, Alexandre Oliva <aoliva@redhat.com> wrote:
>
>> Dropping type decls from block locals before inlining affects DECL_UID
>> ordering, which may in turn cause -g/-g0 codegen differences.  In the
>> given testcase, it's just a -fcompare-debug error, but the test could
>> presumably be expanded to trigger actual differences in codegen.
>
>> The problem is that, when we discard a typedef decl from a lexical
>> block, and then inline or clone it, we fail to remap it and its
>> underlying type at that moment.  We may remap other decls before we even
>> get a chance to get to it: if some variable decl uses that type, we'll
>> remap the variable before remapping the type, so we've already
>> introduced differences.  It would get worse if other significant decls
>> stood in between the typedef and the variable decl.
>
>> The problem is further complicated because the decision on whether the
>> variable can be nonlocalized depends on whether its type, if needing
>> remapping, was already remapped when the time comes to remap the
>> variable.  So, if we've removed the typedef from its lexical block and
>> there's no intervening use of the type, we won't have remapped it yet,
>> and the variable will be kept in the local list.  I'm not sure whether
>> this may have additional implications for codegen.
>
>> I'm a bit concerned that the problem might be even more serious:
>> discarding random variable declarations might change the order of
>> remapping of types, and change which variables are regarded as
>> nonlocalized, both of which might have implications to codegen (the
>> first one certainly would).
>
>> Now, in C and C++, only local types would have to be remapped in this
>> way (global types would reuse the same type AFAIK), and then, if we keep
>> local type decls around, we'll remap them before we get to the
>> variables, and everything should be fine.  I'm concerned, however, that
>> this may not hold for other languages, or maybe even in GNU-extended
>> versions of C (nested functions referencing local types of the enclosing
>> function come to mind).
>
>> Anyhow, it seems to me that dropping local type decls from lexical
>> scopes doesn't buy us much, and even though it is indeed a sledgehammer,
>> as richi put it, this fixes the problem, and I can't envision other
>> simpler solutions that wouldn't risk running into the problems mentioned
>> above, so...
>
>> Regstrapped on x86_64-linux-gnu and i686-pc-linux-gnu.  Ok to install?
>
>
>> One solution I do envision, which might help, would be to try to figure
>> out which types are unused, and discard those.  Say, scan all variables
>> within a lexical scope (including nested blocks), deciding which ones
>> can be discarded, and then, as we move out of the nesting, we can
>> decide, from last to first, which types are unused, and mark as used
>> types refereced from retained variables and other types that are used,
>> removing those that, when reached during this backward scan, remain
>> marked as unused.  Or something along these lines, taking nested
>> functions into account, if needed, and anything else I may have missed
>> ;-)

Ok.

Thanks,
Richard.

>
>
> --
> Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
> You must be the change you wish to see in the world. -- Gandhi
> Be Free! -- http://FSFLA.org/   FSF Latin America board member
> Free Software Evangelist      Red Hat Brazil Compiler Engineer
>
>

Patch

for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR debug/46583
	* tree-ssa-live.c (remove_unused_scope_block_p): Keep type decls.

for  gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR debug/46583
	* g++.dg/debug/pr46583.C: New.

Index: gcc/tree-ssa-live.c
===================================================================
--- gcc/tree-ssa-live.c.orig	2010-11-21 04:57:04.505193778 -0200
+++ gcc/tree-ssa-live.c	2010-11-21 04:53:31.279647303 -0200
@@ -491,11 +491,16 @@  remove_unused_scope_block_p (tree scope)
 	 can be considered dead.  We only want to keep around blocks user can
 	 breakpoint into and ask about value of optimized out variables.
 
-	 Similarly we need to keep around types at least until all variables of
-	 all nested blocks are gone.  We track no information on whether given
-	 type is used or not.  */
+	 Similarly we need to keep around types at least until all
+	 variables of all nested blocks are gone.  We track no
+	 information on whether given type is used or not, so we have
+	 to keep them even when not emitting debug information,
+	 otherwise we may end up remapping variables and their (local)
+	 types in different orders depending on whether debug
+	 information is being generated.  */
 
-      else if (debug_info_level == DINFO_LEVEL_NORMAL
+      else if (TREE_CODE (*t) == TYPE_DECL
+	       || debug_info_level == DINFO_LEVEL_NORMAL
 	       || debug_info_level == DINFO_LEVEL_VERBOSE)
 	;
       else
Index: gcc/testsuite/g++.dg/debug/pr46583.C
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/g++.dg/debug/pr46583.C	2010-11-21 04:56:07.361194389 -0200
@@ -0,0 +1,40 @@ 
+// PR debug/46583
+// { dg-do compile }
+// { dg-options "-O -fno-inline -fipa-cp -fipa-cp-clone -fcompare-debug" }
+
+template < typename = unsigned long >struct A
+{
+  unsigned long elems[3];
+  unsigned long *begin ()
+  {
+    return 0;
+  }
+};
+
+void
+bar (unsigned long *a1, unsigned long, unsigned long *a3, unsigned const &)
+{
+  *a3 = *a1;
+}
+
+A < >operatorM (A < >a1, unsigned long a2)
+{
+  typedef A < >G;
+  G a3;
+  bar (a1.begin (), a2, a3.begin (), 0);
+  return a3;
+}
+
+struct B
+{
+  B (A < >m):n (operatorM (m, 1))
+  {
+  }
+  A < >n;
+};
+
+void
+foo ()
+{
+  B (A < >());
+}