From: Martin Sebor Date: Tue, 9 Jul 2019 23:29:33 +0000 (+0000) Subject: PR tree-optimization X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c2e8bd51418b927c2b31f48aa9cd630d94a59b3a;p=gcc.git PR tree-optimization gcc/ChangeLog: PR tree-optimization * tree-ssa-strlen.c (handle_char_store): Constrain a single character optimization to just single character stores. gcc/testsuite/ChangeLog: PR tree-optimization * gcc.dg/strlenopt-26.c: Exit with test result status. * gcc.dg/strlenopt-67.c: New test. From-SVN: r273317 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4ae2fd81261..f37b1f061e8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Martin Sebor + + PR tree-optimization/90989 + * tree-ssa-strlen.c (handle_char_store): Constrain a single character + optimization to just single character stores. + 2019-07-09 Joern Rennecke * tree-vect-stmts.c (vectorizable_comparison) : diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bf7c992afb9..b0255219450 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-07-09 Martin Sebor + + PR tree-optimization/90989 + * gcc.dg/strlenopt-26.c: Exit with test result status. + * gcc.dg/strlenopt-67.c: New test. + 2019-07-09 Dragan Mladjenovic * gcc.target/mips/cfgcleanup-jalr1.c: New test. diff --git a/gcc/testsuite/gcc.dg/strlenopt-26.c b/gcc/testsuite/gcc.dg/strlenopt-26.c index da2f465a5b5..6bb0263d315 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-26.c +++ b/gcc/testsuite/gcc.dg/strlenopt-26.c @@ -17,8 +17,7 @@ main (void) { char p[] = "foobar"; const char *volatile q = "xyzzy"; - fn1 (p, q); - return 0; + return fn1 (p, q); } /* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */ diff --git a/gcc/testsuite/gcc.dg/strlenopt-67.c b/gcc/testsuite/gcc.dg/strlenopt-67.c new file mode 100644 index 00000000000..a2bcfba68ba --- /dev/null +++ b/gcc/testsuite/gcc.dg/strlenopt-67.c @@ -0,0 +1,104 @@ +/* PR tree-optimization/90989 - incorrrect strlen result after second strcpy + into the same destination. + { dg-do compile } + { dg-options "-O2 -Wall -fdump-tree-optimized" } */ + +// #include "strlenopt.h" + +char a[4]; + +int f4 (void) +{ + char b[4]; + __builtin_strcpy (b, "12"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "123"); + if (__builtin_strlen (b) != 3) + __builtin_abort (); + + return i; +} + +int f6 (void) +{ + char b[6]; + __builtin_strcpy (b, "1234"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "12345"); + if (__builtin_strlen (b) != 5) + __builtin_abort (); + + return i; +} + +int f8 (void) +{ + char b[8]; + __builtin_strcpy (b, "1234"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "1234567"); + if (__builtin_strlen (b) != 7) + __builtin_abort (); + + return i; +} + +/* { dg-final { scan-tree-dump-times "abort|strlen" 0 "optimized" } } */ +/* PR tree-optimization/ - incorrrect strlen result after second strcpy + into the same destination. + { dg-do compile } + { dg-options "-O2 -Wall -fdump-tree-optimized" } */ + +// #include "strlenopt.h" + +char a[4]; + +int f4 (void) +{ + char b[4]; + __builtin_strcpy (b, "12"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "123"); + if (__builtin_strlen (b) != 3) + __builtin_abort (); + + return i; +} + +int f6 (void) +{ + char b[6]; + __builtin_strcpy (b, "1234"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "12345"); + if (__builtin_strlen (b) != 5) + __builtin_abort (); + + return i; +} + +int f8 (void) +{ + char b[8]; + __builtin_strcpy (b, "1234"); + + int i = __builtin_strcmp (a, b); + + __builtin_strcpy (b, "1234567"); + if (__builtin_strlen (b) != 7) + __builtin_abort (); + + return i; +} + +/* { dg-final { scan-tree-dump-times "abort|strlen" 0 "optimized" } } */ diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 74cd6c44874..88b6bd7869e 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -3462,34 +3462,38 @@ handle_char_store (gimple_stmt_iterator *gsi) return false; } } - /* If si->nonzero_chars > OFFSET, we aren't overwriting '\0', - and if we aren't storing '\0', we know that the length of the - string and any other zero terminated string in memory remains - the same. In that case we move to the next gimple statement and - return to signal the caller that it shouldn't invalidate anything. - - This is benefical for cases like: - - char p[20]; - void foo (char *q) - { - strcpy (p, "foobar"); - size_t len = strlen (p); // This can be optimized into 6 - size_t len2 = strlen (q); // This has to be computed - p[0] = 'X'; - size_t len3 = strlen (p); // This can be optimized into 6 - size_t len4 = strlen (q); // This can be optimized into len2 - bar (len, len2, len3, len4); - } - */ - else if (storing_nonzero_p && cmp > 0) + + if (cmp > 0 + && storing_nonzero_p + && TREE_CODE (TREE_TYPE (rhs)) == INTEGER_TYPE) { + /* Handle a single non-nul character store. + If si->nonzero_chars > OFFSET, we aren't overwriting '\0', + and if we aren't storing '\0', we know that the length of the + string and any other zero terminated string in memory remains + the same. In that case we move to the next gimple statement and + return to signal the caller that it shouldn't invalidate anything. + + This is benefical for cases like: + + char p[20]; + void foo (char *q) + { + strcpy (p, "foobar"); + size_t len = strlen (p); // can be folded to 6 + size_t len2 = strlen (q); // has to be computed + p[0] = 'X'; + size_t len3 = strlen (p); // can be folded to 6 + size_t len4 = strlen (q); // can be folded to len2 + bar (len, len2, len3, len4); + } */ gsi_next (gsi); return false; } - else if (storing_all_zeros_p - || storing_nonzero_p - || (offset != 0 && cmp > 0)) + + if (storing_all_zeros_p + || storing_nonzero_p + || (offset != 0 && cmp > 0)) { /* When STORING_NONZERO_P, we know that the string will start with at least OFFSET + 1 nonzero characters. If storing