public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix PR50768, rewrite gimplify_and_update_call_from_tree
@ 2011-10-19 12:14 Richard Guenther
  0 siblings, 0 replies; only message in thread
From: Richard Guenther @ 2011-10-19 12:14 UTC (permalink / raw)
  To: gcc-patches


So my previous patch has caused some bugs - not unreasonable given
the complexity of that function.  Thus the following patch makes
it readable and understandable again, by exchanging the intricate
one-stage processing with a two-stage one, first assigning VDEFs
and then assigning VUSEs in a second stage.  Also doing the
lhs assignment processing upfront which removes the need for
all the duplicate code at the tail.

Bootstrap and regtest ongoing on x86_64-unknown-linux-gnu, let's
hope it can stay this simple ;)

Thanks,
Richard.

2011-10-19  Richard Guenther  <rguenther@suse.de>

	PR middle-end/50768
	* gimple-fold.c (gimplify_and_update_call_from_tree): Rewrite.

	* gcc.dg/torture/pr50768.c: New testcase.

Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c	(revision 180166)
--- gcc/gimple-fold.c	(working copy)
*************** void
*** 534,558 ****
  gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
  {
    tree lhs;
-   tree tmp = NULL_TREE;  /* Silence warning.  */
    gimple stmt, new_stmt;
    gimple_stmt_iterator i;
    gimple_seq stmts = gimple_seq_alloc();
    struct gimplify_ctx gctx;
!   gimple last = NULL;
!   gimple laststore = NULL;
    tree reaching_vuse;
  
    stmt = gsi_stmt (*si_p);
  
    gcc_assert (is_gimple_call (stmt));
  
-   lhs = gimple_call_lhs (stmt);
-   reaching_vuse = gimple_vuse (stmt);
- 
    push_gimplify_context (&gctx);
    gctx.into_ssa = gimple_in_ssa_p (cfun);
  
    if (lhs == NULL_TREE)
      {
        gimplify_and_add (expr, &stmts);
--- 534,555 ----
  gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
  {
    tree lhs;
    gimple stmt, new_stmt;
    gimple_stmt_iterator i;
    gimple_seq stmts = gimple_seq_alloc();
    struct gimplify_ctx gctx;
!   gimple last;
!   gimple laststore;
    tree reaching_vuse;
  
    stmt = gsi_stmt (*si_p);
  
    gcc_assert (is_gimple_call (stmt));
  
    push_gimplify_context (&gctx);
    gctx.into_ssa = gimple_in_ssa_p (cfun);
  
+   lhs = gimple_call_lhs (stmt);
    if (lhs == NULL_TREE)
      {
        gimplify_and_add (expr, &stmts);
*************** gimplify_and_update_call_from_tree (gimp
*** 571,675 ****
  	}
      }
    else
!     tmp = get_initialized_tmp_var (expr, &stmts, NULL);
  
    pop_gimplify_context (NULL);
  
    if (gimple_has_location (stmt))
      annotate_all_with_location (stmts, gimple_location (stmt));
  
!   /* The replacement can expose previously unreferenced variables.  */
    for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
      {
        if (last)
  	{
  	  gsi_insert_before (si_p, last, GSI_NEW_STMT);
  	  gsi_next (si_p);
  	}
        new_stmt = gsi_stmt (i);
        if (gimple_in_ssa_p (cfun))
  	find_new_referenced_vars (new_stmt);
        /* If the new statement possibly has a VUSE, update it with exact SSA
  	 name we know will reach this one.  */
        if (gimple_has_mem_ops (new_stmt))
! 	{
! 	  /* If we've also seen a previous store create a new VDEF for
! 	     the latter one, and make that the new reaching VUSE.  */
! 	  if (laststore)
! 	    {
! 	      reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore);
! 	      gimple_set_vdef (laststore, reaching_vuse);
! 	      update_stmt (laststore);
! 	      laststore = NULL;
! 	    }
! 	  gimple_set_vuse (new_stmt, reaching_vuse);
! 	  gimple_set_modified (new_stmt, true);
! 	}
!       if (gimple_assign_single_p (new_stmt)
! 	  && !is_gimple_reg (gimple_assign_lhs (new_stmt)))
! 	{
! 	  laststore = new_stmt;
! 	}
        last = new_stmt;
      }
  
!   if (lhs == NULL_TREE)
      {
!       /* If we replace a call without LHS that has a VDEF and our new
!          sequence ends with a store we must make that store have the same
! 	 vdef in order not to break the sequencing.  This can happen
! 	 for instance when folding memcpy calls into assignments.  */
!       if (gimple_vdef (stmt) && laststore)
! 	{
! 	  gimple_set_vdef (laststore, gimple_vdef (stmt));
! 	  if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
! 	    SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = laststore;
! 	  update_stmt (laststore);
! 	}
!       else if (gimple_in_ssa_p (cfun))
  	{
  	  unlink_stmt_vdef (stmt);
! 	  release_defs (stmt);
! 	}
!       new_stmt = last;
!     }
!   else
!     {
!       if (last)
! 	{
! 	  gsi_insert_before (si_p, last, GSI_NEW_STMT);
! 	  gsi_next (si_p);
! 	}
!       if (laststore && is_gimple_reg (lhs))
! 	{
! 	  gimple_set_vdef (laststore, gimple_vdef (stmt));
! 	  update_stmt (laststore);
! 	  if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
! 	    SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = laststore;
! 	  laststore = NULL;
! 	}
!       else if (laststore)
! 	{
! 	  reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore);
! 	  gimple_set_vdef (laststore, reaching_vuse);
! 	  update_stmt (laststore);
! 	  laststore = NULL;
! 	}
!       new_stmt = gimple_build_assign (lhs, tmp);
!       if (!is_gimple_reg (tmp))
! 	gimple_set_vuse (new_stmt, reaching_vuse);
!       if (!is_gimple_reg (lhs))
! 	{
! 	  gimple_set_vdef (new_stmt, gimple_vdef (stmt));
! 	  if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
! 	    SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = new_stmt;
  	}
-       else if (reaching_vuse == gimple_vuse (stmt))
- 	unlink_stmt_vdef (stmt);
      }
  
!   gimple_set_location (new_stmt, gimple_location (stmt));
!   gsi_replace (si_p, new_stmt, false);
  }
  
  /* Return the string length, maximum string length or maximum value of
--- 568,648 ----
  	}
      }
    else
!     {
!       tree tmp = get_initialized_tmp_var (expr, &stmts, NULL);
!       new_stmt = gimple_build_assign (lhs, tmp);
!       i = gsi_last (stmts);
!       gsi_insert_after_without_update (&i, new_stmt,
! 				       GSI_CONTINUE_LINKING);
!     }
  
    pop_gimplify_context (NULL);
  
    if (gimple_has_location (stmt))
      annotate_all_with_location (stmts, gimple_location (stmt));
  
!   /* First iterate over the replacement statements backward, assigning
!      virtual operands to their defining statements.  */
!   laststore = NULL;
!   for (i = gsi_last (stmts); !gsi_end_p (i); gsi_prev (&i))
!     {
!       new_stmt = gsi_stmt (i);
!       if (gimple_assign_single_p (new_stmt)
! 	  && !is_gimple_reg (gimple_assign_lhs (new_stmt)))
! 	{
! 	  tree vdef;
! 	  if (!laststore)
! 	    vdef = gimple_vdef (stmt);
! 	  else
! 	    vdef = make_ssa_name (gimple_vop (cfun), new_stmt);
! 	  gimple_set_vdef (new_stmt, vdef);
! 	  SSA_NAME_DEF_STMT (vdef) = new_stmt;
! 	  laststore = new_stmt;
! 	}
!     }
! 
!   /* Second iterate over the statements forward, assigning virtual
!      operands to their uses.  */
!   last = NULL;
!   reaching_vuse = gimple_vuse (stmt);
    for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
      {
+       /* Do not insert the last stmt in this loop but remember it
+          for replacing the original statement.  */
        if (last)
  	{
  	  gsi_insert_before (si_p, last, GSI_NEW_STMT);
  	  gsi_next (si_p);
  	}
        new_stmt = gsi_stmt (i);
+       /* The replacement can expose previously unreferenced variables.  */
        if (gimple_in_ssa_p (cfun))
  	find_new_referenced_vars (new_stmt);
        /* If the new statement possibly has a VUSE, update it with exact SSA
  	 name we know will reach this one.  */
        if (gimple_has_mem_ops (new_stmt))
! 	gimple_set_vuse (new_stmt, reaching_vuse);
!       gimple_set_modified (new_stmt, true);
!       if (gimple_vdef (new_stmt))
! 	reaching_vuse = gimple_vdef (new_stmt);
        last = new_stmt;
      }
  
