| Message ID | 20260407074151.24930-1-josef.melcr@suse.com |
|---|---|
| State | New |
| Headers |
Return-Path: <gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 172004BA2E0D for <patchwork@sourceware.org>; Tue, 7 Apr 2026 07:42:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 172004BA2E0D Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=suse.com header.i=@suse.com header.a=rsa-sha256 header.s=google header.b=avqZOeDn X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) by sourceware.org (Postfix) with ESMTPS id 3A9AC4BA2E06 for <gcc-patches@gcc.gnu.org>; Tue, 7 Apr 2026 07:42:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3A9AC4BA2E06 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=suse.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 3A9AC4BA2E06 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.85.128.48 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1775547731; cv=none; b=h5rvIGoMcx3vnku3iNjmnVWkPGkkXi/CQSJQCMAz55sGdeNrixRKVxiCrMj45Y6+cxkzp2jy26JIoC4bGUOL1z1HIppktN0W6K25X4v69vAFcDSGXERsRQLNAyt6Ad8alXLK9nr709ro0INa0lyCVFtmTOO/0mcoNiWv6Gg4AGM= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1775547731; c=relaxed/simple; bh=ucYL07a97un4hGA1S3IDeR07zo305s6R87Q8mbxQAwY=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=NZsDbrPaql7edGm18cvvQu1F1HXNpt+OrTnsX7744PA5Do5XpGNSL/43ST/6xPFK8N4B5w5rNyMsfe9hgI7pDq6y9qEsOTGoVdXX+n/OYcj5fDUyqzbR7A7oHxKN/Finc7ygsvOg8wvxt2he7YTH2TfbuQIQDVjPaNIE6jfswqs= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3A9AC4BA2E06 Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-4887eca00c4so31680495e9.2 for <gcc-patches@gcc.gnu.org>; Tue, 07 Apr 2026 00:42:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1775547730; x=1776152530; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=s3NPg7WsVQdnHCSxq5HQW4yfSs/zZQP6OSaEr1IF21c=; b=avqZOeDn0eiE/T4xbBdUbgMHQQtomtf5xqzRkAi8PzUiqL3vk0nwbQKYbHgEDIHa0Z cItVNZxnmbIhbFreIwfqe9dkGAtfQ+LvHPSBEjZaFEcmBvV9jkc4NKCRwEQwO0VbGbyP ja4RShTnYTYnqHr/ijZq2Pt0XkZPrtfSNOMabZB29yPgJYt7TxEsZFjCCkxBNRA/oaIX KRwbtQEw+Z+/dXuZhZ9Uy1qaG+qwQLLjfYTO8Y5DEr3WnmILu/bR1GPAIbeeE355JKHB 5gCat61ESSIoJGEj7wwkqsuLEjORSVuw/6naqItt0WFlGGvnmYTSGns8tpPnA3EtAqaO wGyQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775547730; x=1776152530; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=s3NPg7WsVQdnHCSxq5HQW4yfSs/zZQP6OSaEr1IF21c=; b=nXRFFBZyK4IPIzMWKIcTF/MQQgIuNuCvPhbXauuS0lDXIXEjgVdcqj0wKYOEIRbfUg uar1AUq/DZrx8n2rtf7IBr4mgiH7YBNYvdPZZ4Xu4Td7yqSy6opcx2GJoJIp+TUnU9Wh EZumCjjW8GHMEHS37UKiAv5sDpHpBmGqQpH2xfgoRa9ENW1RjhalTT393cvmPYkN6QdY 6Zd4Z1d01fnHwnUA5R66vfh+XrLBlj/Cu5WUgk8yt4h5TNmZ3yGkRjF4a/A77iDKFlaU eGUm+dn9ROsZKHx/zIrOUdFvRdOZhhfgD6qlCco8a2sDrhtLy0eAST6QUp1C+JPUDb9H iELg== X-Gm-Message-State: AOJu0YwIWOQ3ZmSyccrzs7V+5/I0bhHBNGhHMwFMaJQyI0EXskoVRn8R ulSkilMEYfnXuhTfF5qMmX9AS7rlzArcHcqhJyKxMXS8r+ZNrIOWdVtMZYfTYicFIbyYwH5OPP7 X7H0LmoM= X-Gm-Gg: AeBDieuePPCrYwcxcI2WItFtZaHwExFkeDfPjaBKan7lODUhmxr60IdrByTfIZM5cMS 2N/UfSTwvXglUrBr3AyQ5nzZDCKHXJWubAF0x85xT5OuXrvmaiFmdSVTQaS0taxEZJzfsdmeO7R dJT+evdD0odbFBTOurN1sh2yuH8SU+D8aAgt0bU0sa5To624EsAFrmLes8MGVgyJpFiwQkAp0wA P5c8x9miUZL5eSy0hb+vTDeuhAyTLUhdbfgQ8XugqdXVfrgzqidSrdNd1HJiVGERqXDeLceL/ME 4bZfBAz53EqVwMRR6DmDEiQ6G6sAiyWLIQCpRETa7wJn9tBokuHfxmOFRqXiiBDZXqN067yRhTS ymsGAWI6vsyYM9oOMlw7JcLSjd0q8VzOW6bszuJlvWcmrFZGbOOFZYGBbr6zNWyIA0yzsX2mdcQ Odyh03uViPbOn0rqQihIKPO/gIFEGej6T2ro8JDCP+9jdHBYXH/g== X-Received: by 2002:a05:600c:8719:b0:488:b811:51c4 with SMTP id 5b1f17b1804b1-488b8115360mr54965645e9.25.1775547729694; Tue, 07 Apr 2026 00:42:09 -0700 (PDT) Received: from tumbleweed.suse.cz (nat2.prg.suse.com. [195.250.132.146]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-43d1e4f1a99sm50416866f8f.32.2026.04.07.00.42.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 07 Apr 2026 00:42:09 -0700 (PDT) From: Josef Melcr <josef.melcr@suse.com> To: gcc-patches@gcc.gnu.org Cc: Josef Melcr <josef.melcr@suse.com>, mjambor@suse.cz, hubicka@ucw.cz Subject: [PATCH] ipa/124700: Fix rebuild_references for callback functions Date: Tue, 7 Apr 2026 09:41:51 +0200 Message-ID: <20260407074151.24930-1-josef.melcr@suse.com> X-Mailer: git-send-email 2.53.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org |
| Series |
ipa/124700: Fix rebuild_references for callback functions
|
|
Commit Message
Josef Melcr
April 7, 2026, 7:41 a.m. UTC
Hi,
this patch deals with the following situation:
template<typename T>
void foo () {
GOMP_parallel (foo._omp_fn, ...);
}
Before callback edges were implemented, if foo got put into a COMDAT
group and subsequently virtually cloned (by ipa-cp, for example), then
the OpenMP kernel wouldn't be put into the same COMDAT group, since it
would be referred to by functions both inside and outside said COMDAT
group.
With callback edges, the kernel may be cloned as well. If both foo and
foo._omp_fn get cloned, foo's clone will be redirected to the cloned
kernel. This allows us to put foo._omp_fn into the same COMDAT group as
foo via ipa-comdat. As the kernel is artificial, it becomes
comdat-local.
However, this redirection is not immediate, leading to the situation in
the PR, where the clones are properly redirected in the call graph, but
the corresponding gimple call is not yet updated. If one calls
rebuild_references during this time on cloned foo, the reference that
gets rebuilt will still point to the old kernel, which is now in a
COMDAT group, thus creating a reference to a comdat-local symbol outside
of its COMDAT group, leading to a checking ICE. This patch remedies
that by checking for this case and building a reference to the correct
kernel.
Bootstrapped and regtested on x86_64-linux. OK for master?
Thanks,
Josef
PR 124700
gcc/ChangeLog:
* cgraph.cc (cgraph_node::is_clone_of): New method, determines
whether a node is a descendant of another in the clone tree.
* cgraph.h (struct cgraph_node): Add decl of is_clone_of.
* cgraphbuild.cc (mark_address): Fix reference creation for
cloned callback functions.
libgomp/ChangeLog:
* testsuite/libgomp.c++/pr124700.C: New test.
Signed-off-by: Josef Melcr <josef.melcr@suse.com>
---
gcc/cgraph.cc | 10 ++++
gcc/cgraph.h | 3 ++
gcc/cgraphbuild.cc | 18 ++++++-
libgomp/testsuite/libgomp.c++/pr124700.C | 60 ++++++++++++++++++++++++
4 files changed, 90 insertions(+), 1 deletion(-)
create mode 100644 libgomp/testsuite/libgomp.c++/pr124700.C
Comments
Hello, On Tue, Apr 07 2026, Josef Melcr wrote: > Hi, > this patch deals with the following situation: > > template<typename T> > void foo () { > GOMP_parallel (foo._omp_fn, ...); > } > > Before callback edges were implemented, if foo got put into a COMDAT > group and subsequently virtually cloned (by ipa-cp, for example), then > the OpenMP kernel wouldn't be put into the same COMDAT group, since it > would be referred to by functions both inside and outside said COMDAT > group. > > With callback edges, the kernel may be cloned as well. If both foo and > foo._omp_fn get cloned, foo's clone will be redirected to the cloned > kernel. This allows us to put foo._omp_fn into the same COMDAT group as > foo via ipa-comdat. As the kernel is artificial, it becomes > comdat-local. > > However, this redirection is not immediate, leading to the situation in > the PR, where the clones are properly redirected in the call graph, but > the corresponding gimple call is not yet updated. If one calls > rebuild_references during this time on cloned foo, the reference that > gets rebuilt will still point to the old kernel, which is now in a > COMDAT group, thus creating a reference to a comdat-local symbol outside > of its COMDAT group, leading to a checking ICE. This patch remedies > that by checking for this case and building a reference to the correct > kernel. I'd like to add that this is an ordering issue, we do call redirection of the calls from the clone not as a part of node materialization but as a part of the inliner transformation pass - but we do rebuild references there. But before we get to the redirection, the inline materialization pass is called on the clone of the kernel and finds the COMDAT reference. It is expected that until the call redirection the call statements are wrong, but it is a bit unfortunate that we use them to build references during that time. Still, I think the approach in this patch is what we want to do. Some comments inline below: > > Bootstrapped and regtested on x86_64-linux. OK for master? > > Thanks, > Josef > > PR 124700 > > gcc/ChangeLog: > > * cgraph.cc (cgraph_node::is_clone_of): New method, determines > whether a node is a descendant of another in the clone tree. > * cgraph.h (struct cgraph_node): Add decl of is_clone_of. > * cgraphbuild.cc (mark_address): Fix reference creation for > cloned callback functions. > > libgomp/ChangeLog: > > * testsuite/libgomp.c++/pr124700.C: New test. Since this is a compile-only testcase that actually does not depend o the libgomp library, I think it should go to gcc/testsuite/g++.dg/gomp/ directory instead. > > Signed-off-by: Josef Melcr <josef.melcr@suse.com> > --- > gcc/cgraph.cc | 10 ++++ > gcc/cgraph.h | 3 ++ > gcc/cgraphbuild.cc | 18 ++++++- > libgomp/testsuite/libgomp.c++/pr124700.C | 60 ++++++++++++++++++++++++ > 4 files changed, 90 insertions(+), 1 deletion(-) > create mode 100644 libgomp/testsuite/libgomp.c++/pr124700.C > > diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc > index 90635fb5a89..a291bec3af6 100644 > --- a/gcc/cgraph.cc > +++ b/gcc/cgraph.cc > @@ -3626,6 +3626,16 @@ cgraph_node::only_called_directly_p (void) > NULL, true); > } > > +/* Returns TRUE iff THIS is a descendant of N in the clone tree. */ > + > +bool > +cgraph_node::is_clone_of (cgraph_node *n) const > +{ > + for (cgraph_node *walker = clone_of; walker; walker = walker->clone_of) > + if (walker == n) > + return true; > + return false; > +} > > /* Collect all callers of NODE. Worker for collect_callers_of_node. */ > > diff --git a/gcc/cgraph.h b/gcc/cgraph.h > index 39209b53957..36d524e28a9 100644 > --- a/gcc/cgraph.h > +++ b/gcc/cgraph.h > @@ -1294,6 +1294,9 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node > it is not used in any other non-standard way. */ > bool only_called_directly_p (void); > > + /* Returns TRUE iff THIS is a descendant of N in the clone tree. */ > + bool is_clone_of (cgraph_node *n) const; > + > /* Turn profile to global0. Walk into inlined functions. */ > void make_profile_local (); > > diff --git a/gcc/cgraphbuild.cc b/gcc/cgraphbuild.cc > index e50adb955cb..8859031d333 100644 > --- a/gcc/cgraphbuild.cc > +++ b/gcc/cgraphbuild.cc > @@ -214,9 +214,25 @@ mark_address (gimple *stmt, tree addr, tree, void *data) > addr = get_base_address (addr); > if (TREE_CODE (addr) == FUNCTION_DECL) > { > + cgraph_node *caller = (cgraph_node *) data; > cgraph_node *node = cgraph_node::get_create (addr); > + /* If NODE was cloned and the caller is a callback-dispatching function, > + the gimple call might not be updated yet. Check whether that's the > + case and if so, replace NODE with the correct callee. */ > + if (cgraph_edge *e = caller->get_edge (stmt); e && e->has_callback) Please make "cgraph_edge *e = caller->get_edge (stmt)" a separate statement above the if condition. > + { > + for (cgraph_edge *cbe = e->first_callback_edge (); cbe; > + cbe = cbe->next_callback_edge ()) GNU coding style requires that the looping test condition is on a separate line here, even if it is just four characters. Please wait until Thursday whether Honza has any comments on the ordering issue but if not, the patch is OK with the minor nits corrected. Thanks! Martin > + { > + if (cbe->callee->is_clone_of (node)) > + { > + node = cbe->callee; > + break; > + } > + } > + } > node->mark_address_taken (); > - ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt); > + caller->create_reference (node, IPA_REF_ADDR, stmt); > } > else if (addr && VAR_P (addr) > && (TREE_STATIC (addr) || DECL_EXTERNAL (addr))) > diff --git a/libgomp/testsuite/libgomp.c++/pr124700.C b/libgomp/testsuite/libgomp.c++/pr124700.C > new file mode 100644 > index 00000000000..b95754aded2 > --- /dev/null > +++ b/libgomp/testsuite/libgomp.c++/pr124700.C > @@ -0,0 +1,60 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O3" } */ > + > +int a (int); > +struct b > +{ > + b (); > + b (b &); > + ~b (); > +}; > +template <typename c> b d (c); > +int ab; > +void ae (int); > +struct e > +{ > + b g; > + template <typename c> e operator<< (c h) > + { > + d (h); > + return *this; > + } > + b f; > +}; > +template <int = 0> struct i > +{ > + long ah; > + int j () > + { > + e () << "" << aj << 1 << "" << ah << "" << ak << ""; > + return ah; > + } > + char aj; > + int ak; > +}; > +i<> k; > +template <typename> > +int > +ao (bool h) > +{ > +#pragma omp parallel > + { > + int as; > + for (; as;) > + { > + int au = k.j (); > + ae (au); > + if (h) > + b (); > + } > + } > + return a (ab); > +} > +int l = ao<short> (true); > +void > +az () > +{ > + ao<short> (true); > + __builtin_unreachable (); > +} > +template int ao<short> (bool); > -- > 2.53.0
> Hi, > this patch deals with the following situation: > > template<typename T> > void foo () { > GOMP_parallel (foo._omp_fn, ...); > } > > Before callback edges were implemented, if foo got put into a COMDAT > group and subsequently virtually cloned (by ipa-cp, for example), then > the OpenMP kernel wouldn't be put into the same COMDAT group, since it > would be referred to by functions both inside and outside said COMDAT > group. > > With callback edges, the kernel may be cloned as well. If both foo and > foo._omp_fn get cloned, foo's clone will be redirected to the cloned > kernel. This allows us to put foo._omp_fn into the same COMDAT group as > foo via ipa-comdat. As the kernel is artificial, it becomes > comdat-local. > > However, this redirection is not immediate, leading to the situation in > the PR, where the clones are properly redirected in the call graph, but > the corresponding gimple call is not yet updated. If one calls > rebuild_references during this time on cloned foo, the reference that > gets rebuilt will still point to the old kernel, which is now in a > COMDAT group, thus creating a reference to a comdat-local symbol outside > of its COMDAT group, leading to a checking ICE. This patch remedies > that by checking for this case and building a reference to the correct > kernel. > > Bootstrapped and regtested on x86_64-linux. OK for master? > > Thanks, > Josef > > PR 124700 > > gcc/ChangeLog: > > * cgraph.cc (cgraph_node::is_clone_of): New method, determines > whether a node is a descendant of another in the clone tree. > * cgraph.h (struct cgraph_node): Add decl of is_clone_of. > * cgraphbuild.cc (mark_address): Fix reference creation for > cloned callback functions. > > libgomp/ChangeLog: > > * testsuite/libgomp.c++/pr124700.C: New test. OK, thanks! Honza
Hi, I implemented your suggestions and committed the patch as r16-8578-g73ade2eefb5633. Thanks :) Josef On 4/7/26 12:28 PM, Martin Jambor wrote: > Hello, > > On Tue, Apr 07 2026, Josef Melcr wrote: >> Hi, >> this patch deals with the following situation: >> >> template<typename T> >> void foo () { >> GOMP_parallel (foo._omp_fn, ...); >> } >> >> Before callback edges were implemented, if foo got put into a COMDAT >> group and subsequently virtually cloned (by ipa-cp, for example), then >> the OpenMP kernel wouldn't be put into the same COMDAT group, since it >> would be referred to by functions both inside and outside said COMDAT >> group. >> >> With callback edges, the kernel may be cloned as well. If both foo and >> foo._omp_fn get cloned, foo's clone will be redirected to the cloned >> kernel. This allows us to put foo._omp_fn into the same COMDAT group as >> foo via ipa-comdat. As the kernel is artificial, it becomes >> comdat-local. >> >> However, this redirection is not immediate, leading to the situation in >> the PR, where the clones are properly redirected in the call graph, but >> the corresponding gimple call is not yet updated. If one calls >> rebuild_references during this time on cloned foo, the reference that >> gets rebuilt will still point to the old kernel, which is now in a >> COMDAT group, thus creating a reference to a comdat-local symbol outside >> of its COMDAT group, leading to a checking ICE. This patch remedies >> that by checking for this case and building a reference to the correct >> kernel. > I'd like to add that this is an ordering issue, we do call redirection > of the calls from the clone not as a part of node materialization but as > a part of the inliner transformation pass - but we do rebuild references > there. But before we get to the redirection, the inline materialization > pass is called on the clone of the kernel and finds the COMDAT > reference. It is expected that until the call redirection the call > statements are wrong, but it is a bit unfortunate that we use them to > build references during that time. Still, I think the approach in this > patch is what we want to do. > > Some comments inline below: > >> Bootstrapped and regtested on x86_64-linux. OK for master? >> >> Thanks, >> Josef >> >> PR 124700 >> >> gcc/ChangeLog: >> >> * cgraph.cc (cgraph_node::is_clone_of): New method, determines >> whether a node is a descendant of another in the clone tree. >> * cgraph.h (struct cgraph_node): Add decl of is_clone_of. >> * cgraphbuild.cc (mark_address): Fix reference creation for >> cloned callback functions. >> >> libgomp/ChangeLog: >> >> * testsuite/libgomp.c++/pr124700.C: New test. > Since this is a compile-only testcase that actually does not depend o > the libgomp library, I think it should go to gcc/testsuite/g++.dg/gomp/ > directory instead. > >> Signed-off-by: Josef Melcr <josef.melcr@suse.com> >> --- >> gcc/cgraph.cc | 10 ++++ >> gcc/cgraph.h | 3 ++ >> gcc/cgraphbuild.cc | 18 ++++++- >> libgomp/testsuite/libgomp.c++/pr124700.C | 60 ++++++++++++++++++++++++ >> 4 files changed, 90 insertions(+), 1 deletion(-) >> create mode 100644 libgomp/testsuite/libgomp.c++/pr124700.C >> >> diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc >> index 90635fb5a89..a291bec3af6 100644 >> --- a/gcc/cgraph.cc >> +++ b/gcc/cgraph.cc >> @@ -3626,6 +3626,16 @@ cgraph_node::only_called_directly_p (void) >> NULL, true); >> } >> >> +/* Returns TRUE iff THIS is a descendant of N in the clone tree. */ >> + >> +bool >> +cgraph_node::is_clone_of (cgraph_node *n) const >> +{ >> + for (cgraph_node *walker = clone_of; walker; walker = walker->clone_of) >> + if (walker == n) >> + return true; >> + return false; >> +} >> >> /* Collect all callers of NODE. Worker for collect_callers_of_node. */ >> >> diff --git a/gcc/cgraph.h b/gcc/cgraph.h >> index 39209b53957..36d524e28a9 100644 >> --- a/gcc/cgraph.h >> +++ b/gcc/cgraph.h >> @@ -1294,6 +1294,9 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node >> it is not used in any other non-standard way. */ >> bool only_called_directly_p (void); >> >> + /* Returns TRUE iff THIS is a descendant of N in the clone tree. */ >> + bool is_clone_of (cgraph_node *n) const; >> + >> /* Turn profile to global0. Walk into inlined functions. */ >> void make_profile_local (); >> >> diff --git a/gcc/cgraphbuild.cc b/gcc/cgraphbuild.cc >> index e50adb955cb..8859031d333 100644 >> --- a/gcc/cgraphbuild.cc >> +++ b/gcc/cgraphbuild.cc >> @@ -214,9 +214,25 @@ mark_address (gimple *stmt, tree addr, tree, void *data) >> addr = get_base_address (addr); >> if (TREE_CODE (addr) == FUNCTION_DECL) >> { >> + cgraph_node *caller = (cgraph_node *) data; >> cgraph_node *node = cgraph_node::get_create (addr); >> + /* If NODE was cloned and the caller is a callback-dispatching function, >> + the gimple call might not be updated yet. Check whether that's the >> + case and if so, replace NODE with the correct callee. */ >> + if (cgraph_edge *e = caller->get_edge (stmt); e && e->has_callback) > Please make "cgraph_edge *e = caller->get_edge (stmt)" a separate > statement above the if condition. > >> + { >> + for (cgraph_edge *cbe = e->first_callback_edge (); cbe; >> + cbe = cbe->next_callback_edge ()) > GNU coding style requires that the looping test condition is on a > separate line here, even if it is just four characters. > > Please wait until Thursday whether Honza has any comments on the > ordering issue but if not, the patch is OK with the minor nits > corrected. > > Thanks! > > Martin > > >> + { >> + if (cbe->callee->is_clone_of (node)) >> + { >> + node = cbe->callee; >> + break; >> + } >> + } >> + } >> node->mark_address_taken (); >> - ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt); >> + caller->create_reference (node, IPA_REF_ADDR, stmt); >> } >> else if (addr && VAR_P (addr) >> && (TREE_STATIC (addr) || DECL_EXTERNAL (addr))) >> diff --git a/libgomp/testsuite/libgomp.c++/pr124700.C b/libgomp/testsuite/libgomp.c++/pr124700.C >> new file mode 100644 >> index 00000000000..b95754aded2 >> --- /dev/null >> +++ b/libgomp/testsuite/libgomp.c++/pr124700.C >> @@ -0,0 +1,60 @@ >> +/* { dg-do compile } */ >> +/* { dg-options "-O3" } */ >> + >> +int a (int); >> +struct b >> +{ >> + b (); >> + b (b &); >> + ~b (); >> +}; >> +template <typename c> b d (c); >> +int ab; >> +void ae (int); >> +struct e >> +{ >> + b g; >> + template <typename c> e operator<< (c h) >> + { >> + d (h); >> + return *this; >> + } >> + b f; >> +}; >> +template <int = 0> struct i >> +{ >> + long ah; >> + int j () >> + { >> + e () << "" << aj << 1 << "" << ah << "" << ak << ""; >> + return ah; >> + } >> + char aj; >> + int ak; >> +}; >> +i<> k; >> +template <typename> >> +int >> +ao (bool h) >> +{ >> +#pragma omp parallel >> + { >> + int as; >> + for (; as;) >> + { >> + int au = k.j (); >> + ae (au); >> + if (h) >> + b (); >> + } >> + } >> + return a (ab); >> +} >> +int l = ao<short> (true); >> +void >> +az () >> +{ >> + ao<short> (true); >> + __builtin_unreachable (); >> +} >> +template int ao<short> (bool); >> -- >> 2.53.0
diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc index 90635fb5a89..a291bec3af6 100644 --- a/gcc/cgraph.cc +++ b/gcc/cgraph.cc @@ -3626,6 +3626,16 @@ cgraph_node::only_called_directly_p (void) NULL, true); } +/* Returns TRUE iff THIS is a descendant of N in the clone tree. */ + +bool +cgraph_node::is_clone_of (cgraph_node *n) const +{ + for (cgraph_node *walker = clone_of; walker; walker = walker->clone_of) + if (walker == n) + return true; + return false; +} /* Collect all callers of NODE. Worker for collect_callers_of_node. */ diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 39209b53957..36d524e28a9 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1294,6 +1294,9 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node it is not used in any other non-standard way. */ bool only_called_directly_p (void); + /* Returns TRUE iff THIS is a descendant of N in the clone tree. */ + bool is_clone_of (cgraph_node *n) const; + /* Turn profile to global0. Walk into inlined functions. */ void make_profile_local (); diff --git a/gcc/cgraphbuild.cc b/gcc/cgraphbuild.cc index e50adb955cb..8859031d333 100644 --- a/gcc/cgraphbuild.cc +++ b/gcc/cgraphbuild.cc @@ -214,9 +214,25 @@ mark_address (gimple *stmt, tree addr, tree, void *data) addr = get_base_address (addr); if (TREE_CODE (addr) == FUNCTION_DECL) { + cgraph_node *caller = (cgraph_node *) data; cgraph_node *node = cgraph_node::get_create (addr); + /* If NODE was cloned and the caller is a callback-dispatching function, + the gimple call might not be updated yet. Check whether that's the + case and if so, replace NODE with the correct callee. */ + if (cgraph_edge *e = caller->get_edge (stmt); e && e->has_callback) + { + for (cgraph_edge *cbe = e->first_callback_edge (); cbe; + cbe = cbe->next_callback_edge ()) + { + if (cbe->callee->is_clone_of (node)) + { + node = cbe->callee; + break; + } + } + } node->mark_address_taken (); - ((symtab_node *)data)->create_reference (node, IPA_REF_ADDR, stmt); + caller->create_reference (node, IPA_REF_ADDR, stmt); } else if (addr && VAR_P (addr) && (TREE_STATIC (addr) || DECL_EXTERNAL (addr))) diff --git a/libgomp/testsuite/libgomp.c++/pr124700.C b/libgomp/testsuite/libgomp.c++/pr124700.C new file mode 100644 index 00000000000..b95754aded2 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/pr124700.C @@ -0,0 +1,60 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +int a (int); +struct b +{ + b (); + b (b &); + ~b (); +}; +template <typename c> b d (c); +int ab; +void ae (int); +struct e +{ + b g; + template <typename c> e operator<< (c h) + { + d (h); + return *this; + } + b f; +}; +template <int = 0> struct i +{ + long ah; + int j () + { + e () << "" << aj << 1 << "" << ah << "" << ak << ""; + return ah; + } + char aj; + int ak; +}; +i<> k; +template <typename> +int +ao (bool h) +{ +#pragma omp parallel + { + int as; + for (; as;) + { + int au = k.j (); + ae (au); + if (h) + b (); + } + } + return a (ab); +} +int l = ao<short> (true); +void +az () +{ + ao<short> (true); + __builtin_unreachable (); +} +template int ao<short> (bool);