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]

Fix profile updating during recursive inlining


Hi,
while looking into PR 24020 I noticed that updating of profile during recursive
inlining is going seriously wrong.  The actual problem is that I don't decrease
number of expected execution of function when doing recursive inlining that
should matter little in practice but when one is not cureful it leads to
overflow/negative results easilly.

This patch actually does not affect originaly testcase in PR24020 without
profiling tought but the bug would result in failure to inline into recursive
function.

Bootstrapped/regtested i686-pc-gnu-linux, will commit it tomorrow.

Honza

2005-09-23  Jan Hubicka  <jh@suse.cz>
	* cgraph.c (cgraph_clone_edge): Make the scale gcov_type.
	(cgraph_clone_node): Likewise.
	* cgraph.h (cgraph_clone_edge): Update prototype.
	(cgraph_mark_inline_edge, cgraph_clone_inlined_nodes): Remove
	duplicated prototypes; add updating argument.
	* cgraphunit.c (verify_cgraph_node): Verify that counts are non-negative.
	* ipa-inline.c (cgraph_clone_inlined_nodes): Allow clonning without
	updating profile.
	(cgraph_mark_inline_edge): Likewise.
	(cgraph_mark_inline): Update use of cgraph_mark_inline_edge.
	(cgraph_flatten_node): Likewise.
	(cgraph_decide_recursive_inlining): Likewise.
	(cgraph_decide_inlining_of_small_function): Likewise.
	* tree-optimize.c (tree_rest_of_compilation): Likewise.