!   /* If the new sequence does not do a store release the virtual
!      definition of the original statement.  */
!   if (reaching_vuse
!       && reaching_vuse == gimple_vuse (stmt))
      {
!       tree vdef = gimple_vdef (stmt);
!       if (vdef)
  	{
  	  unlink_stmt_vdef (stmt);
! 	  release_ssa_name (vdef);
  	}
      }
  
!   /* Finally replace rhe original statement with the last.  */
!   gsi_replace (si_p, last, false);
  }
  
  /* Return the string length, maximum string length or maximum value of
Index: gcc/testsuite/gcc.dg/torture/pr50768.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr50768.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr50768.c	(revision 0)
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do compile } */
+ /* { dg-options "-ftracer" } */
+ 
+ char data[8];
+ int l1;
+ 
+ void
+ test1 (void)
+ {
+   char buf[8];
+   __builtin___mempcpy_chk (buf, data, l1 ? sizeof (buf) : 4,
+ 			   __builtin_object_size (buf, 0));
+   if (__builtin___memmove_chk
+       (buf, data, l1 ? sizeof (buf) : 4,
+        __builtin_object_size (buf, 0)) != buf)
+     __builtin_abort ();
+ }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2011-10-19 10:09 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-19 12:14 [PATCH] Fix PR50768, rewrite gimplify_and_update_call_from_tree Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).