[gcc r17-2206] i386: Split out call_saved_registers_type detection

"H.J. Lu via Gcc-cvs" <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:d68cbbb3ae0010446c76dacd20b5c225e0535812

commit r17-2206-gd68cbbb3ae0010446c76dacd20b5c225e0535812
Author: Richard Sandiford <[email protected]>
Date:   Thu May 14 22:51:49 2026 +0100

    i386: Split out call_saved_registers_type detection
    
    There are currently two places that want to query a function's
    call_saved_registers_type: ix86_set_func_type (when setting up
    cfun->machine) and ix86_type_no_callee_saved_registers_p
    (a derived query).  The upcoming function_abi patch will add
    another one, so this patch splits the code out into a subroutine.
    
    ix86_set_func_type did some of the detection first, into
    no_callee_saved_registers, but then ignored the result if
    cfun->machine->func_type had already been set.  The patch therefore
    moves all of the detection after the cfun->machine->func_type test,
    rather than moving all of it before.
    
    gcc/
            * config/i386/i386-protos.h (ix86_fntype_call_saved_registers):
            Declare.
            * config/i386/i386-options.cc (ix86_fntype_call_saved_registers): New
            function, split out from...
            (ix86_set_func_type): ...here.  Avoid calling it if the result
            would be ignored.
            * config/i386/i386.cc (ix86_type_no_callee_saved_registers_p): Use
            ix86_fntype_call_saved_registers instead of querying attributes
            directly.

Diff:
---
 gcc/config/i386/i386-options.cc | 135 ++++++++++++++++++++--------------------
 gcc/config/i386/i386-protos.h   |   2 +
 gcc/config/i386/i386.cc         |   8 +--
 3 files changed, 74 insertions(+), 71 deletions(-)

diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
index 8689ba5c883a..da6e45f3f29b 100644
--- a/gcc/config/i386/i386-options.cc
+++ b/gcc/config/i386/i386-options.cc
@@ -3265,13 +3265,53 @@ ix86_simd_clone_adjust (struct cgraph_node *node)
   ix86_set_current_function (node->decl);
 }
 
+/* Return the call_saved_registers_type for function type FNTYPE.
+   If LOC is nonnull, report incompatible attributes against that
+   location, otherwise remain silent.  */
 
