OSDN Git Service

* gcc.dg/i386-local.c: New.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Mar 2003 01:33:27 +0000 (01:33 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 5 Mar 2003 01:33:27 +0000 (01:33 +0000)
* toplev.c (rest_of_compilation):  Deffer RTL compilation only when
RTL inlining is done.

* cgraphunit.c (cgraph_mark_local_functions): New local function.
(cgraph_optimize): Mark local functions.
* i386-protos.h (init_cumulative_args): Update prototype.
* i386.c (init_cumulative_args): Use register passing convention for
local functions.

* cgraph.c (cgraph_global_info_ready): New global variable
(cgraph_local_info, cgraph_global_info): New functions.
* cgraph.h (struct cgraph_local_info, cgraph_global_info): New
structures.
(cgraph_local_info, cgraph_global_info, cgraph_global_info_ready):
Declare.
* cgraphunit.c (cgraph_finalize_function): Set inline_many.
(cgraph_mark_functions_to_output): Use inline_many.
(cgraph_expand_function): Free DECL_SAVED_TREE uncondtionally.
(cgraph_expand_functions): Expand inline functions last.
(cgraph_optimize): Do not emit uneeded functions.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@63822 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/i386-local.c [new file with mode: 0644]
gcc/toplev.c

index 07a7c49..4d30aba 100644 (file)
@@ -1,3 +1,26 @@
+Wed Mar  5 02:04:04 CET 2003  Jan Hubicka  <jh@suse.cz>
+
+       * toplev.c (rest_of_compilation):  Deffer RTL compilation only when
+       RTL inlining is done.
+
+       * cgraphunit.c (cgraph_mark_local_functions): New local function.
+       (cgraph_optimize): Mark local functions.
+       * i386-protos.h (init_cumulative_args): Update prototype.
+       * i386.c (init_cumulative_args): Use register passing convention for
+       local functions.
+
+       * cgraph.c (cgraph_global_info_ready): New global variable
+       (cgraph_local_info, cgraph_global_info): New functions.
+       * cgraph.h (struct cgraph_local_info, cgraph_global_info): New
+       structures.
+       (cgraph_local_info, cgraph_global_info, cgraph_global_info_ready):
+       Declare.
+       * cgraphunit.c (cgraph_finalize_function): Set inline_many.
+       (cgraph_mark_functions_to_output): Use inline_many.
+       (cgraph_expand_function): Free DECL_SAVED_TREE uncondtionally.
+       (cgraph_expand_functions): Expand inline functions last.
+       (cgraph_optimize): Do not emit uneeded functions.
+
 2003-03-04  Steve Ellcey  <sje@cup.hp.com>
 
        * expr.c (convert_modes): Check for legal hard register.
index 7df18f1..d947eb9 100644 (file)
@@ -43,6 +43,9 @@ struct cgraph_node *cgraph_nodes;
 /* Number of nodes in existence.  */
 int cgraph_n_nodes;
 
+/* Set when whole unit has been analyzed so we can access global info.  */
+bool cgraph_global_info_ready = false;
+
 static struct cgraph_edge *create_edge PARAMS ((struct cgraph_node *,
                                                struct cgraph_node *));
 static void remove_edge PARAMS ((struct cgraph_node *, struct cgraph_node *));
@@ -175,6 +178,33 @@ cgraph_calls_p (caller_decl, callee_decl)
   return edge != NULL;
 }
 
+/* Return local info for the compiled function.  */
+
+struct cgraph_local_info *
+cgraph_local_info (decl)
+     tree decl;
+{
+  struct cgraph_node *node;
+  if (TREE_CODE (decl) != FUNCTION_DECL)
+    abort ();
+  node = cgraph_node (decl);
+  return &node->local;
+}
+
+/* Return local info for the compiled function.  */
+
+struct cgraph_global_info *
+cgraph_global_info (decl)
+     tree decl;
+{
+  struct cgraph_node *node;
+  if (TREE_CODE (decl) != FUNCTION_DECL || !cgraph_global_info_ready)
+    abort ();
+  node = cgraph_node (decl);
+  return &node->global;
+}
+
+
 /* Dump the callgraph.  */
 
 void
index 8dd37ed..4404fb8 100644 (file)
@@ -22,6 +22,27 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #ifndef GCC_CGRAPH_H
 #define GCC_CGRAPH_H
 
