I am testing the following (old) patch to value number call lhs
according to the ERF_RETURNS_ARG annotation.  This allows for
more expression simplification and also changes downstream
users of the argument to use the return value which should help
register allocation and register lifetime in general.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

2017-11-22  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/82991
        * tree-ssa-sccvn.c (visit_use): Value number lhs of call to
        argument that we know is returned.
        (eliminate_dom_walker::eliminate_avail): Also lookup available
        leader for default defs.
        (eliminate_dom_walker::before_dom_children): Watch out for
        side-effects even if we know the value of the call result.

        * gcc.dg/tree-ssa/ssa-fre-60.c: New testcase.

Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c        (revision 255051)
+++ gcc/tree-ssa-sccvn.c        (working copy)
@@ -4131,6 +4131,26 @@ visit_use (tree use)
              changed = defs_to_varying (call_stmt);
              goto done;
            }
+
+         /* If the return value is a copy of an argument record that.  */
+         int rflags = gimple_call_return_flags (call_stmt);
+         if (rflags & ERF_RETURNS_ARG)
+           {
+             unsigned argnum = rflags & ERF_RETURN_ARG_MASK;
+             if (argnum < gimple_call_num_args (call_stmt))
+               {
+                 tree arg = gimple_call_arg (call_stmt, argnum);
+                 if (TREE_CODE (arg) == SSA_NAME
+                     || is_gimple_min_invariant (arg))
+                   {
+                     changed = visit_copy (lhs, arg);
+                     if (gimple_vdef (call_stmt))
+                       changed |= set_ssa_val_to (gimple_vdef (call_stmt),
+                                                  gimple_vdef (call_stmt));
+                     goto done;
+                   }
+               }
+           }
        }
 
       /* Pick up flags from a devirtualization target.  */
@@ -5201,10 +5221,10 @@ eliminate_dom_walker::eliminate_avail (t
   tree valnum = VN_INFO (op)->valnum;
   if (TREE_CODE (valnum) == SSA_NAME)
     {
-      if (SSA_NAME_IS_DEFAULT_DEF (valnum))
-       return valnum;
       if (avail.length () > SSA_NAME_VERSION (valnum))
        return avail[SSA_NAME_VERSION (valnum)];
+      if (SSA_NAME_IS_DEFAULT_DEF (valnum))
+       return valnum;
     }
   else if (is_gimple_min_invariant (valnum))
     return valnum;
@@ -5421,6 +5441,14 @@ eliminate_dom_walker::before_dom_childre
                eliminate_push_avail (sprime);
            }
 
+         /* While we might have value numbered a call return value to
+            one of its arguments the call itself might not be solely
+            represented by its return value.  Thus do not ignore
+            side-effects indicated by a VARYING vdef.  */
+         if (gimple_vdef (stmt)
+             && VN_INFO (gimple_vdef (stmt))->valnum == gimple_vdef (stmt))
+           sprime = NULL_TREE;
+
          /* If this now constitutes a copy duplicate points-to
             and range info appropriately.  This is especially
             important for inserted code.  See tree-ssa-copy.c
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-60.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-60.c  (nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-60.c  (working copy)
@@ -0,0 +1,43 @@
+/* { dg-do link } */
+/* { dg-options "-O -fdump-tree-fre1" } */
+
+void link_error (void);
+
+void f1 (char *p)
+{
+  char *q = __builtin_stpcpy (p, "123");
+  unsigned n = q - p;
+
+  if (n != 3)
+    link_error ();
+}
+
+char *f2 (char *p)
+{
+  char *q = __builtin_strcpy (p, "123");
+  unsigned n = q - p;
+
+  if (n)
+    link_error ();
+
+  return p;
+}
+
+char *f3 (char *p, const char *s)
+{
+  char *q = __builtin_memcpy (p, s, 3);
+  unsigned n = q - p;
+
+  if (n)
+    link_error ();
+
+  return q;
+}
+
+int main()
+{
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "link_error" 0 "fre1" } } */
+/* { dg-final { scan-tree-dump-times "return q" 2 "fre1" } } */

Reply via email to