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]

Re: [PATCH] Fix -fcompare-debug failure during inlining (PR tree-optimization/44182, take 2)


On Mon, 31 May 2010, Jakub Jelinek wrote:

> On Mon, May 31, 2010 at 11:30:39AM +0200, Richard Guenther wrote:
> > But you could move them to the last succ instead of copying them
> > there.  Btw - do debug stmts have a location?  If so you probably
> > want to copy those too.
> 
> I think debug stmts don't have location (and even if they would, 1)
> it is completely ignored during expansion and 2) block and location
> is copied over from stmt when stmt is passed as last argument to
> gimple_build_debug_bind).
> 
> The following patch does the moving instead of copying when processing the
> last edge.  Bootstrapped/regtested on x86_64-linux/i686-linux, ok for
> trunk/4.5?

Ok.

Thanks,
Richard.

> 2010-05-31  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR tree-optimization/44182
> 	* tree-inline.c (copy_edges_for_bb): Don't split bb if a stmt that
> 	newly needs to end a bb is followed by debug stmts, instead return
> 	true from the function at the end.
> 	(maybe_move_debug_stmts_to_successors): New function.
> 	(copy_cfg_body): Call it if copy_edges_for_bb returned true.
> 
> 	* g++.dg/debug/pr44182.C: New test.
> 
> --- gcc/tree-inline.c.jj	2010-05-31 14:48:56.000000000 +0200
> +++ gcc/tree-inline.c	2010-05-31 15:05:12.000000000 +0200
> @@ -1834,9 +1834,10 @@ update_ssa_across_abnormal_edges (basic_
>  
>  /* Copy edges from BB into its copy constructed earlier, scale profile
>     accordingly.  Edges will be taken care of later.  Assume aux
> -   pointers to point to the copies of each BB.  */
> +   pointers to point to the copies of each BB.  Return true if any
> +   debug stmts are left after a statement that must end the basic block.  */
>  
> -static void
> +static bool
>  copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb)
>  {
>    basic_block new_bb = (basic_block) bb->aux;
> @@ -1844,6 +1845,7 @@ copy_edges_for_bb (basic_block bb, gcov_
>    edge old_edge;
>    gimple_stmt_iterator si;
>    int flags;
> +  bool need_debug_cleanup = false;
>  
>    /* Use the indices from the original blocks to create edges for the
>       new ones.  */
> @@ -1864,7 +1866,7 @@ copy_edges_for_bb (basic_block bb, gcov_
>        }
>  
>    if (bb->index == ENTRY_BLOCK || bb->index == EXIT_BLOCK)
> -    return;
> +    return false;
>  
>    for (si = gsi_start_bb (new_bb); !gsi_end_p (si);)
>      {
> @@ -1899,6 +1901,13 @@ copy_edges_for_bb (basic_block bb, gcov_
>        if (can_throw || nonlocal_goto)
>  	{
>  	  if (!gsi_end_p (si))
> +	    {
> +	      while (!gsi_end_p (si) && is_gimple_debug (gsi_stmt (si)))
> +		gsi_next (&si);
> +	      if (gsi_end_p (si))
> +		need_debug_cleanup = true;
> +	    }
> +	  if (!gsi_end_p (si))
>  	    /* Note that bb's predecessor edges aren't necessarily
>  	       right at this point; split_block doesn't care.  */
>  	    {
> @@ -1923,6 +1932,7 @@ copy_edges_for_bb (basic_block bb, gcov_
>  	update_ssa_across_abnormal_edges (gimple_bb (copy_stmt), ret_bb,
>  					  can_throw, nonlocal_goto);
>      }
> +  return need_debug_cleanup;
>  }
>  
>  /* Copy the PHIs.  All blocks and edges are copied, some blocks
> @@ -2059,6 +2069,63 @@ initialize_cfun (tree new_fndecl, tree c
>    pop_cfun ();
>  }
>  
> +/* Helper function for copy_cfg_body.  Move debug stmts from the end
> +   of NEW_BB to the beginning of successor basic blocks when needed.  If the
> +   successor has multiple predecessors, reset them, otherwise keep
> +   their value.  */
> +
> +static void
> +maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb)
> +{
> +  edge e;
> +  edge_iterator ei;
> +  gimple_stmt_iterator si = gsi_last_nondebug_bb (new_bb);
> +
> +  if (gsi_end_p (si)
> +      || gsi_one_before_end_p (si)
> +      || !(stmt_can_throw_internal (gsi_stmt (si))
> +	   || stmt_can_make_abnormal_goto (gsi_stmt (si))))
> +    return;
> +
> +  FOR_EACH_EDGE (e, ei, new_bb->succs)
> +    {
> +      gimple_stmt_iterator ssi = gsi_last_bb (new_bb);
> +      gimple_stmt_iterator dsi = gsi_after_labels (e->dest);
> +      while (is_gimple_debug (gsi_stmt (ssi)))
> +	{
> +	  gimple stmt = gsi_stmt (ssi), new_stmt;
> +	  tree var;
> +	  tree value;
> +
> +	  /* For the last edge move the debug stmts instead of copying
> +	     them.  */
> +	  if (ei_one_before_end_p (ei))
> +	    {
> +	      si = ssi;
> +	      gsi_prev (&ssi);
> +	      if (!single_pred_p (e->dest))
> +		gimple_debug_bind_reset_value (stmt);
> +	      gsi_remove (&si, false);
> +	      gsi_insert_before (&dsi, stmt, GSI_SAME_STMT);
> +	      continue;
> +	    }
> +
> +	  var = gimple_debug_bind_get_var (stmt);
> +	  if (single_pred_p (e->dest))
> +	    {
> +	      value = gimple_debug_bind_get_value (stmt);
> +	      value = unshare_expr (value);
> +	    }
> +	  else
> +	    value = NULL_TREE;
> +	  new_stmt = gimple_build_debug_bind (var, value, stmt);
> +	  gsi_insert_before (&dsi, new_stmt, GSI_SAME_STMT);
> +	  VEC_safe_push (gimple, heap, id->debug_stmts, new_stmt);
> +	  gsi_prev (&ssi);
> +	}
> +    }
> +}
> +
>  /* Make a copy of the body of FN so that it can be inserted inline in
>     another function.  Walks FN via CFG, returns new fndecl.  */
>  
> @@ -2072,6 +2139,7 @@ copy_cfg_body (copy_body_data * id, gcov
>    struct function *cfun_to_copy;
>    basic_block bb;
>    tree new_fndecl = NULL;
> +  bool need_debug_cleanup = false;
>    gcov_type count_scale;
>    int last;
>  
> @@ -2112,7 +2180,7 @@ copy_cfg_body (copy_body_data * id, gcov
>  
>    /* Now that we've duplicated the blocks, duplicate their edges.  */
>    FOR_ALL_BB_FN (bb, cfun_to_copy)
> -    copy_edges_for_bb (bb, count_scale, exit_block_map);
> +    need_debug_cleanup |= copy_edges_for_bb (bb, count_scale, exit_block_map);
>  
>    if (gimple_in_ssa_p (cfun))
>      FOR_ALL_BB_FN (bb, cfun_to_copy)
> @@ -2120,6 +2188,10 @@ copy_cfg_body (copy_body_data * id, gcov
>  
>    FOR_ALL_BB_FN (bb, cfun_to_copy)
>      {
> +      if (need_debug_cleanup
> +	  && bb->index != ENTRY_BLOCK
> +	  && bb->index != EXIT_BLOCK)
> +	maybe_move_debug_stmts_to_successors (id, (basic_block) bb->aux);
>        ((basic_block)bb->aux)->aux = NULL;
>        bb->aux = NULL;
>      }
> @@ -2127,7 +2199,11 @@ copy_cfg_body (copy_body_data * id, gcov
>    /* Zero out AUX fields of newly created block during EH edge
>       insertion. */
>    for (; last < last_basic_block; last++)
> -    BASIC_BLOCK (last)->aux = NULL;
> +    {
> +      if (need_debug_cleanup)
> +	maybe_move_debug_stmts_to_successors (id, BASIC_BLOCK (last));
> +      BASIC_BLOCK (last)->aux = NULL;
> +    }
>    entry_block_map->aux = NULL;
>    exit_block_map->aux = NULL;
>  
> --- gcc/testsuite/g++.dg/debug/pr44182.C.jj	2010-05-31 14:52:51.000000000 +0200
> +++ gcc/testsuite/g++.dg/debug/pr44182.C	2010-05-31 14:52:51.000000000 +0200
> @@ -0,0 +1,26 @@
> +// PR tree-optimization/44182
> +// { dg-do compile }
> +// { dg-options "-fcompare-debug" }
> +
> +struct S
> +{
> +  int i;
> +  S ();
> +  ~S ();
> +  void f1 ();
> +  void f2 (S s)
> +  {
> +    f3 (s.i);
> +    for (int j = 0; j < s.i; j++) f1 ();
> +  }
> +  void f3 (int j)
> +  {
> +    if (j > i) f1 ();
> +  }
> +};
> +
> +void
> +f (S *x)
> +{
> +  x->f2 (S ());
> +}
> 
> 
> 	Jakub
> 
> 

-- 
Richard Guenther <rguenther@suse.de>
Novell / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 - GF: Markus Rex


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