PR 81292: ICE on related strlens after r249880
authorRichard Sandiford <richard.sandiford@linaro.org>
Tue, 4 Jul 2017 11:48:44 +0000 (11:48 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 4 Jul 2017 11:48:44 +0000 (11:48 +0000)
r249880 installed the result of a strlen in a strinfo if the strinfo
wasn't previously a full string.  But as Jakub says in the PR comments,
we can't just do that in isolation, because there are no vdefs on the
call that would invalidate any related strinfos.

This patch updates the related strinfos if the adjustment is simple and
invalidates them otherwise.  As elsewhere, we treat adjustments of the
form strlen +/- INTEGER_CST as simple but anything else as too complex.

2017-07-04  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
PR tree-optimization/81292
* tree-ssa-strlen.c (handle_builtin_strlen): When setting
full_string_p, also call adjust_related_strinfos if the adjustment
is simple, otherwise invalidate related strinfos.

gcc/testsuite/
PR tree-optimization/81292
* gcc.dg/pr81292-1.c: New test.
* gcc.dg/pr81292-2.c: Likewise.

From-SVN: r249961

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr81292-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr81292-2.c [new file with mode: 0644]
gcc/tree-ssa-strlen.c

index dda6ea47ea554ec4efdbd00b00d04a4a3a4baf7e..b262a646aec6e9a1279727e0219881cd75b0394d 100644 (file)
@@ -1,3 +1,10 @@
+2017-07-04  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       PR tree-optimization/81292
+       * tree-ssa-strlen.c (handle_builtin_strlen): When setting
+       full_string_p, also call adjust_related_strinfos if the adjustment
+       is simple, otherwise invalidate related strinfos.
+
 2017-07-04  Martin Liska  <mliska@suse.cz>
 
        PR sanitizer/81040
index 7a2e2ae3a6f6898616d0a9a5f36a564d8236cf58..74f9ee6ab97f733ca5b969acb571c17f55d12889 100644 (file)
@@ -1,3 +1,9 @@
+2017-07-04  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       PR tree-optimization/81292
+       * gcc.dg/pr81292-1.c: New test.
+       * gcc.dg/pr81292-2.c: Likewise.
+
 2017-07-04  Martin Liska  <mliska@suse.cz>
 
        PR sanitizer/81040
diff --git a/gcc/testsuite/gcc.dg/pr81292-1.c b/gcc/testsuite/gcc.dg/pr81292-1.c
new file mode 100644 (file)
index 0000000..931e4c3
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#include "strlenopt.h"
+
+char a[10];
+
+int __attribute__ ((noinline, noclone))
+f1 (int n)
+{
+  a[0] = '1';
+  a[1] = '2';
+  return strlen (a + 1) < n ? strlen (a) : 100;
+}
+
+int __attribute__ ((noinline, noclone))
+f2 (char *a, int n)
+{
+  a[0] = '1';
+  a[1] = '2';
+  return strlen (a + 1) < n ? strlen (a) : 100;
+}
+
+int
+main (void)
+{
+  char b[10];
+  strcpy (a + 2, "345");
+  strcpy (b + 2, "34567");
+  if (f1 (100) != 5 || f2 (b, 100) != 7)
+    __builtin_abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/pr81292-2.c b/gcc/testsuite/gcc.dg/pr81292-2.c
new file mode 100644 (file)
index 0000000..c1c507f
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#include "strlenopt.h"
+
+char a[] = { 0, 'a', 0, 'b', 'c', 0, 'd', 'e', 'f', 0 };
+
+int __attribute__ ((noinline, noclone))
+f1 (void)
+{
+  a[0] = '1';
+  a[strlen (a)] = '2';
+  a[strlen (a)] = '3';
+  return strlen (a);
+}
+
+int __attribute__ ((noinline, noclone))
+f2 (char *a)
+{
+  a[0] = '1';
+  a[strlen (a)] = '2';
+  a[strlen (a)] = '3';
+  return strlen (a);
+}
+
+int
+main (void)
+{
+  char b[] = { 0, 0, 'a', 'b', 0, 0 };
+  if (f1 () != 9 || f2 (b) != 5)
+    __builtin_abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 6 "strlen" } } */
index 51184602a3fea222e5fcdbe233291eaff5cfbc24..b0563fe7c324001bc606b680e5ac24856b7d1d86 100644 (file)
@@ -1214,8 +1214,23 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
              /* Until now we only had a lower bound on the string length.
                 Install LHS as the actual length.  */
              si = unshare_strinfo (si);
+             tree old = si->nonzero_chars;
              si->nonzero_chars = lhs;
              si->full_string_p = true;
+             if (TREE_CODE (old) == INTEGER_CST)
+               {
+                 location_t loc = gimple_location (stmt);
+                 old = fold_convert_loc (loc, TREE_TYPE (lhs), old);
+                 tree adj = fold_build2_loc (loc, MINUS_EXPR,
+                                             TREE_TYPE (lhs), lhs, old);
+                 adjust_related_strinfos (loc, si, adj);
+               }
+             else
+               {
+                 si->first = 0;
+                 si->prev = 0;
+                 si->next = 0;
+               }
            }
          return;
        }