+/* Information about the function collected locally.
+   Available after function is lowered  */
+
+struct cgraph_local_info
+{
+  /* Set when function function is visiable in current compilation unit only
+     and it's address is never taken.  */
+  bool local;
+  bool inline_many;
+};
+
+/* Information about the function that needs to be computed globally
+   once compilation is finished.  Available only with -funit-at-time.  */
+
+struct cgraph_global_info
+{
+  /* Empty for the moment.  */
+  int dummy;
+};
+
+
 /* The cgraph data strutcture.
    Each function decl has assigned cgraph_node listing calees and callers.  */
 
@@ -51,6 +72,8 @@ struct cgraph_node
   bool lowered;
   /* Set when function is scheduled to be assembled.  */
   bool output;
+  struct cgraph_local_info local;
+  struct cgraph_global_info global;
 };
 
 struct cgraph_edge
@@ -62,6 +85,7 @@ struct cgraph_edge
 
 extern struct cgraph_node *cgraph_nodes;
 extern int cgraph_n_nodes;
+extern bool cgraph_global_info_ready;
 
 /* In cgraph.c  */
 void dump_cgraph                       PARAMS ((FILE *));
@@ -69,6 +93,8 @@ void cgraph_remove_call                       PARAMS ((tree, tree));
 struct cgraph_edge *cgraph_record_call PARAMS ((tree, tree));
 struct cgraph_node *cgraph_node                PARAMS ((tree decl));
 bool cgraph_calls_p                    PARAMS ((tree, tree));
+struct cgraph_local_info *cgraph_local_info PARAMS ((tree));
+struct cgraph_global_info *cgraph_global_info PARAMS ((tree));
 
 /* In cgraphunit.c  */
 void cgraph_finalize_function          PARAMS ((tree, tree));
index 0a12dda..81a8b2e 100644 (file)
@@ -33,11 +33,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "debug.h"
 #include "target.h"
 #include "cgraph.h"
+#include "diagnostic.h"
 
 static void cgraph_expand_functions PARAMS ((void));
 static void cgraph_mark_functions_to_output PARAMS ((void));
 static void cgraph_expand_function PARAMS ((struct cgraph_node *));
 static tree record_call_1 PARAMS ((tree *, int *, void *));
+static void cgraph_mark_local_functions PARAMS ((void));
 
 /* Analyze function once it is parsed.  Set up the local information
    available - create cgraph edges for function calles via BODY.  */
@@ -51,8 +53,10 @@ cgraph_finalize_function (decl, body)
 
   node->decl = decl;
 
-  /* Set TREE_UNINLINABLE flag.  */
-  tree_inlinable_function_p (decl);
+  if (flag_inline_trees)
+    node->local.inline_many = tree_inlinable_function_p (decl);
+  else
+    node->local.inline_many = 0;
 
   (*debug_hooks->deferred_inline_function) (decl);
 }
@@ -217,7 +221,7 @@ cgraph_mark_functions_to_output ()
 
       if (DECL_SAVED_TREE (decl)
          && (node->needed
-             || (DECL_UNINLINABLE (decl) && node->reachable)
+             || (!node->local.inline_many && node->reachable)
              || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
          && !TREE_ASM_WRITTEN (decl) && !node->origin
          && !DECL_EXTERNAL (decl))
@@ -235,6 +239,8 @@ cgraph_expand_function (node)
   announce_function (decl);
   if (flag_inline_trees)
     optimize_inline_calls (decl);
+
+  /* Avoid RTL inlining from taking place.  */
   (*lang_hooks.callgraph.expand_function) (decl);
   if (DECL_UNINLINABLE (decl))
     DECL_SAVED_TREE (decl) = NULL;
@@ -325,6 +331,30 @@ cgraph_expand_functions ()
   free (order);
 }
 
+/* Mark all local functions.
+   We can not use node->needed directly as it is modified during
+   execution of cgraph_optimize.  */
+
+static void
+cgraph_mark_local_functions ()
+{
+  struct cgraph_node *node;
+
+  if (!quiet_flag)
+    fprintf (stderr, "\n\nMarking local functions:");
+
+  /* Figure out functions we want to assemble.  */
+  for (node = cgraph_nodes; node; node = node->next)
+    {
+      node->local.local = (!node->needed
+                          && DECL_SAVED_TREE (node->decl)
+                          && !TREE_PUBLIC (node->decl));
+      if (node->local.local)
+       announce_function (node->decl);
+    }
+}
+
+
 /* Perform simple optimizations based on callgraph.  */
 
 void
