This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Make cgraph_node smaller


Hi,

This is a first round in an attempt to trim `struct cgraph_node' to something 
smaller.  IMHO it is way too big as it is now: 80 bytes per node.  This patch 
trims that to 68 with still some room for improvement.

At present this makes no difference in compile time or memory use, because the 
cgraph nodes still go into the 88 byte special page order.  Eventually I want 
to trim this struct to less than 64 bytes, which would make the call graph 
smaller.

Bootstrapped c, c++, objc and java, and tested c and c++.  OK?

Gr.
Steven

2003-11-17  Steven Bosscher  <stevenb@suse.de>

	* cgraph.h (struct cgraph_local_info, struct cgraph_global_info,
	cgraph_rtl_info): Unify, replace with a single struct...
	(struct cgraph_function_info): ...this.  Use bitfields instead of
	bools.
	(cgraph_local_info, cgraph_global_info, cgraph_rtl_info): Update
	prototypes.
	* cgraph.c (cgraph_local_info, cgraph_global_info, cgraph_rtl_info):
	Update comment; return pointer to cgraph_function_info after making
	sure the requested information is indeed available.
	(cgraph_mark_reachable_node, cgraph_function_possibly_inlined_p,
	dump_cgraph): Update users these structs.
	* cgraphunit.c (decide_is_function_needed, cgraph_finalize_function,
	cgraph_analyze_function, cgraph_estimate_size_after_inlining,
	cgraph_estimate_growth, cgraph_mark_inline,
	graph_check_inline_limits, cgraph_default_inline_p,
	cgraph_decide_inlining_of_small_function, cgraph_decide_inlining,
	cgraph_decide_inlining_incrementally, cgraph_mark_local_functions):
	Likewise.
	* calls.c (flags_from_decl_or_type, expand_call): Likewise.
	* config/i386/i386.c (ix86_function_regparm): Likewise.

cp/
	* decl2.c (finish_file): Use the cgraph_local_info() abstraction
	instead of accessing call graph nodes directly.
Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.305
diff -c -3 -p -r1.305 calls.c
*** calls.c	14 Nov 2003 08:19:59 -0000	1.305
--- calls.c	16 Nov 2003 21:46:50 -0000
*************** flags_from_decl_or_type (tree exp)
*** 701,707 ****
  
    if (DECL_P (exp))
      {
!       struct cgraph_rtl_info *i = cgraph_rtl_info (exp);
        type = TREE_TYPE (exp);
  
        if (i)
--- 701,707 ----
  
    if (DECL_P (exp))
      {
!       struct cgraph_function_info *i = cgraph_rtl_info (exp);
        type = TREE_TYPE (exp);
  
        if (i)
*************** expand_call (tree exp, rtx target, int i
*** 2313,2319 ****
    preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
    if (fndecl)
      {
!       struct cgraph_rtl_info *i = cgraph_rtl_info (fndecl);
        if (i && i->preferred_incoming_stack_boundary)
  	preferred_stack_boundary = i->preferred_incoming_stack_boundary;
      }
--- 2313,2319 ----
    preferred_stack_boundary = PREFERRED_STACK_BOUNDARY;
    if (fndecl)
      {
!       struct cgraph_function_info *i = cgraph_rtl_info (fndecl);
        if (i && i->preferred_incoming_stack_boundary)
  	preferred_stack_boundary = i->preferred_incoming_stack_boundary;
      }
Index: cgraph.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.36
diff -c -3 -p -r1.36 cgraph.c
*** cgraph.c	13 Nov 2003 02:07:52 -0000	1.36
--- cgraph.c	16 Nov 2003 21:46:51 -0000
*************** cgraph_remove_node (struct cgraph_node *
*** 238,244 ****
  void
  cgraph_mark_reachable_node (struct cgraph_node *node)
  {
!   if (!node->reachable && node->local.finalized)
      {
        notice_global_symbol (node->decl);
        node->reachable = 1;
--- 238,244 ----
  void
  cgraph_mark_reachable_node (struct cgraph_node *node)
  {
!   if (!node->reachable && node->function_info.finalized)
      {
        notice_global_symbol (node->decl);
        node->reachable = 1;
*************** cgraph_calls_p (tree caller_decl, tree c
*** 297,329 ****
    return edge != NULL;
  }
  
! /* Return local info for the compiled function.  */
  
! struct cgraph_local_info *
  cgraph_local_info (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 (tree decl)
  {
    struct cgraph_node *node;
    if (TREE_CODE (decl) != FUNCTION_DECL || !cgraph_global_info_ready)
      abort ();
    node = cgraph_node (decl);
!   return &node->global;
  }
  
! /* Return local info for the compiled function.  */
  
! struct cgraph_rtl_info *
  cgraph_rtl_info (tree decl)
  {
    struct cgraph_node *node;
--- 297,332 ----
    return edge != NULL;
  }
  
! /* Return info for the compiled function, and make sure that
!    the local information is available.  */
  
! struct cgraph_function_info *
  cgraph_local_info (tree decl)
  {
    struct cgraph_node *node;
    if (TREE_CODE (decl) != FUNCTION_DECL)
      abort ();
    node = cgraph_node (decl);
!   return &node->function_info;
  }
  
! /* Return info for the compiled function, and make sure that
!    the global information is available.  */
  
! struct cgraph_function_info *
  cgraph_global_info (tree decl)
  {
    struct cgraph_node *node;
    if (TREE_CODE (decl) != FUNCTION_DECL || !cgraph_global_info_ready)
      abort ();
    node = cgraph_node (decl);
!   return &node->function_info;
  }
  
! /* Return info for the compiled function, and make sure that
!    the information collected in the RTL backend is available.  */
  
! struct cgraph_function_info *
  cgraph_rtl_info (tree decl)
  {
    struct cgraph_node *node;
*************** cgraph_rtl_info (tree decl)
*** 333,339 ****
    if (decl != current_function_decl
        && !TREE_ASM_WRITTEN (node->decl))
      return NULL;
!   return &node->rtl;
  }
  
  /* Return name of the node used in debug output.  */
--- 336,342 ----
    if (decl != current_function_decl
        && !TREE_ASM_WRITTEN (node->decl))
      return NULL;
!   return &node->function_info;
  }
  
  /* Return name of the node used in debug output.  */
*************** dump_cgraph (FILE *f)
*** 355,364 ****
      {
        struct cgraph_edge *edge;
        fprintf (f, "%s:", cgraph_node_name (node));
!       if (node->local.self_insns)
!         fprintf (f, " %i insns", node->local.self_insns);
!       if (node->global.insns && node->global.insns != node->local.self_insns)
! 	fprintf (f, " (%i after inlining)", node->global.insns);
        if (node->origin)
  	fprintf (f, " nested in: %s", cgraph_node_name (node->origin));
        if (node->needed)
--- 358,368 ----
      {
        struct cgraph_edge *edge;
        fprintf (f, "%s:", cgraph_node_name (node));
!       if (node->function_info.self_insns)
!         fprintf (f, " %i insns", node->function_info.self_insns);
!       if (node->function_info.insns
! 	  && node->function_info.insns != node->function_info.self_insns)
! 	fprintf (f, " (%i after inlining)", node->function_info.insns);
        if (node->origin)
  	fprintf (f, " nested in: %s", cgraph_node_name (node->origin));
        if (node->needed)
*************** dump_cgraph (FILE *f)
*** 368,381 ****
        if (DECL_SAVED_TREE (node->decl))
  	fprintf (f, " tree");
  
!       if (node->local.local)
  	fprintf (f, " local");
!       if (node->local.disregard_inline_limits)
  	fprintf (f, " always_inline");
!       else if (node->local.inlinable)
  	fprintf (f, " inlinable");
!       if (node->global.cloned_times > 1)
! 	fprintf (f, " cloned %ix", node->global.cloned_times);
  
        fprintf (f, "\n  called by: ");
        for (edge = node->callers; edge; edge = edge->next_caller)
--- 372,385 ----
        if (DECL_SAVED_TREE (node->decl))
  	fprintf (f, " tree");
  
!       if (node->function_info.local)
  	fprintf (f, " local");
!       if (node->function_info.disregard_inline_limits)
  	fprintf (f, " always_inline");
!       else if (node->function_info.inlinable)
  	fprintf (f, " inlinable");
!       if (node->function_info.cloned_times > 1)
! 	fprintf (f, " cloned %ix", node->function_info.cloned_times);
  
        fprintf (f, "\n  called by: ");
        for (edge = node->callers; edge; edge = edge->next_caller)
*************** cgraph_function_possibly_inlined_p (tree
*** 613,619 ****
  {
    if (!cgraph_global_info_ready)
      return (DECL_INLINE (decl) && !flag_really_no_inline);
!   return cgraph_node (decl)->global.inlined;
  }
  
  #include "gt-cgraph.h"
--- 617,623 ----
  {
    if (!cgraph_global_info_ready)
      return (DECL_INLINE (decl) && !flag_really_no_inline);
!   return cgraph_node (decl)->function_info.inlined;
  }
  
  #include "gt-cgraph.h"
Index: cgraph.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.h,v
retrieving revision 1.23
diff -c -3 -p -r1.23 cgraph.h
*** cgraph.h	22 Oct 2003 11:58:09 -0000	1.23
--- cgraph.h	16 Nov 2003 21:46:51 -0000
*************** Software Foundation, 59 Temple Place - S
*** 22,53 ****
  #ifndef GCC_CGRAPH_H
  #define GCC_CGRAPH_H
  
! /* Information about the function collected locally.
!    Available after function is analyzed.  */
  
! struct cgraph_local_info GTY(())
! {
!   /* Set when function function is visible in current compilation unit only
!      and it's address is never taken.  */
!   bool local;
!   /* Set once it has been finalized so we consider it to be output.  */
!   bool finalized;
  
!   /* False when there something makes inlining impossible (such as va_arg).  */
!   bool inlinable;
!   /* True when function should be inlined independently on it's size.  */
!   bool disregard_inline_limits;
    /* Size of the function before inlining.  */
    int self_insns;
- };
- 
- /* Information about the function that needs to be computed globally
-    once compilation is finished.  Available only with -funit-at-time.  */
- 
- struct cgraph_global_info GTY(())
- {
-   /* Set when the function will be inlined exactly once.  */
-   bool inline_once;
  
    /* Estimated size of the function after inlining.  */
    int insns;
--- 22,49 ----
  #ifndef GCC_CGRAPH_H
  #define GCC_CGRAPH_H
  
! /* Information about a function.  This struct is filled in three
!    different stages of the compilation process.
  
!    Some information is collected locally, and is available after the
!    function is analyzed:
!    self_insns, local, finalized, inlinable, disregard_inline_limits.
! 
!    Some fields are computed computed globally once the front end is
!    finished and the compilation unit is finalized (available only
!    with -funit-at-time, and when the cgraph_global_info flag is set
!    to true):
!    insns, cloned_times, will_be_output, inlned, inlined_once.
! 
!    Finally, some information about the function is propagated by the
!    RTL backend, and is therefore only available for functions that
!    have already been assembled:
!    preferred_incoming_stack_boundary, pure_function, const_function.  */
  
! struct cgraph_function_info GTY(())
! {
    /* Size of the function before inlining.  */
    int self_insns;
  
    /* Estimated size of the function after inlining.  */
    int insns;
*************** struct cgraph_global_info GTY(())
*** 55,80 ****
    /* Number of times given function will be cloned during output.  */
    int cloned_times;
  
    /* Set to true for all reachable functions before inlining is decided.
       Once we inline all calls to the function and the function is local,
       it is set to false.  */
!   bool will_be_output;
  
    /* Set iff at least one of the caller edges has inline_call flag set.  */
!   bool inlined;
! };
  
! /* Information about the function that is propagated by the RTL backend.
!    Available only for functions that has been already assembled.  */
  
! struct cgraph_rtl_info GTY(())
! {
!    bool const_function;
!    bool pure_function;
!    int preferred_incoming_stack_boundary;
  };
  
- 
  /* The cgraph data strutcture.
     Each function decl has assigned cgraph_node listing callees and callers.  */
  
--- 51,93 ----
    /* Number of times given function will be cloned during output.  */
    int cloned_times;
  
+   /* Set to the number to which the stack should be aligned.  */
+   int preferred_incoming_stack_boundary;
+ 
+   /* Set when function function is visible in current compilation unit only
+      and it's address is never taken.  */
+   unsigned local : 1;
+ 
+   /* Set once it has been finalized so we consider it to be output.  */
+   unsigned finalized : 1;
+ 
+   /* False when there something makes inlining impossible (such as va_arg).  */
+   unsigned inlinable : 1;
+ 
+   /* True when function should be inlined independently on it's size.  */
+   unsigned disregard_inline_limits : 1;
+ 
    /* Set to true for all reachable functions before inlining is decided.
       Once we inline all calls to the function and the function is local,
       it is set to false.  */
!   unsigned will_be_output : 1;
  
    /* Set iff at least one of the caller edges has inline_call flag set.  */
!   unsigned inlined : 1;
  
!   /* Set when the function will be inlined exactly once.  */
!   unsigned inline_once : 1;
  
!   /* Set iff a function is found to be a pure function, i.e. its result only
!      depends on its arguments and/or global variables.  */
!   unsigned pure_function : 1;
! 
!   /* Set iff a function is found to be a const function, i.e. it does not
!      examine any values except their arguments, which completely determine
!      the function return value.  */
!   unsigned const_function : 1;
  };
  
  /* The cgraph data strutcture.
     Each function decl has assigned cgraph_node listing callees and callers.  */
  
*************** struct cgraph_node GTY((chain_next ("%h.
*** 85,116 ****
    struct cgraph_edge *callers;
    struct cgraph_node *next;
    struct cgraph_node *previous;
    /* For nested functions points to function the node is nested in.  */
    struct cgraph_node *origin;
    /* Points to first nested function, if any.  */
    struct cgraph_node *nested;
    /* Pointer to the next function with same origin, if any.  */
    struct cgraph_node *next_nested;
    /* Pointer to the next function in cgraph_nodes_queue.  */
    struct cgraph_node *next_needed;
    /* Unique id of the node.  */
    int uid;
    PTR GTY ((skip (""))) aux;
  
    /* Set when function must be output - it is externally visible
       or it's address is taken.  */
!   bool needed;
    /* Set when function is reachable by call from other function
       that is either reachable or needed.  */
!   bool reachable;
    /* Set once the function has been instantiated and its callee
       lists created.  */
!   bool analyzed;
    /* Set when function is scheduled to be assembled.  */
!   bool output;
!   struct cgraph_local_info local;
!   struct cgraph_global_info global;
!   struct cgraph_rtl_info rtl;
  };
  
  struct cgraph_edge GTY(())
--- 98,140 ----
    struct cgraph_edge *callers;
    struct cgraph_node *next;
    struct cgraph_node *previous;
+ 
    /* For nested functions points to function the node is nested in.  */
    struct cgraph_node *origin;
+ 
    /* Points to first nested function, if any.  */
    struct cgraph_node *nested;
+ 
    /* Pointer to the next function with same origin, if any.  */
    struct cgraph_node *next_nested;
+ 
    /* Pointer to the next function in cgraph_nodes_queue.  */
    struct cgraph_node *next_needed;
+ 
    /* Unique id of the node.  */
    int uid;
+ 
+   /* Pointer for various purposes including sorting the nodes and
+      keeping track of how many times a function is inlined.  */
    PTR GTY ((skip (""))) aux;
  
+   /* Information about this function.  */
+   struct cgraph_function_info function_info;
+ 
    /* Set when function must be output - it is externally visible
       or it's address is taken.  */
!   unsigned needed : 1;
! 
    /* Set when function is reachable by call from other function
       that is either reachable or needed.  */
!   unsigned reachable : 1;
! 
    /* Set once the function has been instantiated and its callee
       lists created.  */
!   unsigned analyzed : 1;
! 
    /* Set when function is scheduled to be assembled.  */
!   unsigned output : 1;
  };
  
  struct cgraph_edge GTY(())
*************** struct cgraph_edge *cgraph_record_call (
*** 160,168 ****
  struct cgraph_node *cgraph_node (tree decl);
  struct cgraph_node *cgraph_node_for_identifier (tree id);
  bool cgraph_calls_p (tree, tree);
! struct cgraph_local_info *cgraph_local_info (tree);
! struct cgraph_global_info *cgraph_global_info (tree);
! struct cgraph_rtl_info *cgraph_rtl_info (tree);
  const char * cgraph_node_name (struct cgraph_node *);
  
  struct cgraph_varpool_node *cgraph_varpool_node (tree decl);
--- 184,192 ----
  struct cgraph_node *cgraph_node (tree decl);
  struct cgraph_node *cgraph_node_for_identifier (tree id);
  bool cgraph_calls_p (tree, tree);
! struct cgraph_function_info *cgraph_local_info (tree);
! struct cgraph_function_info *cgraph_global_info (tree);
! struct cgraph_function_info *cgraph_rtl_info (tree);
  const char * cgraph_node_name (struct cgraph_node *);
  
  struct cgraph_varpool_node *cgraph_varpool_node (tree decl);
Index: cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.38
diff -c -3 -p -r1.38 cgraphunit.c
*** cgraphunit.c	9 Nov 2003 02:37:54 -0000	1.38
--- cgraphunit.c	16 Nov 2003 21:46:54 -0000
*************** decide_is_function_needed (struct cgraph
*** 111,121 ****
    if (DECL_COMDAT (decl))
      return false;
    if (!DECL_INLINE (decl)
!       || (!node->local.disregard_inline_limits
  	  /* When declared inline, defer even the uninlinable functions.
  	     This allows them to be eliminated when unused.  */
  	  && !DECL_DECLARED_INLINE_P (decl) 
! 	  && (!node->local.inlinable || !cgraph_default_inline_p (node))))
      return true;
  
    return false;
--- 111,122 ----
    if (DECL_COMDAT (decl))
      return false;
    if (!DECL_INLINE (decl)
!       || (!node->function_info.disregard_inline_limits
  	  /* When declared inline, defer even the uninlinable functions.
  	     This allows them to be eliminated when unused.  */
  	  && !DECL_DECLARED_INLINE_P (decl) 
! 	  && (!node->function_info.inlinable
! 	      || !cgraph_default_inline_p (node))))
      return true;
  
    return false;
*************** cgraph_finalize_function (tree decl, boo
*** 157,163 ****
  {
    struct cgraph_node *node = cgraph_node (decl);
  
!   if (node->local.finalized)
      {
        /* As an GCC extension we allow redefinition of the function.  The
  	 semantics when both copies of bodies differ is not well defined.
--- 158,164 ----
  {
    struct cgraph_node *node = cgraph_node (decl);
  
!   if (node->function_info.finalized)
      {
        /* As an GCC extension we allow redefinition of the function.  The
  	 semantics when both copies of bodies differ is not well defined.
*************** cgraph_finalize_function (tree decl, boo
*** 179,187 ****
  	abort ();
  
        /* Reset our datastructures so we can analyze the function again.  */
!       memset (&node->local, 0, sizeof (node->local));
!       memset (&node->global, 0, sizeof (node->global));
!       memset (&node->rtl, 0, sizeof (node->rtl));
        node->analyzed = false;
        while (node->callees)
  	cgraph_remove_edge (node, node->callees->callee);
--- 180,186 ----
  	abort ();
  
        /* Reset our datastructures so we can analyze the function again.  */
!       memset (&node->function_info, 0, sizeof (node->function_info));
        node->analyzed = false;
        while (node->callees)
  	cgraph_remove_edge (node, node->callees->callee);
*************** cgraph_finalize_function (tree decl, boo
*** 202,208 ****
  
    notice_global_symbol (decl);
    node->decl = decl;
!   node->local.finalized = true;
  
    /* If not unit at a time, then we need to create the call graph
       now, so that called functions can be queued and emitted now.  */
--- 201,207 ----
  
    notice_global_symbol (decl);
    node->decl = decl;
!   node->function_info.finalized = true;
  
    /* If not unit at a time, then we need to create the call graph
       now, so that called functions can be queued and emitted now.  */
*************** cgraph_analyze_function (struct cgraph_n
*** 317,337 ****
    /* First kill forward declaration so reverse inlining works properly.  */
    cgraph_create_edges (decl, DECL_SAVED_TREE (decl));
  
!   node->local.inlinable = tree_inlinable_function_p (decl);
    if (!DECL_ESTIMATED_INSNS (decl))
      DECL_ESTIMATED_INSNS (decl)
        = (*lang_hooks.tree_inlining.estimate_num_insns) (decl);
!   node->local.self_insns = DECL_ESTIMATED_INSNS (decl);
!   if (node->local.inlinable)
!     node->local.disregard_inline_limits
        = (*lang_hooks.tree_inlining.disregard_inline_limits) (decl);
  
    /* Inlining characteristics are maintained by the cgraph_mark_inline.  */
!   node->global.insns = node->local.self_insns;
    if (!DECL_EXTERNAL (decl))
      {
!       node->global.cloned_times = 1;
!       node->global.will_be_output = true;
      }
  
    node->analyzed = true;
--- 316,336 ----
    /* First kill forward declaration so reverse inlining works properly.  */
    cgraph_create_edges (decl, DECL_SAVED_TREE (decl));
  
!   node->function_info.inlinable = tree_inlinable_function_p (decl);
    if (!DECL_ESTIMATED_INSNS (decl))
      DECL_ESTIMATED_INSNS (decl)
        = (*lang_hooks.tree_inlining.estimate_num_insns) (decl);
!   node->function_info.self_insns = DECL_ESTIMATED_INSNS (decl);
!   if (node->function_info.inlinable)
!     node->function_info.disregard_inline_limits
        = (*lang_hooks.tree_inlining.disregard_inline_limits) (decl);
  
    /* Inlining characteristics are maintained by the cgraph_mark_inline.  */
!   node->function_info.insns = node->function_info.self_insns;
    if (!DECL_EXTERNAL (decl))
      {
!       node->function_info.cloned_times = 1;
!       node->function_info.will_be_output = true;
      }
  
    node->analyzed = true;
*************** static int
*** 768,774 ****
  cgraph_estimate_size_after_inlining (int times, struct cgraph_node *to,
  				     struct cgraph_node *what)
  {
!   return (what->global.insns - INSNS_PER_CALL) * times + to->global.insns;
  }
  
  /* Estimate the growth caused by inlining NODE into all callees.  */
--- 767,774 ----
  cgraph_estimate_size_after_inlining (int times, struct cgraph_node *to,
  				     struct cgraph_node *what)
  {
!   return (what->function_info.insns - INSNS_PER_CALL) * times
! 	    + to->function_info.insns;
  }
  
  /* Estimate the growth caused by inlining NODE into all callees.  */
*************** cgraph_estimate_growth (struct cgraph_no
*** 784,801 ****
    for (e = node->callers; e; e = e->next_caller)
      if (!e->inline_call)
        {
! 	growth += ((cgraph_estimate_size_after_inlining (1, e->caller, node)
! 		    -
! 		    e->caller->global.insns) *e->caller->global.cloned_times);
! 	calls_saved += e->caller->global.cloned_times;
! 	clones_added += e->caller->global.cloned_times;
        }
  
    /* ??? Wrong for self recursive functions or cases where we decide to not
       inline for different reasons, but it is not big deal as in that case
       we will keep the body around, but we will also avoid some inlining.  */
    if (!node->needed && !node->origin && !DECL_EXTERNAL (node->decl))
!     growth -= node->global.insns, clones_added--;
  
    if (!calls_saved)
      calls_saved = 1;
--- 784,802 ----
    for (e = node->callers; e; e = e->next_caller)
      if (!e->inline_call)
        {
!         struct cgraph_node *c = e->caller;
! 
! 	growth += ((cgraph_estimate_size_after_inlining (1, c, node) -
! 		    c->function_info.insns) * c->function_info.cloned_times);
! 	calls_saved += c->function_info.cloned_times;
! 	clones_added += c->function_info.cloned_times;
        }
  
    /* ??? Wrong for self recursive functions or cases where we decide to not
       inline for different reasons, but it is not big deal as in that case
       we will keep the body around, but we will also avoid some inlining.  */
    if (!node->needed && !node->origin && !DECL_EXTERNAL (node->decl))
!     growth -= node->function_info.insns, clones_added--;
  
    if (!calls_saved)
      calls_saved = 1;
*************** cgraph_mark_inline (struct cgraph_node *
*** 819,825 ****
    bool called = false;
    int new_insns;
  
!   what->global.inlined = 1;
    for (e = what->callers; e; e = e->next_caller)
      {
        if (e->caller == to)
--- 820,826 ----
    bool called = false;
    int new_insns;
  
!   what->function_info.inlined = 1;
    for (e = what->callers; e; e = e->next_caller)
      {
        if (e->caller == to)
*************** cgraph_mark_inline (struct cgraph_node *
*** 828,834 ****
  	    abort ();
  	  e->inline_call = true;
  	  times++;
! 	  clones += e->caller->global.cloned_times;
  	}
        else if (!e->inline_call)
  	called = true;
--- 829,835 ----
  	    abort ();
  	  e->inline_call = true;
  	  times++;
! 	  clones += e->caller->function_info.cloned_times;
  	}
        else if (!e->inline_call)
  	called = true;
*************** cgraph_mark_inline (struct cgraph_node *
*** 838,871 ****
    ncalls_inlined += times;
  
    new_insns = cgraph_estimate_size_after_inlining (times, to, what);
!   if (to->global.will_be_output)
!     overall_insns += new_insns - to->global.insns;
!   to->global.insns = new_insns;
  
    if (!called && !what->needed && !what->origin
        && flag_unit_at_a_time
        && !DECL_EXTERNAL (what->decl))
      {
!       if (!what->global.will_be_output)
  	abort ();
        clones--;
        nfunctions_inlined++;
!       what->global.will_be_output = 0;
!       overall_insns -= what->global.insns;
      }
!   what->global.cloned_times += clones;
    for (i = 0; i < ninlined; i++)
      {
        new_insns =
  	cgraph_estimate_size_after_inlining (INLINED_TIMES (inlined[i]) *
  					     times, inlined[i], what);
!       if (inlined[i]->global.will_be_output)
! 	overall_insns += new_insns - inlined[i]->global.insns;
!       inlined[i]->global.insns = new_insns;
      }
    for (i = 0; i < ninlined_callees; i++)
      {
!       inlined_callees[i]->global.cloned_times +=
  	INLINED_TIMES (inlined_callees[i]) * clones;
      }
  }
--- 839,872 ----
    ncalls_inlined += times;
  
    new_insns = cgraph_estimate_size_after_inlining (times, to, what);
!   if (to->function_info.will_be_output)
!     overall_insns += new_insns - to->function_info.insns;
!   to->function_info.insns = new_insns;
  
    if (!called && !what->needed && !what->origin
        && flag_unit_at_a_time
        && !DECL_EXTERNAL (what->decl))
      {
!       if (!what->function_info.will_be_output)
  	abort ();
        clones--;
        nfunctions_inlined++;
!       what->function_info.will_be_output = 0;
!       overall_insns -= what->function_info.insns;
      }
!   what->function_info.cloned_times += clones;
    for (i = 0; i < ninlined; i++)
      {
        new_insns =
  	cgraph_estimate_size_after_inlining (INLINED_TIMES (inlined[i]) *
  					     times, inlined[i], what);
!       if (inlined[i]->function_info.will_be_output)
! 	overall_insns += new_insns - inlined[i]->function_info.insns;
!       inlined[i]->function_info.insns = new_insns;
      }
    for (i = 0; i < ninlined_callees; i++)
      {
!       inlined_callees[i]->function_info.cloned_times +=
  	INLINED_TIMES (inlined_callees[i]) * clones;
      }
  }
*************** cgraph_check_inline_limits (struct cgrap
*** 889,898 ****
  
    /* When inlining large function body called once into small function,
       take the inlined function as base for limiting the growth.  */
!   if (to->local.self_insns > what->local.self_insns)
!     limit = to->local.self_insns;
    else
!     limit = what->local.self_insns;
  
    limit += limit * PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH) / 100;
  
--- 890,899 ----
  
    /* When inlining large function body called once into small function,
       take the inlined function as base for limiting the growth.  */
!   if (to->function_info.self_insns > what->function_info.self_insns)
!     limit = to->function_info.self_insns;
    else
!     limit = what->function_info.self_insns;
  
    limit += limit * PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH) / 100;
  
*************** cgraph_check_inline_limits (struct cgrap
*** 907,913 ****
  					     times, inlined[i], what);
        if (newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS)
  	  && newsize >
! 	  inlined[i]->local.self_insns *
  	  (100 + PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH)) / 100)
  	return false;
      }
--- 908,914 ----
  					     times, inlined[i], what);
        if (newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS)
  	  && newsize >
! 	  inlined[i]->function_info.self_insns *
  	  (100 + PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH)) / 100)
  	return false;
      }
*************** cgraph_default_inline_p (struct cgraph_n
*** 922,930 ****
    if (!DECL_INLINE (n->decl) || !DECL_SAVED_TREE (n->decl))
      return false;
    if (DECL_DECLARED_INLINE_P (n->decl))
!     return n->global.insns < MAX_INLINE_INSNS_SINGLE;
    else
!     return n->global.insns < MAX_INLINE_INSNS_AUTO;
  }
  
  /* We use greedy algorithm for inlining of small functions:
--- 923,931 ----
    if (!DECL_INLINE (n->decl) || !DECL_SAVED_TREE (n->decl))
      return false;
    if (DECL_DECLARED_INLINE_P (n->decl))
!     return n->function_info.insns < MAX_INLINE_INSNS_SINGLE;
    else
!     return n->function_info.insns < MAX_INLINE_INSNS_AUTO;
  }
  
  /* We use greedy algorithm for inlining of small functions:
*************** cgraph_decide_inlining_of_small_function
*** 953,959 ****
      {
        struct cgraph_edge *e;
  
!       if (!node->local.inlinable || !node->callers
  	  || !cgraph_default_inline_p (node))
  	continue;
  
--- 954,960 ----
      {
        struct cgraph_edge *e;
  
!       if (!node->function_info.inlinable || !node->callers
  	  || !cgraph_default_inline_p (node))
  	continue;
  
*************** cgraph_decide_inlining_of_small_function
*** 979,985 ****
  	fprintf (cgraph_dump_file, 
  		 "\nConsidering %s with %i insns\n"
  		 " Estimated growth is %+i insns.\n",
! 		 cgraph_node_name (node), node->global.insns,
  		 cgraph_estimate_growth (node));
        if (!cgraph_default_inline_p (node))
  	{
--- 980,986 ----
  	fprintf (cgraph_dump_file, 
  		 "\nConsidering %s with %i insns\n"
  		 " Estimated growth is %+i insns.\n",
! 		 cgraph_node_name (node), node->function_info.insns,
  		 cgraph_estimate_growth (node));
        if (!cgraph_default_inline_p (node))
  	{
*************** cgraph_decide_inlining_of_small_function
*** 1022,1028 ****
  	  fprintf (cgraph_dump_file, 
  		   " Inlined into %s which now has %i insns.\n",
  		   cgraph_node_name (e->caller),
! 		   e->caller->global.insns);
  
  	  }
  
--- 1023,1029 ----
  	  fprintf (cgraph_dump_file, 
  		   " Inlined into %s which now has %i insns.\n",
  		   cgraph_node_name (e->caller),
! 		   e->caller->function_info.insns);
  
  	  }
  
*************** cgraph_decide_inlining_of_small_function
*** 1048,1054 ****
        if (cgraph_dump_file)
  	fprintf (cgraph_dump_file, 
  		 " Inlined %i times for a net change of %+i insns.\n",
! 		 node->global.cloned_times, overall_insns - old_insns);
      }
    if (cgraph_dump_file && !fibheap_empty (heap))
      fprintf (cgraph_dump_file, "\nReached the inline-unit-growth limit.\n");
--- 1049,1055 ----
        if (cgraph_dump_file)
  	fprintf (cgraph_dump_file, 
  		 " Inlined %i times for a net change of %+i insns.\n",
! 		 node->function_info.cloned_times, overall_insns - old_insns);
      }
    if (cgraph_dump_file && !fibheap_empty (heap))
      fprintf (cgraph_dump_file, "\nReached the inline-unit-growth limit.\n");
*************** cgraph_decide_inlining (void)
*** 1076,1082 ****
    int i, y;
  
    for (node = cgraph_nodes; node; node = node->next)
!     initial_insns += node->local.self_insns;
    overall_insns = initial_insns;
  
    nnodes = cgraph_postorder (order);
--- 1077,1083 ----
    int i, y;
  
    for (node = cgraph_nodes; node; node = node->next)
!     initial_insns += node->function_info.self_insns;
    overall_insns = initial_insns;
  
    nnodes = cgraph_postorder (order);
*************** cgraph_decide_inlining (void)
*** 1101,1119 ****
        node = order[i];
  
        for (e = node->callees; e; e = e->next_callee)
! 	if (e->callee->local.disregard_inline_limits)
  	  break;
        if (!e)
  	continue;
        if (cgraph_dump_file)
  	fprintf (cgraph_dump_file,
  		 "\nConsidering %s %i insns (always inline)\n",
! 		 cgraph_node_name (e->callee), e->callee->global.insns);
        ninlined = cgraph_inlined_into (order[i], inlined);
        for (; e; e = e->next_callee)
  	{
  	  old_insns = overall_insns;
! 	  if (e->inline_call || !e->callee->local.disregard_inline_limits)
  	    continue;
  	  if (e->callee->output || e->callee == node)
  	    continue;
--- 1102,1120 ----
        node = order[i];
  
        for (e = node->callees; e; e = e->next_callee)
! 	if (e->callee->function_info.disregard_inline_limits)
  	  break;
        if (!e)
  	continue;
        if (cgraph_dump_file)
  	fprintf (cgraph_dump_file,
  		 "\nConsidering %s %i insns (always inline)\n",
! 		 cgraph_node_name (e->callee), e->callee->function_info.insns);
        ninlined = cgraph_inlined_into (order[i], inlined);
        for (; e; e = e->next_callee)
  	{
  	  old_insns = overall_insns;
! 	  if (e->inline_call || !e->callee->function_info.disregard_inline_limits)
  	    continue;
  	  if (e->callee->output || e->callee == node)
  	    continue;
*************** cgraph_decide_inlining (void)
*** 1127,1138 ****
  	    fprintf (cgraph_dump_file, 
  		     " Inlined into %s which now has %i insns.\n",
  		     cgraph_node_name (node->callees->caller),
! 	             node->callees->caller->global.insns);
  	}
! 	if (cgraph_dump_file && node->global.cloned_times > 0)
  	  fprintf (cgraph_dump_file, 
  		   " Inlined %i times for a net change of %+i insns.\n",
! 		   node->global.cloned_times, overall_insns - old_insns);
        for (y = 0; y < ninlined; y++)
  	inlined[y]->output = 0, node->aux = 0;
      }
--- 1128,1139 ----
  	    fprintf (cgraph_dump_file, 
  		     " Inlined into %s which now has %i insns.\n",
  		     cgraph_node_name (node->callees->caller),
! 	             node->callees->caller->function_info.insns);
  	}
! 	if (cgraph_dump_file && node->function_info.cloned_times > 0)
  	  fprintf (cgraph_dump_file, 
  		   " Inlined %i times for a net change of %+i insns.\n",
! 		   node->function_info.cloned_times, overall_insns - old_insns);
        for (y = 0; y < ninlined; y++)
  	inlined[y]->output = 0, node->aux = 0;
      }
*************** cgraph_decide_inlining (void)
*** 1149,1155 ****
        node = order[i];
  
        if (node->callers && !node->callers->next_caller && !node->needed
! 	  && node->local.inlinable && !node->callers->inline_call
  	  && !DECL_EXTERNAL (node->decl) && !DECL_COMDAT (node->decl))
  	{
  	  bool ok = true;
--- 1150,1156 ----
        node = order[i];
  
        if (node->callers && !node->callers->next_caller && !node->needed
! 	  && node->function_info.inlinable && !node->callers->inline_call
  	  && !DECL_EXTERNAL (node->decl) && !DECL_COMDAT (node->decl))
  	{
  	  bool ok = true;
*************** cgraph_decide_inlining (void)
*** 1167,1175 ****
  		fprintf (cgraph_dump_file,
  			 "\nConsidering %s %i insns.\n"
  			 " Called once from %s %i insns.\n",
! 			 cgraph_node_name (node), node->global.insns,
  			 cgraph_node_name (node->callers->caller),
! 			 node->callers->caller->global.insns);
  	      ninlined = cgraph_inlined_into (node->callers->caller, inlined);
  	      old_insns = overall_insns;
  	      if (cgraph_check_inline_limits
--- 1168,1176 ----
  		fprintf (cgraph_dump_file,
  			 "\nConsidering %s %i insns.\n"
  			 " Called once from %s %i insns.\n",
! 			 cgraph_node_name (node), node->function_info.insns,
  			 cgraph_node_name (node->callers->caller),
! 			 node->callers->caller->function_info.insns);
  	      ninlined = cgraph_inlined_into (node->callers->caller, inlined);
  	      old_insns = overall_insns;
  	      if (cgraph_check_inline_limits
*************** cgraph_decide_inlining (void)
*** 1187,1193 ****
  			     " Inlined into %s which now has %i insns"
  			     " for a net change of %+i insns.\n",
  			     cgraph_node_name (node->callers->caller),
! 			     node->callers->caller->global.insns,
  			     overall_insns - old_insns);
  		}
  	      else
--- 1188,1194 ----
  			     " Inlined into %s which now has %i insns"
  			     " for a net change of %+i insns.\n",
  			     cgraph_node_name (node->callers->caller),
! 			     node->callers->caller->function_info.insns,
  			     overall_insns - old_insns);
  		}
  	      else
*************** cgraph_decide_inlining_incrementally (st
*** 1232,1239 ****
  
    /* First of all look for always inline functions.  */
    for (e = node->callees; e; e = e->next_callee)
!     if (e->callee->local.disregard_inline_limits && !e->callee->output
! 	&& e->callee != node && !e->inline_call)
        {
  	ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees);
  	cgraph_mark_inline (node, e->callee, inlined, ninlined,
--- 1233,1242 ----
  
    /* First of all look for always inline functions.  */
    for (e = node->callees; e; e = e->next_callee)
!     if (e->callee->function_info.disregard_inline_limits
! 	&& !e->callee->output
! 	&& e->callee != node
! 	&& !e->inline_call)
        {
  	ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees);
  	cgraph_mark_inline (node, e->callee, inlined, ninlined,
*************** cgraph_decide_inlining_incrementally (st
*** 1244,1254 ****
  
    /* Now do the automatic inlining.  */
    for (e = node->callees; e; e = e->next_callee)
!     if (e->callee->local.inlinable && !e->callee->output
! 	&& e->callee != node && !e->inline_call
          && cgraph_default_inline_p (e->callee)
! 	&& cgraph_check_inline_limits (node, e->callee, inlined,
! 				       ninlined))
        {
  	ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees);
  	cgraph_mark_inline (node, e->callee, inlined, ninlined,
--- 1247,1258 ----
  
    /* Now do the automatic inlining.  */
    for (e = node->callees; e; e = e->next_callee)
!     if (e->callee->function_info.inlinable
! 	&& !e->callee->output
! 	&& e->callee != node
! 	&& !e->inline_call
          && cgraph_default_inline_p (e->callee)
! 	&& cgraph_check_inline_limits (node, e->callee, inlined, ninlined))
        {
  	ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees);
  	cgraph_mark_inline (node, e->callee, inlined, ninlined,
*************** cgraph_mark_local_functions (void)
*** 1338,1347 ****
    /* 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 (cgraph_dump_file && node->local.local)
  	fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
      }
    if (cgraph_dump_file)
--- 1342,1351 ----
    /* Figure out functions we want to assemble.  */
    for (node = cgraph_nodes; node; node = node->next)
      {
!       node->function_info.local = (!node->needed
! 			           && DECL_SAVED_TREE (node->decl)
! 			           && !TREE_PUBLIC (node->decl));
!       if (cgraph_dump_file && node->function_info.local)
  	fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
      }
    if (cgraph_dump_file)
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.618
diff -c -3 -p -r1.618 i386.c
*** config/i386/i386.c	7 Nov 2003 09:26:06 -0000	1.618
--- config/i386/i386.c	16 Nov 2003 21:47:30 -0000
*************** ix86_function_regparm (tree type, tree d
*** 1694,1700 ****
        if (!TARGET_64BIT && !user_convention && decl
  	  && flag_unit_at_a_time && !profile_flag)
  	{
! 	  struct cgraph_local_info *i = cgraph_local_info (decl);
  	  if (i && i->local)
  	    {
  	      /* We can't use regparm(3) for nested functions as these use
--- 1694,1700 ----
        if (!TARGET_64BIT && !user_convention && decl
  	  && flag_unit_at_a_time && !profile_flag)
  	{
! 	  struct cgraph_function_info *i = cgraph_local_info (decl);
  	  if (i && i->local)
  	    {
  	      /* We can't use regparm(3) for nested functions as these use
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.686
diff -c -3 -p -r1.686 decl2.c
*** cp/decl2.c	13 Nov 2003 02:07:53 -0000	1.686
--- cp/decl2.c	16 Nov 2003 21:47:36 -0000
*************** finish_file (void)
*** 2773,2779 ****
  	      && DECL_SAVED_TREE (decl)
  	      && !TREE_ASM_WRITTEN (decl)
  	      && (!flag_unit_at_a_time 
! 		  || !cgraph_node (decl)->local.finalized))
  	    {
  	      /* We will output the function; no longer consider it in this
  		 loop.  */
--- 2773,2779 ----
  	      && DECL_SAVED_TREE (decl)
  	      && !TREE_ASM_WRITTEN (decl)
  	      && (!flag_unit_at_a_time 
! 		  || !cgraph_local_info (decl)->finalized))
  	    {
  	      /* We will output the function; no longer consider it in this
  		 loop.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]