mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
03cd7d3fa2
commit
b36bc89e32
|
|
@ -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>
|
2018-06-25 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
PR tree-optimization/85700
|
PR tree-optimization/85700
|
||||||
|
|
|
||||||
|
|
@ -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>
|
2018-06-25 Martin Sebor <msebor@redhat.com>
|
||||||
|
|
||||||
PR tree-optimization/85700
|
PR tree-optimization/85700
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -1270,8 +1270,20 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
|
||||||
rhs = unshare_expr (rhs);
|
rhs = unshare_expr (rhs);
|
||||||
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
|
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
|
||||||
rhs = fold_convert_loc (loc, TREE_TYPE (lhs), 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)
|
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))
|
if (!update_call_from_tree (gsi, rhs))
|
||||||
gimplify_and_update_call_from_tree (gsi, rhs);
|
gimplify_and_update_call_from_tree (gsi, rhs);
|
||||||
stmt = gsi_stmt (*gsi);
|
stmt = gsi_stmt (*gsi);
|
||||||
|
|
@ -1281,6 +1293,12 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
|
||||||
fprintf (dump_file, "into: ");
|
fprintf (dump_file, "into: ");
|
||||||
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
|
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
|
if (si != NULL
|
||||||
&& TREE_CODE (si->nonzero_chars) != SSA_NAME
|
&& TREE_CODE (si->nonzero_chars) != SSA_NAME
|
||||||
&& TREE_CODE (si->nonzero_chars) != INTEGER_CST
|
&& 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))
|
if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
idx = new_stridx (src);
|
idx = new_stridx (src);
|
||||||
else
|
else
|
||||||
|
|
@ -1333,9 +1352,14 @@ handle_builtin_strlen (gimple_stmt_iterator *gsi)
|
||||||
}
|
}
|
||||||
if (idx)
|
if (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);
|
strinfo *si = new_strinfo (src, idx, lhs, true);
|
||||||
set_strinfo (idx, si);
|
set_strinfo (idx, si);
|
||||||
find_equal_ptrs (src, idx);
|
find_equal_ptrs (src, idx);
|
||||||
|
}
|
||||||
|
|
||||||
/* For SRC that is an array of N elements, set LHS's range
|
/* For SRC that is an array of N elements, set LHS's range
|
||||||
to [0, min (N, BOUND)]. A constant return value means
|
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));
|
strlen_to_stridx->put (lhs, stridx_strlenloc (idx, loc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue