PR tree-optimization/86204 - wrong strlen result after prior strnlen
authorMartin Sebor <msebor@redhat.com>
Mon, 25 Jun 2018 20:46:45 +0000 (20:46 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Mon, 25 Jun 2018 20:46:45 +0000 (14:46 -0600)
gcc/ChangeLog:

PR tree-optimization/86204
* tree-ssa-strlen.c (handle_builtin_strlen): Avoid storing
a strnlen result if it's less than the length of the string.

gcc/testsuite/ChangeLog:

PR tree-optimization/86204
* gcc.dg/strlenopt-46.c: New test.

From-SVN: r262114

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

index 5334c36708d55b35ce2a8148a165499107f5a39c..dedbffd651fddb3188e9de2a49d8e9923fdd9a9e 100644 (file)
@@ -1,3 +1,9 @@
+2018-06-25  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/86204
+       * tree-ssa-strlen.c (handle_builtin_strlen): Avoid storing
+       a strnlen result if it's less than the length of the string.
+
 2018-06-25  Martin Sebor  <msebor@redhat.com>
 
        PR tree-optimization/85700
index 46064749e3fadf0ea4d8730716e2b1e70d6a1f6b..4a90a33986d40497aaeef14b2b22ad3e6a106fa0 100644 (file)
@@ -1,3 +1,8 @@
+2018-06-25  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/86204
+       * gcc.dg/strlenopt-46.c: New test.
+
 2018-06-25  Martin Sebor  <msebor@redhat.com>
 
        PR tree-optimization/85700
diff --git a/gcc/testsuite/gcc.dg/strlenopt-46.c b/gcc/testsuite/gcc.dg/strlenopt-46.c
new file mode 100644 (file)
index 0000000..dc6eef7
--- /dev/null
@@ -0,0 +1,131 @@
+/* PR tree-optimization/86204 - wrong strlen result after prior strnlen
+   { dg-do run }
+   { dg-options "-O2 -Wall" } */
+
+#include "strlenopt.h"
+
+#define NOIPA   __attribute__ ((noipa))
+
+char a[] = "12345";
+
+NOIPA void f0 (void)
+{
+  unsigned n0 = strnlen (a, 0);
+  unsigned n1 = strlen (a);
+
+  if (n0 != 0 || n1 != 5)
+    abort ();
+}
+
+NOIPA void f1 (void)
+{
+  unsigned n0 = strnlen (a, 1);
+  unsigned n1 = strlen (a);
+
+  if (n0 != 1 || n1 != 5)
+    abort ();
+}
+
+NOIPA void f2 (void)
+{
+  unsigned n0 = strnlen (a, 2);
+  unsigned n1 = strlen (a);
+
+  if (n0 != 2 || n1 != 5)
+    abort ();
+}
+
+NOIPA void f3 (void)
+{
+  unsigned n0 = strnlen (a, 3);
+  unsigned n1 = strlen (a);
+
+  if (n0 != 3 || n1 != 5)
+    abort ();
+}
+
+NOIPA void f4 (void)
+{
+  unsigned n0 = strnlen (a, 4);
+  unsigned n1 = strlen (a);
+
+  if (n0 != 4 || n1 != 5)
+    abort ();
+}
+
+NOIPA void f5 (void)
+{
+  unsigned n0 = strnlen (a, 5);
+  unsigned n1 = strlen (a);
+
+  if (n0 != 5 || n1 != 5)
+    abort ();
+}
+
+NOIPA void f6 (void)
+{
+  unsigned n0 = strnlen (a, 6);
+  unsigned n1 = strlen (a);
+
+  if (n0 != 5 || n1 != 5)
+    abort ();
+}
+
+NOIPA void fx (unsigned n)
+{
+  unsigned n0 = strnlen (a, n);
+  unsigned n1 = strlen (a);
+
+  unsigned min = n < 5 ? n : 5;
+  if (n0 != min || n1 != 5)
+    abort ();
+}
+
+NOIPA void g2 (void)
+{
+  strcpy (a, "123");
+  unsigned n0 = strnlen (a, 2);
+  unsigned n1 = strlen (a);
+
+  if (n0 != 2 || n1 != 3)
+    abort ();
+}
+
+NOIPA void g7 (void)
+{
+  strcpy (a, "123");
+  unsigned n0 = strnlen (a, 7);
+  unsigned n1 = strlen (a);
+
+  if (n0 != 3 || n1 != 3)
+    abort ();
+}
+
+NOIPA void gx (unsigned n)
+{
+  strcpy (a, "123");
+  unsigned n0 = strnlen (a, n);
+  unsigned n1 = strlen (a);
+
+  unsigned min = n < 3 ? n : 3;
+  if (n0 != min || n1 != 3)
+    abort ();
+}
+
+int main (void)
+{
+  f0 ();
+  f1 ();
+  f2 ();
+  f3 ();
+  f4 ();
+  f5 ();
+  f6 ();
+  fx (2);
+  fx (7);
+
+  g2 ();
+  g7 ();
+  gx (2);
+  gx (7);
+}
index 2da82a878e3e6b2b21a26f7121b46cc6a8d3866f..5807c79f205ca8da79ef33941300febb64727c3c 100644 (file)
@@ -1270,8 +1270,20 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
          rhs = unshare_expr (rhs);
          if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
            rhs = fold_convert_loc (loc, TREE_TYPE (lhs), rhs);
+
+         /* Set for strnlen() calls with a non-constant bound.  */
+         bool noncst_bound = false;
          if (bound)
-           rhs = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
+           {
+             tree new_rhs
+               = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (rhs), rhs, bound);
+
+             noncst_bound = (TREE_CODE (new_rhs) != INTEGER_CST
+                             || tree_int_cst_lt (new_rhs, rhs));
+
+             rhs = new_rhs;
+           }
+
          if (!update_call_from_tree (gsi, rhs))
            gimplify_and_update_call_from_tree (gsi, rhs);
          stmt = gsi_stmt (*gsi);
@@ -1281,6 +1293,12 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
              fprintf (dump_file, "into: ");
              print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
            }
+
+         /* Avoid storing the length for calls to strnlen() with
+            a non-constant bound.  */
+         if (noncst_bound)
+           return;
+
          if (si != NULL
              && TREE_CODE (si->nonzero_chars) != SSA_NAME
              && TREE_CODE (si->nonzero_chars) != INTEGER_CST
@@ -1299,6 +1317,7 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
     }
   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
     return;
+
   if (idx == 0)
     idx = new_stridx (src);
   else
@@ -1333,9 +1352,14 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
     }
   if (idx)
     {
-      strinfo *si = new_strinfo (src, idx, lhs, true);
-      set_strinfo (idx, si);
-      find_equal_ptrs (src, idx);
+      if (!bound)
+       {
+         /* Only store the new length information for calls to strlen(),
+            not for those to strnlen().  */
+         strinfo *si = new_strinfo (src, idx, lhs, true);
+         set_strinfo (idx, si);
+         find_equal_ptrs (src, idx);
+       }
 
       /* For SRC that is an array of N elements, set LHS's range
         to [0, min (N, BOUND)].  A constant return value means
@@ -1362,7 +1386,7 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
              }
          }
 
-      if (strlen_to_stridx)
+      if (strlen_to_stridx && !bound)
        strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
     }
 }