Index: cgraph.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.83
diff -c -3 -p -r1.83 cgraph.c
*** cgraph.c	28 Jul 2005 21:45:24 -0000	1.83
--- cgraph.c	23 Sep 2005 13:43:33 -0000
*************** cgraph_function_possibly_inlined_p (tree
*** 884,890 ****
  /* Create clone of E in the node N represented by CALL_EXPR the callgraph.  */
  struct cgraph_edge *
  cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
! 		   tree call_stmt, int count_scale, int loop_nest,
  		   bool update_original)
  {
    struct cgraph_edge *new;
--- 884,890 ----
  /* Create clone of E in the node N represented by CALL_EXPR the callgraph.  */
  struct cgraph_edge *
  cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
! 		   tree call_stmt, gcov_type count_scale, int loop_nest,
  		   bool update_original)
  {
    struct cgraph_edge *new;
*************** cgraph_clone_node (struct cgraph_node *n
*** 911,917 ****
  {
    struct cgraph_node *new = cgraph_create_node ();
    struct cgraph_edge *e;
!   int count_scale;
  
    new->decl = n->decl;
    new->origin = n->origin;
--- 911,917 ----
  {
    struct cgraph_node *new = cgraph_create_node ();
    struct cgraph_edge *e;
!   gcov_type count_scale;
  
    new->decl = n->decl;
    new->origin = n->origin;
Index: cgraph.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.h,v
retrieving revision 1.64
diff -c -3 -p -r1.64 cgraph.h
*** cgraph.h	1 Aug 2005 07:41:48 -0000	1.64
--- cgraph.h	23 Sep 2005 13:43:33 -0000
*************** struct cgraph_rtl_info *cgraph_rtl_info 
*** 242,248 ****
  const char * cgraph_node_name (struct cgraph_node *);
  struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *,
  				        struct cgraph_node *,
! 				        tree, int, int, bool);
  struct cgraph_node * cgraph_clone_node (struct cgraph_node *, gcov_type,
  					int, bool);
  
--- 242,248 ----
  const char * cgraph_node_name (struct cgraph_node *);
  struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *,
  				        struct cgraph_node *,
! 				        tree, gcov_type, int, bool);
  struct cgraph_node * cgraph_clone_node (struct cgraph_node *, gcov_type,
  					int, bool);
  
*************** bool cgraph_inline_p (struct cgraph_edge
*** 276,283 ****
  bool cgraph_preserve_function_body_p (tree);
  void verify_cgraph (void);
  void verify_cgraph_node (struct cgraph_node *);
- void cgraph_mark_inline_edge (struct cgraph_edge *e);
- void cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate);
  void cgraph_build_static_cdtor (char which, tree body, int priority);
  void cgraph_reset_static_var_maps (void);
  void init_cgraph (void);
--- 276,281 ----
*************** int cgraph_postorder (struct cgraph_node
*** 290,296 ****
  
  /* In ipa-inline.c  */
  bool cgraph_decide_inlining_incrementally (struct cgraph_node *, bool);
! void cgraph_clone_inlined_nodes (struct cgraph_edge *, bool);
! void cgraph_mark_inline_edge (struct cgraph_edge *);
  bool cgraph_default_inline_p (struct cgraph_node *, const char **);
  #endif  /* GCC_CGRAPH_H  */
--- 288,294 ----
  
  /* In ipa-inline.c  */
  bool cgraph_decide_inlining_incrementally (struct cgraph_node *, bool);
! void cgraph_clone_inlined_nodes (struct cgraph_edge *, bool, bool);
! void cgraph_mark_inline_edge (struct cgraph_edge *, bool);
  bool cgraph_default_inline_p (struct cgraph_node *, const char **);
  #endif  /* GCC_CGRAPH_H  */
Index: cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.127
diff -c -3 -p -r1.127 cgraphunit.c
*** cgraphunit.c	18 Aug 2005 15:22:42 -0000	1.127
--- cgraphunit.c	23 Sep 2005 13:43:33 -0000
*************** verify_cgraph_node (struct cgraph_node *
*** 657,664 ****
--- 657,674 ----
  	       cgraph_node_name (e->caller), cgraph_node_name (e->callee));
  	error_found = true;
        }
+   if (node->count < 0)
+     {
+       error ("Execution count is negative");
+       error_found = true;
+     }
    for (e = node->callers; e; e = e->next_caller)
      {
+       if (e->count < 0)
+ 	{
+ 	  error ("caller edge count is negative");
+ 	  error_found = true;
+ 	}
        if (!e->inline_failed)
  	{
  	  if (node->global.inlined_to
Index: ipa-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ipa-inline.c,v
retrieving revision 2.15
diff -c -3 -p -r2.15 ipa-inline.c
*** ipa-inline.c	28 Jul 2005 21:45:25 -0000	2.15
--- ipa-inline.c	23 Sep 2005 13:43:34 -0000
*************** cgraph_estimate_size_after_inlining (int
*** 113,119 ****
     clones or re-using node originally representing out-of-line function call.
     */
  void
! cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate)
  {
    struct cgraph_node *n;
  
--- 113,119 ----
     clones or re-using node originally representing out-of-line function call.
     */
  void
! cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, bool update_original)
  {
    struct cgraph_node *n;
  
*************** cgraph_clone_inlined_nodes (struct cgrap
*** 131,137 ****
      }
     else if (duplicate)
      {
!       n = cgraph_clone_node (e->callee, e->count, e->loop_nest, true);
        cgraph_redirect_edge_callee (e, n);
      }
  
--- 131,137 ----
      }
     else if (duplicate)
      {
!       n = cgraph_clone_node (e->callee, e->count, e->loop_nest, update_original);
        cgraph_redirect_edge_callee (e, n);
      }
  
*************** cgraph_clone_inlined_nodes (struct cgrap
*** 143,155 ****
    /* Recursively clone all bodies.  */
    for (e = e->callee->callees; e; e = e->next_callee)
      if (!e->inline_failed)
!       cgraph_clone_inlined_nodes (e, duplicate);
  }
  
! /* Mark edge E as inlined and update callgraph accordingly.  */
  
  void
! cgraph_mark_inline_edge (struct cgraph_edge *e)
  {
    int old_insns = 0, new_insns = 0;
    struct cgraph_node *to = NULL, *what;
--- 143,157 ----
    /* Recursively clone all bodies.  */
    for (e = e->callee->callees; e; e = e->next_callee)
      if (!e->inline_failed)
!       cgraph_clone_inlined_nodes (e, duplicate, update_original);
  }
  
! /* Mark edge E as inlined and update callgraph accordingly. 
!    UPDATE_ORIGINAL specify whether profile of original function should be
!    updated. */
  
  void
! cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original)
  {
    int old_insns = 0, new_insns = 0;
    struct cgraph_node *to = NULL, *what;
*************** cgraph_mark_inline_edge (struct cgraph_e
*** 161,167 ****
      DECL_POSSIBLY_INLINED (e->callee->decl) = true;
    e->callee->global.inlined = true;
  
!   cgraph_clone_inlined_nodes (e, true);
  
    what = e->callee;
  
--- 163,169 ----
      DECL_POSSIBLY_INLINED (e->callee->decl) = true;
    e->callee->global.inlined = true;
  
!   cgraph_clone_inlined_nodes (e, true, update_original);
  
    what = e->callee;
  
*************** cgraph_mark_inline (struct cgraph_edge *
*** 200,206 ****
        next = e->next_caller;
        if (e->caller == to && e->inline_failed)
  	{
!           cgraph_mark_inline_edge (e);
  	  if (e == edge)
  	    edge = next;
  	  times++;
--- 202,208 ----
        next = e->next_caller;
        if (e->caller == to && e->inline_failed)
  	{
!           cgraph_mark_inline_edge (e, true);
  	  if (e == edge)
  	    edge = next;
  	  times++;
*************** cgraph_flatten_node (struct cgraph_node 
*** 520,526 ****
  	{
  	  if (dump_file)
      	    fprintf (dump_file, " inlining %s", cgraph_node_name (e->callee));
!           cgraph_mark_inline_edge (e);
  	  cgraph_flatten_node (e->callee, cycles);
  	}
        else if (dump_file)
--- 522,528 ----
  	{
  	  if (dump_file)
      	    fprintf (dump_file, " inlining %s", cgraph_node_name (e->callee));
!           cgraph_mark_inline_edge (e, true);
  	  cgraph_flatten_node (e->callee, cycles);
  	}
        else if (dump_file)
*************** cgraph_decide_recursive_inlining (struct
*** 571,577 ****
    master_clone->needed = true;
    for (e = master_clone->callees; e; e = e->next_callee)
      if (!e->inline_failed)
!       cgraph_clone_inlined_nodes (e, true);
  
    /* Do the inlining and update list of recursive call during process.  */
    while (!fibheap_empty (heap)
--- 573,579 ----
    master_clone->needed = true;
    for (e = master_clone->callees; e; e = e->next_callee)
      if (!e->inline_failed)
!       cgraph_clone_inlined_nodes (e, true, false);
  
    /* Do the inlining and update list of recursive call during process.  */
    while (!fibheap_empty (heap)
*************** cgraph_decide_recursive_inlining (struct
*** 623,630 ****
  	  fprintf (dump_file, "\n");
  	}
        cgraph_redirect_edge_callee (curr, master_clone);
!       cgraph_mark_inline_edge (curr);
        lookup_recursive_calls (node, curr->callee, heap);
        n++;
      }
    if (!fibheap_empty (heap) && dump_file)
--- 625,632 ----
  	  fprintf (dump_file, "\n");
  	}
        cgraph_redirect_edge_callee (curr, master_clone);
!       cgraph_mark_inline_edge (curr, false);
        lookup_recursive_calls (node, curr->callee, heap);
        n++;
      }
    if (!fibheap_empty (heap) && dump_file)
*************** cgraph_decide_inlining_of_small_function
*** 808,814 ****
  	      continue;
  	    }
  	  callee = edge->callee;
! 	  cgraph_mark_inline_edge (edge);
  	  update_callee_keys (heap, callee, updated_nodes);
  	}
        where = edge->caller;
--- 811,817 ----
  	      continue;
  	    }
  	  callee = edge->callee;
! 	  cgraph_mark_inline_edge (edge, true);
  	  update_callee_keys (heap, callee, updated_nodes);
  	}
        where = edge->caller;
*************** cgraph_decide_inlining (void)
*** 930,936 ****
  	  if (cgraph_recursive_inlining_p (e->caller, e->callee,
  				  	   &e->inline_failed))
  	    continue;
! 	  cgraph_mark_inline_edge (e);
  	  if (dump_file)
  	    fprintf (dump_file, 
  		     " Inlined into %s which now has %i insns.\n",
--- 933,939 ----
  	  if (cgraph_recursive_inlining_p (e->caller, e->callee,
  				  	   &e->inline_failed))
  	    continue;
! 	  cgraph_mark_inline_edge (e, true);
  	  if (dump_file)
  	    fprintf (dump_file, 
  		     " Inlined into %s which now has %i insns.\n",
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 2.122
diff -c -3 -p -r2.122 tree-optimize.c
*** tree-optimize.c	10 Aug 2005 09:02:48 -0000	2.122
--- tree-optimize.c	23 Sep 2005 13:43:34 -0000
*************** tree_rest_of_compilation (tree fndecl)
*** 375,381 ****
  	  saved_node = cgraph_clone_node (node, node->count, 1, false);
  	  for (e = saved_node->callees; e; e = e->next_callee)
  	    if (!e->inline_failed)
! 	      cgraph_clone_inlined_nodes (e, true);
  	}
        cfun->saved_static_chain_decl = cfun->static_chain_decl;
        save_body (fndecl, &cfun->saved_args, &cfun->saved_static_chain_decl);
--- 375,381 ----
  	  saved_node = cgraph_clone_node (node, node->count, 1, false);
  	  for (e = saved_node->callees; e; e = e->next_callee)
  	    if (!e->inline_failed)
! 	      cgraph_clone_inlined_nodes (e, true, false);
  	}
        cfun->saved_static_chain_decl = cfun->static_chain_decl;
        save_body (fndecl, &cfun->saved_args, &cfun->saved_static_chain_decl);


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