OSDN Git Service

2011-10-19 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Oct 2011 12:59:21 +0000 (12:59 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Oct 2011 12:59:21 +0000 (12:59 +0000)
PR middle-end/50768
* gimple-fold.c (gimplify_and_update_call_from_tree): Rewrite.

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

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

gcc/ChangeLog
gcc/gimple-fold.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr50768.c [new file with mode: 0644]

index 4a3bc75..ba3f707 100644 (file)
@@ -1,3 +1,8 @@
+2011-10-19  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/50768
+       * gimple-fold.c (gimplify_and_update_call_from_tree): Rewrite.
+
 2011-10-19  Andrey Belevantsev  <abel@ispras.ru>
 
        PR rtl-optimization/50340
index 7df7e69..aa67d24 100644 (file)
@@ -534,25 +534,22 @@ void
 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;
+  gimple last;
+  gimple laststore;
   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);
 
+  lhs = gimple_call_lhs (stmt);
   if (lhs == NULL_TREE)
     {
       gimplify_and_add (expr, &stmts);
@@ -571,105 +568,83 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
        }
     }
   else
-    tmp = get_initialized_tmp_var (expr, &stmts, NULL);
+    {
+      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));
 
-  /* The replacement can expose previously unreferenced variables.  */
+  /* 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);
+         if (TREE_CODE (vdef) == SSA_NAME)
+           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))
-       {
-         /* 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;
-       }
+       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 (lhs == NULL_TREE)
+  /* 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))
     {
-      /* 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))
+      tree vdef = gimple_vdef (stmt);
+      if (vdef
+         && TREE_CODE (vdef) == SSA_NAME)
        {
          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;
+         release_ssa_name (vdef);
        }
-      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);
+  /* 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 72c85cd..1bed600 100644 (file)
@@ -1,3 +1,8 @@
+2011-10-19  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/50768
+       * gcc.dg/torture/pr50768.c: New testcase.
+
 2011-10-19  Alexander Monakov  <amonakov@ispras.ru>
 
        PR rtl-optimization/50340
diff --git a/gcc/testsuite/gcc.dg/torture/pr50768.c b/gcc/testsuite/gcc.dg/torture/pr50768.c
new file mode 100644 (file)
index 0000000..351b2f9
--- /dev/null
@@ -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 ();
+}