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:
parent
980889d814
commit
93a90db6b0
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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" } } */
|
|
@ -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" } } */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue