Analyzes references from toplevel extended assembly.

We cannot perform IPA optimizations with toplevel assembly, so
symtab_node only needs ref_by_asm to know that it should not be removed.

        PR ipa/122458

gcc/ChangeLog:

        * Makefile.in: Add new file.
        * cgraph.h (analyze_toplevel_extended_asm): New.
        * cgraphunit.cc (symbol_table::finalize_compilation_unit):
        Call analyze_toplevel_extended_asm.
        * asm-toplevel.cc: New file.

gcc/lto/ChangeLog:

        * lto-common.cc (read_cgraph_and_symbols):
        Call analyze_toplevel_extended_asm.

gcc/testsuite/ChangeLog:

        * gcc.dg/ipa/pr122458.c: New test.
---
 gcc/Makefile.in                     |  1 +
 gcc/asm-toplevel.cc                 | 67 +++++++++++++++++++++++++++++
 gcc/cgraph.h                        |  7 ++-
 gcc/cgraphunit.cc                   |  2 +
 gcc/lto/lto-common.cc               |  1 +
 gcc/testsuite/gcc.dg/ipa/pr122458.c |  9 ++++
 6 files changed, 86 insertions(+), 1 deletion(-)
 create mode 100644 gcc/asm-toplevel.cc
 create mode 100644 gcc/testsuite/gcc.dg/ipa/pr122458.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index d05e15e2b6c..c3f36c5285d 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1409,6 +1409,7 @@ OBJS = \
        adjust-alignment.o \
        alias.o \
        alloc-pool.o \
+       asm-toplevel.o \
        auto-inc-dec.o \
        auto-profile.o \
        bb-reorder.o \
diff --git a/gcc/asm-toplevel.cc b/gcc/asm-toplevel.cc
new file mode 100644
index 00000000000..9d7ba934e29
--- /dev/null
+++ b/gcc/asm-toplevel.cc
@@ -0,0 +1,67 @@
+/* Toplevel assembly.
+   Copyright (C) 2025-2025 Free Software Foundation, Inc.
+   Contributed by Michal Jires <[email protected]>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "cgraph.h"
+
+/* Mark symbols in constraints.  */
+static tree
+walk_through_constraints (tree* t, int*, void* data)
+{
+  asm_node* anode = (asm_node*) data;
+  if (VAR_OR_FUNCTION_DECL_P (*t))
+    {
+      symtab_node* node;
+      if (!flag_wpa && !flag_ltrans)
+       {
+         node = symtab_node::get_create (*t);
+         node->ref_by_asm = true;
+       }
+      else
+       {
+         node = symtab_node::get (*t);
+         gcc_assert (node);
+       }
+      anode->symbols_referenced.safe_push (node);
+    }
+  return NULL;
+}
+
+/* Analyze constraints of toplevel extended assembly.  */
+void
+analyze_toplevel_extended_asm ()
+{
+  asm_node *anode;
+  for (anode = symtab->first_asm_symbol (); anode; anode = anode->next)
+    {
+      if (TREE_CODE (anode->asm_str) != ASM_EXPR)
+       continue;
+
+      for (tree l = ASM_INPUTS (anode->asm_str); l; l = TREE_CHAIN (l))
+       walk_tree (&l, walk_through_constraints, (void*) anode, NULL);
+      for (tree l = ASM_OUTPUTS (anode->asm_str); l; l = TREE_CHAIN (l))
+       walk_tree (&l, walk_through_constraints, (void*) anode, NULL);
+    }
+}
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 4aed690bac9..036a89da9cb 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -2246,13 +2246,18 @@ private:
 
 struct GTY ((tag ("TOPLEVEL_ASM"))) asm_node: public toplevel_node {
   explicit asm_node (tree asm_str)
-    : toplevel_node (TOPLEVEL_ASM), next (NULL), asm_str (asm_str)
+    : toplevel_node (TOPLEVEL_ASM), next (NULL), asm_str (asm_str),
+    symbols_referenced ()
   {}
   /* Next asm node.  */
   asm_node *next;
   /* String for this asm node.  */
   tree asm_str;
+  /* Vector of referenced symbols used for LTO partitioning.
+     Not populated in flag_ltrans.  */
+  vec<symtab_node*> GTY ((skip)) symbols_referenced;
 };
+void analyze_toplevel_extended_asm (void);
 
 /* Report whether or not THIS symtab node is a function, aka cgraph_node.  */
 
diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index d50ffd270b6..e27bee1309b 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -2581,6 +2581,8 @@ symbol_table::finalize_compilation_unit (void)
   if (flag_dump_passes)
     dump_passes ();
 
+  analyze_toplevel_extended_asm ();
+
   /* Gimplify and lower all functions, compute reachability and
      remove unreachable nodes.  */
   analyze_functions (/*first_time=*/true);
diff --git a/gcc/lto/lto-common.cc b/gcc/lto/lto-common.cc
index 3d35c038916..f5e3c53bbe5 100644
--- a/gcc/lto/lto-common.cc
+++ b/gcc/lto/lto-common.cc
@@ -2998,6 +2998,7 @@ read_cgraph_and_symbols (unsigned nfiles, const char 
**fnames)
          symtab->dump (dump_file);
        }
       lto_symtab_merge_symbols ();
+      analyze_toplevel_extended_asm ();
       /* Removal of unreachable symbols is needed to make verify_symtab to 
pass;
         we are still having duplicated comdat groups containing local statics.
         We could also just remove them while merging.  */
diff --git a/gcc/testsuite/gcc.dg/ipa/pr122458.c 
b/gcc/testsuite/gcc.dg/ipa/pr122458.c
new file mode 100644
index 00000000000..bec608ad486
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr122458.c
@@ -0,0 +1,9 @@
+/* PR ipa/122458 */
+/* { dg-do link } */
+/* { dg-options "-O2" } */
+
+static int foo (void) { return 0; };
+
+asm (".quad %c0" :: "i" (foo));
+
+int main() {}
-- 
2.51.1

Reply via email to