]> gcc.gnu.org Git - gcc.git/commitdiff
tree-ssa-strlen.c (get_string_length): Change assertion to STPCPY.
authorAndreas Krebbel <Andreas.Krebbel@de.ibm.com>
Mon, 24 Oct 2011 20:14:35 +0000 (20:14 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Mon, 24 Oct 2011 20:14:35 +0000 (20:14 +0000)
2011-10-24  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

* tree-ssa-strlen.c (get_string_length): Change assertion to STPCPY.
(zero_length_string): Change assertion to accept strinfo without
length but with stmt instead.
Set the endptr pointer also if starting a new chain.
(adjust_related_strinfos): Ignore strinfos marked for delayed
length computation.
(handle_builtin_strcpy): Mark earlier strinfo elements also for
delayed length computation.

2011-10-24  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

* gcc.dg/strlenopt-22.c: New testcase.
* gcc.dg/strlenopt-4.c: Change scan value for s390(x).

From-SVN: r180402

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/strlenopt-22.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/strlenopt-4.c
gcc/tree-ssa-strlen.c

index efe02f745d3381979920698bf70ab0b0564b634c..bd04d776c1873bcfc2b268e76690bd3cea2d300d 100644 (file)
@@ -1,3 +1,14 @@
+2011-10-24  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
+
+       * tree-ssa-strlen.c (get_string_length): Change assertion to STPCPY.
+       (zero_length_string): Change assertion to accept strinfo without
+       length but with stmt instead.
+       Set the endptr pointer also if starting a new chain.
+       (adjust_related_strinfos): Ignore strinfos marked for delayed
+       length computation.
+       (handle_builtin_strcpy): Mark earlier strinfo elements also for
+       delayed length computation.
+
 2011-10-24  Georg-Johann Lay  <avr@gjlay.de>
 
        PR target/50820
index 822fde544e0c8f456582cfaf7cfc0a4366b38147..0e7ee4c98e2d5037f30d8f00587e05c4c9d30113 100644 (file)
@@ -1,3 +1,8 @@
+2011-10-24  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>
+
+       * gcc.dg/strlenopt-22.c: New testcase.
+       * gcc.dg/strlenopt-4.c: Change scan value for s390(x).
+
 2011-10-24  Uros Bizjak  <ubizjak@gmail.com>
 
        * gcc.target/i386/sse-5.c (dg-options): Add -mno-sse.
diff --git a/gcc/testsuite/gcc.dg/strlenopt-22.c b/gcc/testsuite/gcc.dg/strlenopt-22.c
new file mode 100644 (file)
index 0000000..541bfdc
--- /dev/null
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#define USE_GNU
+#include "strlenopt.h"
+
+__attribute__((noinline, noclone)) size_t
+bar (char *p, char *q)
+{
+  size_t l1, l2, l3;
+  char *r = strchr (p, '\0');
+  strcpy (r, "abcde");
+  char *s = strchr (r, '\0');
+  strcpy (s, q);
+  l1 = strlen (p);
+  l2 = strlen (r);
+  l3 = strlen (s);
+  return l1 + l2 + l3;
+}
+
+int
+main ()
+{
+  char buf[16] = "01234";
+
+  if (bar (buf, "56789") != 30)
+    abort ();
+
+  if (memcmp (buf, "01234abcde56789", 16) != 0)
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen" } } */
+/* { dg-final { cleanup-tree-dump "strlen" } } */
index beea4959245f17d5e7036229f02bf6544437fb9e..5997d31985fab3cd7865c555af6e6034b2cb4051 100644 (file)
@@ -66,10 +66,16 @@ main ()
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" } } */
+/* For targets providing a movstr pattern strcat is already decomposed
+   into strlen + strcpy by fold_builtin_strcat.  */
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" { target { ! s390*-*-* } } } } */
+/* { dg-final { scan-tree-dump-times "strlen \\(" 6 "strlen" { target s390*-*-* } } } */
 /* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "strcpy \\(" 3 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "strcat \\(" 3 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "strcpy \\(" 3 "strlen" { target { ! s390*-*-* } } } } */
+/* { dg-final { scan-tree-dump-times "strcpy \\(" 6 "strlen" { target s390*-*-* } } } */
+/* { dg-final { scan-tree-dump-times "strcat \\(" 3 "strlen" { target { ! s390*-*-* } } } } */
+/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" { target s390*-*-* } } } */
 /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
 /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
 /* { dg-final { cleanup-tree-dump "strlen" } } */
index 697340f535aaa2b77d1e19fd473126a93c84e25f..72da15e9893e53960bda14de7fc7c505b7bdcbc8 100644 (file)
@@ -397,7 +397,7 @@ get_string_length (strinfo si)
       callee = gimple_call_fndecl (stmt);
       gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
       lhs = gimple_call_lhs (stmt);
-      gcc_assert (builtin_decl_implicit_p (BUILT_IN_STRCPY));
+      gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
       /* unshare_strinfo is intentionally not called here.  The (delayed)
         transformation of strcpy or strcat into stpcpy is done at the place
         of the former strcpy/strcat call and so can affect all the strinfos
@@ -588,13 +588,13 @@ zero_length_string (tree ptr, strinfo chainsi)
                  || si->prev != chainsi->idx)
                break;
            }
-         gcc_assert (chainsi->length);
+         gcc_assert (chainsi->length || chainsi->stmt);
          if (chainsi->endptr == NULL_TREE)
            {
              chainsi = unshare_strinfo (chainsi);
              chainsi->endptr = ptr;
            }
-         if (integer_zerop (chainsi->length))
+         if (chainsi->length && integer_zerop (chainsi->length))
            {
              if (chainsi->next)
                {
@@ -626,6 +626,8 @@ zero_length_string (tree ptr, strinfo chainsi)
       if (chainsi->first == 0)
        chainsi->first = chainsi->idx;
       chainsi->next = idx;
+      if (chainsi->endptr == NULL_TREE)
+       chainsi->endptr = ptr;
       si->prev = chainsi->idx;
       si->first = chainsi->first;
       si->writable = chainsi->writable;
@@ -654,11 +656,19 @@ adjust_related_strinfos (location_t loc, strinfo origsi, tree adj)
          tree tem;
 
          si = unshare_strinfo (si);
-         gcc_assert (si->length);
-         tem = fold_convert_loc (loc, TREE_TYPE (si->length), adj);
-         si->length = fold_build2_loc (loc, PLUS_EXPR,
-                                       TREE_TYPE (si->length), si->length,
-                                       tem);
+         if (si->length)
+           {
+             tem = fold_convert_loc (loc, TREE_TYPE (si->length), adj);
+             si->length = fold_build2_loc (loc, PLUS_EXPR,
+                                           TREE_TYPE (si->length), si->length,
+                                           tem);
+           }
+         else if (si->stmt != NULL)
+           /* Delayed length computation is unaffected.  */
+           ;
+         else
+           gcc_unreachable ();
+
          si->endptr = NULL_TREE;
          si->dont_invalidate = true;
        }
@@ -1117,10 +1127,30 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
 
   if (dsi->length == NULL_TREE)
     {
+      strinfo chainsi;
+
       /* If string length of src is unknown, use delayed length
         computation.  If string lenth of dst will be needed, it
         can be computed by transforming this strcpy call into
         stpcpy and subtracting dst from the return value.  */
+
+      /* Look for earlier strings whose length could be determined if
+        this strcpy is turned into an stpcpy.  */
+
+      if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
+       {
+         for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
+           {
+             /* When setting a stmt for delayed length computation
+                prevent all strinfos through dsi from being
+                invalidated.  */
+             chainsi = unshare_strinfo (chainsi);
+             chainsi->stmt = stmt;
+             chainsi->length = NULL_TREE;
+             chainsi->endptr = NULL_TREE;
+             chainsi->dont_invalidate = true;
+           }
+       }
       dsi->stmt = stmt;
       return;
     }
This page took 0.141226 seconds and 5 git commands to generate.