Since r167795, cfgexpand has resolved a function's section before RTL
expansion.  r168624 added resolve_unique_section to the direct thunk
emission path, when thunks were still emitted directly as assembly.  When
r202592 added a GIMPLE thunk path, the call was retained in both paths.  The
direct assembler path still needs it, but the GIMPLE path later reaches
cfgexpand, so its call is redundant.

It can also be too early.  IPA ICF can turn equivalent functions whose
addresses matter into GIMPLE wrappers during WPA, before LTO privatizes their
assembler names.  The early call records a section based on the old name,
and that stale section is streamed into LTRANS.  IPA strub has the same
problem in the GIMPLE wrapper code added in r14-6201.

Remove the early calls for GIMPLE wrappers and let cfgexpand resolve their
sections from the final assembler names.  Keep the call for directly emitted
assembler thunks; during LTO output it is reached only after privatization.
Explicit and deliberately inherited section names remain unchanged.  This
fixes the stale name at its source instead of discarding an already-resolved
section only when LTO privatizes a symbol.

Bootstrapped and regression-tested on x86_64-pc-linux-gnu (C and C++ only),
with no new failures.  Both new tests fail without the change and pass with
it.  The complete gcc.dg/lto and g++.dg/lto suites, the strub tests, and
g++.dg/other/pr47218* have no unexpected results.

        PR lto/126841

gcc/ChangeLog:

        * doc/invoke.texi (-ffunction-sections): Document implicit function
        section names under LTO.
        * ipa-strub.cc (pass_ipa_strub::execute): Let cfgexpand resolve the
        GIMPLE wrapper section.
        * symtab-thunks.cc (expand_thunk): Likewise for generic GIMPLE thunks.
        Clarify the direct-assembler case.

gcc/testsuite/ChangeLog:

        * gcc.dg/lto/pr126841-strub_0.c: New test.
        * gcc.dg/lto/pr126841-strub_1.c: New test.
        * 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]>
---
Changes in v2:
- Fix the premature section resolution at the GIMPLE-wrapper construction
  sites instead of changing LTO streaming.
- Cover the same issue in IPA strub with an independent regression test.
- Narrow the documentation to implicit function sections and retain the
  exception for deliberate co-location.

I tried the suggested lto_output_node approach.  It needs exceptions for
thunks and former thunks that deliberately inherit a section.  Aliases are
another issue because they have no body of their own to pass through
cfgexpand.  Removing the premature calls is narrower: these GIMPLE wrappers
already pass through cfgexpand, while directly emitted assembler thunks
retain their output-time call.  This forgoes the possible reduction in
streaming size, but avoids changing established section relationships.

For functions that are not deliberately co-located, keeping one section per
function matches the documented -ffunction-sections behavior.  Here the final
lto_priv names already provide the disambiguation discussed in comment #6;
resolving from the pre-privatization name instead silently puts distinct
functions in one section.

I also compared explicit-section ICF and strub cases before and after the
change; their LTRANS assembly is unchanged.  The updated manual also builds
successfully with makeinfo.

 gcc/doc/invoke.texi                         |  6 ++++++
 gcc/ipa-strub.cc                            |  4 ----
 gcc/symtab-thunks.cc                        |  7 ++-----
 gcc/testsuite/gcc.dg/lto/pr126841-strub_0.c | 21 ++++++++++++++++++++
 gcc/testsuite/gcc.dg/lto/pr126841-strub_1.c |  7 +++++++
 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 +++++
 9 files changed, 77 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/lto/pr126841-strub_0.c
 create mode 100644 gcc/testsuite/gcc.dg/lto/pr126841-strub_1.c
 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 01925ecf30d..ed341e88f48 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -16927,6 +16927,12 @@ 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 function section name is
+derived from the final assembler name unless the compiler deliberately places
+related functions, such as a thunk and its target, in the same section.  The
+final assembler name may include a compiler-generated suffix that distinguishes
+identically named internal-linkage items from different translation units.
+
 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/ipa-strub.cc b/gcc/ipa-strub.cc
index b0156fe46f6..118c4a08082 100644
--- a/gcc/ipa-strub.cc
+++ b/gcc/ipa-strub.cc
@@ -3124,10 +3124,6 @@ pass_ipa_strub::execute (function *)
 
            current_function_decl = thunk_fndecl;
 
-           /* Ensure thunks are emitted in their correct sections.  */
-           resolve_unique_section (thunk_fndecl, 0,
-                                   flag_function_sections);
-
            bitmap_obstack_initialize (NULL);
 
            /* Build the return declaration for the function.  */
diff --git a/gcc/symtab-thunks.cc b/gcc/symtab-thunks.cc
index fb4ff87c988..e0a8d5e9357 100644
--- a/gcc/symtab-thunks.cc
+++ b/gcc/symtab-thunks.cc
@@ -363,7 +363,8 @@ expand_thunk (cgraph_node *node, bool output_asm_thunks,
 
       current_function_decl = thunk_fndecl;
 
-      /* Ensure thunks are emitted in their correct sections.  */
+      /* This thunk is emitted directly and bypasses cfgexpand, so resolve
+        its section here.  */
       resolve_unique_section (thunk_fndecl, 0,
                              flag_function_sections);
 
@@ -432,10 +433,6 @@ expand_thunk (cgraph_node *node, bool output_asm_thunks,
 
       current_function_decl = thunk_fndecl;
 
-      /* Ensure thunks are emitted in their correct sections.  */
-      resolve_unique_section (thunk_fndecl, 0,
-                             flag_function_sections);
-
       bitmap_obstack_initialize (NULL);
 
       if (info->virtual_offset_p)
diff --git a/gcc/testsuite/gcc.dg/lto/pr126841-strub_0.c 
b/gcc/testsuite/gcc.dg/lto/pr126841-strub_0.c
new file mode 100644
index 00000000000..bd8e628ade5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr126841-strub_0.c
@@ -0,0 +1,21 @@
+/* { 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-effective-target strub } */
+/* { dg-require-linker-plugin "" } */
+/* { dg-lto-options { { -O2 -flto -fPIC -shared -ffunction-sections 
-save-temps -fstrub=all -fno-ipa-icf } } } */
+
+static int
+same_fn (int x)
+{
+  return x * 33 + 7;
+}
+
+int (*a_callback) (int) = same_fn;
+
+/* The strub wrappers must use sections derived from their privatized
+   assembler names.  */
+/* { 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"]} } } */
diff --git a/gcc/testsuite/gcc.dg/lto/pr126841-strub_1.c 
b/gcc/testsuite/gcc.dg/lto/pr126841-strub_1.c
new file mode 100644
index 00000000000..39356acba71
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr126841-strub_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_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;
+}
-- 
2.55.0

Reply via email to