From patchwork Tue May 14 15:17:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Jambor X-Patchwork-Id: 1935078 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=suse.cz header.i=@suse.cz header.a=rsa-sha256 header.s=susede2_rsa header.b=M7kfiXzG; dkim=pass header.d=suse.cz header.i=@suse.cz header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=1Xaidztp; dkim=pass (1024-bit key) header.d=suse.cz header.i=@suse.cz header.a=rsa-sha256 header.s=susede2_rsa header.b=M7kfiXzG; dkim=neutral header.d=suse.cz header.i=@suse.cz header.a=ed25519-sha256 header.s=susede2_ed25519 header.b=1Xaidztp; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Vf0Nf4p6fz1ymw for ; Wed, 15 May 2024 01:18:10 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BED83384AB5A for ; Tue, 14 May 2024 15:18:03 +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:2a07:de40:b251:101:10:150:64:2]) by sourceware.org (Postfix) with ESMTPS id 764A13858CDA for ; Tue, 14 May 2024 15:17:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 764A13858CDA Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.cz Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.cz ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 764A13858CDA Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a07:de40:b251:101:10:150:64:2 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1715699862; cv=none; b=MZBGiI64IVEPqzmpcTjI6Vev+t8aWcSoy41+wV2ZRqejRr8p6IgMqLosR0kkdEoB8+p/fUnbyHsSWTc4WSm0/eflzkPk/YCWMi6kirWdI1TOdx1LWH8QzFROKIlU/2BtMtAQhs5yEXhQhjSuGpFYYk0/xpXNWBAmtdPSy0Yn4qo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1715699862; c=relaxed/simple; bh=XfttLANHP/YUyavEzJzwi/a/BuhIW5Gc3hvgw2PeqGc=; h=DKIM-Signature:DKIM-Signature:DKIM-Signature:DKIM-Signature:From: To:Subject:Date:Message-ID:MIME-Version; b=OS136jeuqcjP7MbQ76297FfadHzrSZ2alKoGrVVrSE3oeQikssOCQzuIXkHuZ4Q8II5Plk6ESYvJoPgd8sXcX2jKAUxld2GKOL1qB3TTSmrOnERwMi2WCjSBufbTpjqFC/ZvS+doVZtc38DibTVd7alLBfnnRfjKEvRx9KChnec= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from imap1.dmz-prg2.suse.org (unknown [10.150.64.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 5272260D7C for ; Tue, 14 May 2024 15:17:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1715699858; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version:content-type:content-type; bh=ReUDfPKsmBP8wKCc4CLvLWD/AuzHioLAwbUFfqcHEFA=; b=M7kfiXzGyV+k3TmLUmEw69KZpwhfyEko8/YQgvZ89rSGLkaPAqYbUQ4XyQkwho0cOtJhrb IX12OfmQfaVy40TaDXZSzsIMvpYWJjRTZmBiHKrleSNnSBxS6ra3jNdJblgf2So07GKqQe bs/WuYGwx0u0EFC8JQ9v26iuvbOFzG4= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1715699858; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version:content-type:content-type; bh=ReUDfPKsmBP8wKCc4CLvLWD/AuzHioLAwbUFfqcHEFA=; b=1XaidztpgWb/MCr/SbpSROkJ4JOmJ/k+Wtqkgd9Mmlr1YcZlfJmrA11SNxIjjF1tesWu3F 23MJSsIzvJv+Z4Cw== Authentication-Results: smtp-out2.suse.de; none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_rsa; t=1715699858; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version:content-type:content-type; bh=ReUDfPKsmBP8wKCc4CLvLWD/AuzHioLAwbUFfqcHEFA=; b=M7kfiXzGyV+k3TmLUmEw69KZpwhfyEko8/YQgvZ89rSGLkaPAqYbUQ4XyQkwho0cOtJhrb IX12OfmQfaVy40TaDXZSzsIMvpYWJjRTZmBiHKrleSNnSBxS6ra3jNdJblgf2So07GKqQe bs/WuYGwx0u0EFC8JQ9v26iuvbOFzG4= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.cz; s=susede2_ed25519; t=1715699858; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version:content-type:content-type; bh=ReUDfPKsmBP8wKCc4CLvLWD/AuzHioLAwbUFfqcHEFA=; b=1XaidztpgWb/MCr/SbpSROkJ4JOmJ/k+Wtqkgd9Mmlr1YcZlfJmrA11SNxIjjF1tesWu3F 23MJSsIzvJv+Z4Cw== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 4C520137C3 for ; Tue, 14 May 2024 15:17:38 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id skOdEpKAQ2biSgAAD6G6ig (envelope-from ) for ; Tue, 14 May 2024 15:17:38 +0000 From: Martin Jambor To: GCC Patches Subject: [commited, gcc13] ipa: Compare jump functions in ICF (PR 113907) User-Agent: Notmuch/0.38.2 (https://notmuchmail.org) Emacs/29.3 (x86_64-suse-linux-gnu) Date: Tue, 14 May 2024 17:17:33 +0200 Message-ID: MIME-Version: 1.0 X-Spam-Score: -4.30 X-Spam-Level: X-Spamd-Result: default: False [-4.30 / 50.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; RCVD_TLS_ALL(0.00)[]; MID_RHS_MATCH_FROMTLD(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; ARC_NA(0.00)[]; RCPT_COUNT_ONE(0.00)[1]; DKIM_SIGNED(0.00)[suse.cz:s=susede2_rsa,suse.cz:s=susede2_ed25519]; FUZZY_BLOCKED(0.00)[rspamd.com]; TO_DN_ALL(0.00)[]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; MIME_TRACE(0.00)[0:+]; RCVD_COUNT_TWO(0.00)[2]; PREVIOUSLY_DELIVERED(0.00)[gcc-patches@gcc.gnu.org]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[imap1.dmz-prg2.suse.org:helo,suse.cz:email] 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_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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Hi, This is a manual backport of r14-9840-g1162861439fd3c from master. Manual because the bits and value range representation in jump functions have changes during the gcc 14 development cycle. In PR 113907 comment #58, Honza found a case where ICF thinks bodies of functions are equivalent but becaise of difference in aliases in a memory access, different aggregate jump functions are associated with supposedly equivalent call statements. This patch adds a way to compare jump functions and plugs it into ICF to avoid the issue. Bootstrapped and tested on x86_64-linux. Committed to the gcc-13 branch. Martin gcc/ChangeLog: 2024-05-14 Martin Jambor PR ipa/113907 * ipa-prop.h (ipa_jump_functions_equivalent_p): Declare. (values_equal_for_ipcp_p): Likewise. * ipa-prop.cc (ipa_agg_pass_through_jf_equivalent_p): New function. (ipa_agg_jump_functions_equivalent_p): Likewise. (ipa_jump_functions_equivalent_p): Likewise. * ipa-cp.cc (values_equal_for_ipcp_p): Make function public. * ipa-icf-gimple.cc: Include alloc-pool.h, symbol-summary.h, sreal.h, ipa-cp.h and ipa-prop.h. (func_checker::compare_gimple_call): Comapre jump functions. gcc/testsuite/ChangeLog: 2024-05-10 Martin Jambor PR ipa/113907 * gcc.dg/lto/pr113907_0.c: New. * gcc.dg/lto/pr113907_1.c: Likewise. * gcc.dg/lto/pr113907_2.c: Likewise. --- gcc/ipa-cp.cc | 2 +- gcc/ipa-icf-gimple.cc | 29 +++++ gcc/ipa-prop.cc | 157 ++++++++++++++++++++++++++ gcc/ipa-prop.h | 3 + gcc/testsuite/gcc.dg/lto/pr113907_0.c | 18 +++ gcc/testsuite/gcc.dg/lto/pr113907_1.c | 35 ++++++ gcc/testsuite/gcc.dg/lto/pr113907_2.c | 11 ++ 7 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/lto/pr113907_0.c create mode 100644 gcc/testsuite/gcc.dg/lto/pr113907_1.c create mode 100644 gcc/testsuite/gcc.dg/lto/pr113907_2.c diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc index b3e0f62e400..8f36608cf33 100644 --- a/gcc/ipa-cp.cc +++ b/gcc/ipa-cp.cc @@ -458,7 +458,7 @@ ipcp_lattice::is_single_const () /* Return true iff X and Y should be considered equal values by IPA-CP. */ -static bool +bool values_equal_for_ipcp_p (tree x, tree y) { gcc_checking_assert (x != NULL_TREE && y != NULL_TREE); diff --git a/gcc/ipa-icf-gimple.cc b/gcc/ipa-icf-gimple.cc index 49302ad56c6..054a557bd58 100644 --- a/gcc/ipa-icf-gimple.cc +++ b/gcc/ipa-icf-gimple.cc @@ -42,7 +42,11 @@ along with GCC; see the file COPYING3. If not see #include "tree-sra.h" #include "tree-ssa-alias-compare.h" +#include "alloc-pool.h" +#include "symbol-summary.h" #include "ipa-icf-gimple.h" +#include "sreal.h" +#include "ipa-prop.h" namespace ipa_icf_gimple { @@ -751,6 +755,31 @@ func_checker::compare_gimple_call (gcall *s1, gcall *s2) && !compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2))) return return_false_with_msg ("GIMPLE internal call LHS type mismatch"); + if (!gimple_call_internal_p (s1)) + { + cgraph_edge *e1 = cgraph_node::get (m_source_func_decl)->get_edge (s1); + cgraph_edge *e2 = cgraph_node::get (m_target_func_decl)->get_edge (s2); + class ipa_edge_args *args1 = ipa_edge_args_sum->get (e1); + class ipa_edge_args *args2 = ipa_edge_args_sum->get (e2); + if ((args1 != nullptr) != (args2 != nullptr)) + return return_false_with_msg ("ipa_edge_args mismatch"); + if (args1) + { + int n1 = ipa_get_cs_argument_count (args1); + int n2 = ipa_get_cs_argument_count (args2); + if (n1 != n2) + return return_false_with_msg ("ipa_edge_args nargs mismatch"); + for (int i = 0; i < n1; i++) + { + struct ipa_jump_func *jf1 = ipa_get_ith_jump_func (args1, i); + struct ipa_jump_func *jf2 = ipa_get_ith_jump_func (args2, i); + if (((jf1 != nullptr) != (jf2 != nullptr)) + || (jf1 && !ipa_jump_functions_equivalent_p (jf1, jf2))) + return return_false_with_msg ("jump function mismatch"); + } + } + } + return compare_operand (t1, t2, get_operand_access_type (&map, t1)); } diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index 0d816749534..11ba2521b2c 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -6022,5 +6022,162 @@ ipcp_transform_function (struct cgraph_node *node) return modified_mem_access ? TODO_update_ssa_only_virtuals : 0; } +/* Return true if the two pass_through components of two jump functions are + known to be equivalent. AGG_JF denotes whether they are part of aggregate + functions or not. The function can be used before the IPA phase of IPA-CP + or inlining because it cannot cope with refdesc changes these passes can + carry out. */ + +static bool +ipa_agg_pass_through_jf_equivalent_p (ipa_pass_through_data *ipt1, + ipa_pass_through_data *ipt2, + bool agg_jf) + +{ + gcc_assert (agg_jf || + (!ipt1->refdesc_decremented && !ipt2->refdesc_decremented)); + if (ipt1->operation != ipt2->operation + || ipt1->formal_id != ipt2->formal_id + || (!agg_jf && (ipt1->agg_preserved != ipt2->agg_preserved))) + return false; + if (((ipt1->operand != NULL_TREE) != (ipt2->operand != NULL_TREE)) + || (ipt1->operand + && !values_equal_for_ipcp_p (ipt1->operand, ipt2->operand))) + return false; + return true; +} + +/* Return true if the two aggregate jump functions are known to be equivalent. + The function can be used before the IPA phase of IPA-CP or inlining because + it cannot cope with refdesc changes these passes can carry out. */ + +static bool +ipa_agg_jump_functions_equivalent_p (ipa_agg_jf_item *ajf1, + ipa_agg_jf_item *ajf2) +{ + if (ajf1->offset != ajf2->offset + || ajf1->jftype != ajf2->jftype + || !types_compatible_p (ajf1->type, ajf2->type)) + return false; + + switch (ajf1->jftype) + { + case IPA_JF_CONST: + if (!values_equal_for_ipcp_p (ajf1->value.constant, + ajf2->value.constant)) + return false; + break; + case IPA_JF_PASS_THROUGH: + { + ipa_pass_through_data *ipt1 = &ajf1->value.pass_through; + ipa_pass_through_data *ipt2 = &ajf2->value.pass_through; + if (!ipa_agg_pass_through_jf_equivalent_p (ipt1, ipt2, true)) + return false; + } + break; + case IPA_JF_LOAD_AGG: + { + ipa_load_agg_data *ila1 = &ajf1->value.load_agg; + ipa_load_agg_data *ila2 = &ajf2->value.load_agg; + if (!ipa_agg_pass_through_jf_equivalent_p (&ila1->pass_through, + &ila2->pass_through, true)) + return false; + if (ila1->offset != ila2->offset + || ila1->by_ref != ila2->by_ref + || !types_compatible_p (ila1->type, ila2->type)) + return false; + } + break; + default: + gcc_unreachable (); + } + return true; +} + +/* Return true if the two jump functions are known to be equivalent. The + function can be used before the IPA phase of IPA-CP or inlining because it + cannot cope with refdesc changes these passes can carry out. */ + +bool +ipa_jump_functions_equivalent_p (ipa_jump_func *jf1, ipa_jump_func *jf2) +{ + if (jf1->type != jf2->type) + return false; + + switch (jf1->type) + { + case IPA_JF_UNKNOWN: + break; + case IPA_JF_CONST: + { + tree cst1 = ipa_get_jf_constant (jf1); + tree cst2 = ipa_get_jf_constant (jf2); + if (!values_equal_for_ipcp_p (cst1, cst2)) + return false; + + ipa_cst_ref_desc *rd1 = jfunc_rdesc_usable (jf1); + ipa_cst_ref_desc *rd2 = jfunc_rdesc_usable (jf2); + if (rd1 && rd2) + { + gcc_assert (rd1->refcount == 1 + && rd2->refcount == 1); + gcc_assert (!rd1->next_duplicate && !rd2->next_duplicate); + } + else if (rd1) + return false; + else if (rd2) + return false; + } + break; + case IPA_JF_PASS_THROUGH: + { + ipa_pass_through_data *ipt1 = &jf1->value.pass_through; + ipa_pass_through_data *ipt2 = &jf2->value.pass_through; + if (!ipa_agg_pass_through_jf_equivalent_p (ipt1, ipt2, false)) + return false; + } + break; + case IPA_JF_ANCESTOR: + { + ipa_ancestor_jf_data *ia1 = &jf1->value.ancestor; + ipa_ancestor_jf_data *ia2 = &jf2->value.ancestor; + + if (ia1->formal_id != ia2->formal_id + || ia1->agg_preserved != ia2->agg_preserved + || ia1->keep_null != ia2->keep_null + || ia1->offset != ia2->offset) + return false; + } + break; + default: + gcc_unreachable (); + } + + if (((jf1->bits != nullptr) != (jf2->bits != nullptr)) + || (jf1->bits && ((jf1->bits->value != jf2->bits->value) + || (jf1->bits->mask != jf2->bits->mask)))) + return false; + + if (((jf1->m_vr != nullptr) != (jf2->m_vr != nullptr)) + || (jf1->m_vr && *jf1->m_vr != *jf2->m_vr)) + return false; + + unsigned alen = vec_safe_length (jf1->agg.items); + if (vec_safe_length (jf2->agg.items) != alen) + return false; + + if (!alen) + return true; + + if (jf1->agg.by_ref != jf2->agg.by_ref) + return false; + + for (unsigned i = 0 ; i < alen; i++) + if (!ipa_agg_jump_functions_equivalent_p (&(*jf1->agg.items)[i], + &(*jf2->agg.items)[i])) + return false; + + return true; +} #include "gt-ipa-prop.h" diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 7eb5c8f44ea..fdea86228d8 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -1194,11 +1194,14 @@ bool ipcp_get_parm_bits (tree, tree *, widest_int *); bool unadjusted_ptr_and_unit_offset (tree op, tree *ret, poly_int64 *offset_ret); +bool ipa_jump_functions_equivalent_p (ipa_jump_func *jf1, ipa_jump_func *jf2); + /* From tree-sra.cc: */ tree build_ref_for_offset (location_t, tree, poly_int64, bool, tree, gimple_stmt_iterator *, bool); /* In ipa-cp.cc */ void ipa_cp_cc_finalize (void); +bool values_equal_for_ipcp_p (tree x, tree y); #endif /* IPA_PROP_H */ diff --git a/gcc/testsuite/gcc.dg/lto/pr113907_0.c b/gcc/testsuite/gcc.dg/lto/pr113907_0.c new file mode 100644 index 00000000000..3c4dd475c01 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr113907_0.c @@ -0,0 +1,18 @@ +/* { dg-lto-do run } */ +/* { dg-lto-options {{-O3 -flto}} } */ + +struct bar {int a;}; +struct foo {int a;}; +struct barp {struct bar *f; struct bar *g;}; +extern struct foo **ptr; +int test2 (void *); +int test3 (void *); +int +testb(void) +{ + struct bar *fp; + test2 ((void *)&fp); + fp = (void *) 0; + (*ptr)++; + test3 ((void *)&fp); +} diff --git a/gcc/testsuite/gcc.dg/lto/pr113907_1.c b/gcc/testsuite/gcc.dg/lto/pr113907_1.c new file mode 100644 index 00000000000..1c48bfd83a4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr113907_1.c @@ -0,0 +1,35 @@ +__attribute__((used)) int val,val2 = 1; + +struct foo {int a;}; + +struct foo **ptr; + +__attribute__ ((noipa)) +int +test2 (void *a) +{ + ptr = (struct foo **)a; +} +int test3 (void *a); + +int +test(void) +{ + struct foo *fp; + test2 ((void *)&fp); + fp = (void *) 0; + (*ptr)++; + test3 ((void *)&fp); +} + +int testb (void); + +int +main() +{ + for (int i = 0; i < val2; i++) + if (val) + testb (); + else + test(); +} diff --git a/gcc/testsuite/gcc.dg/lto/pr113907_2.c b/gcc/testsuite/gcc.dg/lto/pr113907_2.c new file mode 100644 index 00000000000..172e86e8b0b --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr113907_2.c @@ -0,0 +1,11 @@ +/* { dg-options "-O3 -flto -fno-strict-aliasing" } */ + +__attribute__ ((noinline)) +int +test3 (void *a) +{ + if (!*(void **)a) + __builtin_abort (); + return 0; +} +