Re: [PATCH] debug/126355 - preserve debug info for IPA ICF wrappers

Longjun Luo <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <CAKL4jwWcPBhKNG2FZ+-0pWr7XMDFQFOvJG+0+FkhzHSdfZtUjQ@mail.gmail.com>
Thanks for the approval, and apologies for the delayed follow-up.

I have rechecked the original patch against current trunk; it still applies
unchanged.  I also bootstrapped and regression-tested it on
x86_64-pc-linux-gnu (C and C++ only), with no new failures.  The new test
fails without the patch and passes with it.

I do not currently have commit access.  Could someone please commit this
approved patch for me?

I am continuing to work on LTO-related debug issues and have several related
problems under investigation.  If you think it would be appropriate at this
stage, Richard, would you be willing to sponsor me for write-after-approval
access?

Richard Biener <[email protected]> 于2026年7月29日周三 20:17写道:

> On Sat, 25 Jul 2026, Longjun Luo wrote:
>
> > I tested the global-removal variant based on trunk commit
> > 5453f858146 on x86_64-pc-linux-gnu.
> >
> > The bootstrap completed successfully, including the stage2/stage3
> > comparison, and the new PR126355 testcase passed. However, the full
> > regression test exposed ICEs in the following existing tests with
> > -O3 -g:
> >
> > g++.dg/torture/covariant-1.C
> > g++.dg/torture/pr45699.C
> > g++.dg/torture/pr46287.C
> > g++.dg/torture/pr48661.C
> > g++.dg/torture/pr58585.C
> > g++.dg/torture/pr59226.C
> > g++.dg/torture/pr94202.C
> >
> > They all fail at the same assertion:
> >
> > old_die = lookup_decl_die (decl);
> > gcc_assert (old_die != NULL);
> >
> > in dwarf2out_abstract_function. A representative backtrace is:
> >
> > dwarf2out_abstract_function
> > tree_function_versioning
> > save_inline_function_body
> > inline_transform
> >
> > These cases involve C++ thunks expanded through the inline path. Without
> > the DECL_IGNORED_P setting, final debug processing reaches declarations
> > which do not have an early DIE, and lookup_decl_die returns NULL.
> >
> > Thus, although g++.dg/other/pr87574.C itself no longer reproduces its
> > original ICE on current trunk, it is not a sufficient guard for the
> > underlying condition. At least some forced GIMPLE thunks expanded through
> > the inline path still rely on DECL_IGNORED_P.
>
> Thanks for investigating.
>
> > I therefore will not post the global-removal variant as v2. The
> > caller-specific save/restore in cgraph_node::create_wrapper remains the
> > narrower fix: it bypasses the protection only for an ICF wrapper which
> > reuses the original source declaration and its early DIE, while leaving
> > late-created thunks in the other callers unchanged.
> >
> > Unless there is a better way to distinguish forced thunks which already
> > have a usable early DIE, I suggest keeping the ICF-local approach.
>
> I agree, so the original patch is OK.
>
> Thanks,
> Richard.
>
> > Richard Biener <[email protected]> 于2026年7月24日周五 15:56写道:
> >
> > > On Thu, 23 Jul 2026, Longjun Luo wrote:
> > >
> > > > Thanks. I traced the setting back to PR middle-end/87574.
> > > >
> > > > r264943 removed the previously unconditional DECL_IGNORED_P setting
> from
> > > > expand_thunk, which exposed the DWARF ICE reported as PR87574.
> r265028
> > > > (Eric Botcazou) then restored it conditionally for forced GIMPLE
> thunks.
> > > >
> > > > For the record, the PR87574 reproducer itself is not LTO-related: it
> is a
> > > > plain "-O2 -g" ICE in add_data_member_location_attribute
> > > > (dwarf2out.c:19226), and its testcase g++.dg/other/pr87574.C is a
> > > > { dg-do compile }, so compiling it exercises the original failure
> mode
> > > > directly.
> > > >
> > > > There are in fact three callers of
> > > > expand_thunk (..., /*force_gimple_thunk=*/true): inline_call
> > > > (ipa-inline-transform.cc), the ICF wrapper
> > > > (cgraph_node::create_wrapper), and coverage instrumentation
> > > > (tree-profile.cc).
> > > >
> > > > I built an x86_64-pc-linux-gnu compiler from trunk commit 5453f858146
> > > > with only the conditional DECL_IGNORED_P setting removed, and ran
> these
> > > > targeted compile checks:
> > > >
> > > > - g++.dg/other/pr87574.C compiled with -O2 -g and no ICE; an
> additional
> > > > IPA inline dump showed the thunk expanded through inline_call;
> > > > - the new PR126355 test source compiled with the test options; the
> ICF
> > > > dump showed that the wrapper was created, and the assembly showed an
> > > > address-bearing DIE for pr_icf_wrapper_b;
> > > > - g++.dg/tree-prof/devirt.C compiled to assembly with
> > > > -O3 -g -fprofile-generate -fno-profile-values
> > > > -fdump-ipa-cgraph-details -S -dA, and the generated thunks contained
> > > > their __gcov counters, exercising the tree-profile.cc path.
> > > >
> > > > Thus, the original PR87574 failure no longer reproduces on this trunk
> > > > checkout with the setting removed, and g++.dg/other/pr87574.C
> remains as
> > > > a guard should it ever return.
> > > >
> > > > Given that, removing the setting globally looks worth testing as the
> > > > simpler fix. It addresses the common setting in expand_thunk rather
> than
> > > > undoing it only in the ICF caller. It also changes debug emission
> for the
> > > > inline_call and coverage paths, however, so I will do a full
> bootstrap
> > > and
> > > > regtest, with particular attention to the LTO, debug, guality,
> dwarf2,
> > > and
> > > > tree-prof suites, before posting such a revision.
> > > >
> > > > Would you prefer that global removal, or the more conservative
> > > > caller-specific patch as posted? I can go either way; the ICF-only
> > > version
> > > > remains a fallback if the removal turns up any fallout.
> > >
> > > I prefer the global removal, but I CCed Eric in case he remembers
> > > details and can argue the actual issue still exists.
> > >
> > > Thanks,
> > > Richard.
> > >
> > > > Richard Biener <[email protected]> 于2026年7月23日周四 16:38写道:
> > > >
> > > > > On Thu, 23 Jul 2026, Longjun Luo wrote:
> > > > >
> > > > > > When IPA ICF keeps a distinct symbol for an address-taken
> function by
> > > > > > replacing its body with a wrapper, cgraph_node::create_wrapper
> > > reuses the
> > > > > > original function declaration and its early debug DIE.
> > > > > >
> > > > > > create_wrapper then calls expand_thunk with force_gimple_thunk
> set.
> > > > > Forced
> > > > > > GIMPLE thunks are normally created after early debug, so
> expand_thunk
> > > > > marks
> > > > > > their declarations ignored.  For an ICF wrapper this also
> prevents
> > > final
> > > > > > debug emission from attaching the wrapper address to the existing
> > > DIE.
> > > > > > The wrapper consequently has code and an STT_FUNC symbol but no
> > > > > > address-bearing DW_TAG_subprogram DIE.
> > > > > >
> > > > > > Preserve the declaration's original DECL_IGNORED_P value across
> > > forced
> > > > > > GIMPLE thunk expansion in create_wrapper.  Declarations that were
> > > already
> > > > > > ignored remain ignored, while an original source declaration can
> > > receive
> > > > > > its final address information.
> > > > > >
> > > > > > Tested on x86_64-pc-linux-gnu with the new gcc.dg/debug/dwarf2
> > > test.  The
> > > > > > test fails before the change and passes afterwards.
> > > > >
> > > > > There's two calls to expand_thunk (..., true), one from ICF as you
> > > > > figured and one from inline_call ().  I wonder if it's better to
> > > > > remove
> > > > >
> > > > >       /* We need to force DECL_IGNORED_P when the thunk is created
> > > > >          after early debug was run.  */
> > > > >       if (force_gimple_thunk)
> > > > >         DECL_IGNORED_P (thunk_fndecl) = 1;
> > > > >
> > > > > or figure why it was put there and see if the reason still holds
> > > > > (sounds LTO-ish).
> > > > >
> > > > > Richard.
> > > > >
> > > > > >       PR debug/126355
> > > > > >
> > > > > > gcc/ChangeLog:
> > > > > >
> > > > > >       * cgraphunit.cc (cgraph_node::create_wrapper): Preserve
> > > > > >       DECL_IGNORED_P across forced GIMPLE thunk expansion.
> > > > > >
> > > > > > gcc/testsuite/ChangeLog:
> > > > > >
> > > > > >       * gcc.dg/debug/dwarf2/pr126355.c: New test.
> > > > > >
> > > > > > Signed-off-by: Longjun Luo <[email protected]>
> > > > > > ---
> > > > > >  gcc/cgraphunit.cc                            |  5 +++
> > > > > >  gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c | 35
> > > ++++++++++++++++++++
> > > > > >  2 files changed, 40 insertions(+)
> > > > > >  create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c
> > > > > >
> > > > > > diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
> > > > > > index 67aaebf108b..d397c9ae4cc 100644
> > > > > > --- a/gcc/cgraphunit.cc
> > > > > > +++ b/gcc/cgraphunit.cc
> > > > > > @@ -2683,7 +2683,12 @@ cgraph_node::create_wrapper (cgraph_node
> > > *target)
> > > > > >        arguments = TREE_CHAIN (arguments);
> > > > > >      }
> > > > > >
> > > > > > +  /* Forced GIMPLE thunks are normally ignored because they are
> > > created
> > > > > > +     after early debug.  ICF wrappers retain the original
> function
> > > decl
> > > > > and
> > > > > > +     its early DIE, so preserve its original debug state.  */
> > > > > > +  bool ignored_p = DECL_IGNORED_P (decl);
> > > > > >    expand_thunk (this, false, true);
> > > > > > +  DECL_IGNORED_P (decl) = ignored_p;
> > > > > >    thunk_info::remove (this);
> > > > > >
> > > > > >    /* Inline summary set-up.  */
> > > > > > diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c
> > > > > b/gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c
> > > > > > new file mode 100644
> > > > > > index 00000000000..35e321008aa
> > > > > > --- /dev/null
> > > > > > +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr126355.c
> > > > > > @@ -0,0 +1,35 @@
> > > > > > +/* PR debug/126355 */
> > > > > > +/* Verify that an IPA ICF wrapper for an address-taken function
> > > keeps an
> > > > > > +   address-bearing subprogram DIE.  */
> > > > > > +/* { dg-do compile } */
> > > > > > +/* { dg-options "-O2 -g -gdwarf -dA -fdump-ipa-icf-details" } */
> > > > > > +
> > > > > > +int
> > > > > > +pr_icf_wrapper_a (const char *host)
> > > > > > +{
> > > > > > +  (void) host;
> > > > > > +  return 0;
> > > > > > +}
> > > > > > +
> > > > > > +int
> > > > > > +pr_icf_wrapper_b (const char *host)
> > > > > > +{
> > > > > > +  (void) host;
> > > > > > +  return 0;
> > > > > > +}
> > > > > > +
> > > > > > +int (*keep_a) (const char *) = pr_icf_wrapper_a;
> > > > > > +int (*keep_b) (const char *) = pr_icf_wrapper_b;
> > > > > > +
> > > > > > +int
> > > > > > +main (int argc, char **argv)
> > > > > > +{
> > > > > > +  const char *arg = argc > 1 ? argv[1] : "x";
> > > > > > +  return keep_a (arg) + keep_b (arg);
> > > > > > +}
> > > > > > +
> > > > > > +/* Check the ICF direction explicitly because the DWARF scan
> below
> > > > > inspects
> > > > > > +   pr_icf_wrapper_b, the wrapper.  */
> > > > > > +/* { dg-final { scan-ipa-dump "Semantic equality
> > > > > hit:pr_icf_wrapper_a/\[0-9+\]+->pr_icf_wrapper_b/\[0-9+\]+" "icf"
> } }
> > > */
> > > > > > +/* { dg-final { scan-ipa-dump "Wrapper has been created" "icf"
> } }
> > > */
> > > > > > +/* { dg-final { scan-assembler "\\(DIE \\(0x\[0-9a-f\]+\\)
> > > > >
> > >
> DW_TAG_subprogram\\)\[\r\n\]+(\[^\r\n\]*\[\r\n\]+){1,12}\[^\r\n\]*DW_AT_name:
> > > > >
> > >
> \"pr_icf_wrapper_b\"\[\r\n\]+(\[^\r\n\]*\[\r\n\]+){1,12}\[^\r\n\]*DW_AT_low_pc"
> > > > > } } */
> > > > > >
> > > > >
> > > > > --
> > > > > Richard Biener <[email protected]>
> > > > > SUSE Software Solutions Germany GmbH,
> > > > > Frankenstrasse 146, 90461 Nuernberg, Germany;
> > > > > GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG
> > > Nuernberg)
> > > > >
> > > >
> > >
> > > --
> > > Richard Biener <[email protected]>
> > > SUSE Software Solutions Germany GmbH,
> > > Frankenstrasse 146, 90461 Nuernberg, Germany;
> > > GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG
> Nuernberg)
> >
>
> --
> Richard Biener <[email protected]>
> SUSE Software Solutions Germany GmbH,
> Frankenstrasse 146, 90461 Nuernberg, Germany;
> GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.