From patchwork Tue Jul 13 03:12:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 1504328 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GP5LM6Wxrz9sWd for ; Tue, 13 Jul 2021 13:13:15 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id ABDB0393C869 for ; Tue, 13 Jul 2021 03:13:13 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from rock.gnat.com (rock.gnat.com [205.232.38.15]) by sourceware.org (Postfix) with ESMTPS id 9AEA4383B437 for ; Tue, 13 Jul 2021 03:13:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 9AEA4383B437 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 746DE116256; Mon, 12 Jul 2021 23:13:00 -0400 (EDT) X-Virus-Scanned: Debian amavisd-new at gnat.com Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id Uqx705Ip-Uw7; Mon, 12 Jul 2021 23:13:00 -0400 (EDT) Received: from free.home (tron.gnat.com [IPv6:2620:20:4000:0:46a8:42ff:fe0e:e294]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by rock.gnat.com (Postfix) with ESMTPS id 00C061161E8; Mon, 12 Jul 2021 23:12:59 -0400 (EDT) Received: from livre (livre.home [172.31.160.2]) by free.home (8.15.2/8.15.2) with ESMTPS id 16D3Cok7104207 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 13 Jul 2021 00:12:51 -0300 From: Alexandre Oliva To: gcc-patches@gcc.gnu.org Subject: avoid early reference to debug-only symbol Organization: Free thinker, does not speak for AdaCore Date: Tue, 13 Jul 2021 00:12:50 -0300 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jim Wilson Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" If some IPA pass replaces the only reference to a constant non-public non-automatic variable with its initializer, namely the address of another such variable, the former becomes unreferenced and it's discarded by symbol_table::remove_unreachable_nodes. It calls debug_hooks->late_global_decl while at that, and this expands the initializer, which assigs RTL to the latter variable and forces it to be retained by remove_unreferenced_decls, and eventually be output despite not being referenced. Without debug information, it's not output. This has caused a bootstrap-debug compare failure in libdecnumber/decContext.o, while developing a transformation that ends up enabling the above substitution in constprop. This patch makes reference_to_unused slightly more conservative about such variables at the end of IPA passes, falling back onto expand_debug_expr for expressions referencing symbols that might or might not be output, avoiding the loss of debug information when the symbol is output, while avoiding a symbol output only because of debug info. Regstrapped on x86_64-linux-gnu. Ok to install? for gcc/ChangeLog * dwarf2out.c (add_const_value_attribute): Return false if resolve_one_addr fails. (reference_to_unused): Don't assume local symbol presence while it can still be optimized out. (rtl_for_decl_init): Fallback to expand_debug_expr. * cfgexpand.c (expand_debug_expr): Export. * expr.h (expand_debug_expr): Declare. --- gcc/cfgexpand.c | 12 +++++++++--- gcc/dwarf2out.c | 15 +++++++++++++-- gcc/expr.h | 2 ++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 3edd53c37dcb3..b731a5598230c 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -91,8 +91,6 @@ struct ssaexpand SA; of comminucating the profile info to the builtin expanders. */ gimple *currently_expanding_gimple_stmt; -static rtx expand_debug_expr (tree); - static bool defer_stack_allocation (tree, bool); static void record_alignment_for_reg_var (unsigned int); @@ -4413,7 +4411,7 @@ expand_debug_parm_decl (tree decl) /* Return an RTX equivalent to the value of the tree expression EXP. */ -static rtx +rtx expand_debug_expr (tree exp) { rtx op0 = NULL_RTX, op1 = NULL_RTX, op2 = NULL_RTX; @@ -5285,6 +5283,14 @@ expand_debug_expr (tree exp) else goto flag_unsupported; + case COMPOUND_LITERAL_EXPR: + exp = COMPOUND_LITERAL_EXPR_DECL_EXPR (exp); + /* DECL_EXPR is a tcc_statement, which expand_debug_expr does + not expect, so instead of recursing we take care of it right + away. */ + exp = DECL_EXPR_DECL (exp); + return expand_debug_expr (exp); + case CALL_EXPR: /* ??? Maybe handle some builtins? */ return NULL; diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 82783c4968b85..bb7e2b8dc4e2c 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -20170,7 +20170,8 @@ add_const_value_attribute (dw_die_ref die, rtx rtl) if (dwarf_version >= 4 || !dwarf_strict) { dw_loc_descr_ref loc_result; - resolve_one_addr (&rtl); + if (!resolve_one_addr (&rtl)) + return false; rtl_addr: loc_result = new_addr_loc_descr (rtl, dtprel_false); add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0)); @@ -20255,6 +20256,12 @@ reference_to_unused (tree * tp, int * walk_subtrees, varpool_node *node = varpool_node::get (*tp); if (!node || !node->definition) return *tp; + /* If it's local, it might still be optimized out, unless we've + already committed to outputting it by assigning RTL to it. */ + if (! TREE_PUBLIC (*tp) && ! TREE_ASM_WRITTEN (*tp) + && symtab->state <= IPA_SSA_AFTER_INLINING + && ! DECL_RTL_SET_P (*tp)) + return *tp; } else if (TREE_CODE (*tp) == FUNCTION_DECL && (!DECL_EXTERNAL (*tp) || DECL_DECLARED_INLINE_P (*tp))) @@ -20279,6 +20286,7 @@ static rtx rtl_for_decl_init (tree init, tree type) { rtx rtl = NULL_RTX; + bool valid_p = false; STRIP_NOPS (init); @@ -20322,7 +20330,7 @@ rtl_for_decl_init (tree init, tree type) /* If the initializer is something that we know will expand into an immediate RTL constant, expand it now. We must be careful not to reference variables which won't be output. */ - else if (initializer_constant_valid_p (init, type) + else if ((valid_p = initializer_constant_valid_p (init, type)) && ! walk_tree (&init, reference_to_unused, NULL, NULL)) { /* Convert vector CONSTRUCTOR initializers to VECTOR_CST if @@ -20367,6 +20375,9 @@ rtl_for_decl_init (tree init, tree type) /* If expand_expr returns a MEM, it wasn't immediate. */ gcc_assert (!rtl || !MEM_P (rtl)); } + else if (valid_p) + /* Perhaps we could just use this and skip all of the above? */ + rtl = expand_debug_expr (init); return rtl; } diff --git a/gcc/expr.h b/gcc/expr.h index a4f44265759ce..7b060462020be 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -307,6 +307,8 @@ expand_normal (tree exp) return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL, false); } +/* This one is defined in cfgexpand.c. */ +extern rtx expand_debug_expr (tree); /* Return STRING_CST and set offset, size and decl, if the first argument corresponds to a string constant. */