re PR tree-optimization/83501 (strlen(a) not folded after strcpy(a, "..."))
authorMartin Sebor <msebor@gmail.com>
Thu, 11 Jan 2018 04:37:48 +0000 (04:37 +0000)
committerPrathamesh Kulkarni <prathamesh3492@gcc.gnu.org>
Thu, 11 Jan 2018 04:37:48 +0000 (04:37 +0000)
2018-01-11  Martin Sebor  <msebor@gmail.com>
    Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>

PR tree-optimization/83501
PR tree-optimization/81703

* tree-ssa-strlen.c (get_string_cst): Rename...
(get_string_len): ...to this.  Handle global constants.
(handle_char_store): Adjust.

testsuite/
* gcc.dg/strlenopt-39.c: New test-case.
* gcc.dg/pr81703.c: Likewise.

Co-Authored-By: Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
From-SVN: r256475

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

index 3662659fee064b15a26dceb45338836a77de86fb..bb6bf49107df2de756470a9411da6d6aec0ff728 100644 (file)
@@ -1,3 +1,13 @@
+2018-01-11  Martin Sebor  <msebor@gmail.com>
+           Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>
+
+       PR tree-optimization/83501
+       PR tree-optimization/81703
+
+       * tree-ssa-strlen.c (get_string_cst): Rename...
+       (get_string_len): ...to this.  Handle global constants.
+       (handle_char_store): Adjust.
+
 2018-01-10  Kito Cheng  <kito.cheng@gmail.com>
            Jim Wilson  <jimw@sifive.com>
 
index 016f6774cee51e0ade89b96320953ea4d61a62fd..dd4bfcec00ca1eb3d12737170ed54a60bf6dba2d 100644 (file)
@@ -1,3 +1,12 @@
+2018-01-11  Martin Sebor  <msebor@gmail.com>
+           Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>
+
+       PR tree-optimization/83501
+       PR tree-optimization/81703
+
+       * gcc.dg/strlenopt-39.c: New test-case.
+       * gcc.dg/pr81703.c: Likewise.
+
 2018-01-10  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/atomic10.adb: New test.
diff --git a/gcc/testsuite/gcc.dg/pr81703.c b/gcc/testsuite/gcc.dg/pr81703.c
new file mode 100644 (file)
index 0000000..190f4a8
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+unsigned g (void)
+{
+  char d[8];
+  const char s[] = "0123";
+  __builtin_memcpy (d, s, sizeof s);
+  return __builtin_strlen (d);
+}
+
+/* { dg-final { scan-tree-dump-not "__builtin_strlen" "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-39.c b/gcc/testsuite/gcc.dg/strlenopt-39.c
new file mode 100644 (file)
index 0000000..a4177c9
--- /dev/null
@@ -0,0 +1,66 @@
+/* PR tree-optimization/83444
+   { dg-do compile }
+   { dg-options "-O2 -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+#define STR "1234567"
+
+const char str[] = STR;
+
+char dst[10];
+
+void copy_from_global_str (void)
+{
+  strcpy (dst, str);
+
+  if (strlen (dst) != sizeof str - 1)
+    abort ();
+}
+
+void copy_from_local_str (void)
+{
+  const char s[] = STR;
+
+  strcpy (dst, s);
+
+  if (strlen (dst) != sizeof s - 1)
+    abort ();
+}
+
+void copy_from_local_memstr (void)
+{
+  struct {
+    char s[sizeof STR];
+  } x = { STR };
+
+  strcpy (dst, x.s);
+
+  if (strlen (dst) != sizeof x.s - 1)
+    abort ();
+}
+
+void copy_to_local_str (void)
+{
+  char d[sizeof STR];
+
+  strcpy (d, str);
+
+  if (strlen (d) != sizeof str - 1)
+    abort ();
+}
+
+void copy_to_local_memstr (void)
+{
+  struct {
+    char d[sizeof STR];
+  } x;
+
+  strcpy (x.d, str);
+
+  if (strlen (x.d) != sizeof str- 1)
+    abort ();
+}
+
+/* Verify that all calls to strlen have been eliminated.
+  { dg-final { scan-tree-dump-not "(abort|strlen) \\(\\)" "optimized" } } */
index aae242d93d6d30847bcd51f5be1d965092aea1f7..4e363278ea21792b6a148a387ec169e3c1646dfd 100644 (file)
@@ -2773,18 +2773,40 @@ handle_pointer_plus (gimple_stmt_iterator *gsi)
 }
 
 /* Check if RHS is string_cst possibly wrapped by mem_ref.  */
-static tree
-get_string_cst (tree rhs)
+static int
+get_string_len (tree rhs)
 {
   if (TREE_CODE (rhs) == MEM_REF
       && integer_zerop (TREE_OPERAND (rhs, 1)))
     {
-      rhs = TREE_OPERAND (rhs, 0);
+      tree rhs_addr = rhs = TREE_OPERAND (rhs, 0);
       if (TREE_CODE (rhs) == ADDR_EXPR)
-       rhs = TREE_OPERAND (rhs, 0);
+       {
+         rhs = TREE_OPERAND (rhs, 0);
+         if (TREE_CODE (rhs) != STRING_CST)
+           {
+             int idx = get_stridx (rhs_addr);
+             if (idx > 0)
+               {
+                 strinfo *si = get_strinfo (idx);
+                 if (si && si->full_string_p)
+                   return tree_to_shwi (si->nonzero_chars);
+               }
+           }
+       }
     }
 
-  return (TREE_CODE (rhs) == STRING_CST) ? rhs : NULL_TREE;
+  if (TREE_CODE (rhs) == VAR_DECL
+      && TREE_READONLY (rhs))
+    rhs = DECL_INITIAL (rhs);
+
+  if (rhs && TREE_CODE (rhs) == STRING_CST)
+    {
+      unsigned HOST_WIDE_INT ilen = strlen (TREE_STRING_POINTER (rhs));
+      return ilen <= INT_MAX ? ilen : -1;
+    }
+
+  return -1;
 }
 
 /* Handle a single character store.  */
@@ -2799,6 +2821,9 @@ handle_char_store (gimple_stmt_iterator *gsi)
   tree rhs = gimple_assign_rhs1 (stmt);
   unsigned HOST_WIDE_INT offset = 0;
 
+  /* Set to the length of the string being assigned if known.  */
+  int rhslen;
+
   if (TREE_CODE (lhs) == MEM_REF
       && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME)
     {
@@ -2942,19 +2967,18 @@ handle_char_store (gimple_stmt_iterator *gsi)
        }
     }
   else if (idx == 0
-          && (rhs = get_string_cst (gimple_assign_rhs1 (stmt)))
+          && (rhslen = get_string_len (gimple_assign_rhs1 (stmt))) >= 0
           && ssaname == NULL_TREE
           && TREE_CODE (TREE_TYPE (lhs)) == ARRAY_TYPE)
     {
-      size_t l = strlen (TREE_STRING_POINTER (rhs));
       HOST_WIDE_INT a = int_size_in_bytes (TREE_TYPE (lhs));
-      if (a > 0 && (unsigned HOST_WIDE_INT) a > l)
+      if (a > 0 && (unsigned HOST_WIDE_INT) a > (unsigned HOST_WIDE_INT) rhslen)
        {
          int idx = new_addr_stridx (lhs);
          if (idx != 0)
            {
              si = new_strinfo (build_fold_addr_expr (lhs), idx,
-                               build_int_cst (size_type_node, l), true);
+                               build_int_cst (size_type_node, rhslen), true);
              set_strinfo (idx, si);
              si->dont_invalidate = true;
            }