@@ -332,8 +362,10 @@ cgraph_optimize ()
 {
   struct cgraph_node *node;
   bool changed = true;
-  struct cgraph_edge *edge;
 
+  cgraph_mark_local_functions ();
+
+  cgraph_global_info_ready = true;
   if (!quiet_flag)
     fprintf (stderr, "\n\nAssembling functions:");
 
@@ -343,18 +375,29 @@ cgraph_optimize ()
      Later we should move all inlining decisions to callgraph code to make
      this impossible.  */
   cgraph_expand_functions ();
-  while (changed)
+  if (!quiet_flag)
+    fprintf (stderr, "\n\nAssembling functions that failed to inline:");
+  while (changed && !errorcount && !sorrycount)
     {
       changed = false;
       for (node = cgraph_nodes; node; node = node->next)
        {
-         if (!node->needed)
-           continue;
-
-         for (edge = node->callees; edge; edge = edge->next_callee)
-           if (!edge->callee->needed)
-             changed = edge->callee->needed = true;
+         tree decl = node->decl;
+         if (!node->origin
+             && !TREE_ASM_WRITTEN (decl)
+             && DECL_SAVED_TREE (decl)
+             && !DECL_EXTERNAL (decl))
+           {
+             struct cgraph_edge *edge;
+
+             for (edge = node->callers; edge; edge = edge->next_caller)
+               if (TREE_ASM_WRITTEN (edge->caller->decl))
+                 {
+                   changed = true;
+                   cgraph_expand_function (node);
+                   break;
+                 }
+           }
        }
     }
-  cgraph_expand_functions ();
 }
index b83aae7..beafa79 100644 (file)
@@ -194,7 +194,7 @@ extern void x86_emit_floatuns PARAMS ((rtx [2]));
 
 
 #ifdef TREE_CODE
-extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx));
+extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx, tree));
 extern rtx function_arg PARAMS ((CUMULATIVE_ARGS *, enum machine_mode, tree, int));
 extern int function_arg_pass_by_reference PARAMS ((CUMULATIVE_ARGS *,
                                                   enum machine_mode,
@@ -226,6 +226,7 @@ extern int x86_field_alignment PARAMS ((tree, int));
 
 extern rtx ix86_tls_get_addr PARAMS ((void));
 extern void x86_machine_dependent_reorg PARAMS ((rtx));
+extern bool ix86_must_pass_in_stack PARAMS ((enum machine_mode mode, tree));
 
 /* In winnt.c  */
 extern int i386_pe_dllexport_name_p PARAMS ((const char *));
index 81d6437..639ea1b 100644 (file)
@@ -45,6 +45,7 @@ Boston, MA 02111-1307, USA.  */
 #include "target.h"
 #include "target-def.h"
 #include "langhooks.h"
+#include "cgraph.h"
 
 #ifndef CHECK_STACK_LIMIT
 #define CHECK_STACK_LIMIT (-1)
@@ -1765,13 +1766,15 @@ ix86_function_arg_regno_p (regno)
    For a library call, FNTYPE is 0.  */
 
 void
-init_cumulative_args (cum, fntype, libname)
+init_cumulative_args (cum, fntype, libname, fndecl)
      CUMULATIVE_ARGS *cum;     /* Argument info to initialize */
      tree fntype;              /* tree ptr for function decl */
      rtx libname;              /* SYMBOL_REF of library name or 0 */
+     tree fndecl;
 {
   static CUMULATIVE_ARGS zero_cum;
   tree param, next_param;
+  bool user_convention = false;
 
   if (TARGET_DEBUG_ARG)
     {
@@ -1797,7 +1800,10 @@ init_cumulative_args (cum, fntype, libname)
       tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype));
 
       if (attr)
-       cum->nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
+       {
+         cum->nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
+         user_convention = true;
+       }
     }
   cum->maybe_vaarg = false;
 
@@ -1808,6 +1814,23 @@ init_cumulative_args (cum, fntype, libname)
        {
          cum->nregs = 2;
          cum->fastcall = 1;
+         user_convention = true;
+       }
+    }
+
+  /* Use register calling convention for local functions when possible.  */
+  if (!TARGET_64BIT && !user_convention && fndecl
+      && flag_unit_at_a_time)
+    {
+      struct cgraph_local_info *i = cgraph_local_info (fndecl);
+      if (i && i->local)
+       {
+         /* We can't use regparm(3) for nested functions as these use
+            static chain pointer in third argument.  */
+         if (DECL_CONTEXT (fndecl) && !DECL_NO_STATIC_CHAIN (fndecl))
+           cum->nregs = 2;
+         else
+           cum->nregs = 3;
        }
     }
 
