From patchwork Sat Nov 12 01:44:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60461 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DFD1438356B9 for ; Sat, 12 Nov 2022 01:45:19 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [IPv6:2001:67c:2178:6::1d]) by sourceware.org (Postfix) with ESMTPS id 06DE438438E2 for ; Sat, 12 Nov 2022 01:45:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 06DE438438E2 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 279C91F45F; Sat, 12 Nov 2022 01:44:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217499; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=f+AMXUZu0LSwpdChPA2uh8bqC5Pzw0FQQ5zFXWdPnXI=; b=kTBrj2yYt3A4aPTJy8f7GkOvI0vGcJRY+Rir3duGKlrKY/BljjAiNwrfmjR+KC0bMnTj0U lhvwYGPsawm/25iFNg1XZ8qA2Hx2K/xqZ2/hG/r7O6L/PKWUCrGnTNPMfN2WlIA12k7rpC CeLn1/cJI4rskT92AYMafAaFZW97flc= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217499; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=f+AMXUZu0LSwpdChPA2uh8bqC5Pzw0FQQ5zFXWdPnXI=; b=zIC0SsRPeRNIKzyZ5cSWJV9z02rlP6mO4t2/19Tk5aDc4gjBTqJlXsT3aN09FH3hRToZLa Gergk2Thd4dMqnBA== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 19B0413273; Sat, 12 Nov 2022 01:44:59 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 5es9Bpv6bmNeYwAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:44:59 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 01/12] ipa: IPA-SRA split detection simplification User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:44:58 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, I have noticed that the flag m_split_modifications_p of ipa_param_body_adjustments is not really necessary as it has to correspond to whether m_replacements is non-empty so this patch removes it. This also simplifies a bit some patches I work on. Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2022-11-10 Martin Jambor * ipa-param-manipulation.cc (ipa_param_body_adjustments::common_initialization): Do not set m_split_modifications_p. (ipa_param_body_adjustments::ipa_param_body_adjustments): Remove initializations of m_split_modifications_p. (ipa_param_body_adjustments::modify_call_stmt): Check that m_replacements is empty instead of m_split_modifications_p. --- gcc/ipa-param-manipulation.cc | 29 +++++++++++++---------------- gcc/ipa-param-manipulation.h | 4 ---- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/gcc/ipa-param-manipulation.cc b/gcc/ipa-param-manipulation.cc index 23a8cb84d48..cee0e23f946 100644 --- a/gcc/ipa-param-manipulation.cc +++ b/gcc/ipa-param-manipulation.cc @@ -1378,7 +1378,6 @@ ipa_param_body_adjustments::common_initialization (tree old_fndecl, if (apm->op == IPA_PARAM_OP_SPLIT) { - m_split_modifications_p = true; split[prev_index] = true; register_replacement (apm, new_parm); } @@ -1472,10 +1471,10 @@ ipa_param_body_adjustments ::ipa_param_body_adjustments (vec *adj_params, tree fndecl) : m_adj_params (adj_params), m_adjustments (NULL), m_reset_debug_decls (), - m_split_modifications_p (false), m_dead_stmts (), m_dead_ssas (), - m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl), - m_id (NULL), m_oparms (), m_new_decls (), m_new_types (), m_replacements (), - m_removed_decls (), m_removed_map (), m_method2func (false) + m_dead_stmts (), m_dead_ssas (), m_dead_ssa_debug_equiv (), + m_dead_stmt_debug_equiv (), m_fndecl (fndecl), m_id (NULL), m_oparms (), + m_new_decls (), m_new_types (), m_replacements (), m_removed_decls (), + m_removed_map (), m_method2func (false) { common_initialization (fndecl, NULL, NULL); } @@ -1489,11 +1488,10 @@ ipa_param_body_adjustments ::ipa_param_body_adjustments (ipa_param_adjustments *adjustments, tree fndecl) : m_adj_params (adjustments->m_adj_params), m_adjustments (adjustments), - m_reset_debug_decls (), m_split_modifications_p (false), m_dead_stmts (), - m_dead_ssas (), m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), - m_fndecl (fndecl), m_id (NULL), m_oparms (), m_new_decls (), - m_new_types (), m_replacements (), m_removed_decls (), m_removed_map (), - m_method2func (false) + m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (), + m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl), + m_id (NULL), m_oparms (), m_new_decls (), m_new_types (), m_replacements (), + m_removed_decls (), m_removed_map (), m_method2func (false) { common_initialization (fndecl, NULL, NULL); } @@ -1513,11 +1511,10 @@ ipa_param_body_adjustments copy_body_data *id, tree *vars, vec *tree_map) : m_adj_params (adjustments->m_adj_params), m_adjustments (adjustments), - m_reset_debug_decls (), m_split_modifications_p (false), m_dead_stmts (), - m_dead_ssas (), m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), - m_fndecl (fndecl), m_id (id), m_oparms (), m_new_decls (), m_new_types (), - m_replacements (), m_removed_decls (), m_removed_map (), - m_method2func (false) + m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (), + m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl), + m_id (id), m_oparms (), m_new_decls (), m_new_types (), m_replacements (), + m_removed_decls (), m_removed_map (), m_method2func (false) { common_initialization (old_fndecl, vars, tree_map); } @@ -1979,7 +1976,7 @@ ipa_param_body_adjustments::modify_call_stmt (gcall **stmt_p, && m_dead_ssas.contains (t)) recreate = true; - if (!m_split_modifications_p) + if (m_replacements.is_empty ()) continue; tree base; diff --git a/gcc/ipa-param-manipulation.h b/gcc/ipa-param-manipulation.h index a9ad2b216be..e5654f4ff70 100644 --- a/gcc/ipa-param-manipulation.h +++ b/gcc/ipa-param-manipulation.h @@ -350,10 +350,6 @@ public: auto_vec m_reset_debug_decls; - /* Set to true if there are any IPA_PARAM_OP_SPLIT adjustments among stored - adjustments. */ - bool m_split_modifications_p; - /* Sets of statements and SSA_NAMEs that only manipulate data from parameters removed because they are not necessary. */ hash_set m_dead_stmts; From patchwork Sat Nov 12 01:45:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60463 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2A69638418A5 for ; Sat, 12 Nov 2022 01:45:47 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2001:67c:2178:6::1c]) by sourceware.org (Postfix) with ESMTPS id DB6BF3887F4E for ; Sat, 12 Nov 2022 01:45:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DB6BF3887F4E Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 1D0D222532; Sat, 12 Nov 2022 01:45:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217529; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=QsMZeET++YKl7lHt01TlkcYrSM751unyF63gH3XR0t4=; b=Q2FhlRM5Z5fC8CvsoQPIW+nzt2jxlRQCeXaCuZ8EdM0a3fNpnbjH6+FLL000byGIuRijqL QDMPuExSEeykzjj8QMhmK4aH5J5YudtBe2xsGI/g+qAbFe86RmOPAv5xpLE99GMm0wx/R1 pAdODcGVe5A2K8M8gijQWsoWWPVDl7Q= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217529; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=QsMZeET++YKl7lHt01TlkcYrSM751unyF63gH3XR0t4=; b=5jQMnZns7e7bEl24o5CGTlhPWnSsjADDIrAImKm+oVFTSlJrxrcf6AxtcTMjERdkoVr9I5 rHOyHgZgGolFHwDw== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 0E1AE13273; Sat, 12 Nov 2022 01:45:29 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id KD05A7n6bmO4YwAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:45:29 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 02/12] ipa-cp: Do not consider useless aggregate constants User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:45:28 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, When building vectors of known aggregate values, there is no point in including those for parameters which are not used in any way whatsoever. Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2022-11-11 Martin Jambor * ipa-cp.cc (push_agg_values_from_edge): Do not consider constants in unused aggregate parameters. --- gcc/ipa-cp.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc index d2bcd5e5e69..02bd6a0fd1a 100644 --- a/gcc/ipa-cp.cc +++ b/gcc/ipa-cp.cc @@ -5783,7 +5783,8 @@ push_agg_values_from_edge (struct cgraph_edge *cs, } ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, index); - if (plats->aggs_bottom) + if (!ipa_is_param_used (dest_info, index) + || plats->aggs_bottom) continue; push_agg_values_for_index_from_edge (cs, index, res, interim); } From patchwork Sat Nov 12 01:45:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60464 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 488BF3894C18 for ; Sat, 12 Nov 2022 01:46:19 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by sourceware.org (Postfix) with ESMTPS id 5C18C388A026 for ; Sat, 12 Nov 2022 01:45:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 5C18C388A026 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 7B5411F381; Sat, 12 Nov 2022 01:45:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217541; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=SpMEI3LeCnotike/OoRx5l/IXKOha7SAc93Z6mILflA=; b=2yf/g3kUPVo5OKIGBOLvANNdYWZzJB9l1tyLdoIVrAOnNr/UjbJ6ZhngUn9SbOXFk5h2+s 4cXAi9UEuBcjtW+JuX6SjauxcOhJqSCRAdSwb7FgGQxQNwTkNYfMWJ/xuHKs0b48G3BQjc DvJiy6Nl3tfa0SddVFx5qZUeMsfPyPg= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217541; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=SpMEI3LeCnotike/OoRx5l/IXKOha7SAc93Z6mILflA=; b=E/Ig7ouzvlLJPcW9flSiYB6paOtL0ro9iprUIwhLNzCtM5OTmXhKZ4rni9tmuXqSSetZcV K9YhflZjJ+kLcKBw== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 6C43613273; Sat, 12 Nov 2022 01:45:41 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id oVVWGsX6bmPTYwAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:45:41 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 03/12] ipa-cp: Write transformation summaries of all functions User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:45:40 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, IPA-CP transformation summary streaming code currently won't stream out transformations necessary for clones which are only necessary for materialization of other clones (such as an IPA-CP clone which is then cloned again by IPA-SRA). However, a follow-up patch for bettor reconciling IPA-SRA and IPA-CP modifications requires to have that information at its disposal and so this one reworks the streaming to write out all non-empty transformation summaries. This should actually mean less streaming in typical case because previously we streamed three zeros for all nodes in a partition with no useful information associated with them. Currently we don't stream anything for those. When reworking the streaming, I also simplified it a little a converted it writing to nicer C++ vector iterations. Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2022-11-11 Martin Jambor * ipa-prop.cc (useful_ipcp_transformation_info_p): New function. (write_ipcp_transformation_info): Added a parameter, simplified given that is known not to be NULL. (ipcp_write_transformation_summaries): Write out all useful transformation summaries. (read_ipcp_transformation_info): Simplify given that some info will be read. (read_replacements_section): Remove assert. --- gcc/ipa-prop.cc | 151 +++++++++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 80 deletions(-) diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index e6cf25591b3..cfd12a97b36 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -5279,80 +5279,72 @@ ipa_prop_read_jump_functions (void) } } -void -write_ipcp_transformation_info (output_block *ob, cgraph_node *node) +/* Return true if the IPA-CP transformation summary TS is non-NULL and contains + useful info. */ +static bool +useful_ipcp_transformation_info_p (ipcp_transformation *ts) { - int node_ref; - unsigned int count = 0; - lto_symtab_encoder_t encoder; + if (!ts) + return false; + if (!vec_safe_is_empty (ts->m_agg_values) + || !vec_safe_is_empty (ts->bits) + || !vec_safe_is_empty (ts->m_vr)) + return true; + return false; +} - encoder = ob->decl_state->symtab_node_encoder; - node_ref = lto_symtab_encoder_encode (encoder, node); +/* Write into OB IPA-CP transfromation summary TS describing NODE. */ + +void +write_ipcp_transformation_info (output_block *ob, cgraph_node *node, + ipcp_transformation *ts) +{ + lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder; + int node_ref = lto_symtab_encoder_encode (encoder, node); streamer_write_uhwi (ob, node_ref); - ipcp_transformation *ts = ipcp_get_transformation_summary (node); - if (ts && !vec_safe_is_empty (ts->m_agg_values)) + streamer_write_uhwi (ob, vec_safe_length (ts->m_agg_values)); + for (const ipa_argagg_value &av : ts->m_agg_values) { - streamer_write_uhwi (ob, ts->m_agg_values->length ()); - for (const ipa_argagg_value &av : ts->m_agg_values) + struct bitpack_d bp; + + stream_write_tree (ob, av.value, true); + streamer_write_uhwi (ob, av.unit_offset); + streamer_write_uhwi (ob, av.index); + + bp = bitpack_create (ob->main_stream); + bp_pack_value (&bp, av.by_ref, 1); + streamer_write_bitpack (&bp); + } + + streamer_write_uhwi (ob, vec_safe_length (ts->m_vr)); + for (const ipa_vr &parm_vr : ts->m_vr) + { + struct bitpack_d bp; + bp = bitpack_create (ob->main_stream); + bp_pack_value (&bp, parm_vr.known, 1); + streamer_write_bitpack (&bp); + if (parm_vr.known) { - struct bitpack_d bp; - - stream_write_tree (ob, av.value, true); - streamer_write_uhwi (ob, av.unit_offset); - streamer_write_uhwi (ob, av.index); - - bp = bitpack_create (ob->main_stream); - bp_pack_value (&bp, av.by_ref, 1); - streamer_write_bitpack (&bp); + streamer_write_enum (ob->main_stream, value_rang_type, + VR_LAST, parm_vr.type); + streamer_write_wide_int (ob, parm_vr.min); + streamer_write_wide_int (ob, parm_vr.max); } } - else - streamer_write_uhwi (ob, 0); - if (ts && vec_safe_length (ts->m_vr) > 0) + streamer_write_uhwi (ob, vec_safe_length (ts->bits)); + for (const ipa_bits *bits_jfunc : ts->bits) { - count = ts->m_vr->length (); - streamer_write_uhwi (ob, count); - for (unsigned i = 0; i < count; ++i) + struct bitpack_d bp = bitpack_create (ob->main_stream); + bp_pack_value (&bp, !!bits_jfunc, 1); + streamer_write_bitpack (&bp); + if (bits_jfunc) { - struct bitpack_d bp; - ipa_vr *parm_vr = &(*ts->m_vr)[i]; - bp = bitpack_create (ob->main_stream); - bp_pack_value (&bp, parm_vr->known, 1); - streamer_write_bitpack (&bp); - if (parm_vr->known) - { - streamer_write_enum (ob->main_stream, value_rang_type, - VR_LAST, parm_vr->type); - streamer_write_wide_int (ob, parm_vr->min); - streamer_write_wide_int (ob, parm_vr->max); - } + streamer_write_widest_int (ob, bits_jfunc->value); + streamer_write_widest_int (ob, bits_jfunc->mask); } } - else - streamer_write_uhwi (ob, 0); - - if (ts && vec_safe_length (ts->bits) > 0) - { - count = ts->bits->length (); - streamer_write_uhwi (ob, count); - - for (unsigned i = 0; i < count; ++i) - { - const ipa_bits *bits_jfunc = (*ts->bits)[i]; - struct bitpack_d bp = bitpack_create (ob->main_stream); - bp_pack_value (&bp, !!bits_jfunc, 1); - streamer_write_bitpack (&bp); - if (bits_jfunc) - { - streamer_write_widest_int (ob, bits_jfunc->value); - streamer_write_widest_int (ob, bits_jfunc->mask); - } - } - } - else - streamer_write_uhwi (ob, 0); } /* Stream in the aggregate value replacement chain for NODE from IB. */ @@ -5362,12 +5354,12 @@ read_ipcp_transformation_info (lto_input_block *ib, cgraph_node *node, data_in *data_in) { unsigned int count, i; + ipcp_transformation_initialize (); + ipcp_transformation *ts = ipcp_transformation_sum->get_create (node); count = streamer_read_uhwi (ib); if (count > 0) { - ipcp_transformation_initialize (); - ipcp_transformation *ts = ipcp_transformation_sum->get_create (node); vec_safe_grow_cleared (ts->m_agg_values, count, true); for (i = 0; i 0) { - ipcp_transformation_initialize (); - ipcp_transformation *ts = ipcp_transformation_sum->get_create (node); vec_safe_grow_cleared (ts->m_vr, count, true); for (i = 0; i < count; i++) { @@ -5407,10 +5397,7 @@ read_ipcp_transformation_info (lto_input_block *ib, cgraph_node *node, count = streamer_read_uhwi (ib); if (count > 0) { - ipcp_transformation_initialize (); - ipcp_transformation *ts = ipcp_transformation_sum->get_create (node); vec_safe_grow_cleared (ts->bits, count, true); - for (i = 0; i < count; i++) { struct bitpack_d bp = streamer_read_bitpack (ib); @@ -5432,31 +5419,36 @@ read_ipcp_transformation_info (lto_input_block *ib, cgraph_node *node, void ipcp_write_transformation_summaries (void) { - struct cgraph_node *node; struct output_block *ob; unsigned int count = 0; - lto_symtab_encoder_iterator lsei; lto_symtab_encoder_t encoder; ob = create_output_block (LTO_section_ipcp_transform); encoder = ob->decl_state->symtab_node_encoder; ob->symbol = NULL; - for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei); - lsei_next_function_in_partition (&lsei)) + + for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) { - node = lsei_cgraph_node (lsei); - if (node->has_gimple_body_p ()) + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast (snode); + if (!cnode) + continue; + ipcp_transformation *ts = ipcp_get_transformation_summary (cnode); + if (useful_ipcp_transformation_info_p (ts)) count++; } streamer_write_uhwi (ob, count); - for (lsei = lsei_start_function_in_partition (encoder); !lsei_end_p (lsei); - lsei_next_function_in_partition (&lsei)) + for (int i = 0; i < lto_symtab_encoder_size (encoder); i++) { - node = lsei_cgraph_node (lsei); - if (node->has_gimple_body_p ()) - write_ipcp_transformation_info (ob, node); + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); + cgraph_node *cnode = dyn_cast (snode); + if (!cnode) + continue; + ipcp_transformation *ts = ipcp_get_transformation_summary (cnode); + if (useful_ipcp_transformation_info_p (ts)) + write_ipcp_transformation_info (ob, cnode, ts); } streamer_write_char_stream (ob->main_stream, 0); produce_asm (ob, NULL); @@ -5497,7 +5489,6 @@ read_replacements_section (struct lto_file_decl_data *file_data, encoder = file_data->symtab_node_encoder; node = dyn_cast (lto_symtab_encoder_deref (encoder, index)); - gcc_assert (node->definition); read_ipcp_transformation_info (&ib_main, node, data_in); } lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, From patchwork Sat Nov 12 01:46:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60465 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5B4F038A1403 for ; Sat, 12 Nov 2022 01:46:23 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by sourceware.org (Postfix) with ESMTPS id 6ABFB384F00C for ; Sat, 12 Nov 2022 01:46:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 6ABFB384F00C Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id A48411F381; Sat, 12 Nov 2022 01:46:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217561; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=HnXW6AD6dpimaovHQnoyn0mN+fWmQEkLypM7PUgVPQc=; b=C16Xs6iLzPhUuMlCsRJM3P+1NKY/n95FGB+ZKExS7WHZCsHyXgCSH6nvTWClRkO1XVBBJI WXlAzy0vDLEGdz/+LS5e3qqtuGH7X5uKqfrf3oq3/WGK/IYP4XV3iccb3Uk0ZgwRPu9nwE RxwRs6LF0qK7+Byz47DMuOmMvZ4fNAU= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217561; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=HnXW6AD6dpimaovHQnoyn0mN+fWmQEkLypM7PUgVPQc=; b=ZAVjy3wfgDJtYDZo+w6sJ+r3VKz99aqiWV3miTqNXGSor5GMIQwEpHiTbp6pN6qtZY6Cp3 HQM5uFdfp1tf88BA== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 91AEB13273; Sat, 12 Nov 2022 01:46:01 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id MOc9I9n6bmP3YwAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:46:01 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 04/12] ipa: Better way of applying both IPA-CP and IPA-SRA (PR 103227) User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:46:01 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, this is basically a better fix for PR 103227. The one currently in use, rushed in late at stage3, which means that IPA-CP transformation simply does a replacement of default-definition of IPA-SRA-created scalar parameters with a constant, meant that IPA-SRA actually often led to creation of a bunch of unused parameters, which was rather ironic and sub-optimal. This patch rips that old way out and makes sure the clash is resolved at clone-materialization time. What happens is that: 1) IPA-SRA IPA analysis (decision) stage recognizes the clash and does not create a param adjustment entry for such a scalar component. 2) Clone materialization code checks the IPA-CP transformation summary and when it realizes that it is removing a parameter that is a base for a discovered IPA-CP aggregate constant, and: a) the value is passed by reference, it internally records that any load of the value is replaced directly with the known constant value. IPA-SRA will not attempt to split values passed by reference when there is a write to it so we know such a load won't be on a a LHS. b) the value is passed by value, there can be stores to the corresponding bit of the aggregate and so all accesses are replaced with a new decl and an assignment of the constant to this decl is generated at the beginning of the function. The new testcase contains an xfail as the patch does not fix PR 107640 but it is one that ICEs when one is not careful about remapping indices of parameters, so I'd like to have it in testsuite/gcc.gd/ipa/ even now. I don't think that PR 107640 should be attempted through ipa-param-manipulation replacements because the information is not really there any more and we'd either need to do the replacements earlier or dig deep into the clone parent info. Instead, we should record somewhere that at the beginning of the function the bits of the global decl have known values and use that in the value numbering. That way we could one day encode also known constants in globals that do not come through parameters. Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2022-11-11 Martin Jambor PR ipa/103227 * ipa-param-manipulation.h (class ipa_param_adjustments): Removed member function get_updated_index_or_split. (class ipa_param_body_adjustments): New overload of register_replacement, new member function append_init_stmts, new member m_split_agg_csts_inits. * ipa-param-manipulation.cc: Include ipa-prop.h. (ipa_param_adjustments::get_updated_index_or_split): Removed. (ipa_param_body_adjustments::register_replacement): New overload, use it from the older one. (ipa_param_body_adjustments::common_initialization): Added the capability to create replacements for conflicting IPA-CP discovered constants. (ipa_param_body_adjustments::ipa_param_body_adjustments): Construct the new member. (ipa_param_body_adjustments::append_init_stmts): New function. * ipa-sra.cc: Include ipa-prop.h. (push_param_adjustments_for_index): Require IPA-CP transformation summary as a parameter, do not create replacements which are known to have constant values. (process_isra_node_results): Find and pass to the above function the IPA-CP transformation summary. * ipa-prop.cc (adjust_agg_replacement_values): Remove the functionality replacing IPA-SRA created scalar parameters with constants. Simplify, do not require parameter descriptors, do not return anything. (ipcp_transform_function): Simplify now that adjust_agg_replacement_values does not change cfg. Move definition and initialization of descriptors lower. * tree-inline.cc (tree_function_versioning): Call append_init_stmts of param_body_adjs, if there are any. gcc/testsuite/ChangeLog: 2022-11-11 Martin Jambor PR ipa/103227 PR ipa/107640 * gcc.dg/ipa/pr107640-2.c: New test. --- gcc/ipa-param-manipulation.cc | 155 ++++++++++++++++---------- gcc/ipa-param-manipulation.h | 19 ++-- gcc/ipa-prop.cc | 66 ++++------- gcc/ipa-sra.cc | 30 ++++- gcc/testsuite/gcc.dg/ipa/pr107640-2.c | 50 +++++++++ gcc/tree-inline.cc | 2 + 6 files changed, 208 insertions(+), 114 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/ipa/pr107640-2.c diff --git a/gcc/ipa-param-manipulation.cc b/gcc/ipa-param-manipulation.cc index cee0e23f946..e92cfc0b6d5 100644 --- a/gcc/ipa-param-manipulation.cc +++ b/gcc/ipa-param-manipulation.cc @@ -46,7 +46,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-phinodes.h" #include "cfgexpand.h" #include "attribs.h" - +#include "ipa-prop.h" /* Actual prefixes of different newly synthetized parameters. Keep in sync with IPA_PARAM_PREFIX_* defines. */ @@ -449,39 +449,6 @@ ipa_param_adjustments::get_updated_indices (vec *new_indices) } } -/* If a parameter with original INDEX has survived intact, return its new - index. Otherwise return -1. In that case, if it has been split and there - is a new parameter representing a portion at unit OFFSET for which a value - of a TYPE can be substituted, store its new index into SPLIT_INDEX, - otherwise store -1 there. */ -int -ipa_param_adjustments::get_updated_index_or_split (int index, - unsigned unit_offset, - tree type, int *split_index) -{ - unsigned adj_len = vec_safe_length (m_adj_params); - for (unsigned i = 0; i < adj_len ; i++) - { - ipa_adjusted_param *apm = &(*m_adj_params)[i]; - if (apm->base_index != index) - continue; - if (apm->op == IPA_PARAM_OP_COPY) - return i; - if (apm->op == IPA_PARAM_OP_SPLIT - && apm->unit_offset == unit_offset) - { - if (useless_type_conversion_p (apm->type, type)) - *split_index = i; - else - *split_index = -1; - return -1; - } - } - - *split_index = -1; - return -1; -} - /* Return the original index for the given new parameter index. Return a negative number if not available. */ @@ -1020,6 +987,21 @@ ipa_param_adjustments::debug () dump (stderr); } +/* Register a REPLACEMENT for accesses to BASE at UNIT_OFFSET. */ + +void +ipa_param_body_adjustments::register_replacement (tree base, + unsigned unit_offset, + tree replacement) +{ + ipa_param_body_replacement psr; + psr.base = base; + psr.repl = replacement; + psr.dummy = NULL_TREE; + psr.unit_offset = unit_offset; + m_replacements.safe_push (psr); +} + /* Register that REPLACEMENT should replace parameter described in APM. */ void @@ -1029,12 +1011,8 @@ ipa_param_body_adjustments::register_replacement (ipa_adjusted_param *apm, gcc_checking_assert (apm->op == IPA_PARAM_OP_SPLIT || apm->op == IPA_PARAM_OP_NEW); gcc_checking_assert (!apm->prev_clone_adjustment); - ipa_param_body_replacement psr; - psr.base = m_oparms[apm->prev_clone_index]; - psr.repl = replacement; - psr.dummy = NULL_TREE; - psr.unit_offset = apm->unit_offset; - m_replacements.safe_push (psr); + register_replacement (m_oparms[apm->prev_clone_index], apm->unit_offset, + replacement); } /* Copy or not, as appropriate given m_id and decl context, a pre-existing @@ -1386,23 +1364,73 @@ ipa_param_body_adjustments::common_initialization (tree old_fndecl, gcc_unreachable (); } + auto_vec index_mapping; + bool need_remap = false; + if (m_id) + { + clone_info *cinfo = clone_info::get (m_id->src_node); + if (cinfo && cinfo->param_adjustments) + { + cinfo->param_adjustments->get_updated_indices (&index_mapping); + need_remap = true; + } + + if (ipcp_transformation *ipcp_ts + = ipcp_get_transformation_summary (m_id->src_node)) + { + for (const ipa_argagg_value &av : ipcp_ts->m_agg_values) + { + int parm_num = av.index; + + if (need_remap) + { + /* FIXME: We cannot handle the situation when IPA-CP + identified that a parameter is a pointer to a global + variable and at the same time the variable has some known + constant contents (PR 107640). The best place to make + sure we don't drop such constants on the floor probably is + not here, but we have to make sure that it does not + confuse the remapping. */ + if (parm_num >= (int) index_mapping.length ()) + continue; + parm_num = index_mapping[parm_num]; + if (parm_num < 0) + continue; + } + + if (!kept[parm_num]) + { + /* IPA-CP has detected an aggregate constant in a parameter + that will not be kept, which means that IPA-SRA would have + split it if there wasn't a constant. Because we are about + to remove the original, this is the last chance where we + can substitute the uses with a constant (for values passed + by reference) or do the split but initialize the + replacement with a constant (for split aggregates passed + by value). */ + + tree repl; + if (av.by_ref) + repl = av.value; + else + { + repl = create_tmp_var (TREE_TYPE (av.value), + "removed_ipa_cp"); + gimple *init_stmt = gimple_build_assign (repl, av.value); + m_split_agg_csts_inits.safe_push (init_stmt); + } + register_replacement (m_oparms[parm_num], av.unit_offset, + repl); + split[parm_num] = true; + } + } + } + } + if (tree_map) { /* Do not treat parameters which were replaced with a constant as completely vanished. */ - auto_vec index_mapping; - bool need_remap = false; - - if (m_id) - { - clone_info *cinfo = clone_info::get (m_id->src_node); - if (cinfo && cinfo->param_adjustments) - { - cinfo->param_adjustments->get_updated_indices (&index_mapping); - need_remap = true; - } - } - for (unsigned i = 0; i < tree_map->length (); i++) { int parm_num = (*tree_map)[i]->parm_num; @@ -1473,8 +1501,9 @@ ipa_param_body_adjustments : m_adj_params (adj_params), m_adjustments (NULL), m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (), m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl), m_id (NULL), m_oparms (), - m_new_decls (), m_new_types (), m_replacements (), m_removed_decls (), - m_removed_map (), m_method2func (false) + m_new_decls (), m_new_types (), m_replacements (), + m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (), + m_method2func (false) { common_initialization (fndecl, NULL, NULL); } @@ -1491,7 +1520,8 @@ ipa_param_body_adjustments m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (), m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl), m_id (NULL), m_oparms (), m_new_decls (), m_new_types (), m_replacements (), - m_removed_decls (), m_removed_map (), m_method2func (false) + m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (), + m_method2func (false) { common_initialization (fndecl, NULL, NULL); } @@ -1514,7 +1544,8 @@ ipa_param_body_adjustments m_reset_debug_decls (), m_dead_stmts (), m_dead_ssas (), m_dead_ssa_debug_equiv (), m_dead_stmt_debug_equiv (), m_fndecl (fndecl), m_id (id), m_oparms (), m_new_decls (), m_new_types (), m_replacements (), - m_removed_decls (), m_removed_map (), m_method2func (false) + m_split_agg_csts_inits (), m_removed_decls (), m_removed_map (), + m_method2func (false) { common_initialization (old_fndecl, vars, tree_map); } @@ -2383,6 +2414,16 @@ ipa_param_body_adjustments::perform_cfun_body_modifications () } +/* If there are any initialization statements that need to be emitted into + the basic block BB right at ther start of the new function, do so. */ +void +ipa_param_body_adjustments::append_init_stmts (basic_block bb) +{ + gimple_stmt_iterator si = gsi_last_bb (bb); + while (!m_split_agg_csts_inits.is_empty ()) + gsi_insert_after (&si, m_split_agg_csts_inits.pop (), GSI_NEW_STMT); +} + /* Deallocate summaries which otherwise stay alive until the end of compilation. */ diff --git a/gcc/ipa-param-manipulation.h b/gcc/ipa-param-manipulation.h index e5654f4ff70..e20d34918b3 100644 --- a/gcc/ipa-param-manipulation.h +++ b/gcc/ipa-param-manipulation.h @@ -236,13 +236,6 @@ public: void get_surviving_params (vec *surviving_params); /* Fill a vector with new indices of surviving original parameters. */ void get_updated_indices (vec *new_indices); - /* If a parameter with original INDEX has survived intact, return its new - index. Otherwise return -1. In that case, if it has been split and there - is a new parameter representing a portion at UNIT_OFFSET for which a value - of a TYPE can be substituted, store its new index into SPLIT_INDEX, - otherwise store -1 there. */ - int get_updated_index_or_split (int index, unsigned unit_offset, tree type, - int *split_index); /* Return the original index for the given new parameter index. Return a negative number if not available. */ int get_original_index (int newidx); @@ -321,6 +314,8 @@ public: /* Change the PARM_DECLs. */ void modify_formal_parameters (); + /* Register a REPLACEMENT for accesses to BASE at UNIT_OFFSET. */ + void register_replacement (tree base, unsigned unit_offset, tree replacement); /* Register a replacement decl for the transformation done in APM. */ void register_replacement (ipa_adjusted_param *apm, tree replacement); /* Lookup a replacement for a given offset within a given parameter. */ @@ -340,6 +335,10 @@ public: they are mapped to. */ void remap_with_debug_expressions (tree *t); + /* If there are any initialization statements that need to be emitted into + the basic block BB right at ther start of the new function, do so. */ + void append_init_stmts (basic_block bb); + /* Pointers to data structures defining how the function should be modified. */ vec *m_adj_params; @@ -405,6 +404,12 @@ private: auto_vec m_replacements; + /* List of initialization assignments to be put at the beginning of the + cloned function to deal with split aggregates which however have known + constant value and so their PARM_DECL disappears. */ + + auto_vec m_split_agg_csts_inits; + /* Vector for remapping SSA_BASES from old parameter declarations that are being removed as a part of the transformation. Before a new VAR_DECL is created, it holds the old PARM_DECL, once the variable is built it is diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index cfd12a97b36..1cc9cf3ad22 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -5516,29 +5516,21 @@ ipcp_read_transformation_summaries (void) } } -/* Adjust the aggregate replacements in TS to reflect parameters skipped in - NODE but also if any parameter was IPA-SRAed into a scalar go ahead with - substitution of the default_definitions of that new param with the - appropriate constant. +/* Adjust the aggregate replacements in TS to reflect any parameter removals + which might have already taken place. If after adjustments there are no + aggregate replacements left, the m_agg_values will be set to NULL. In other + cases, it may be shrunk. */ - If after adjustments there are no aggregate replacements left, the - m_agg_values will be set to NULL. In other cases, it may be shrunk. - - Return true if any values were already substituted for scalarized parameters - and update_cfg shuld be run after replace_uses_by. */ - -static bool -adjust_agg_replacement_values (cgraph_node *node, - ipcp_transformation *ts, - const vec - &descriptors) +static void +adjust_agg_replacement_values (cgraph_node *node, ipcp_transformation *ts) { clone_info *cinfo = clone_info::get (node); if (!cinfo || !cinfo->param_adjustments) - return false; + return; + auto_vec new_indices; + cinfo->param_adjustments->get_updated_indices (&new_indices); bool removed_item = false; - bool done_replacement = false; unsigned dst_index = 0; unsigned count = ts->m_agg_values->length (); for (unsigned i = 0; i < count; i++) @@ -5546,13 +5538,10 @@ adjust_agg_replacement_values (cgraph_node *node, ipa_argagg_value *v = &(*ts->m_agg_values)[i]; gcc_checking_assert (v->index >= 0); - tree cst_type = TREE_TYPE (v->value); - int split_idx; - int new_idx - = cinfo->param_adjustments->get_updated_index_or_split (v->index, - v->unit_offset, - cst_type, - &split_idx); + int new_idx = -1; + if ((unsigned) v->index < new_indices.length ()) + new_idx = new_indices[v->index]; + if (new_idx >= 0) { v->index = new_idx; @@ -5561,19 +5550,7 @@ adjust_agg_replacement_values (cgraph_node *node, dst_index++; } else - { - removed_item = true; - if (split_idx >= 0) - { - tree parm = ipa_get_param (descriptors, split_idx); - tree ddef = ssa_default_def (cfun, parm); - if (ddef) - { - replace_uses_by (ddef, v->value); - done_replacement = true; - } - } - } + removed_item = true; } if (dst_index == 0) @@ -5584,7 +5561,7 @@ adjust_agg_replacement_values (cgraph_node *node, else if (removed_item) ts->m_agg_values->truncate (dst_index); - return done_replacement; + return; } /* Dominator walker driving the ipcp modification phase. */ @@ -5953,7 +5930,6 @@ ipcp_update_vr (struct cgraph_node *node) unsigned int ipcp_transform_function (struct cgraph_node *node) { - vec *descriptors = NULL; struct ipa_func_body_info fbi; int param_count; @@ -5972,18 +5948,13 @@ ipcp_transform_function (struct cgraph_node *node) param_count = count_formal_params (node->decl); if (param_count == 0) return 0; - vec_safe_grow_cleared (descriptors, param_count, true); - ipa_populate_param_decls (node, *descriptors); - bool cfg_changed = adjust_agg_replacement_values (node, ts, *descriptors); + adjust_agg_replacement_values (node, ts); if (vec_safe_is_empty (ts->m_agg_values)) { - vec_free (descriptors); if (dump_file) fprintf (dump_file, " All affected aggregate parameters were either " "removed or converted into scalars, phase done.\n"); - if (cfg_changed) - delete_unreachable_blocks_update_callgraph (node, false); return 0; } if (dump_file) @@ -6000,12 +5971,15 @@ ipcp_transform_function (struct cgraph_node *node) fbi.param_count = param_count; fbi.aa_walk_budget = opt_for_fn (node->decl, param_ipa_max_aa_steps); + vec *descriptors = NULL; + vec_safe_grow_cleared (descriptors, param_count, true); + ipa_populate_param_decls (node, *descriptors); bool modified_mem_access = false; calculate_dominance_info (CDI_DOMINATORS); ipcp_modif_dom_walker walker (&fbi, descriptors, ts, &modified_mem_access); walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun)); free_dominance_info (CDI_DOMINATORS); - cfg_changed |= walker.cleanup_eh (); + bool cfg_changed = walker.cleanup_eh (); int i; struct ipa_bb_info *bi; diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc index 2237ac6d92f..959e8829777 100644 --- a/gcc/ipa-sra.cc +++ b/gcc/ipa-sra.cc @@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see #include "internal-fn.h" #include "symtab-clones.h" #include "attribs.h" +#include "ipa-prop.h" static void ipa_sra_summarize_function (cgraph_node *); @@ -3608,13 +3609,16 @@ retval_used_p (cgraph_node *node, void *) /* Push into NEW_PARAMS all required parameter adjustment entries to copy or modify parameter which originally had index BASE_INDEX, in the adjustment vector of parent clone (if any) had PREV_CLONE_INDEX and was described by - PREV_ADJUSTMENT. If the parent clone is the original function, - PREV_ADJUSTMENT is NULL and PREV_CLONE_INDEX is equal to BASE_INDEX. */ + PREV_ADJUSTMENT. If IPA-CP has created a transformation summary for the + original node, it needs to be passed in IPCP_TS, otherwise it should be + NULL. If the parent clone is the original function, PREV_ADJUSTMENT is NULL + and PREV_CLONE_INDEX is equal to BASE_INDEX. */ static void push_param_adjustments_for_index (isra_func_summary *ifs, unsigned base_index, unsigned prev_clone_index, ipa_adjusted_param *prev_adjustment, + ipcp_transformation *ipcp_ts, vec **new_params) { isra_param_desc *desc = &(*ifs->m_parameters)[base_index]; @@ -3655,6 +3659,23 @@ push_param_adjustments_for_index (isra_func_summary *ifs, unsigned base_index, param_access *pa = (*desc->accesses)[j]; if (!pa->certain) continue; + + if (ipcp_ts) + { + ipa_argagg_value_list avl (ipcp_ts); + tree value = avl.get_value (base_index, pa->unit_offset); + if (value + && (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (value))) / BITS_PER_UNIT + == pa->unit_size)) + { + if (dump_file) + fprintf (dump_file, " - omitting component at byte " + "offset %u which is known to have a constant value\n ", + pa->unit_offset); + continue; + } + } + if (dump_file) fprintf (dump_file, " - component at byte offset %u, " "size %u\n", pa->unit_offset, pa->unit_size); @@ -3735,6 +3756,7 @@ process_isra_node_results (cgraph_node *node, fprintf (dump_file, " Will remove return value.\n"); } + ipcp_transformation *ipcp_ts = ipcp_get_transformation_summary (node); vec *new_params = NULL; if (ipa_param_adjustments *old_adjustments = cinfo ? cinfo->param_adjustments : NULL) @@ -3744,12 +3766,12 @@ process_isra_node_results (cgraph_node *node, { ipa_adjusted_param *old_adj = &(*old_adjustments->m_adj_params)[i]; push_param_adjustments_for_index (ifs, old_adj->base_index, i, - old_adj, &new_params); + old_adj, ipcp_ts, &new_params); } } else for (unsigned i = 0; i < param_count; i++) - push_param_adjustments_for_index (ifs, i, i, NULL, &new_params); + push_param_adjustments_for_index (ifs, i, i, NULL, ipcp_ts, &new_params); ipa_param_adjustments *new_adjustments = (new (ggc_alloc ()) diff --git a/gcc/testsuite/gcc.dg/ipa/pr107640-2.c b/gcc/testsuite/gcc.dg/ipa/pr107640-2.c new file mode 100644 index 00000000000..94cbe02860d --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr107640-2.c @@ -0,0 +1,50 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized-slim" } */ + +struct S +{ + int a, b, c; +}; + +int ellide (int c); +volatile short gi; + +void __attribute__((noipa)) +consume_s (struct S *p) +{ + gi = p->a; +} + +static void __attribute__((noinline)) +foo (struct S *p, short *r) +{ + gi = *r; + if (!__builtin_constant_p (p->b)) + ellide (1); + consume_s (p); +} + +static void __attribute__((noinline)) +bar (short *r, struct S *p) +{ + gi = *r; + if (!__builtin_constant_p (p->c)) + ellide (2); + consume_s (p); +} + +struct S gs; + +int main (int argc, char *argv[]) +{ + short i = 42; + gs.a = 10; + gs.b = 20; + foo (&gs, &i); + gs.b = 30; + gs.c = 40; + bar (&i, &gs); + return 0; +} + +/* { dg-final { scan-tree-dump-not "ellide" "optimized" { xfail *-*-* } } } */ diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 8091ba8f13b..15a1a389493 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -6377,6 +6377,8 @@ tree_function_versioning (tree old_decl, tree new_decl, bb = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))); while (init_stmts.length ()) insert_init_stmt (&id, bb, init_stmts.pop ()); + if (param_body_adjs) + param_body_adjs->append_init_stmts (bb); update_clone_info (&id); /* Remap the nonlocal_goto_save_area, if any. */ From patchwork Sat Nov 12 01:46:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60467 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 42EFD38AA275 for ; Sat, 12 Nov 2022 01:47:00 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by sourceware.org (Postfix) with ESMTPS id 18F1A3896C38 for ; Sat, 12 Nov 2022 01:46:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 18F1A3896C38 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 6A2201F45F; Sat, 12 Nov 2022 01:46:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217568; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=p7TD9Ix4eyfDRIuvRdcMegQRb0IlFtoWXjEKtP5Gf9s=; b=Kk4QIBzDsOSfwr/AYb7sjdTE5ZubxyU5kBYycvE+qxwySftsqWg5z4Abnwem9YYafPaPj8 efMSfTIKjaURM6RqApIjRPG2bKGxqH9NVkn0dMkp38zyFw1YDfhGyFkpRMXUcmAcj7p41L oOOdp9uc+JeYeqxJKuINrsfnOxIj9FQ= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217568; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=p7TD9Ix4eyfDRIuvRdcMegQRb0IlFtoWXjEKtP5Gf9s=; b=pr/GiYTaGOMqBbrPkqpragDVWsyF5HK2KjDJD/ZDaQo2aluF0A8q+RyRUezcZjNFGV5RWv /5FAZNgJF0MplLDw== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 5CC5D13A08; Sat, 12 Nov 2022 01:46:08 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id HwdlFuD6bmMOZAAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:46:08 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 05/12] ipa-sra: Dump edge summaries also for non-candidates User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:46:07 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, this should have been part of r12-578-g717d278af93a4a. Call edge summaries provide information required for IPA-SRA transformations in the callees but are generated when analyzing callers and thus also callers which are not IPA-SRA candidates themselves. Therefore we analyze them but don't dump them, which makes the dumops quite incomplete. This patch fixes that. Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2021-12-14 Martin Jambor * ipa-sra.c (ipa_sra_dump_all_summaries): Dump edge summaries even for non-candidates. --- gcc/ipa-sra.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc index 959e8829777..0f137e810fe 100644 --- a/gcc/ipa-sra.cc +++ b/gcc/ipa-sra.cc @@ -2806,13 +2806,10 @@ ipa_sra_dump_all_summaries (FILE *f) if (!ifs) fprintf (f, " Function does not have any associated IPA-SRA " "summary\n"); + else if (!ifs->m_candidate) + fprintf (f, " Not a candidate function\n"); else { - if (!ifs->m_candidate) - { - fprintf (f, " Not a candidate function\n"); - continue; - } if (ifs->m_returns_value) fprintf (f, " Returns value\n"); if (vec_safe_is_empty (ifs->m_parameters)) From patchwork Sat Nov 12 01:46:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60466 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 52E7C388A026 for ; Sat, 12 Nov 2022 01:46:58 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2001:67c:2178:6::1c]) by sourceware.org (Postfix) with ESMTPS id 4CEB938A8157 for ; Sat, 12 Nov 2022 01:46:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 4CEB938A8157 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 8A0BC22329; Sat, 12 Nov 2022 01:46:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217589; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=m1F1MnxsXWTzJEkvoPejEncw67WGLvmcf01rkiOZ1qE=; b=HX+Mh3v3BReMCNENTxFmkD3lDEawclJq9gqlICkkZpuit0dnQgOQyC+Uihy8QIIADzvGjG jysTucfutQX6hqla6KgzO2e3Od+wHckADBmJ2qG9/0qSlF/sPinXUn1bHCRO0l0JSr7H8r tKfsKpe5xK+UDD+0umbF9mFEQvRHtB0= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217589; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=m1F1MnxsXWTzJEkvoPejEncw67WGLvmcf01rkiOZ1qE=; b=Afy2mrLgfs/cNM1iB758CrjAcpI7Ld0e/2Ik47Y6tkTMITcofUYGHYBXbwYTLHAn7Dtser +wUAgiXTwl7KJvBQ== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 7A90113A08; Sat, 12 Nov 2022 01:46:29 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id gPLnHfX6bmMwZAAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:46:29 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 06/12] ipa-cp: Leave removal of unused parameters to IPA-SRA User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:46:28 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, looking at some benchmarks I have noticed many cases when IPA-CP cloned a function for all contexts just because it knew that some parameters were not used at all. Then IPA-SRA looked at the function and cloned it again to split another parameter or two. The latter pass is better equipped to detect when parameters can be altogether removed and so the IPA-CP cloning was for no good reason. This patch simply alters the IPA-CP not to do that in the situations where IPA-SRA can (for nodes which can be made local). Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2022-11-11 Martin Jambor * ipa-cp.cc (estimate_local_effects): Do not clone potentionally local nodes for all contexts just to remove unused parameters. --- gcc/ipa-cp.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc index 02bd6a0fd1a..eb4474eb8b3 100644 --- a/gcc/ipa-cp.cc +++ b/gcc/ipa-cp.cc @@ -3722,7 +3722,10 @@ estimate_local_effects (struct cgraph_node *node) &removable_params_cost); int devirt_bonus = devirtualization_time_bonus (node, &avals); if (always_const || devirt_bonus - || (removable_params_cost && node->can_change_signature)) + || (removable_params_cost + && node->can_change_signature + /* If IPA-SRA can do it, it can do it better. */ + && !node->can_be_local_p ())) { struct caller_statistics stats; ipa_call_estimates estimates; From patchwork Sat Nov 12 01:46:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60469 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 458BC3898C6F for ; Sat, 12 Nov 2022 01:47:43 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by sourceware.org (Postfix) with ESMTPS id 3AC2638A9087 for ; Sat, 12 Nov 2022 01:46:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3AC2638A9087 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 7425022329; Sat, 12 Nov 2022 01:46:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217596; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=kp8hmCMaU8KYpnQ5mPDEqjal+ruxPJc8BhCn53TXyEE=; b=ONhD6sLdhzn5EsfsNzTUcEdvomeZ6aa/UJ/p2lBaB1d6rJL5tp7plk3dvSEHQAvl1byyZp sFi7BlRIyjZsxuQrnYbV0mVI4u6Fa1iZM7TIFGRQLqu3RL0YlT5yLqQPFMXZ5agpZFvs0N vXn/yoC0pEoxfv8aeksT28OqhEFJYIc= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217596; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=kp8hmCMaU8KYpnQ5mPDEqjal+ruxPJc8BhCn53TXyEE=; b=FmWGd92NMGrllLo5HirOT4U1zf7BbSup/NY3hAzRcd2uyJWGw5KiL0FaUAGRhTSL7T2JTm j4sTlzQCkLzfyhBg== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 642AD13A08; Sat, 12 Nov 2022 01:46:36 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id RwoAGPz6bmM8ZAAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:46:36 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 07/12] ipa-sra: Treat REFERENCE_TYPES as always dereferencable User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:46:35 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, C++ and especially Fortran pass data by references which are not pointers potentially pointing anywhere and so can be assumed to be safely dereferencable. This patch teaches IPA-SRA to treat them as such and avoid the dance we do to prove that we can move loads from them to the caller. When we do not know that a dereference will happen all the time, we need a heuristics so that we do not force memory accesses that normally happen only rarely. The patch simply uses the (possibly guessed) profile and checks whether the (expected) number of loads is at least half of function invocations invocations. Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2022-11-11 Martin Jambor PR ipa/103585 * ipa-sra.c (struct gensum_param_access): New field load_count. (struct gensum_param_desc): New field safe_ref, adjusted comments. (by_ref_count): Renamed to unsafe_by_ref_count, adjusted all uses. (dump_gensum_access): Dump the new field. (dump_gensum_param_descriptor): Likewise. (create_parameter_descriptors): Set safe_ref field, move setting by_ref forward. Only increment unsafe_by_ref_count for unsafe by_ref parameters. (allocate_access): Initialize new field. (mark_param_dereference): Adjust indentation. Only add data to bb_dereferences for unsafe by_ref parameters. (scan_expr_access): For loads, accumulate BB counts. (dereference_probable_p): New function. (check_gensum_access): Fix leading comment, add parameter FUN. Check cumulative counts of loads for safe by_ref accesses instead of dereferences. (process_scan_results): Do not propagate dereference distances for safe by_ref parameters. Pass fun to check_gensum_access. Safe by_ref params do not need the postdominance check. gcc/testsuite/ChangeLog: 2022-11-11 Martin Jambor * g++.dg/ipa/ipa-sra-5.C: New test --- gcc/ipa-sra.cc | 100 +++++++++++++++++++-------- gcc/testsuite/g++.dg/ipa/ipa-sra-5.C | 23 ++++++ 2 files changed, 95 insertions(+), 28 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ipa/ipa-sra-5.C diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc index 0f137e810fe..e8a4cd47429 100644 --- a/gcc/ipa-sra.cc +++ b/gcc/ipa-sra.cc @@ -151,6 +151,8 @@ struct gensum_param_access arguments. */ tree alias_ptr_type; + /* Cumulative count of all loads. */ + profile_count load_count; /* Have there been writes to or reads from this exact location except for as arguments to a function call that can be tracked. */ bool nonarg; @@ -207,8 +209,13 @@ struct gensum_param_desc by reference that is a candidate for being converted to a set of parameters passing those data by value. */ bool split_candidate; - /* Is this a parameter passing stuff by reference? */ + /* Is this a parameter passing stuff by reference (either a pointer or a + source language reference type)? */ bool by_ref; + /* If this parameter passes stuff by reference, can it be safely dereferenced + without performing further checks (for example because it is a + REFERENCE_TYPE)? */ + bool safe_ref; /* The number of this parameter as they are ordered in function decl. */ int param_number; @@ -561,7 +568,7 @@ int aa_walking_limit; accessed in that BB. */ HOST_WIDE_INT *bb_dereferences = NULL; /* How many by-reference parameters there are in the current function. */ -int by_ref_count; +int unsafe_by_ref_count; /* Bitmap of BBs that can cause the function to "stop" progressing by returning, throwing externally, looping infinitely or calling a function @@ -643,6 +650,8 @@ dump_gensum_access (FILE *f, gensum_param_access *access, unsigned indent) print_generic_expr (f, access->type); fprintf (f, ", alias_ptr_type: "); print_generic_expr (f, access->alias_ptr_type); + fprintf (f, ", load_count: "); + access->load_count.dump (f); fprintf (f, ", nonarg: %u, reverse: %u\n", access->nonarg, access->reverse); for (gensum_param_access *ch = access->first_child; ch; @@ -692,7 +701,8 @@ dump_gensum_param_descriptor (FILE *f, gensum_param_desc *desc) return; } if (desc->by_ref) - fprintf (f, " by_ref with %u pass throughs\n", desc->ptr_pt_count); + fprintf (f, " %s by_ref with %u pass throughs\n", + desc->safe_ref ? "safe" : "unsafe", desc->ptr_pt_count); for (gensum_param_access *acc = desc->accesses; acc; acc = acc->next_sibling) dump_gensum_access (f, acc, 2); @@ -1140,6 +1150,8 @@ create_parameter_descriptors (cgraph_node *node, if (POINTER_TYPE_P (type)) { + desc->by_ref = true; + desc->safe_ref = (TREE_CODE (type) == REFERENCE_TYPE); type = TREE_TYPE (type); if (TREE_CODE (type) == FUNCTION_TYPE @@ -1187,7 +1199,6 @@ create_parameter_descriptors (cgraph_node *node, "nonarg uses\n"); continue; } - desc->by_ref = true; } else if (!AGGREGATE_TYPE_P (type)) { @@ -1231,8 +1242,8 @@ create_parameter_descriptors (cgraph_node *node, ret = true; desc->split_candidate = true; - if (desc->by_ref) - desc->deref_index = by_ref_count++; + if (desc->by_ref && !desc->safe_ref) + desc->deref_index = unsafe_by_ref_count++; } return ret; } @@ -1301,6 +1312,7 @@ allocate_access (gensum_param_desc *desc, memset (access, 0, sizeof (*access)); access->offset = offset; access->size = size; + access->load_count = profile_count::zero (); return access; } @@ -1555,15 +1567,16 @@ asm_visit_addr (gimple *, tree op, tree, void *) static void mark_param_dereference (gensum_param_desc *desc, HOST_WIDE_INT dist, - basic_block bb) + basic_block bb) { gcc_assert (desc->by_ref); gcc_checking_assert (desc->split_candidate); - if (bitmap_bit_p (final_bbs, bb->index)) + if (desc->safe_ref + || bitmap_bit_p (final_bbs, bb->index)) return; - int idx = bb->index * by_ref_count + desc->deref_index; + int idx = bb->index * unsafe_by_ref_count + desc->deref_index; if (bb_dereferences[idx] < dist) bb_dereferences[idx] = dist; } @@ -1811,6 +1824,8 @@ scan_expr_access (tree expr, gimple *stmt, isra_scan_context ctx, other. */ access->nonarg = true; } + else if (ctx == ISRA_CTX_LOAD && bb->count.initialized_p ()) + access->load_count += bb->count; if (!access->type) { @@ -2092,9 +2107,9 @@ dump_dereferences_table (FILE *f, struct function *fun, const char *str) if (bb != EXIT_BLOCK_PTR_FOR_FN (fun)) { int i; - for (i = 0; i < by_ref_count; i++) + for (i = 0; i < unsafe_by_ref_count; i++) { - int idx = bb->index * by_ref_count + i; + int idx = bb->index * unsafe_by_ref_count + i; fprintf (f, " %4" HOST_WIDE_INT_PRINT "d", bb_dereferences[idx]); } } @@ -2139,15 +2154,15 @@ propagate_dereference_distances (struct function *fun) if (bitmap_bit_p (final_bbs, bb->index)) continue; - for (i = 0; i < by_ref_count; i++) + for (i = 0; i < unsafe_by_ref_count; i++) { - int idx = bb->index * by_ref_count + i; + int idx = bb->index * unsafe_by_ref_count + i; bool first = true; HOST_WIDE_INT inh = 0; FOR_EACH_EDGE (e, ei, bb->succs) { - int succ_idx = e->dest->index * by_ref_count + i; + int succ_idx = e->dest->index * unsafe_by_ref_count + i; if (e->dest == EXIT_BLOCK_PTR_FOR_FN (fun)) continue; @@ -2184,13 +2199,23 @@ propagate_dereference_distances (struct function *fun) "Dereference table after propagation:\n"); } -/* Perform basic checks on ACCESS to PARM described by DESC and all its - children, return true if the parameter cannot be split, otherwise return - true and update *TOTAL_SIZE and *ONLY_CALLS. ENTRY_BB_INDEX must be the - index of the entry BB in the function of PARM. */ +/* Return true if the ACCESS loads happen frequently enough in FUN to risk + moving them to the caller and only pass the result. */ static bool -check_gensum_access (tree parm, gensum_param_desc *desc, +dereference_probable_p (struct function *fun, gensum_param_access *access) +{ + return access->load_count + >= ENTRY_BLOCK_PTR_FOR_FN (fun)->count.apply_scale (1, 2); +} + +/* Perform basic checks on ACCESS to PARM (of FUN) described by DESC and all + its children, return true if the parameter cannot be split, otherwise return + false and update *NONARG_ACC_SIZE and *ONLY_CALLS. ENTRY_BB_INDEX must be + the index of the entry BB in the function of PARM. */ + +static bool +check_gensum_access (struct function *fun, tree parm, gensum_param_desc *desc, gensum_param_access *access, HOST_WIDE_INT *nonarg_acc_size, bool *only_calls, int entry_bb_index) @@ -2218,19 +2243,31 @@ check_gensum_access (tree parm, gensum_param_desc *desc, if (desc->by_ref) { - int idx = (entry_bb_index * by_ref_count + desc->deref_index); - if ((access->offset + access->size) > bb_dereferences[idx]) + if (desc->safe_ref) { - disqualify_split_candidate (desc, "Would create a possibly " - "illegal dereference in a caller."); - return true; + if (!dereference_probable_p (fun, access)) + { + disqualify_split_candidate (desc, "Dereferences in callers " + "would happen much more frequently."); + return true; + } + } + else + { + int idx = (entry_bb_index * unsafe_by_ref_count + desc->deref_index); + if ((access->offset + access->size) > bb_dereferences[idx]) + { + disqualify_split_candidate (desc, "Would create a possibly " + "illegal dereference in a caller."); + return true; + } } } for (gensum_param_access *ch = access->first_child; ch; ch = ch->next_sibling) - if (check_gensum_access (parm, desc, ch, nonarg_acc_size, only_calls, + if (check_gensum_access (fun, parm, desc, ch, nonarg_acc_size, only_calls, entry_bb_index)) return true; @@ -2288,6 +2325,7 @@ process_scan_results (cgraph_node *node, struct function *fun, if (!dereferences_propagated && desc->by_ref + && !desc->safe_ref && desc->accesses) { propagate_dereference_distances (fun); @@ -2302,8 +2340,8 @@ process_scan_results (cgraph_node *node, struct function *fun, for (gensum_param_access *acc = desc->accesses; acc; acc = acc->next_sibling) - if (check_gensum_access (parm, desc, acc, &nonarg_acc_size, &only_calls, - entry_bb_index)) + if (check_gensum_access (fun, parm, desc, acc, &nonarg_acc_size, + &only_calls, entry_bb_index)) { check_failed = true; break; @@ -2394,6 +2432,12 @@ process_scan_results (cgraph_node *node, struct function *fun, if (!uses_memory_as_obtained) continue; + if (desc->safe_ref) + { + csum->m_arg_flow[argidx].safe_to_import_accesses = true; + continue; + } + /* Post-dominator check placed last, hoping that it usually won't be needed. */ if (!pdoms_calculated) @@ -4124,7 +4168,7 @@ ipa_sra_summarize_function (cgraph_node *node) cfun_pushed = true; final_bbs = BITMAP_ALLOC (NULL); bb_dereferences = XCNEWVEC (HOST_WIDE_INT, - by_ref_count + unsafe_by_ref_count * last_basic_block_for_fn (fun)); aa_walking_limit = opt_for_fn (node->decl, param_ipa_max_aa_steps); scan_function (node, fun); diff --git a/gcc/testsuite/g++.dg/ipa/ipa-sra-5.C b/gcc/testsuite/g++.dg/ipa/ipa-sra-5.C new file mode 100644 index 00000000000..26a221e1734 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/ipa-sra-5.C @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-ipa-sra" } */ + +volatile int vi; + +static void __attribute__((noinline)) +foo (int c, int &r) +{ + int i; + if (c) + i = r; + else + i = 0; + vi = i; +} + +void +bar (int c, int j) +{ + foo (c, j); +} + +/* { dg-final { scan-ipa-dump "Will split parameter" "sra" } } */ From patchwork Sat Nov 12 01:46:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60470 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9F5CB389EC54 for ; Sat, 12 Nov 2022 01:47:46 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by sourceware.org (Postfix) with ESMTPS id B628B3896C18 for ; Sat, 12 Nov 2022 01:46:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B628B3896C18 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id E98591F45F; Sat, 12 Nov 2022 01:46:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217615; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=yb7q7S6byU5rCsrko45UrveHWKyjnqQXOy/hzK04xws=; b=FkpkjOePNwp1cQ0xJ8hsSasVJhku9g5SNZBFZTmhC3+JPo5Pfa3SsCCOjOo2pG++udnC/U a959P1s870QFN9btUJBrA6J2Ujq/OHNfH8Y0weD24gUNC6HZwjiNsg94tSR6iQ8/7+Wu6U vTTIgi4SqKKLwRlrdfz2iW+WwbDVf3M= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217615; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=yb7q7S6byU5rCsrko45UrveHWKyjnqQXOy/hzK04xws=; b=2tt0r7qHLIOjb7mh+ssHCjF+Q2gyAtEdBxlRVM3EIsIwO1P2F2maTyYsU4Dr9CCrZG+8Rl ciP3+sJtg5up/fDA== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id DBD8213A08; Sat, 12 Nov 2022 01:46:55 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id zfeINQ/7bmNqZAAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:46:55 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 08/12] ipa-sra: Move caller->callee propagation before callee->caller one User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:46:55 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, this patch does not do any functional changes, it merely moves top-down propagation in the IPA-SRA WPA phase before bottom-up one. This also meant moving some preliminary checks from the latter to the former - where they need to be in their own loop over each SCC because the subsequent one looks at callers. Currently the propagations are independent (top-down is used for return value rermoval, bottom-up for parameter removal and splitting) but subsequent patches will introduce flags about parameters which should be propagated from callers first and used in splitting. I separated this change to test ir independently and make those subsequent patches cleaner. While at it, I also replaced couple of FOR_EACH_VEC_ELT macros with C++11 style iteration. Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2022-11-11 Martin Jambor * ipa-sra.c (ipa_sra_analysis): Move top-down analysis before bottom-up analysis. Replace FOR_EACH_VEC_ELT with C++11 iteration. gcc/testsuite/ChangeLog: 2021-12-14 Martin Jambor * gcc.dg/ipa/ipa-sra-25.c: New test --- gcc/ipa-sra.cc | 145 +++++++++++++------------- gcc/testsuite/gcc.dg/ipa/ipa-sra-25.c | 17 +++ 2 files changed, 89 insertions(+), 73 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-sra-25.c diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc index e8a4cd47429..fa5a01ec07c 100644 --- a/gcc/ipa-sra.cc +++ b/gcc/ipa-sra.cc @@ -3925,95 +3925,28 @@ ipa_sra_analysis (void) auto_vec stack; int node_scc_count = ipa_reduced_postorder (order, true, NULL); - /* One sweep from callees to callers for parameter removal and splitting. */ - for (int i = 0; i < node_scc_count; i++) + /* One sweep from callers to callees for return value removal. */ + for (int i = node_scc_count - 1; i >= 0 ; i--) { cgraph_node *scc_rep = order[i]; vec cycle_nodes = ipa_get_nodes_in_cycle (scc_rep); - unsigned j; - /* Preliminary IPA function level checks and first step of parameter - removal. */ - cgraph_node *v; - FOR_EACH_VEC_ELT (cycle_nodes, j, v) + /* Preliminary IPA function level checks. */ + for (cgraph_node *v : cycle_nodes) { isra_func_summary *ifs = func_sums->get (v); if (!ifs || !ifs->m_candidate) continue; if (!ipa_sra_ipa_function_checks (v) || check_all_callers_for_issues (v)) - { - ifs->zap (); - continue; - } - if (disable_unavailable_parameters (v, ifs)) - continue; - for (cgraph_edge *cs = v->indirect_calls; cs; cs = cs->next_callee) - process_edge_to_unknown_caller (cs); - for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee) - if (!ipa_edge_within_scc (cs)) - param_removal_cross_scc_edge (cs); + ifs->zap (); } - /* Look at edges within the current SCC and propagate used-ness across - them, pushing onto the stack all notes which might need to be - revisited. */ - FOR_EACH_VEC_ELT (cycle_nodes, j, v) - v->call_for_symbol_thunks_and_aliases (propagate_used_to_scc_callers, - &stack, true); - - /* Keep revisiting and pushing until nothing changes. */ - while (!stack.is_empty ()) - { - cgraph_node *v = stack.pop (); - isra_func_summary *ifs = func_sums->get (v); - gcc_checking_assert (ifs && ifs->m_queued); - ifs->m_queued = false; - - v->call_for_symbol_thunks_and_aliases (propagate_used_to_scc_callers, - &stack, true); - } - - /* Parameter splitting. */ - bool repeat_scc_access_propagation; - do - { - repeat_scc_access_propagation = false; - FOR_EACH_VEC_ELT (cycle_nodes, j, v) - { - isra_func_summary *ifs = func_sums->get (v); - if (!ifs - || !ifs->m_candidate - || vec_safe_is_empty (ifs->m_parameters)) - continue; - for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee) - if (param_splitting_across_edge (cs)) - repeat_scc_access_propagation = true; - } - } - while (repeat_scc_access_propagation); - - if (flag_checking) - FOR_EACH_VEC_ELT (cycle_nodes, j, v) - verify_splitting_accesses (v, true); - - cycle_nodes.release (); - } - - /* One sweep from caller to callees for result removal. */ - for (int i = node_scc_count - 1; i >= 0 ; i--) - { - cgraph_node *scc_rep = order[i]; - vec cycle_nodes = ipa_get_nodes_in_cycle (scc_rep); - unsigned j; - - cgraph_node *v; - FOR_EACH_VEC_ELT (cycle_nodes, j, v) + for (cgraph_node *v : cycle_nodes) { isra_func_summary *ifs = func_sums->get (v); if (!ifs || !ifs->m_candidate) continue; - bool return_needed = (ifs->m_returns_value && (!dbg_cnt (ipa_sra_retvalues) @@ -4048,6 +3981,72 @@ ipa_sra_analysis (void) cycle_nodes.release (); } + /* One sweep from callees to callers for parameter removal and splitting. */ + for (int i = 0; i < node_scc_count; i++) + { + cgraph_node *scc_rep = order[i]; + vec cycle_nodes = ipa_get_nodes_in_cycle (scc_rep); + + /* First step of parameter removal. */ + for (cgraph_node *v : cycle_nodes) + { + isra_func_summary *ifs = func_sums->get (v); + if (!ifs || !ifs->m_candidate) + continue; + if (disable_unavailable_parameters (v, ifs)) + continue; + for (cgraph_edge *cs = v->indirect_calls; cs; cs = cs->next_callee) + process_edge_to_unknown_caller (cs); + for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee) + if (!ipa_edge_within_scc (cs)) + param_removal_cross_scc_edge (cs); + } + + /* Look at edges within the current SCC and propagate used-ness across + them, pushing onto the stack all notes which might need to be + revisited. */ + for (cgraph_node *v : cycle_nodes) + v->call_for_symbol_thunks_and_aliases (propagate_used_to_scc_callers, + &stack, true); + + /* Keep revisiting and pushing until nothing changes. */ + while (!stack.is_empty ()) + { + cgraph_node *v = stack.pop (); + isra_func_summary *ifs = func_sums->get (v); + gcc_checking_assert (ifs && ifs->m_queued); + ifs->m_queued = false; + + v->call_for_symbol_thunks_and_aliases (propagate_used_to_scc_callers, + &stack, true); + } + + /* Parameter splitting. */ + bool repeat_scc_access_propagation; + do + { + repeat_scc_access_propagation = false; + for (cgraph_node *v : cycle_nodes) + { + isra_func_summary *ifs = func_sums->get (v); + if (!ifs + || !ifs->m_candidate + || vec_safe_is_empty (ifs->m_parameters)) + continue; + for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee) + if (param_splitting_across_edge (cs)) + repeat_scc_access_propagation = true; + } + } + while (repeat_scc_access_propagation); + + if (flag_checking) + for (cgraph_node *v : cycle_nodes) + verify_splitting_accesses (v, true); + + cycle_nodes.release (); + } + ipa_free_postorder_info (); free (order); diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-25.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-25.c new file mode 100644 index 00000000000..46fc1a54571 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-25.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wmaybe-uninitialized -Werror" } */ + +int cbos(); +static int aos() { + cbos(); + return 0; +} +int cbos_ptr; +long cbos_psize; +int cbos() { + if (cbos_ptr) + return aos(); + if (cbos_psize) + return 1; + return 0; +} From patchwork Sat Nov 12 01:47:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60468 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E08093949083 for ; Sat, 12 Nov 2022 01:47:31 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [IPv6:2001:67c:2178:6::1d]) by sourceware.org (Postfix) with ESMTPS id D0DFE393A412 for ; Sat, 12 Nov 2022 01:47:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org D0DFE393A412 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 135591F45F; Sat, 12 Nov 2022 01:47:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217626; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=EFXlTZ2PalNzK4h+UyHxEQnG9HR4LcNTKWvVEhlHRtw=; b=hyryb27Baz+M0XwLdaL7rD38bpMRJjnWuhYakVXD7YS6uWH1DvpTwqL26agOE7GQTQnajV y3lbjshFgtNTMl988w6TLw82J2s+AP3eRYeyH/lF5AReNFHfZZ4pgsMCDIA7U5SCA5RgZR gkZf+l8tjaVEiebBW0XPW8FOXYttrzI= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217626; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=EFXlTZ2PalNzK4h+UyHxEQnG9HR4LcNTKWvVEhlHRtw=; b=+nxIHqUUUnFOaTsiYzHsms8dvCXcmVa6XT85rhueXRznorX1OpgT3qtK1rcw82gOJSjWlk mYjfwB2tvPzXLvAg== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id F2B7013A08; Sat, 12 Nov 2022 01:47:05 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id UcAPOxn7bmOFZAAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:47:05 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 09/12] ipa-sra: Be optimistic about Fortran descriptors User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:47:05 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, SPF_HELO_NONE, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, Fortran descriptors are structures which are often constructed just for a particular argument of a particular call where it is passed by reference. When the called function is under compiler's control, it can be beneficial to split up the descriptor and pass it in individual parameters. Unfortunately, currently we allow IPA-SRA to replace a pointer with a set of replacements which are at most twice as big in total and for descriptors we'd need to bump that factor to seven. This patch looks for parameters which are ADDR_EXPRs of local variables which are written to and passed as arguments by reference but are never loaded from and marks them with a flag in the call edge summary. The IPA analysis phase then identifies formal parameters which are always fed such arguments and then is more lenient when it comoes to size. In order not to store to maximums per formal parameter, I calculate the more lenient one by multiplying the existing one with a new parameter. If it is preferable to keep the maximums independent, we can do that. Documentation for the new parameter is missing as I still need to re-base the patch on a version which has sphinx. I will write it before committing. I have disable IPA-SRA in pr48636-2.f90 in order to be able to keep using its dump-scan expressions. The new testcase is basically a copy of it with different options and IPA-SRA dump scans. Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2022-11-11 Martin Jambor * ipa-sra.c (isra_param_desc): New field not_specially_constructed. (struct isra_param_flow): New field constructed_for_calls. (isra_call_summary::dump): Dump the new flag. (loaded_decls): New variable. (dump_isra_param_descriptor): New parameter hints, dump not_specially_constructed if it is true. (dump_isra_param_descriptors): New parameter hints, pass it to dump_isra_param_descriptor. (ipa_sra_function_summaries::duplicate): Duplicate new flag. (create_parameter_descriptors): Adjust comment. (get_gensum_param_desc): Bail out when decl2desc is NULL. (scan_expr_access): Add loaded local variables to loaded_decls. (scan_function): Survive if final_bbs is NULL. (isra_analyze_call): Compute constructed_for_calls flag. (process_scan_results): Be optimistic about size limits. Do not dump computed param hints when dumpint IPA-SRA structures. (isra_write_edge_summary): Stream constructed_for_calls. (isra_read_edge_summary): Likewise. (ipa_sra_dump_all_summaries): New parameter hints, pass it to dump_isra_param_descriptor. (flip_all_hints_pessimistic): New function. (flip_all_param_hints_pessimistic): Likewise. (propagate_param_hints): Likewise. (disable_unavailable_parameters): Renamed to adjust_parameter_descriptions. Expand size limits for parameters which are specially contstructed by all callers. Check limits again.p (ipa_sra_analysis): Pass required hints to ipa_sra_dump_all_summaries. Add hint propagation. (ipa_sra_summarize_function): Initialize and destory loaded_decls, rearrange so that scan_function is called even when there are no candidates. * params.opt (ipa-sra-ptrwrap-growth-factor): New parameter. gcc/testsuite/ChangeLog: 2021-11-11 Martin Jambor * gfortran.dg/pr48636-2.f90: Disable IPA-SRA. * gfortran.dg/ipa-sra-1.f90: New test. --- gcc/ipa-sra.cc | 278 +++++++++++++++++++----- gcc/params.opt | 6 +- gcc/testsuite/gfortran.dg/ipa-sra-1.f90 | 37 ++++ gcc/testsuite/gfortran.dg/pr48636-2.f90 | 2 +- 4 files changed, 267 insertions(+), 56 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/ipa-sra-1.f90 diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc index fa5a01ec07c..c35c0d7162a 100644 --- a/gcc/ipa-sra.cc +++ b/gcc/ipa-sra.cc @@ -181,6 +181,10 @@ struct GTY(()) isra_param_desc unsigned split_candidate : 1; /* Is this a parameter passing stuff by reference? */ unsigned by_ref : 1; + /* Parameter hint set during IPA analysis when there is a caller which does + not construct the argument just to pass it to calls. Only meaningful for + by_ref parameters. */ + unsigned not_specially_constructed : 1; }; /* Structure used when generating summaries that describes a parameter. */ @@ -340,6 +344,10 @@ struct isra_param_flow /* True when it is safe to copy access candidates here from the callee, which would mean introducing dereferences into callers of the caller. */ unsigned safe_to_import_accesses : 1; + /* True when the passed value is an address of a structure that has been + constructed in the caller just to be passed by reference to functions + (i.e. is never read). */ + unsigned constructed_for_calls : 1; }; /* Structure used to convey information about calls from the intra-procedural @@ -420,6 +428,7 @@ ipa_sra_function_summaries::duplicate (cgraph_node *, cgraph_node *, d->locally_unused = s->locally_unused; d->split_candidate = s->split_candidate; d->by_ref = s->by_ref; + d->not_specially_constructed = s->not_specially_constructed; unsigned acc_count = vec_safe_length (s->accesses); vec_safe_reserve_exact (d->accesses, acc_count); @@ -531,6 +540,9 @@ isra_call_summary::dump (FILE *f) if (ipf->pointer_pass_through) fprintf (f, " Pointer pass through from the param given above, " "safe_to_import_accesses: %u\n", ipf->safe_to_import_accesses); + if (ipf->constructed_for_calls) + fprintf (f, " Variable constructed just to be passed to " + "calls.\n"); } } @@ -559,6 +571,10 @@ namespace { hash_map *decl2desc; +/* All local DECLs ever loaded from. */ + +hash_set *loaded_decls; + /* Countdown of allowed Alias Analysis steps during summary building. */ int aa_walking_limit; @@ -728,10 +744,11 @@ dump_gensum_param_descriptors (FILE *f, tree fndecl, } -/* Dump DESC to F. */ +/* Dump DESC to F. If HINTS is true, also dump IPA-analysis computed + hints. */ static void -dump_isra_param_descriptor (FILE *f, isra_param_desc *desc) +dump_isra_param_descriptor (FILE *f, isra_param_desc *desc, bool hints) { if (desc->locally_unused) { @@ -742,9 +759,15 @@ dump_isra_param_descriptor (FILE *f, isra_param_desc *desc) fprintf (f, " not a candidate for splitting\n"); return; } - fprintf (f, " param_size_limit: %u, size_reached: %u%s\n", + fprintf (f, " param_size_limit: %u, size_reached: %u%s", desc->param_size_limit, desc->size_reached, desc->by_ref ? ", by_ref" : ""); + if (hints) + { + if (desc->by_ref && !desc->not_specially_constructed) + fprintf (f, ", args_specially_constructed"); + } + fprintf (f, "\n"); for (unsigned i = 0; i < vec_safe_length (desc->accesses); ++i) { @@ -753,12 +776,12 @@ dump_isra_param_descriptor (FILE *f, isra_param_desc *desc) } } -/* Dump all parameter descriptors in IFS, assuming it describes FNDECL, to - F. */ +/* Dump all parameter descriptors in IFS, assuming it describes FNDECL, to F. + If HINTS is true, also dump IPA-analysis computed hints. */ static void -dump_isra_param_descriptors (FILE *f, tree fndecl, - isra_func_summary *ifs) +dump_isra_param_descriptors (FILE *f, tree fndecl, isra_func_summary *ifs, + bool hints) { tree parm = DECL_ARGUMENTS (fndecl); if (!ifs->m_parameters) @@ -774,7 +797,7 @@ dump_isra_param_descriptors (FILE *f, tree fndecl, fprintf (f, " Descriptor for parameter %i ", i); print_generic_expr (f, parm, TDF_UID); fprintf (f, "\n"); - dump_isra_param_descriptor (f, &(*ifs->m_parameters)[i]); + dump_isra_param_descriptor (f, &(*ifs->m_parameters)[i], hints); } } @@ -1086,7 +1109,7 @@ ptr_parm_has_nonarg_uses (cgraph_node *node, function *fun, tree parm, /* Initialize vector of parameter descriptors of NODE. Return true if there are any candidates for splitting or unused aggregate parameter removal (the function may return false if there are candidates for removal of register - parameters) and function body must be scanned. */ + parameters). */ static bool create_parameter_descriptors (cgraph_node *node, @@ -1254,6 +1277,8 @@ create_parameter_descriptors (cgraph_node *node, static gensum_param_desc * get_gensum_param_desc (tree decl) { + if (!decl2desc) + return NULL; gcc_checking_assert (TREE_CODE (decl) == PARM_DECL); gensum_param_desc **slot = decl2desc->get (decl); if (!slot) @@ -1705,6 +1730,12 @@ scan_expr_access (tree expr, gimple *stmt, isra_scan_context ctx, return; deref = true; } + else if (TREE_CODE (base) == VAR_DECL + && !TREE_STATIC (base) + && (ctx == ISRA_CTX_ARG + || ctx == ISRA_CTX_LOAD)) + loaded_decls->add (base); + if (TREE_CODE (base) != PARM_DECL) return; @@ -1884,7 +1915,7 @@ scan_function (cgraph_node *node, struct function *fun) { gimple *stmt = gsi_stmt (gsi); - if (stmt_can_throw_external (fun, stmt)) + if (final_bbs && stmt_can_throw_external (fun, stmt)) bitmap_set_bit (final_bbs, bb->index); switch (gimple_code (stmt)) { @@ -1893,7 +1924,8 @@ scan_function (cgraph_node *node, struct function *fun) tree t = gimple_return_retval (as_a (stmt)); if (t != NULL_TREE) scan_expr_access (t, stmt, ISRA_CTX_LOAD, bb); - bitmap_set_bit (final_bbs, bb->index); + if (final_bbs) + bitmap_set_bit (final_bbs, bb->index); } break; @@ -1938,8 +1970,9 @@ scan_function (cgraph_node *node, struct function *fun) if (lhs) scan_expr_access (lhs, stmt, ISRA_CTX_STORE, bb); int flags = gimple_call_flags (stmt); - if (((flags & (ECF_CONST | ECF_PURE)) == 0) - || (flags & ECF_LOOPING_CONST_OR_PURE)) + if (final_bbs + && (((flags & (ECF_CONST | ECF_PURE)) == 0) + || (flags & ECF_LOOPING_CONST_OR_PURE))) bitmap_set_bit (final_bbs, bb->index); } break; @@ -1949,7 +1982,8 @@ scan_function (cgraph_node *node, struct function *fun) gasm *asm_stmt = as_a (stmt); walk_stmt_load_store_addr_ops (asm_stmt, NULL, NULL, NULL, asm_visit_addr); - bitmap_set_bit (final_bbs, bb->index); + if (final_bbs) + bitmap_set_bit (final_bbs, bb->index); for (unsigned i = 0; i < gimple_asm_ninputs (asm_stmt); i++) { @@ -2045,6 +2079,23 @@ isra_analyze_call (cgraph_edge *cs) for (unsigned i = 0; i < count; i++) { tree arg = gimple_call_arg (call_stmt, i); + if (TREE_CODE (arg) == ADDR_EXPR) + { + poly_int64 poffset, psize, pmax_size; + bool reverse; + tree base = get_ref_base_and_extent (TREE_OPERAND (arg, 0), &poffset, + &psize, &pmax_size, &reverse); + /* TODO: Next patch will need the offset too, so we cannot use + get_base_address. */ + if (TREE_CODE (base) == VAR_DECL + && !TREE_STATIC (base) + && !loaded_decls->contains (base)) + { + csum->init_inputs (count); + csum->m_arg_flow[i].constructed_for_calls = true; + } + } + if (is_gimple_reg (arg)) continue; @@ -2354,18 +2405,28 @@ process_scan_results (cgraph_node *node, struct function *fun, HOST_WIDE_INT cur_param_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (parm))); - HOST_WIDE_INT param_size_limit; + HOST_WIDE_INT param_size_limit, optimistic_limit; if (!desc->by_ref || optimize_function_for_size_p (fun)) - param_size_limit = cur_param_size; + { + param_size_limit = cur_param_size; + optimistic_limit = cur_param_size; + } else + { param_size_limit = opt_for_fn (node->decl, param_ipa_sra_ptr_growth_factor) * cur_param_size; - if (nonarg_acc_size > param_size_limit + optimistic_limit + = (opt_for_fn (node->decl, param_ipa_sra_ptrwrap_growth_factor) + * param_size_limit); + } + + if (nonarg_acc_size > optimistic_limit || (!desc->by_ref && nonarg_acc_size == param_size_limit)) { disqualify_split_candidate (desc, "Would result into a too big set " - "of replacements."); + "of replacements even in best " + "scenarios."); } else { @@ -2486,7 +2547,7 @@ process_scan_results (cgraph_node *node, struct function *fun, } if (dump_file) - dump_isra_param_descriptors (dump_file, node->decl, ifs); + dump_isra_param_descriptors (dump_file, node->decl, ifs, false); } /* Return true if there are any overlaps among certain accesses of DESC. If @@ -2587,6 +2648,7 @@ isra_write_edge_summary (output_block *ob, cgraph_edge *e) bp_pack_value (&bp, ipf->aggregate_pass_through, 1); bp_pack_value (&bp, ipf->pointer_pass_through, 1); bp_pack_value (&bp, ipf->safe_to_import_accesses, 1); + bp_pack_value (&bp, ipf->constructed_for_calls, 1); streamer_write_bitpack (&bp); streamer_write_uhwi (ob, ipf->unit_offset); streamer_write_uhwi (ob, ipf->unit_size); @@ -2635,6 +2697,7 @@ isra_write_node_summary (output_block *ob, cgraph_node *node) bp_pack_value (&bp, desc->locally_unused, 1); bp_pack_value (&bp, desc->split_candidate, 1); bp_pack_value (&bp, desc->by_ref, 1); + gcc_assert (!desc->not_specially_constructed); streamer_write_bitpack (&bp); } bitpack_d bp = bitpack_create (ob->main_stream); @@ -2708,6 +2771,7 @@ isra_read_edge_summary (struct lto_input_block *ib, cgraph_edge *cs) ipf->aggregate_pass_through = bp_unpack_value (&bp, 1); ipf->pointer_pass_through = bp_unpack_value (&bp, 1); ipf->safe_to_import_accesses = bp_unpack_value (&bp, 1); + ipf->constructed_for_calls = bp_unpack_value (&bp, 1); ipf->unit_offset = streamer_read_uhwi (ib); ipf->unit_size = streamer_read_uhwi (ib); } @@ -2754,6 +2818,7 @@ isra_read_node_info (struct lto_input_block *ib, cgraph_node *node, desc->locally_unused = bp_unpack_value (&bp, 1); desc->split_candidate = bp_unpack_value (&bp, 1); desc->by_ref = bp_unpack_value (&bp, 1); + desc->not_specially_constructed = 0; } bitpack_d bp = streamer_read_bitpack (ib); ifs->m_candidate = bp_unpack_value (&bp, 1); @@ -2836,10 +2901,11 @@ ipa_sra_read_summary (void) } } -/* Dump all IPA-SRA summary data for all cgraph nodes and edges to file F. */ +/* Dump all IPA-SRA summary data for all cgraph nodes and edges to file F. If + HINTS is true, also dump IPA-analysis computed hints. */ static void -ipa_sra_dump_all_summaries (FILE *f) +ipa_sra_dump_all_summaries (FILE *f, bool hints) { cgraph_node *node; FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) @@ -2862,7 +2928,7 @@ ipa_sra_dump_all_summaries (FILE *f) for (unsigned i = 0; i < ifs->m_parameters->length (); ++i) { fprintf (f, " Descriptor for parameter %i:\n", i); - dump_isra_param_descriptor (f, &(*ifs->m_parameters)[i]); + dump_isra_param_descriptor (f, &(*ifs->m_parameters)[i], hints); } fprintf (f, "\n"); } @@ -3199,6 +3265,61 @@ isra_mark_caller_param_used (isra_func_summary *from_ifs, int input_idx, } } +/* Set all param hints in DESC to the pessimistic values. */ + +static void +flip_all_hints_pessimistic (isra_param_desc *desc) +{ + desc->not_specially_constructed = true; + + return; +} + +/* Because we have not analyzed a caller, go over all parameter int flags of + NODE and turn them pessimistic. */ + +static void +flip_all_param_hints_pessimistic (cgraph_node *node) +{ + isra_func_summary *ifs = func_sums->get (node); + if (!ifs || !ifs->m_candidate) + return; + + unsigned param_count = vec_safe_length (ifs->m_parameters); + + for (unsigned i = 0; i < param_count; i++) + flip_all_hints_pessimistic (&(*ifs->m_parameters)[i]); + + return; +} + +/* Propagate hints accross edge CS which ultimately leads to CALLEE. */ + +static void +propagate_param_hints (cgraph_edge *cs, cgraph_node *callee) +{ + isra_call_summary *csum = call_sums->get (cs); + isra_func_summary *to_ifs = func_sums->get (callee); + if (!to_ifs || !to_ifs->m_candidate) + return; + + unsigned args_count = csum->m_arg_flow.length (); + unsigned param_count = vec_safe_length (to_ifs->m_parameters); + + for (unsigned i = 0; i < param_count; i++) + { + isra_param_desc *desc = &(*to_ifs->m_parameters)[i]; + if (i >= args_count) + { + flip_all_hints_pessimistic (desc); + continue; + } + + if (desc->by_ref && !csum->m_arg_flow[i].constructed_for_calls) + desc->not_specially_constructed = true; + } + return; +} /* Propagate information that any parameter is not used only locally within a SCC across CS to the caller, which must be in the same SCC as the @@ -3849,10 +3970,12 @@ process_isra_node_results (cgraph_node *node, /* Check which parameters of NODE described by IFS have survived until IPA-SRA and disable transformations for those which have not or which should not transformed because the associated debug counter reached its limit. Return - true if none survived or if there were no candidates to begin with. */ + true if none survived or if there were no candidates to begin with. + Additionally, also adjust parameter descriptions based on debug counters and + hints propagated earlier. */ static bool -disable_unavailable_parameters (cgraph_node *node, isra_func_summary *ifs) +adjust_parameter_descriptions (cgraph_node *node, isra_func_summary *ifs) { bool ret = true; unsigned len = vec_safe_length (ifs->m_parameters); @@ -3897,8 +4020,23 @@ disable_unavailable_parameters (cgraph_node *node, isra_func_summary *ifs) fprintf (dump_file, " %u", i); } } - else if (desc->locally_unused || desc->split_candidate) - ret = false; + else + { + if (desc->split_candidate) + { + if (desc->by_ref && !desc->not_specially_constructed) + { + int extra_factor + = opt_for_fn (node->decl, + param_ipa_sra_ptrwrap_growth_factor); + desc->param_size_limit = extra_factor * desc->param_size_limit; + } + if (size_would_violate_limit_p (desc, desc->size_reached)) + desc->split_candidate = false; + } + if (desc->locally_unused || desc->split_candidate) + ret = false; + } } if (dumped_first) @@ -3916,7 +4054,7 @@ ipa_sra_analysis (void) if (dump_file) { fprintf (dump_file, "\n========== IPA-SRA IPA stage ==========\n"); - ipa_sra_dump_all_summaries (dump_file); + ipa_sra_dump_all_summaries (dump_file, false); } gcc_checking_assert (func_sums); @@ -3978,6 +4116,24 @@ ipa_sra_analysis (void) } } } + + /* Parameter hint propagation. */ + for (cgraph_node *v : cycle_nodes) + { + isra_func_summary *ifs = func_sums->get (v); + for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee) + { + enum availability availability; + cgraph_node *callee = cs->callee->function_symbol (&availability); + if (!ifs) + { + flip_all_param_hints_pessimistic (callee); + continue; + } + propagate_param_hints (cs, callee); + } + } + cycle_nodes.release (); } @@ -3993,7 +4149,7 @@ ipa_sra_analysis (void) isra_func_summary *ifs = func_sums->get (v); if (!ifs || !ifs->m_candidate) continue; - if (disable_unavailable_parameters (v, ifs)) + if (adjust_parameter_descriptions (v, ifs)) continue; for (cgraph_edge *cs = v->indirect_calls; cs; cs = cs->next_callee) process_edge_to_unknown_caller (cs); @@ -4056,7 +4212,7 @@ ipa_sra_analysis (void) { fprintf (dump_file, "\n========== IPA-SRA propagation final state " " ==========\n"); - ipa_sra_dump_all_summaries (dump_file); + ipa_sra_dump_all_summaries (dump_file, true); } fprintf (dump_file, "\n========== IPA-SRA decisions ==========\n"); } @@ -4137,30 +4293,32 @@ ipa_sra_summarize_function (cgraph_node *node) if (dump_file) fprintf (dump_file, "Creating summary for %s/%i:\n", node->name (), node->order); - if (!ipa_sra_preliminary_function_checks (node)) - { - isra_analyze_all_outgoing_calls (node); - return; - } gcc_obstack_init (&gensum_obstack); - isra_func_summary *ifs = func_sums->get_create (node); - ifs->m_candidate = true; - tree ret = TREE_TYPE (TREE_TYPE (node->decl)); - ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE); + loaded_decls = new hash_set; - decl2desc = new hash_map; + isra_func_summary *ifs = NULL; unsigned count = 0; - for (tree parm = DECL_ARGUMENTS (node->decl); parm; parm = DECL_CHAIN (parm)) - count++; + if (ipa_sra_preliminary_function_checks (node)) + { + ifs = func_sums->get_create (node); + ifs->m_candidate = true; + tree ret = TREE_TYPE (TREE_TYPE (node->decl)); + ifs->m_returns_value = (TREE_CODE (ret) != VOID_TYPE); + for (tree parm = DECL_ARGUMENTS (node->decl); + parm; + parm = DECL_CHAIN (parm)) + count++; + } + auto_vec param_descriptions (count); + struct function *fun = DECL_STRUCT_FUNCTION (node->decl); + bool cfun_pushed = false; if (count > 0) { - auto_vec param_descriptions (count); + decl2desc = new hash_map; param_descriptions.reserve_exact (count); param_descriptions.quick_grow_cleared (count); - bool cfun_pushed = false; - struct function *fun = DECL_STRUCT_FUNCTION (node->decl); if (create_parameter_descriptors (node, ¶m_descriptions)) { push_cfun (fun); @@ -4170,15 +4328,22 @@ ipa_sra_summarize_function (cgraph_node *node) unsafe_by_ref_count * last_basic_block_for_fn (fun)); aa_walking_limit = opt_for_fn (node->decl, param_ipa_max_aa_steps); - scan_function (node, fun); - - if (dump_file) - { - dump_gensum_param_descriptors (dump_file, node->decl, - ¶m_descriptions); - fprintf (dump_file, "----------------------------------------\n"); - } } + } + /* Scan function is run even when there are no removal or splitting + candidates so that we can calculate hints on call edges which can be + useful in callees. */ + scan_function (node, fun); + + if (count > 0) + { + if (dump_file) + { + dump_gensum_param_descriptors (dump_file, node->decl, + ¶m_descriptions); + fprintf (dump_file, "----------------------------------------\n"); + } + process_scan_results (node, fun, ifs, ¶m_descriptions); if (cfun_pushed) @@ -4193,8 +4358,13 @@ ipa_sra_summarize_function (cgraph_node *node) } isra_analyze_all_outgoing_calls (node); - delete decl2desc; - decl2desc = NULL; + delete loaded_decls; + loaded_decls = NULL; + if (decl2desc) + { + delete decl2desc; + decl2desc = NULL; + } obstack_free (&gensum_obstack, NULL); if (dump_file) fprintf (dump_file, "\n\n"); diff --git a/gcc/params.opt b/gcc/params.opt index 3001566e641..e19d7899ea9 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -288,7 +288,11 @@ Maximum pieces that IPA-SRA tracks per formal parameter, as a consequence, also -param=ipa-sra-ptr-growth-factor= Common Joined UInteger Var(param_ipa_sra_ptr_growth_factor) Init(2) Param Optimization -Maximum allowed growth of number and total size of new parameters that ipa-sra replaces a pointer to an aggregate with. +Maximum allowed growth of total size of new parameters that ipa-sra replaces a pointer to an aggregate with. + +-param=ipa-sra-ptrwrap-growth-factor= +Common Joined UInteger Var(param_ipa_sra_ptrwrap_growth_factor) Init(4) IntegerRange(1, 8) Param Optimization +Additional maximum allowed growth of total size of new parameters that ipa-sra replaces a pointer to an aggregate with, if it points to a local variable that the caller never writes to. -param=ira-loop-reserved-regs= Common Joined UInteger Var(param_ira_loop_reserved_regs) Init(2) Param Optimization diff --git a/gcc/testsuite/gfortran.dg/ipa-sra-1.f90 b/gcc/testsuite/gfortran.dg/ipa-sra-1.f90 new file mode 100644 index 00000000000..0c916c76148 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/ipa-sra-1.f90 @@ -0,0 +1,37 @@ +! { dg-do compile } +! { dg-options "-O2 -fno-inline -fno-ipa-cp -fwhole-program -fdump-ipa-sra-details" } + +module foo + implicit none +contains + subroutine bar(a,x) + real, dimension(:,:), intent(in) :: a + real, intent(out) :: x + integer :: i,j + + x = 0 + do j=1,ubound(a,2) + do i=1,ubound(a,1) + x = x + a(i,j)**2 + end do + end do + end subroutine bar +end module foo + +program main + use foo + implicit none + real, dimension(2,3) :: a + real :: x + integer :: i + + data a /1.0, 2.0, 3.0, -1.0, -2.0, -3.0/ + + do i=1,2000000 + call bar(a,x) + end do + print *,x +end program main + +! { dg-final { scan-ipa-dump "Created new node.*bar\\.isra" "sra" } } +! { dg-final { scan-ipa-dump-times "IPA_PARAM_OP_SPLIT" 7 "sra" } } diff --git a/gcc/testsuite/gfortran.dg/pr48636-2.f90 b/gcc/testsuite/gfortran.dg/pr48636-2.f90 index 30a7e75614a..4d2bd69b47e 100644 --- a/gcc/testsuite/gfortran.dg/pr48636-2.f90 +++ b/gcc/testsuite/gfortran.dg/pr48636-2.f90 @@ -1,5 +1,5 @@ ! { dg-do compile } -! { dg-options "-O3 -fdump-ipa-cp-details -fno-inline" } +! { dg-options "-O3 -fdump-ipa-cp-details -fno-inline -fno-ipa-sra" } module foo implicit none From patchwork Sat Nov 12 01:47:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60473 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 570113959CB2 for ; Sat, 12 Nov 2022 01:48:38 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by sourceware.org (Postfix) with ESMTPS id 773353899047 for ; Sat, 12 Nov 2022 01:47:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 773353899047 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 9F82B1F381; Sat, 12 Nov 2022 01:47:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217655; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=96yuyE2F21GicB1NpsykOKa1A75JfNAuS+e4305+8js=; b=L92PDO25PnspeENE+aLXXdvf1V1XZuEA/p8J6cgUZPJah58YJFydAHHfGXRYySJNKShso/ gaFm50j+K1QX3+yM+aV0OZGkIwUh+NmkgzvwZvAyK66ivr8rCfd9oASmW+tEQ8gtEAAjUK gKn6zh3kKx9Sn/Uqkkgv88tooTbfEJY= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217655; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=96yuyE2F21GicB1NpsykOKa1A75JfNAuS+e4305+8js=; b=r85pl1mngxtkbUXGkuxxYxUn9EEwgDBOP0GREWThNbo+/w7Y38hFgtVEgbW4bCI1fy3UN7 aFdHizX0VjS5J3BQ== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 8D8D513A08; Sat, 12 Nov 2022 01:47:35 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id nG1gIjf7bmO7ZAAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:47:35 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 10/12] ipa-sra: Forward propagation of sizes which are safe to dereference User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:47:35 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, the previous patch established a way to propagate information about parameters from callers to callees (even though then the actual splitting is done in the opposite direction), this patch adds to that information about size of the parameters that is known to be safe to dereference in the callers - the information currently does not come from actual dereferences but only when we pass a reference to a known declaration, but we can use e.g. dereferences in BBs dominating the call, for example too, if we decide it is worth it. References which look like splitting candidates but are not always dereferenced are - assuming the dereferences are not improbable - not discarded straight away but only marked as conditionally dereferenceable. IPA phase then makes sure that they stay candidates only if all incoming edges have big enough known-to-be-safe size. Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2022-11-11 Martin Jambor * ipa-sra.cc (isra_param_desc): New fields safe_size, conditionally_dereferenceable and safe_size_set. (struct gensum_param_desc): New field conditionally_dereferenceable. (struct isra_param_flow): Updated comment of field unit_size. (ipa_sra_function_summaries::duplicate): Copy the new fields. (isra_call_summary::dump): Dump unit_size when representing safe_size. (dump_gensum_param_descriptor): Dump new flag. (dump_isra_param_descriptor): Dump new fields. (isra_analyze_call): Fill unit_size when it represents known safe size. (check_gensum_access): Instead of disqualifying pointers which are not always dereference, mark them as conditionally dereferencable if loads are frequent enough. (process_scan_results): Copy the conditionally_dereferenceable flag. (isra_write_node_summary): Stream new fields, or assert they are not initialized yet. (isra_read_node_info): Stream new fields. (update_safe_size): New function. (propagate_param_hints_accross_call): Propagate safe_sizes. (propagate_hints_to_all_callees): New function. (adjust_parameter_descriptions): Check conditionally_dereferenceable candidates, rework dumping. (ipa_sra_analysis): Move most of hint propagation for one node to propagate_hints_to_all_callees. Add another loop to stabilize within SCCs and another one to verify. gcc/testsuite/ChangeLog: 2022-11-11 Martin Jambor * gcc.dg/ipa/ipa-sra-26.c: New test. * gcc.dg/ipa/ipa-sra-27.c: Likewise. * gcc.dg/ipa/ipa-sra-28.c: Likewise. --- gcc/ipa-sra.cc | 253 ++++++++++++++++++++------ gcc/testsuite/gcc.dg/ipa/ipa-sra-26.c | 31 ++++ gcc/testsuite/gcc.dg/ipa/ipa-sra-27.c | 49 +++++ gcc/testsuite/gcc.dg/ipa/ipa-sra-28.c | 51 ++++++ 4 files changed, 328 insertions(+), 56 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-sra-26.c create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-sra-27.c create mode 100644 gcc/testsuite/gcc.dg/ipa/ipa-sra-28.c diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc index c35c0d7162a..93fceeafc73 100644 --- a/gcc/ipa-sra.cc +++ b/gcc/ipa-sra.cc @@ -173,6 +173,10 @@ struct GTY(()) isra_param_desc unsigned param_size_limit : ISRA_ARG_SIZE_LIMIT_BITS; /* Sum of unit sizes of all certain replacements. */ unsigned size_reached : ISRA_ARG_SIZE_LIMIT_BITS; + /* Minimum offset that is known to be safe to dereference because of callers + pass pointers to DECLs of at least this size or because of dereferences in + callers. */ + unsigned safe_size : ISRA_ARG_SIZE_LIMIT_BITS; /* A parameter that is used only in call arguments and can be removed if all concerned actual arguments are removed. */ @@ -185,6 +189,12 @@ struct GTY(()) isra_param_desc not construct the argument just to pass it to calls. Only meaningful for by_ref parameters. */ unsigned not_specially_constructed : 1; + /* Only meaningful for by_ref parameters. If set, this parameter can only be + a split candidate if all callers pass pointers that are known to point to + a chunk of memory large enough to contain all accesses. */ + unsigned conditionally_dereferenceable : 1; + /* Set when safe_size has been updated from at least one caller. */ + unsigned safe_size_set : 1; }; /* Structure used when generating summaries that describes a parameter. */ @@ -220,6 +230,10 @@ struct gensum_param_desc without performing further checks (for example because it is a REFERENCE_TYPE)? */ bool safe_ref; + /* Only meaningful for by_ref parameters. If set, this parameter can only be + a split candidate if all callers pass pointers that are known to point to + a chunk of memory large enough to contain all accesses. */ + bool conditionally_dereferenceable; /* The number of this parameter as they are ordered in function decl. */ int param_number; @@ -332,10 +346,12 @@ struct isra_param_flow /* Offset within the formal parameter. */ unsigned unit_offset; - /* Size of the portion of the formal parameter that is being passed. */ + /* When aggregate_pass_through is set, this is the size of the portion of an + aggregate formal parameter that is being passed. Otherwise, this is size + of pointed to memory that is known to be valid be dereferenced. */ unsigned unit_size : ISRA_ARG_SIZE_LIMIT_BITS; - /* True when the value of this actual copy is a portion of a formal + /* True when the value of this actual argument is a portion of a formal parameter. */ unsigned aggregate_pass_through : 1; /* True when the value of this actual copy is a verbatim pass through of an @@ -425,10 +441,13 @@ ipa_sra_function_summaries::duplicate (cgraph_node *, cgraph_node *, d->param_size_limit = s->param_size_limit; d->size_reached = s->size_reached; + d->safe_size = s->safe_size; d->locally_unused = s->locally_unused; d->split_candidate = s->split_candidate; d->by_ref = s->by_ref; d->not_specially_constructed = s->not_specially_constructed; + d->conditionally_dereferenceable = s->conditionally_dereferenceable; + d->safe_size_set = s->safe_size_set; unsigned acc_count = vec_safe_length (s->accesses); vec_safe_reserve_exact (d->accesses, acc_count); @@ -537,6 +556,8 @@ isra_call_summary::dump (FILE *f) fprintf (f, " Aggregate pass through from the param given above, " "unit offset: %u , unit size: %u\n", ipf->unit_offset, ipf->unit_size); + else if (ipf->unit_size > 0) + fprintf (f, " Known dereferenceable size: %u\n", ipf->unit_size); if (ipf->pointer_pass_through) fprintf (f, " Pointer pass through from the param given above, " "safe_to_import_accesses: %u\n", ipf->safe_to_import_accesses); @@ -717,8 +738,11 @@ dump_gensum_param_descriptor (FILE *f, gensum_param_desc *desc) return; } if (desc->by_ref) - fprintf (f, " %s by_ref with %u pass throughs\n", - desc->safe_ref ? "safe" : "unsafe", desc->ptr_pt_count); + fprintf (f, " %s%s by_ref with %u pass throughs\n", + desc->safe_ref ? "safe" : "unsafe", + desc->conditionally_dereferenceable + ? " conditionally_dereferenceable" : " ok", + desc->ptr_pt_count); for (gensum_param_access *acc = desc->accesses; acc; acc = acc->next_sibling) dump_gensum_access (f, acc, 2); @@ -756,16 +780,23 @@ dump_isra_param_descriptor (FILE *f, isra_param_desc *desc, bool hints) } if (!desc->split_candidate) { - fprintf (f, " not a candidate for splitting\n"); + fprintf (f, " not a candidate for splitting"); + if (hints && desc->by_ref && desc->safe_size_set) + fprintf (f, ", safe_size: %u", (unsigned) desc->safe_size); + fprintf (f, "\n"); return; } fprintf (f, " param_size_limit: %u, size_reached: %u%s", desc->param_size_limit, desc->size_reached, desc->by_ref ? ", by_ref" : ""); + if (desc->by_ref && desc->conditionally_dereferenceable) + fprintf (f, ", conditionally_dereferenceable"); if (hints) { if (desc->by_ref && !desc->not_specially_constructed) fprintf (f, ", args_specially_constructed"); + if (desc->by_ref && desc->safe_size_set) + fprintf (f, ", safe_size: %u", (unsigned) desc->safe_size); } fprintf (f, "\n"); @@ -2085,8 +2116,19 @@ isra_analyze_call (cgraph_edge *cs) bool reverse; tree base = get_ref_base_and_extent (TREE_OPERAND (arg, 0), &poffset, &psize, &pmax_size, &reverse); - /* TODO: Next patch will need the offset too, so we cannot use - get_base_address. */ + HOST_WIDE_INT offset; + unsigned HOST_WIDE_INT ds; + if (DECL_P (base) + && (poffset.is_constant (&offset)) + && tree_fits_uhwi_p (DECL_SIZE (base)) + && ((ds = tree_to_uhwi (DECL_SIZE (base)) - offset) + < ISRA_ARG_SIZE_LIMIT * BITS_PER_UNIT)) + { + csum->init_inputs (count); + gcc_assert (!csum->m_arg_flow[i].aggregate_pass_through); + csum->m_arg_flow[i].unit_size = ds / BITS_PER_UNIT; + } + if (TREE_CODE (base) == VAR_DECL && !TREE_STATIC (base) && !loaded_decls->contains (base)) @@ -2308,9 +2350,14 @@ check_gensum_access (struct function *fun, tree parm, gensum_param_desc *desc, int idx = (entry_bb_index * unsafe_by_ref_count + desc->deref_index); if ((access->offset + access->size) > bb_dereferences[idx]) { - disqualify_split_candidate (desc, "Would create a possibly " - "illegal dereference in a caller."); - return true; + if (!dereference_probable_p (fun, access)) + { + disqualify_split_candidate (desc, "Would create a possibly " + "illegal dereference in a " + "caller."); + return true; + } + desc->conditionally_dereferenceable = true; } } } @@ -2539,6 +2586,7 @@ process_scan_results (cgraph_node *node, struct function *fun, d->locally_unused = s->locally_unused; d->split_candidate = s->split_candidate; d->by_ref = s->by_ref; + d->conditionally_dereferenceable = s->conditionally_dereferenceable; for (gensum_param_access *acc = s->accesses; acc; @@ -2693,11 +2741,14 @@ isra_write_node_summary (output_block *ob, cgraph_node *node) } streamer_write_uhwi (ob, desc->param_size_limit); streamer_write_uhwi (ob, desc->size_reached); + gcc_assert (desc->safe_size == 0); bitpack_d bp = bitpack_create (ob->main_stream); bp_pack_value (&bp, desc->locally_unused, 1); bp_pack_value (&bp, desc->split_candidate, 1); bp_pack_value (&bp, desc->by_ref, 1); gcc_assert (!desc->not_specially_constructed); + bp_pack_value (&bp, desc->conditionally_dereferenceable, 1); + gcc_assert (!desc->safe_size_set); streamer_write_bitpack (&bp); } bitpack_d bp = bitpack_create (ob->main_stream); @@ -2814,11 +2865,14 @@ isra_read_node_info (struct lto_input_block *ib, cgraph_node *node, } desc->param_size_limit = streamer_read_uhwi (ib); desc->size_reached = streamer_read_uhwi (ib); + desc->safe_size = 0; bitpack_d bp = streamer_read_bitpack (ib); desc->locally_unused = bp_unpack_value (&bp, 1); desc->split_candidate = bp_unpack_value (&bp, 1); desc->by_ref = bp_unpack_value (&bp, 1); desc->not_specially_constructed = 0; + desc->conditionally_dereferenceable = bp_unpack_value (&bp, 1); + desc->safe_size_set = 0; } bitpack_d bp = streamer_read_bitpack (ib); ifs->m_candidate = bp_unpack_value (&bp, 1); @@ -3265,44 +3319,65 @@ isra_mark_caller_param_used (isra_func_summary *from_ifs, int input_idx, } } -/* Set all param hints in DESC to the pessimistic values. */ +/* Combine safe_size of DESC with SIZE and return true if it has changed. */ -static void +static bool +update_safe_size (isra_param_desc *desc, unsigned size) +{ + if (!desc->safe_size_set) + { + desc->safe_size_set = 1; + desc->safe_size = size; + return true; + } + if (desc->safe_size <= size) + return false; + desc->safe_size = size; + return true; +} + +/* Set all param hints in DESC to the pessimistic values. Return true if any + hints that need to potentially trigger further propagation have changed. */ + +static bool flip_all_hints_pessimistic (isra_param_desc *desc) { desc->not_specially_constructed = true; - - return; + return update_safe_size (desc, 0); } -/* Because we have not analyzed a caller, go over all parameter int flags of - NODE and turn them pessimistic. */ +/* Because we have not analyzed or otherwise problematic caller, go over all + parameter int flags of IFS describing a call graph node of a calllee and + turn them pessimistic. Return true if any hints that need to potentially + trigger further propagation have changed. */ -static void -flip_all_param_hints_pessimistic (cgraph_node *node) +static bool +flip_all_param_hints_pessimistic (isra_func_summary *ifs) { - isra_func_summary *ifs = func_sums->get (node); if (!ifs || !ifs->m_candidate) - return; + return false; + bool ret = false; unsigned param_count = vec_safe_length (ifs->m_parameters); for (unsigned i = 0; i < param_count; i++) - flip_all_hints_pessimistic (&(*ifs->m_parameters)[i]); + ret |= flip_all_hints_pessimistic (&(*ifs->m_parameters)[i]); - return; + return ret; } -/* Propagate hints accross edge CS which ultimately leads to CALLEE. */ +/* Propagate hints accross edge CS which ultimately leads to a node described + by TO_IFS. Return true if any hints of the callee which should potentially + trigger further propagation have changed. */ -static void -propagate_param_hints (cgraph_edge *cs, cgraph_node *callee) +static bool +propagate_param_hints_accross_call (cgraph_edge *cs, isra_func_summary *to_ifs) { - isra_call_summary *csum = call_sums->get (cs); - isra_func_summary *to_ifs = func_sums->get (callee); if (!to_ifs || !to_ifs->m_candidate) - return; + return false; + isra_call_summary *csum = call_sums->get (cs); + bool ret = false; unsigned args_count = csum->m_arg_flow.length (); unsigned param_count = vec_safe_length (to_ifs->m_parameters); @@ -3311,14 +3386,62 @@ propagate_param_hints (cgraph_edge *cs, cgraph_node *callee) isra_param_desc *desc = &(*to_ifs->m_parameters)[i]; if (i >= args_count) { - flip_all_hints_pessimistic (desc); + ret |= flip_all_hints_pessimistic (desc); continue; } - if (desc->by_ref && !csum->m_arg_flow[i].constructed_for_calls) - desc->not_specially_constructed = true; + if (desc->by_ref) + { + isra_param_flow *ipf = &csum->m_arg_flow[i]; + + if (!ipf->constructed_for_calls) + desc->not_specially_constructed = true; + + if (ipf->pointer_pass_through) + { + isra_func_summary *from_ifs = func_sums->get (cs->caller); + int srcidx = get_single_param_flow_source (ipf); + if (vec_safe_length (from_ifs->m_parameters) > (unsigned) srcidx) + { + isra_param_desc *src_d = &(*from_ifs->m_parameters)[srcidx]; + if (src_d->safe_size_set) + ret |= update_safe_size (desc, src_d->safe_size); + } + else + ret |= update_safe_size (desc, 0); + } + else if (!ipf->aggregate_pass_through) + ret |= update_safe_size (desc, ipf->unit_size); + else + /* LTOing type-mismatched programs can end up here. */ + ret |= update_safe_size (desc, 0); + } + } + return ret; +} + +/* Propagate hints from NODE described by FROM_IFS to all its (dorect) callees, + push those that may need re-visiting onto STACK. */ + +static void +propagate_hints_to_all_callees (cgraph_node *node, isra_func_summary *from_ifs, + vec *stack) +{ + for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee) + { + enum availability availability; + cgraph_node *callee = cs->callee->function_symbol (&availability); + isra_func_summary *to_ifs = func_sums->get (callee); + if (!from_ifs) + { + if (flip_all_param_hints_pessimistic (to_ifs) + && ipa_edge_within_scc (cs)) + isra_push_node_to_stack (callee, to_ifs, stack); + } + else if (propagate_param_hints_accross_call (cs, to_ifs) + && ipa_edge_within_scc (cs)) + isra_push_node_to_stack (callee, to_ifs, stack); } - return; } /* Propagate information that any parameter is not used only locally within a @@ -3990,7 +4113,8 @@ adjust_parameter_descriptions (cgraph_node *node, isra_func_summary *ifs) check_surviving = true; cinfo->param_adjustments->get_surviving_params (&surviving_params); } - bool dumped_first = false; + auto_vec dump_dead_indices; + auto_vec dump_bad_cond_indices; for (unsigned i = 0; i < len; i++) { isra_param_desc *desc = &(*ifs->m_parameters)[i]; @@ -4009,19 +4133,23 @@ adjust_parameter_descriptions (cgraph_node *node, isra_func_summary *ifs) desc->split_candidate = false; if (dump_file && (dump_flags & TDF_DETAILS)) - { - if (!dumped_first) - { - fprintf (dump_file, - "The following parameters of %s are dead on " - "arrival:", node->dump_name ()); - dumped_first = true; - } - fprintf (dump_file, " %u", i); - } + dump_dead_indices.safe_push (i); } else { + if (desc->split_candidate && desc->conditionally_dereferenceable) + { + gcc_assert (desc->safe_size_set); + for (param_access *pa : *desc->accesses) + if ((pa->unit_offset + pa->unit_size) > desc->safe_size) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + dump_bad_cond_indices.safe_push (i); + desc->split_candidate = false; + break; + } + } + if (desc->split_candidate) { if (desc->by_ref && !desc->not_specially_constructed) @@ -4039,8 +4167,22 @@ adjust_parameter_descriptions (cgraph_node *node, isra_func_summary *ifs) } } - if (dumped_first) - fprintf (dump_file, "\n"); + if (!dump_dead_indices.is_empty ()) + { + fprintf (dump_file, "The following parameters of %s are dead on arrival:", + node->dump_name ()); + for (unsigned i : dump_dead_indices) + fprintf (dump_file, " %u", i); + fprintf (dump_file, "\n"); + } + if (!dump_bad_cond_indices.is_empty ()) + { + fprintf (dump_file, "The following parameters of %s are not safe to " + "derefernce in all callers:", node->dump_name ()); + for (unsigned i : dump_bad_cond_indices) + fprintf (dump_file, " %u", i); + fprintf (dump_file, "\n"); + } return ret; } @@ -4121,17 +4263,16 @@ ipa_sra_analysis (void) for (cgraph_node *v : cycle_nodes) { isra_func_summary *ifs = func_sums->get (v); - for (cgraph_edge *cs = v->callees; cs; cs = cs->next_callee) - { - enum availability availability; - cgraph_node *callee = cs->callee->function_symbol (&availability); - if (!ifs) - { - flip_all_param_hints_pessimistic (callee); - continue; - } - propagate_param_hints (cs, callee); - } + propagate_hints_to_all_callees (v, ifs, &stack); + } + + while (!stack.is_empty ()) + { + cgraph_node *node = stack.pop (); + isra_func_summary *ifs = func_sums->get (node); + gcc_checking_assert (ifs && ifs->m_queued); + ifs->m_queued = false; + propagate_hints_to_all_callees (node, ifs, &stack); } cycle_nodes.release (); diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-26.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-26.c new file mode 100644 index 00000000000..08a40da1482 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-26.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-ipa-sra-details" } */ + +struct S +{ + short a, b, c; +}; + +extern int gc; +extern int *arr; + +static void __attribute__((noinline)) +foo (struct S *p) +{ + for (int i = 0; i < gc; i++) + arr += p->b; +} + +void +bar (short a, short b, short c) +{ + struct S s; + s.a = a; + s.b = b; + s.c = c; + foo (&s); + return; +} + +/* { dg-final { scan-ipa-dump "Will split parameter" "sra" } } */ + diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-27.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-27.c new file mode 100644 index 00000000000..b815e8a83b1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-27.c @@ -0,0 +1,49 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-ipa-sra-details" } */ + +struct S +{ + short a, b, c; +}; + +extern int gc; +extern int *arr; + +static void __attribute__((noinline)) +foo (struct S *p) +{ + for (int i = 0; i < gc; i++) + arr += p->b; +} + +static void __attribute__((noinline)) +baz (struct S *p) +{ + foo (p); + gc = p->a + p->c; +} + +void +bar (short a, short b, short c) +{ + struct S s; + s.a = a; + s.b = b; + s.c = c; + foo (&s); + return; +} + +void +bar2 (short a, short b, short c) +{ + struct S s; + s.a = a; + s.b = b; + s.c = c; + baz (&s); + return; +} + +/* { dg-final { scan-ipa-dump-times "Will split parameter" 2 "sra" } } */ + diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-28.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-28.c new file mode 100644 index 00000000000..d77d33a3608 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-28.c @@ -0,0 +1,51 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-ipa-sra-details" } */ + +struct S +{ + short a, b, c; +}; + +volatile int gc; +volatile int *arr; + +static void __attribute__((noinline)) +foo (struct S *p) +{ + for (int i = 0; i < gc; i++) + arr += p->b; +} + +void +bar (short a, short b, short c) +{ + struct S s; + s.a = a; + s.b = b; + s.c = c; + foo (&s); + return; +} + +void +baz (void) +{ + foo ((struct S *) 0); +} + +void __attribute__((noipa)) +confuse (void) +{ + gc = 0; + baz (); +} + +int +main (int argc, char **argv) +{ + confuse (); + return 0; +} + +/* { dg-final { scan-ipa-dump-not "Will split parameter" "sra" } } */ + From patchwork Sat Nov 12 01:47:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60471 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 74AEA395440D for ; Sat, 12 Nov 2022 01:48:15 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [IPv6:2001:67c:2178:6::1d]) by sourceware.org (Postfix) with ESMTPS id 82A4E3899019 for ; Sat, 12 Nov 2022 01:47:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 82A4E3899019 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id BD3681F45F; Sat, 12 Nov 2022 01:47:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217661; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=O74rV96i+0GTv+a/56rCjiq4422FpChwP+saC/m4dOo=; b=Xcwvj+RuPb2ZOcSF6PvAdQgLF+DnttHfOvVeg0tzKAbLE5N48Ca1yAQ4SKxTJRiE8ryLjJ xD6Ly8gzsaiMwdi4mk45lAiBKVeAsJxKaCjC0GerEGdhzgUqfoLloWtQb0XyFPRqYdBPeq GXpMjxzKQvBXv5XbQV3GEiOL9/Qv1fw= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217661; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=O74rV96i+0GTv+a/56rCjiq4422FpChwP+saC/m4dOo=; b=KkFUxeJ/COUFSSvEUn8Yl3bvrfr5IGPHSqvTjRSXcXIwF1/N2mQhlFudFnpYI+tBshFCvQ ayPfjRuyalgjNPCA== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id B005413A08; Sat, 12 Nov 2022 01:47:41 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 1l0KKz37bmPIZAAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:47:41 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 11/12] ipa-sra: Make scan_expr_access bail out on uninteresting expressions User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:47:41 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, I have noticed that scan_expr_access passes all the expressions it gets to get_ref_base_and_extent even when we are really only interested in memory accesses. So bail out when the expression is something clearly uninteresting. Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2021-12-14 Martin Jambor * ipa-sra.c (scan_expr_access): Bail out early if expr is something we clearly do not need to pass to get_ref_base_and_extent. --- gcc/ipa-sra.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc index 93fceeafc73..3646d71468c 100644 --- a/gcc/ipa-sra.cc +++ b/gcc/ipa-sra.cc @@ -1748,6 +1748,11 @@ scan_expr_access (tree expr, gimple *stmt, isra_scan_context ctx, || TREE_CODE (expr) == REALPART_EXPR) expr = TREE_OPERAND (expr, 0); + if (!handled_component_p (expr) + && !DECL_P (expr) + && TREE_CODE (expr) != MEM_REF) + return; + base = get_ref_base_and_extent (expr, &poffset, &psize, &pmax_size, &reverse); if (TREE_CODE (base) == MEM_REF) From patchwork Sat Nov 12 01:47:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 60472 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DF96838A908A for ; Sat, 12 Nov 2022 01:48:28 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by sourceware.org (Postfix) with ESMTPS id F0B02389EC5F for ; Sat, 12 Nov 2022 01:47:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org F0B02389EC5F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.cz Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 29F7B1F91B; Sat, 12 Nov 2022 01:47:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1668217666; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=KMC5B7R3Qiis6dE5+HF1JMmwSrAZiXeTu1U7gEG6QNg=; b=Lhg1aEnntStdygEp7W3qb6yS5H2D+tCaadqRjOnZK3Vc5UQ8k+8TOQZlV1ULZtr8bIUxB6 62M/gXyUXL1ZXL+G5sv3kPBRR/Ukl1hnHRNd1YE3nUGBqZecq60vj18+cg34Cuz0XAv4Bd DpjwA7kGJdfvpk8IfhfophzgrTYUk1I= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1668217666; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type; bh=KMC5B7R3Qiis6dE5+HF1JMmwSrAZiXeTu1U7gEG6QNg=; b=qUEWNRh8YH128/dSi8ZHbNpoA99bQChrrq751I64Iwz0mMCnLAoSZ0Btbfb6SJUjG79TIX Mh5kkdoYfgjzMEAg== Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 1D2B213A08; Sat, 12 Nov 2022 01:47:46 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id BOYZB0L7bmPOZAAAMHmgww (envelope-from ); Sat, 12 Nov 2022 01:47:46 +0000 From: Martin Jambor To: GCC Patches Cc: Jan Hubicka , Jan Hubicka Subject: [PATCH 12/12] ipa: Avoid looking for IPA-SRA replacements where there are none User-Agent: Notmuch/0.37 (https://notmuchmail.org) Emacs/28.1 (x86_64-suse-linux-gnu) Date: Sat, 12 Nov 2022 02:47:45 +0100 Message-ID: MIME-Version: 1.0 X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi, while modifying the code, I realized that we do look into statements even when there are no replacements. This patch adds the necessary early bail-outs to avoid that. ipa_param_body_adjustments::modify_call_stmt cannot have the same at the very beginning because calls can still contain otherwise removed parameters that need to be removed from the statements too. Bootstrapped and tested on x86_64-linux. OK for master? Thanks, Martin gcc/ChangeLog: 2022-11-11 Martin Jambor * ipa-param-manipulation.cc (ipa_param_body_adjustments::modify_expression): Bail out early if there are no replacements. (ipa_param_body_adjustments::modify_assignment): Likewise. gcc/testsuite/ChangeLog: 2022-11-11 Martin Jambor PR ipa/103227 PR ipa/107640 * gcc.dg/ipa/pr107640-2.c: New test. --- gcc/ipa-param-manipulation.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gcc/ipa-param-manipulation.cc b/gcc/ipa-param-manipulation.cc index e92cfc0b6d5..da19d64cbce 100644 --- a/gcc/ipa-param-manipulation.cc +++ b/gcc/ipa-param-manipulation.cc @@ -1762,6 +1762,8 @@ ipa_param_body_adjustments::modify_expression (tree *expr_p, bool convert) { tree expr = *expr_p; + if (m_replacements.is_empty ()) + return false; if (TREE_CODE (expr) == BIT_FIELD_REF || TREE_CODE (expr) == IMAGPART_EXPR || TREE_CODE (expr) == REALPART_EXPR) @@ -1809,7 +1811,7 @@ ipa_param_body_adjustments::modify_assignment (gimple *stmt, tree *lhs_p, *rhs_p; bool any; - if (!gimple_assign_single_p (stmt)) + if (m_replacements.is_empty () || !gimple_assign_single_p (stmt)) return false; rhs_p = gimple_assign_rhs1_ptr (stmt);