From: Martin Sebor Date: Fri, 2 Aug 2019 16:57:19 +0000 (+0000) Subject: backport: PR tree-optimization/90989 - incorrrect strlen result after second strcpy X-Git-Tag: releases/gcc-9.2.0~70 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6575dd24084b1dcc246a130d66aa4015f1349c19;p=thirdparty%2Fgcc.git backport: PR tree-optimization/90989 - incorrrect strlen result after second strcpy Backport from mainline PR tree-optimization/90989 - incorrrect strlen result after second strcpy into the same destination gcc/ChangeLog: PR tree-optimization/90989 * tree-ssa-strlen.c (handle_char_store): Constrain a single character optimization to just single character stores. gcc/testsuite/ChangeLog: PR tree-optimization/90989 * gcc.dg/strlenopt-26.c: Exit with test result status. * gcc.dg/strlenopt-67.c: New test. From-SVN: r274021 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3dfa70af9e52..a967df1bd2e8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-08-02 Martin Sebor + + Backport from mainline + 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-08-02 Iain Sandoe Backport from mainline diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 65021fb36440..ec03b2ca47cd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2019-08-02 Martin Sebor + + Backport from mainline + 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-08-02 Iain Sandoe 2019-06-13 Iain Sandoe diff --git a/gcc/testsuite/gcc.dg/strlenopt-26.c b/gcc/testsuite/gcc.dg/strlenopt-26.c index da2f465a5b50..6bb0263d315b 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 000000000000..e1b1de27d9e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/strlenopt-67.c @@ -0,0 +1,52 @@ +/* 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" } } */ diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index a2dc9c7b1026..14b09ab0145e 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -3351,32 +3351,37 @@ 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