From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5542 invoked by alias); 23 Jan 2015 18:45:25 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 5479 invoked by uid 89); 23 Jan 2015 18:45:18 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-0.9 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,SPF_HELO_PASS,SPF_PASS,T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 23 Jan 2015 18:45:14 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t0NIjBvm020908 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 23 Jan 2015 13:45:12 -0500 Received: from reynosa.quesejoda.com (vpn-60-145.rdu2.redhat.com [10.10.60.145]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t0NIjAEj013536; Fri, 23 Jan 2015 13:45:10 -0500 Message-ID: <54C296B5.4050506@redhat.com> Date: Fri, 23 Jan 2015 19:53:00 -0000 From: Aldy Hernandez User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: Jason Merrill CC: Richard Biener , gcc-patches Subject: Re: [debug-early] C++ clones and limbo DIEs References: <54B87E5B.1090502@redhat.com> <54B88149.1040906@redhat.com> <54B94F4D.4040009@redhat.com> <54B97854.7040007@redhat.com> In-Reply-To: <54B97854.7040007@redhat.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-SW-Source: 2015-01/txt/msg02129.txt.bz2 Phew... ok, I'm a little stuck here with the interaction between dwarf2out and LTO, and I'm hoping y'all can shed some light. Please bear with me through the verbosity, it gets clearer (I hope) near the end. On 01/16/2015 12:45 PM, Jason Merrill wrote: > On 01/16/2015 12:50 PM, Aldy Hernandez wrote: >>> Can you remove the first flush and just do it in the second place? >> >> If I only flush the limbo list in the second place, that's basically >> what mainline does, albeit abstracted into a function. I thought the >> whole point was to get rid of the limbo list, or at least keep it from >> being a structure that has to go through LTO streaming. > > It would expect it to be before free_lang_data and LTO streaming. The reason this wouldn't make a difference is because, as it stands, dwarf for the clones are not generated until final.c: if (!DECL_IGNORED_P (current_function_decl)) debug_hooks->function_decl (current_function_decl); which happens after free_lang_data. However, we can generate early dwarf for the clones right from the parser, and things _mostly_ work: diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 62e32d2..5539244 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -539,6 +539,11 @@ maybe_clone_body (tree fn) /* Start processing the function. */ start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED); + /* Generate early dwarf for the clone now that we have a body + for it. */ + debug_hooks->early_global_decl (clone); + /* Tell cgraph if both ctors or both dtors are known to have the same body. */ if (can_alias And I say _mostly_ work, because now local statics will have the DECL_ABSTRACT_P bit set, making LTO think that things live in another partition, and are no longer trivially needed. For instance: struct TYPE { TYPE (int); } ; TYPE::TYPE (int some_argument) { static int static_p = 5; } With the above patch, early dwarf generation will call gen_decl_die, which eventually does: /* If we're emitting a clone, emit info for the abstract instance. */ if (origin || DECL_ORIGIN (decl) != decl) dwarf2out_abstract_function (origin ? DECL_ORIGIN (origin) : DECL_ABSTRACT_ORIGIN (decl)); Where decl and DECL_ABSTRACT_ORIGIN(decl) are: (gdb) p decl $87 = (gdb) p decl.decl_common.abstract_origin $88 = Now dwarf2out_abstract_function() will set DECL_ABSTRACT_P for all the children of the abstract origin: was_abstract = DECL_ABSTRACT_P (decl); set_decl_abstract_flags (decl, 1); dwarf2out_decl (decl); if (! was_abstract) set_decl_abstract_flags (decl, 0); Unfortunately, this sets DECL_ABSTRACT_P for the "static_p" above, and refuses to unset it after the call to dwarf2out_decl. Through some miraculous gymnastics, LTO streams out symbols without the "analyzed" bit set if things are not "in partition", which happens because symtab_node::get_partitioning_class() returns SYMBOL_EXTERNAL (ahem, not in partition) when the DECL_ABSTRACT_P bit is set. So... dwarf2out_abstract_function() sets the DECL_ABSTRACT_P bit, and LTO thinks that local statics in a clone are in another partition, which causes the analyzed bit to be dropped on the floor, which causes symbol_table::remove_unreferenced_decls() to no longer think that local statics are trivially needed. And if the local static is no longer needed, varpool will not output its definition in the assembly file. I am very uncomfortable with a call to dwarf2out_abstract_function() changing the behavior of the LTO streamer (and the optimizers), but it looks like twiddling the DECL_ABSTRACT_P flag (and refusing to reset it) is by design. I am all ears on solutions on either the LTO or the dwarf side. Thanks. Aldy