tree-ssa-strlen.c (get_string_length): Change assertion to STPCPY.

2011-10-24  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* tree-ssa-strlen.c (get_string_length): Change assertion to STPCPY.
	(zero_length_string): Change assertion to accept strinfo without
	length but with stmt instead.
	Set the endptr pointer also if starting a new chain.
	(adjust_related_strinfos): Ignore strinfos marked for delayed
	length computation.
	(handle_builtin_strcpy): Mark earlier strinfo elements also for
	delayed length computation.

2011-10-24  Andreas Krebbel  <Andreas.Krebbel@de.ibm.com>

	* gcc.dg/strlenopt-22.c: New testcase.
	* gcc.dg/strlenopt-4.c: Change scan value for s390(x).

From-SVN: r180402
This commit is contained in:
Andreas Krebbel 2011-10-24 20:14:35 +00:00 committed by Andreas Krebbel
parent 980889d814
commit 93a90db6b0
5 changed files with 104 additions and 11 deletions

View File

@ -1,3 +1,14 @@
2011-10-24 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* tree-ssa-strlen.c (get_string_length): Change assertion to STPCPY.
(zero_length_string): Change assertion to accept strinfo without
length but with stmt instead.
Set the endptr pointer also if starting a new chain.
(adjust_related_strinfos): Ignore strinfos marked for delayed
length computation.
(handle_builtin_strcpy): Mark earlier strinfo elements also for
delayed length computation.
2011-10-24 Georg-Johann Lay <avr@gjlay.de>
PR target/50820

View File

@ -1,3 +1,8 @@
2011-10-24 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* gcc.dg/strlenopt-22.c: New testcase.
* gcc.dg/strlenopt-4.c: Change scan value for s390(x).
2011-10-24 Uros Bizjak <ubizjak@gmail.com>
* gcc.target/i386/sse-5.c (dg-options): Add -mno-sse.

View File

@ -0,0 +1,41 @@
/* { dg-do run } */
/* { dg-options "-O2 -fdump-tree-strlen" } */
#define USE_GNU
#include "strlenopt.h"
__attribute__((noinline, noclone)) size_t
bar (char *p, char *q)
{
size_t l1, l2, l3;
char *r = strchr (p, '\0');
strcpy (r, "abcde");
char *s = strchr (r, '\0');
strcpy (s, q);
l1 = strlen (p);
l2 = strlen (r);
l3 = strlen (s);
return l1 + l2 + l3;
}
int
main ()
{
char buf[16] = "01234";
if (bar (buf, "56789") != 30)
abort ();
if (memcmp (buf, "01234abcde56789", 16) != 0)
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen" } } */
/* { dg-final { cleanup-tree-dump "strlen" } } */

View File

@ -66,10 +66,16 @@ main ()
return 0;
}
/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" } } */
/* For targets providing a movstr pattern strcat is already decomposed
into strlen + strcpy by fold_builtin_strcat. */
/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" { target { ! s390*-*-* } } } } */
/* { dg-final { scan-tree-dump-times "strlen \\(" 6 "strlen" { target s390*-*-* } } } */
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcpy \\(" 3 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 3 "strlen" } } */
/* { dg-final { scan-tree-dump-times "strcpy \\(" 3 "strlen" { target { ! s390*-*-* } } } } */
/* { dg-final { scan-tree-dump-times "strcpy \\(" 6 "strlen" { target s390*-*-* } } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 3 "strlen" { target { ! s390*-*-* } } } } */
/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" { target s390*-*-* } } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
/* { dg-final { cleanup-tree-dump "strlen" } } */

View File

@ -397,7 +397,7 @@ get_string_length (strinfo si)
callee = gimple_call_fndecl (stmt);
gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
lhs = gimple_call_lhs (stmt);
gcc_assert (builtin_decl_implicit_p (BUILT_IN_STRCPY));
gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
/* unshare_strinfo is intentionally not called here. The (delayed)
transformation of strcpy or strcat into stpcpy is done at the place
of the former strcpy/strcat call and so can affect all the strinfos
@ -588,13 +588,13 @@ zero_length_string (tree ptr, strinfo chainsi)
|| si->prev != chainsi->idx)
break;
}
gcc_assert (chainsi->length);
gcc_assert (chainsi->length || chainsi->stmt);
if (chainsi->endptr == NULL_TREE)
{
chainsi = unshare_strinfo (chainsi);
chainsi->endptr = ptr;
}
if (integer_zerop (chainsi->length))
if (chainsi->length && integer_zerop (chainsi->length))
{
if (chainsi->next)
{
@ -626,6 +626,8 @@ zero_length_string (tree ptr, strinfo chainsi)
if (chainsi->first == 0)
chainsi->first = chainsi->idx;
chainsi->next = idx;
if (chainsi->endptr == NULL_TREE)
chainsi->endptr = ptr;
si->prev = chainsi->idx;
si->first = chainsi->first;
si->writable = chainsi->writable;
@ -654,11 +656,19 @@ adjust_related_strinfos (location_t loc, strinfo origsi, tree adj)
tree tem;
si = unshare_strinfo (si);
gcc_assert (si->length);
tem = fold_convert_loc (loc, TREE_TYPE (si->length), adj);
si->length = fold_build2_loc (loc, PLUS_EXPR,
TREE_TYPE (si->length), si->length,
tem);
if (si->length)
{
tem = fold_convert_loc (loc, TREE_TYPE (si->length), adj);
si->length = fold_build2_loc (loc, PLUS_EXPR,
TREE_TYPE (si->length), si->length,
tem);
}
else if (si->stmt != NULL)
/* Delayed length computation is unaffected. */
;
else
gcc_unreachable ();
si->endptr = NULL_TREE;
si->dont_invalidate = true;
}
@ -1117,10 +1127,30 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
if (dsi->length == NULL_TREE)
{
strinfo chainsi;
/* If string length of src is unknown, use delayed length
computation. If string lenth of dst will be needed, it
can be computed by transforming this strcpy call into
stpcpy and subtracting dst from the return value. */
/* Look for earlier strings whose length could be determined if
this strcpy is turned into an stpcpy. */
if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
{
for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
{
/* When setting a stmt for delayed length computation
prevent all strinfos through dsi from being
invalidated. */
chainsi = unshare_strinfo (chainsi);
chainsi->stmt = stmt;
chainsi->length = NULL_TREE;
chainsi->endptr = NULL_TREE;
chainsi->dont_invalidate = true;
}
}
dsi->stmt = stmt;
return;
}