From: Richard Sandiford <[email protected]>

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.
---
 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 f7282dbe36f..626e1eab929 100644
--- a/gcc/config/i386/i386-options.cc
+++ b/gcc/config/i386/i386-options.cc
@@ -3267,13 +3267,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
@@ -3289,74 +3329,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 10bb1e421e9..7dac3ed8e6c 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 8cd6701ca4f..4c8b7840fc3 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
-- 
2.54.0

Reply via email to