From patchwork Wed Jan 19 22:24:50 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [PR,debug/46583] don't prune local type decls From: Alexandre Oliva X-Patchwork-Id: 79606 Message-Id: To: gcc-patches@gcc.gnu.org Date: Wed, 19 Jan 2011 20:24:50 -0200 Ping? On Nov 24, 2010, Alexandre Oliva 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 > ;-) for gcc/ChangeLog from Alexandre Oliva PR debug/46583 * tree-ssa-live.c (remove_unused_scope_block_p): Keep type decls. for gcc/testsuite/ChangeLog from Alexandre Oliva 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 < >()); +}