Commit 915afed6 by Jakub Jelinek Committed by Jakub Jelinek

tree-ssa-structalias.c (find_func_aliases_for_builtin_call): Handle…

tree-ssa-structalias.c (find_func_aliases_for_builtin_call): Handle BUILT_IN_STRDUP and BUILT_IN_STRNDUP.

	* tree-ssa-structalias.c (find_func_aliases_for_builtin_call): Handle
	BUILT_IN_STRDUP and BUILT_IN_STRNDUP.
	* tree-ssa-alias.c (call_may_clobber_ref_p_1): Likewise.  Fix
	handling of BUILT_IN_STRNCAT and BUILT_IN_STRNCAT_CHK.
	(ref_maybe_used_by_call_p_1): Fix handling of BUILT_IN_STRCAT,
	BUILT_IN_STRNCAT, BUILT_IN_STRCAT_CHK and BUILT_IN_STRNCAT_CHK.

	* gcc.dg/strlenopt-21.c: New test.

Co-Authored-By: Richard Guenther <rguenther@suse.de>

From-SVN: r179387
parent 49f836ba
2011-09-30 Jakub Jelinek <jakub@redhat.com>
Richard Guenther <rguenther@suse.de>
* tree-ssa-structalias.c (find_func_aliases_for_builtin_call): Handle
BUILT_IN_STRDUP and BUILT_IN_STRNDUP.
* tree-ssa-alias.c (call_may_clobber_ref_p_1): Likewise. Fix
handling of BUILT_IN_STRNCAT and BUILT_IN_STRNCAT_CHK.
(ref_maybe_used_by_call_p_1): Fix handling of BUILT_IN_STRCAT,
BUILT_IN_STRNCAT, BUILT_IN_STRCAT_CHK and BUILT_IN_STRNCAT_CHK.
2011-09-30 Jan Beulich <jbeulich@suse.com>
* lto-cgraph.c (output_cgraph): Remove processing of
2011-09-30 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/strlenopt-21.c: New test.
2011-09-30 Revital Eres <revital.eres@linaro.org>
* gcc.dg/sms-10.c: New file
......
/* { dg-do run } */
/* { dg-options "-O2 -fdump-tree-strlen -fdump-tree-optimized" } */
#include "strlenopt.h"
struct S { char *p; size_t l; };
__attribute__((noinline, noclone)) struct S
foo (char *x, int n)
{
int i;
char a[64];
char *p = strchr (x, '\0');
struct S s;
/* strcpy here is optimized into memcpy, length computed as p - x + 1. */
strcpy (a, x);
/* strcat here is optimized into memcpy. */
strcat (p, "abcd");
for (i = 0; i < n; i++)
if ((i % 123) == 53)
/* strcat here is optimized into strlen and memcpy. */
strcat (a, "efg");
s.p = strdup (a);
/* The strlen should be optimized here into 4. */
s.l = strlen (p);
return s;
}
int
main ()
{
char buf[32];
struct S s;
buf[0] = 'z';
buf[1] = '\0';
s = foo (buf, 0);
if (s.l != 4 || memcmp (buf, "zabcd", 6) != 0)
abort ();
if (s.p == NULL)
return 0;
if (memcmp (s.p, "z", 2) != 0)
abort ();
s = foo (buf, 60);
if (s.l != 4 || memcmp (buf, "zabcdabcd", 10) != 0)
abort ();
if (s.p == NULL)
return 0;
if (memcmp (s.p, "zabcdefg", 9) != 0)
abort ();
s = foo (buf, 240);
if (s.l != 4 || memcmp (buf, "zabcdabcdabcd", 14) != 0)
abort ();
if (s.p == NULL)
return 0;
if (memcmp (s.p, "zabcdabcdefgefg", 16) != 0)
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
/* { dg-final { scan-tree-dump-times "memcpy \\(" 3 "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 \\(" 0 "strlen" } } */
/* { dg-final { cleanup-tree-dump "strlen" } } */
......@@ -1178,8 +1178,20 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
&& DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (callee))
{
/* All the following functions clobber memory pointed to by
their first argument. */
/* All the following functions read memory pointed to by
their second argument. strcat/strncat additionally
reads memory pointed to by the first argument. */
case BUILT_IN_STRCAT:
case BUILT_IN_STRNCAT:
{
ao_ref dref;
ao_ref_init_from_ptr_and_size (&dref,
gimple_call_arg (call, 0),
NULL_TREE);
if (refs_may_alias_p_1 (&dref, ref, false))
return true;
}
/* FALLTHRU */
case BUILT_IN_STRCPY:
case BUILT_IN_STRNCPY:
case BUILT_IN_MEMCPY:
......@@ -1187,8 +1199,6 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
case BUILT_IN_MEMPCPY:
case BUILT_IN_STPCPY:
case BUILT_IN_STPNCPY:
case BUILT_IN_STRCAT:
case BUILT_IN_STRNCAT:
{
ao_ref dref;
tree size = NULL_TREE;
......@@ -1199,14 +1209,23 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
size);
return refs_may_alias_p_1 (&dref, ref, false);
}
case BUILT_IN_STRCAT_CHK:
case BUILT_IN_STRNCAT_CHK:
{
ao_ref dref;
ao_ref_init_from_ptr_and_size (&dref,
gimple_call_arg (call, 0),
NULL_TREE);
if (refs_may_alias_p_1 (&dref, ref, false))
return true;
}
/* FALLTHRU */
case BUILT_IN_STRCPY_CHK:
case BUILT_IN_STRNCPY_CHK:
case BUILT_IN_MEMCPY_CHK:
case BUILT_IN_MEMMOVE_CHK:
case BUILT_IN_MEMPCPY_CHK:
case BUILT_IN_STPCPY_CHK:
case BUILT_IN_STRCAT_CHK:
case BUILT_IN_STRNCAT_CHK:
{
ao_ref dref;
tree size = NULL_TREE;
......@@ -1226,6 +1245,19 @@ ref_maybe_used_by_call_p_1 (gimple call, ao_ref *ref)
size);
return refs_may_alias_p_1 (&dref, ref, false);
}
/* These read memory pointed to by the first argument. */
case BUILT_IN_STRDUP:
case BUILT_IN_STRNDUP:
{
ao_ref dref;
tree size = NULL_TREE;
if (gimple_call_num_args (call) == 2)
size = gimple_call_arg (call, 1);
ao_ref_init_from_ptr_and_size (&dref,
gimple_call_arg (call, 0),
size);
return refs_may_alias_p_1 (&dref, ref, false);
}
/* The following builtins do not read from memory. */
case BUILT_IN_FREE:
case BUILT_IN_MALLOC:
......@@ -1467,7 +1499,12 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
{
ao_ref dref;
tree size = NULL_TREE;
if (gimple_call_num_args (call) == 3)
/* Don't pass in size for strncat, as the maximum size
is strlen (dest) + n + 1 instead of n, resp.
n + 1 at dest + strlen (dest), but strlen (dest) isn't
known. */
if (gimple_call_num_args (call) == 3
&& DECL_FUNCTION_CODE (callee) != BUILT_IN_STRNCAT)
size = gimple_call_arg (call, 2);
ao_ref_init_from_ptr_and_size (&dref,
gimple_call_arg (call, 0),
......@@ -1486,7 +1523,12 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
{
ao_ref dref;
tree size = NULL_TREE;
if (gimple_call_num_args (call) == 4)
/* Don't pass in size for __strncat_chk, as the maximum size
is strlen (dest) + n + 1 instead of n, resp.
n + 1 at dest + strlen (dest), but strlen (dest) isn't
known. */
if (gimple_call_num_args (call) == 4
&& DECL_FUNCTION_CODE (callee) != BUILT_IN_STRNCAT_CHK)
size = gimple_call_arg (call, 2);
ao_ref_init_from_ptr_and_size (&dref,
gimple_call_arg (call, 0),
......@@ -1506,6 +1548,8 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
being the definition point for the pointer. */
case BUILT_IN_MALLOC:
case BUILT_IN_CALLOC:
case BUILT_IN_STRDUP:
case BUILT_IN_STRNDUP:
/* Unix98 specifies that errno is set on allocation failure. */
if (flag_errno_math
&& targetm.ref_may_alias_errno (ref))
......
......@@ -4130,6 +4130,24 @@ find_func_aliases_for_builtin_call (gimple t)
case BUILT_IN_REMQUOL:
case BUILT_IN_FREE:
return true;
case BUILT_IN_STRDUP:
case BUILT_IN_STRNDUP:
if (gimple_call_lhs (t))
{
handle_lhs_call (t, gimple_call_lhs (t), gimple_call_flags (t),
NULL, fndecl);
get_constraint_for_ptr_offset (gimple_call_lhs (t),
NULL_TREE, &lhsc);
get_constraint_for_ptr_offset (gimple_call_arg (t, 0),
NULL_TREE, &rhsc);
do_deref (&lhsc);
do_deref (&rhsc);
process_all_all_constraints (lhsc, rhsc);
VEC_free (ce_s, heap, lhsc);
VEC_free (ce_s, heap, rhsc);
return true;
}
break;
/* Trampolines are special - they set up passing the static
frame. */
case BUILT_IN_INIT_TRAMPOLINE:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment