From patchwork Wed Nov 24 04:48:50 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 72789 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 9CD88B70A5 for ; Wed, 24 Nov 2010 15:49:36 +1100 (EST) Received: (qmail 11118 invoked by alias); 24 Nov 2010 04:49:33 -0000 Received: (qmail 11106 invoked by uid 22791); 24 Nov 2010 04:49:31 -0000 X-SWARE-Spam-Status: No, hits=-5.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 24 Nov 2010 04:49:26 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oAO4nOqr019284 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 23 Nov 2010 23:49:24 -0500 Received: from freie.oliva.athome.lsd.ic.unicamp.br (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id oAO4n8Mx008586 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 23 Nov 2010 23:49:17 -0500 Received: from livre.localdomain (livre-to-gw.oliva.athome.lsd.ic.unicamp.br [172.31.160.19]) by freie.oliva.athome.lsd.ic.unicamp.br (8.14.4/8.14.4) with ESMTP id oAO4mx2Y004356 for ; Wed, 24 Nov 2010 02:49:02 -0200 Received: from livre.localdomain (aoliva@localhost [127.0.0.1]) by livre.localdomain (8.14.3/8.14.3/Debian-5+lenny1) with ESMTP id oAO4mubc005776; Wed, 24 Nov 2010 02:48:57 -0200 Received: (from aoliva@localhost) by livre.localdomain (8.14.3/8.14.3/Submit) id oAO4moi5005774; Wed, 24 Nov 2010 02:48:50 -0200 From: Alexandre Oliva To: gcc-patches@gcc.gnu.org Subject: [PR debug/46583] don't prune local type decls Date: Wed, 24 Nov 2010 02:48:50 -0200 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 < >()); +}