Change in v3:
Add safe_as_a<asm_node*> needed for rebase.

---

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                 | 68 +++++++++++++++++++++++++++++
 gcc/cgraph.h                        |  6 ++-
 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 e099fc1bb09..99853104b4b 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1413,6 +1413,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..336564bb95e
--- /dev/null
+++ b/gcc/asm-toplevel.cc
@@ -0,0 +1,68 @@
+/* Toplevel assembly.
+   Copyright (C) 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 = safe_as_a<asm_node*> (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 905244eac20..84970d7d89c 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -2362,11 +2362,15 @@ private:
 
 struct GTY ((tag ("TOPLEVEL_ASM"))) asm_node: public toplevel_node {
   explicit asm_node (tree asm_str)
-    : toplevel_node (TOPLEVEL_ASM), asm_str (asm_str)
+    : toplevel_node (TOPLEVEL_ASM), asm_str (asm_str), symbols_referenced ()
   {}
   /* 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 61f33725d85..1133a51e94b 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -2583,6 +2583,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 13aca2c9d2a..6aeeae42b6c 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.52.0

Reply via email to