+call_saved_registers_type
+ix86_fntype_call_saved_registers (const_tree fntype, location_t *loc)
+{
+  auto call_saved_registers = TYPE_DEFAULT_CALL_SAVED_REGISTERS;
+  const char *interrupt_conflict = nullptr;
+  if (lookup_attribute ("preserve_none", TYPE_ATTRIBUTES (fntype)))
+    {
+      call_saved_registers = TYPE_PRESERVE_NONE;
+      interrupt_conflict = "preserve_none";
+    }
+  else if (lookup_attribute ("no_callee_saved_registers",
+			     TYPE_ATTRIBUTES (fntype)))
+    {
+      call_saved_registers = TYPE_NO_CALLEE_SAVED_REGISTERS;
+      interrupt_conflict = "no_callee_saved_registers";
+    }
+  else if (lookup_attribute ("no_caller_saved_registers",
+			     TYPE_ATTRIBUTES (fntype)))
+    call_saved_registers = TYPE_NO_CALLER_SAVED_REGISTERS;
+
+  if (lookup_attribute ("interrupt", TYPE_ATTRIBUTES (fntype)))
+    {
+      if (loc && interrupt_conflict)
+	error_at (*loc, "%qs and %qs attributes are not compatible",
+		  "interrupt", interrupt_conflict);
+      return TYPE_NO_CALLER_SAVED_REGISTERS;
+    }
+
+  return call_saved_registers;
+}
 
 /* Set the func_type field from the function FNDECL.  */
 
 static void
 ix86_set_func_type (tree fndecl)
 {
+  if (cfun->machine->func_type != TYPE_UNKNOWN)
+    return;
+
+  cfun->machine->call_saved_registers
+    = ix86_fntype_call_saved_registers (TREE_TYPE (fndecl),
+					&DECL_SOURCE_LOCATION (fndecl));
+
   /* No need to save and restore callee-saved registers for a noreturn
      function with nothrow or compiled with -fno-exceptions unless when
      compiling with -O0 or -Og, except that it interferes with debugging
@@ -3287,74 +3327,37 @@ ix86_set_func_type (tree fndecl)
      function is marked with TREE_THIS_VOLATILE in the IR output, which
      leads to the incompatible attribute error in LTO1.  Ignore the
      interrupt function in this case.  */
-  enum call_saved_registers_type no_callee_saved_registers
-    = TYPE_DEFAULT_CALL_SAVED_REGISTERS;
-  if (lookup_attribute ("preserve_none",
-			     TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
-    no_callee_saved_registers = TYPE_PRESERVE_NONE;
-  else if ((lookup_attribute ("no_callee_saved_registers",
-			      TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
-	   || (ix86_noreturn_no_callee_saved_registers
-	       && TREE_THIS_VOLATILE (fndecl)
-	       && optimize
-	       && !optimize_debug
-	       && (TREE_NOTHROW (fndecl) || !flag_exceptions)
-	       && !lookup_attribute ("interrupt",
-				     TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))
-	       && !lookup_attribute ("no_caller_saved_registers",
-				 TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))))
-    no_callee_saved_registers = TYPE_NO_CALLEE_SAVED_REGISTERS;
-
-  if (cfun->machine->func_type == TYPE_UNKNOWN)
+  if (cfun->machine->call_saved_registers == TYPE_DEFAULT_CALL_SAVED_REGISTERS
+      && ix86_noreturn_no_callee_saved_registers
+      && TREE_THIS_VOLATILE (fndecl)
+      && optimize
+      && !optimize_debug
+      && (TREE_NOTHROW (fndecl) || !flag_exceptions))
+    cfun->machine->call_saved_registers = TYPE_NO_CALLEE_SAVED_REGISTERS;
+
+  if (lookup_attribute ("interrupt",
+			TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
     {
-      if (lookup_attribute ("interrupt",
-			    TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
-	{
-	  if (ix86_function_naked (fndecl))
-	    error_at (DECL_SOURCE_LOCATION (fndecl),
-		      "interrupt and naked attributes are not compatible");
-
-	  if (no_callee_saved_registers)
-	    {
-	      const char *attr;
-	      if (no_callee_saved_registers == TYPE_PRESERVE_NONE)
-		attr = "preserve_none";
-	      else
-		attr = "no_callee_saved_registers";
-	      error_at (DECL_SOURCE_LOCATION (fndecl),
-			"%qs and %qs attributes are not compatible",
-			"interrupt", attr);
-	    }
-
-	  int nargs = 0;
-	  for (tree arg = DECL_ARGUMENTS (fndecl);
-	       arg;
-	       arg = TREE_CHAIN (arg))
-	    nargs++;
-	  cfun->machine->call_saved_registers
-	    = TYPE_NO_CALLER_SAVED_REGISTERS;
-	  cfun->machine->func_type
-	    = nargs == 2 ? TYPE_EXCEPTION : TYPE_INTERRUPT;
-
-	  ix86_optimize_mode_switching[X86_DIRFLAG] = 1;
-
-	  /* Only dwarf2out.cc can handle -WORD(AP) as a pointer argument.  */
-	  if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG)
-	    sorry ("only DWARF debug format is supported for interrupt "
-		   "service routine");
-	}
-      else
-	{
-	  cfun->machine->func_type = TYPE_NORMAL;
-	  if (no_callee_saved_registers)
-	    cfun->machine->call_saved_registers
-	      = no_callee_saved_registers;
-	  else if (lookup_attribute ("no_caller_saved_registers",
-				     TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
-	    cfun->machine->call_saved_registers
-	      = TYPE_NO_CALLER_SAVED_REGISTERS;
-	}
+      if (ix86_function_naked (fndecl))
+	error_at (DECL_SOURCE_LOCATION (fndecl),
+		  "interrupt and naked attributes are not compatible");
+
+      int nargs = 0;
+      for (tree arg = DECL_ARGUMENTS (fndecl);
+	   arg;
+	   arg = TREE_CHAIN (arg))
+	nargs++;
+      cfun->machine->func_type = nargs == 2 ? TYPE_EXCEPTION : TYPE_INTERRUPT;
+
+      ix86_optimize_mode_switching[X86_DIRFLAG] = 1;
+
+      /* Only dwarf2out.cc can handle -WORD(AP) as a pointer argument.  */
+      if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG)
+	sorry ("only DWARF debug format is supported for interrupt "
+	       "service routine");
     }
+  else
+    cfun->machine->func_type = TYPE_NORMAL;
 }
 
 /* Set the indirect_branch_type field from the function FNDECL.  */
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index d11fa2df35d7..870dcb68d2f2 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -47,6 +47,8 @@ extern enum calling_abi ix86_function_type_abi (const_tree);
 extern bool ix86_use_pseudo_pic_reg (void);
 
 extern void ix86_reset_previous_fndecl (void);
+extern call_saved_registers_type
+  ix86_fntype_call_saved_registers (const_tree, location_t * = nullptr);
 
 extern bool ix86_using_red_zone (void);
 
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 01cab02f0d37..2e5a225574b9 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -933,12 +933,10 @@ x86_64_elf_unique_section (tree decl, int reloc)
    attribute.  */
 
 bool
-ix86_type_no_callee_saved_registers_p (const_tree type)
+ix86_type_no_callee_saved_registers_p (const_tree fntype)
 {
-  return (lookup_attribute ("no_callee_saved_registers",
-			    TYPE_ATTRIBUTES (type)) != NULL
-	  || lookup_attribute ("preserve_none",
-			       TYPE_ATTRIBUTES (type)) != NULL);
+  auto type = ix86_fntype_call_saved_registers (fntype);
+  return type == TYPE_PRESERVE_NONE || type == TYPE_NO_CALLEE_SAVED_REGISTERS;
 }
 
 #ifdef COMMON_ASM_OP
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.