diff options
author | Martin Sebor <msebor@redhat.com> | 2018-06-25 20:46:45 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2018-06-25 14:46:45 -0600 |
commit | b36bc89e32a52ac41b6b68d834c7692b890741e6 (patch) | |
tree | 5b89ff8ce0de4a470d9653841c70fa1d0d32d042 /gcc | |
parent | 03cd7d3fa2d756cb4fb7d62d4aba277893932ace (diff) | |
download | gcc-b36bc89e32a52ac41b6b68d834c7692b890741e6.zip gcc-b36bc89e32a52ac41b6b68d834c7692b890741e6.tar.gz gcc-b36bc89e32a52ac41b6b68d834c7692b890741e6.tar.bz2 |
PR tree-optimization/86204 - wrong strlen result after prior strnlen
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-46.c | 131 | ||||
-rw-r--r-- | gcc/tree-ssa-strlen.c | 34 |
4 files changed, 171 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5334c36..dedbffd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 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 * gimple-fold.c (gimple_fold_builtin_strncat): Adjust comment. * tree-ssa-strlen.c (is_strlen_related_p): Handle integer subtraction. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4606474..4a90a33 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 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 * gcc.dg/Wstringop-truncation-4.c: New test. diff --git a/gcc/testsuite/gcc.dg/strlenopt-46.c b/gcc/testsuite/gcc.dg/strlenopt-46.c new file mode 100644 index 0000000..dc6eef7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/strlenopt-46.c @@ -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); +} diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 2da82a8..5807c79 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -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)); } } |