@@ -1914,6 +1937,10 @@ classify_argument (mode, type, classes, bit_offset)
   if (bytes < 0)
     return 0;
 
+  if (mode != VOIDmode
+      && MUST_PASS_IN_STACK (mode, type))
+    return 0;
+
   if (type && AGGREGATE_TYPE_P (type))
     {
       int i;
@@ -15639,4 +15666,15 @@ x86_emit_floatuns (operands)
   emit_label (donelab);
 }
 
+/* Return if we do not know how to pass TYPE solely in registers.  */
+bool
+ix86_must_pass_in_stack (mode, type)
+       enum machine_mode mode;
+       tree type;
+{
+   if (default_must_pass_in_stack (mode, type))
+     return true;
+   return (!TARGET_64BIT && type && mode == TImode);
+}
+
 #include "gt-i386.h"
index e5daa5d..4b21c86 100644 (file)
@@ -1664,18 +1664,7 @@ enum reg_class
    definition that is usually appropriate, refer to expr.h for additional
    documentation. If `REG_PARM_STACK_SPACE' is defined, the argument will be
    computed in the stack and then loaded into a register.  */
-#define MUST_PASS_IN_STACK(MODE, TYPE)                         \
-  ((TYPE) != 0                                                 \
-   && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST             \
-       || TREE_ADDRESSABLE (TYPE)                              \
-       || ((MODE) == TImode)                                   \
-       || ((MODE) == BLKmode                                   \
-          && ! ((TYPE) != 0                                    \
-                && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
-                && 0 == (int_size_in_bytes (TYPE)              \
-                         % (PARM_BOUNDARY / BITS_PER_UNIT)))   \
-          && (FUNCTION_ARG_PADDING (MODE, TYPE)                \
-              == (BYTES_BIG_ENDIAN ? upward : downward)))))
+#define MUST_PASS_IN_STACK(MODE, TYPE)  ix86_must_pass_in_stack ((MODE), (TYPE))
 
 /* Value is the number of bytes of arguments automatically
    popped when returning from a subroutine call.
@@ -1743,8 +1732,8 @@ typedef struct ix86_args {
    for a call to a function whose data type is FNTYPE.
    For a library call, FNTYPE is 0.  */
 
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
-  init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME))
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL) \
+  init_cumulative_args (&(CUM), (FNTYPE), (LIBNAME), (FNDECL))
 
 /* Update the data in CUM to advance over an argument
    of mode MODE and data type TYPE.
index 54a283c..c779bfb 100644 (file)
@@ -3521,8 +3521,8 @@ invoking @option{-O2} on programs that use computed gotos.
 @item -O3
 @opindex O3
 Optimize yet more.  @option{-O3} turns on all optimizations specified by
-@option{-O2} and also turns on the @option{-finline-functions} and
-@option{-frename-registers} options.
+@option{-O2} and also turns on the @option{-finline-functions},
+@option{-funit-at-a-time} and @option{-frename-registers} options.
 
 @item -O0
 @opindex O0
index 043908a..b67b566 100644 (file)
@@ -1,3 +1,7 @@
+Wed Mar  5 02:05:19 CET 2003  Jan Hubicka  <jh@suse.cz>
+
+       * gcc.dg/i386-local.c: New.
+
 Tue Mar  4 19:39:18 2003  J"orn Rennecke <joern.rennecke@superh.com>
 
        * gcc.dg/sh-relax.c: Disable for sh64-*-*.
diff --git a/gcc/testsuite/gcc.dg/i386-local.c b/gcc/testsuite/gcc.dg/i386-local.c
new file mode 100644 (file)
index 0000000..ed4cef3
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -funit-at-a-time" } */
+/* { dg-final { scan-assembler "magic.*eax" } } */
+
+/* Verify that local calling convention is used.  */
+static t(int) __attribute__ ((noinline));
+m()
+{
+       t(1);
+}
+static t(int a)
+{
+       asm("magic %1"::"g"(a));
+}
index e6c67d8..2dbdf4f 100644 (file)
@@ -2518,6 +2518,7 @@ rest_of_compilation (decl)
 
       if (inlinable
          || (DECL_INLINE (decl)
+             && flag_inline_functions
              && ((! TREE_PUBLIC (decl) && ! TREE_ADDRESSABLE (decl)
                   && ! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
                   && ! flag_keep_inline_functions)