Re: [PATCH] lto: Regenerate implicit section names after privatization [PR lto/126841]
Richard Biener <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
On Mon, 17 Aug 2026, Longjun Luo wrote: > IPA ICF can create address-preserving wrappers during WPA. Expanding > such a wrapper resolves its implicit function-section name before LTO > privatizes the symbol. The symbol is subsequently renamed with an > lto_priv suffix, but the section keeps the pre-privatization name. > > Clear implicit section names on the renamed symbol and its aliases so > that LTRANS regenerates them from the final assembler name. Leave > explicit user-specified section names unchanged. > > Tested on x86_64-pc-linux-gnu. The new test fails without the change and > passes with it. The complete gcc.dg/lto and g++.dg/lto test suites have no > unexpected results. > > PR lto/126841 > > gcc/ChangeLog: > > * doc/invoke.texi (-ffunction-sections): Document implicitly generated > section names under LTO. > > gcc/lto/ChangeLog: > > * lto-partition.cc (clear_implicit_section): New. > (privatize_symbol_name_1): Clear implicit section names after > renaming. > > gcc/testsuite/ChangeLog: > > * gcc.dg/lto/pr126841_0.c: New test. > * gcc.dg/lto/pr126841_1.c: New test. > * gcc.dg/lto/pr126841_2.c: New test. > * gcc.dg/lto/pr126841_3.c: New test. > > Signed-off-by: Longjun Luo <[email protected]> > --- > The change is intentionally kept in privatize_symbol_name_1 rather than > symbol_table::change_decl_assembler_name. LTO privatization is the path > covered by the reproducer and regression test; other assembler-name changes > have not been audited. > > gcc/doc/invoke.texi | 5 +++++ > gcc/lto/lto-partition.cc | 12 ++++++++++++ > gcc/testsuite/gcc.dg/lto/pr126841_0.c | 22 ++++++++++++++++++++++ > gcc/testsuite/gcc.dg/lto/pr126841_1.c | 7 +++++++ > gcc/testsuite/gcc.dg/lto/pr126841_2.c | 7 +++++++ > gcc/testsuite/gcc.dg/lto/pr126841_3.c | 5 +++++ > 6 files changed, 58 insertions(+) > create mode 100644 gcc/testsuite/gcc.dg/lto/pr126841_0.c > create mode 100644 gcc/testsuite/gcc.dg/lto/pr126841_1.c > create mode 100644 gcc/testsuite/gcc.dg/lto/pr126841_2.c > create mode 100644 gcc/testsuite/gcc.dg/lto/pr126841_3.c > > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index 2e53a8c8a7e..e66cb895ae5 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -16927,6 +16927,11 @@ file if the target supports arbitrary sections. The name of the > function or the name of the data item determines the section's name > in the output file. > > +With link-time optimization, an implicitly generated section name is derived > +from the final assembler name, which may include a compiler-generated suffix > +to distinguish identically named internal-linkage items from different > +translation units. > + So this doesn't match the implementation which re-computes the section only when a symbol is privatized? To match the above it would work if we'd simply not stream the section name / implicit_section flag in lto_output_node (for implicit_section section names, that is)? Saving on streaming size sounds like a good thing as well. The question is of course what meets user expectation best here. Richard. > Use these options on systems where the linker can perform optimizations to > improve locality of reference in the instruction space. Most systems using the > ELF object format have linkers with such optimizations. On AIX, the linker > diff --git a/gcc/lto/lto-partition.cc b/gcc/lto/lto-partition.cc > index 5033ae3f97d..facb5d25907 100644 > --- a/gcc/lto/lto-partition.cc > +++ b/gcc/lto/lto-partition.cc > @@ -1797,6 +1797,17 @@ validize_symbol_for_target (symtab_node *node) > /* Maps symbol names to unique lto clone counters. */ > static hash_map<const char *, unsigned> *lto_clone_numbers; > > +/* Clear compiler-generated section names after changing an assembler name, > + so they are regenerated from the final name. */ > + > +static bool > +clear_implicit_section (symtab_node *node, void *) > +{ > + if (node->implicit_section) > + node->set_section_for_node (NULL); > + return false; > +} > + > /* Helper for privatize_symbol_name. Mangle NODE symbol name > represented by DECL. */ > > @@ -1813,6 +1824,7 @@ privatize_symbol_name_1 (symtab_node *node, tree decl) > symtab->change_decl_assembler_name (decl, > clone_function_name ( > name, "lto_priv", clone_number)); > + node->call_for_symbol_and_aliases (clear_implicit_section, NULL, true); > clone_number++; > > if (node->lto_file_data) > diff --git a/gcc/testsuite/gcc.dg/lto/pr126841_0.c b/gcc/testsuite/gcc.dg/lto/pr126841_0.c > new file mode 100644 > index 00000000000..a0222d3336f > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/lto/pr126841_0.c > @@ -0,0 +1,22 @@ > +/* { dg-lto-do link } */ > +/* { dg-require-effective-target elf } */ > +/* { dg-require-effective-target named_sections } */ > +/* { dg-require-effective-target fpic } */ > +/* { dg-require-effective-target shared } */ > +/* { dg-require-linker-plugin "" } */ > +/* { dg-lto-options { { -O2 -flto -fPIC -shared -ffunction-sections -save-temps } } } */ > + > +static int > +same_fn (int x) > +{ > + return x * 33 + 7; > +} > + > +int (*a_callback) (int) = same_fn; > + > +/* The exported function keeps the unsuffixed section, and each privatized > + function must have its own section. */ > +/* { dg-final { scan-lto-assembler {\.section[ \t]+\.text\.same_fn[, \t"]} } } */ > +/* { dg-final { scan-lto-assembler {\.section[ \t]+\.text\.same_fn\.lto_priv\.0[, \t"]} } } */ > +/* { dg-final { scan-lto-assembler {\.section[ \t]+\.text\.same_fn\.lto_priv\.1[, \t"]} } } */ > +/* { dg-final { scan-lto-assembler {\.section[ \t]+\.text\.same_fn\.lto_priv\.2[, \t"]} } } */ > diff --git a/gcc/testsuite/gcc.dg/lto/pr126841_1.c b/gcc/testsuite/gcc.dg/lto/pr126841_1.c > new file mode 100644 > index 00000000000..39356acba71 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/lto/pr126841_1.c > @@ -0,0 +1,7 @@ > +static int > +same_fn (int x) > +{ > + return x * 33 + 7; > +} > + > +int (*b_callback) (int) = same_fn; > diff --git a/gcc/testsuite/gcc.dg/lto/pr126841_2.c b/gcc/testsuite/gcc.dg/lto/pr126841_2.c > new file mode 100644 > index 00000000000..369eb1836a6 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/lto/pr126841_2.c > @@ -0,0 +1,7 @@ > +static int > +same_fn (int x) > +{ > + return x * 33 + 7; > +} > + > +int (*c_callback) (int) = same_fn; > diff --git a/gcc/testsuite/gcc.dg/lto/pr126841_3.c b/gcc/testsuite/gcc.dg/lto/pr126841_3.c > new file mode 100644 > index 00000000000..567eb29cda0 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/lto/pr126841_3.c > @@ -0,0 +1,5 @@ > +int > +same_fn (int x) > +{ > + return x - 1; > +} > -- 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)