mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-23 14:39:57 +08:00
builtins.c (c_strlen): Add only_value argument.
* builtins.c (c_strlen): Add only_value argument. Handle COND_EXPR and COMPOUND_EXPR. (expand_builtin_strlen): Optimize also strlen (i++ ? "foo" : "bar"). Adjust c_strlen callers. (expand_builtin_strcpy, expand_builtin_strncpy, expand_builtin_strcmp, expand_builtin_strncmp, expand_builtin_fputs, expand_builtin_sprintf, fold_builtin): Adjust c_strlen callers. * gcc.c-torture/execute/builtins/string-8.c: New test. * gcc.c-torture/execute/builtins/string-8-lib.c: New. * gcc.c-torture/execute/stdio-opt-1.c (main): Add new tests. * gcc.c-torture/execute/string-opt-7.c (main): Add new test. From-SVN: r68634
This commit is contained in:
parent
a487649ce8
commit
ae808627c3
@ -1,3 +1,14 @@
|
||||
2003-06-28 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* builtins.c (c_strlen): Add only_value argument.
|
||||
Handle COND_EXPR and COMPOUND_EXPR.
|
||||
(expand_builtin_strlen): Optimize also strlen (i++ ? "foo" : "bar").
|
||||
Adjust c_strlen callers.
|
||||
(expand_builtin_strcpy, expand_builtin_strncpy,
|
||||
expand_builtin_strcmp, expand_builtin_strncmp,
|
||||
expand_builtin_fputs, expand_builtin_sprintf,
|
||||
fold_builtin): Adjust c_strlen callers.
|
||||
|
||||
2003-06-28 Josef Zlomek <zlomekj@suse.cz>
|
||||
|
||||
* bb-reorder.c (find_traces_1_round): Do not send basic block
|
||||
|
@ -85,7 +85,7 @@ static REAL_VALUE_TYPE dconstpi;
|
||||
static REAL_VALUE_TYPE dconste;
|
||||
|
||||
static int get_pointer_alignment (tree, unsigned int);
|
||||
static tree c_strlen (tree);
|
||||
static tree c_strlen (tree, int);
|
||||
static const char *c_getstr (tree);
|
||||
static rtx c_readstr (const char *, enum machine_mode);
|
||||
static int target_char_cast (tree, char *);
|
||||
@ -242,19 +242,42 @@ get_pointer_alignment (tree exp, unsigned int max_align)
|
||||
way, because it could contain a zero byte in the middle.
|
||||
TREE_STRING_LENGTH is the size of the character array, not the string.
|
||||
|
||||
ONLY_VALUE should be non-zero if the result is not going to be emitted
|
||||
into the instruction stream and zero if it si going to be expanded.
|
||||
E.g. with i++ ? "foo" : "bar", if ONLY_VALUE is non-zero, constant 3
|
||||
is returned, otherwise NULL, since
|
||||
len = c_strlen (src, 1); if (len) expand_expr (len, ...); would not
|
||||
evaluate the side-effects.
|
||||
|
||||
The value returned is of type `ssizetype'.
|
||||
|
||||
Unfortunately, string_constant can't access the values of const char
|
||||
arrays with initializers, so neither can we do so here. */
|
||||
|
||||
static tree
|
||||
c_strlen (tree src)
|
||||
c_strlen (tree src, int only_value)
|
||||
{
|
||||
tree offset_node;
|
||||
HOST_WIDE_INT offset;
|
||||
int max;
|
||||
const char *ptr;
|
||||
|
||||
STRIP_NOPS (src);
|
||||
if (TREE_CODE (src) == COND_EXPR
|
||||
&& (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
|
||||
{
|
||||
tree len1, len2;
|
||||
|
||||
len1 = c_strlen (TREE_OPERAND (src, 1), only_value);
|
||||
len2 = c_strlen (TREE_OPERAND (src, 2), only_value);
|
||||
if (tree_int_cst_equal (len1, len2))
|
||||
return len1;
|
||||
}
|
||||
|
||||
if (TREE_CODE (src) == COMPOUND_EXPR
|
||||
&& (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0))))
|
||||
return c_strlen (TREE_OPERAND (src, 1), only_value);
|
||||
|
||||
src = string_constant (src, &offset_node);
|
||||
if (src == 0)
|
||||
return 0;
|
||||
@ -2176,10 +2199,22 @@ expand_builtin_strlen (tree arglist, rtx target,
|
||||
int align;
|
||||
|
||||
/* If the length can be computed at compile-time, return it. */
|
||||
len = c_strlen (src);
|
||||
len = c_strlen (src, 0);
|
||||
if (len)
|
||||
return expand_expr (len, target, target_mode, EXPAND_NORMAL);
|
||||
|
||||
/* If the length can be computed at compile-time and is constant
|
||||
integer, but there are side-effects in src, evaluate
|
||||
src for side-effects, then return len.
|
||||
E.g. x = strlen (i++ ? "xfoo" + 1 : "bar");
|
||||
can be optimized into: i++; x = 3; */
|
||||
len = c_strlen (src, 1);
|
||||
if (len && TREE_CODE (len) == INTEGER_CST)
|
||||
{
|
||||
expand_expr (src, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||
return expand_expr (len, target, target_mode, EXPAND_NORMAL);
|
||||
}
|
||||
|
||||
align = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
|
||||
|
||||
/* If SRC is not a pointer type, don't do this operation inline. */
|
||||
@ -2759,7 +2794,7 @@ expand_builtin_strcpy (tree arglist, rtx target, enum machine_mode mode)
|
||||
return 0;
|
||||
|
||||
src = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
len = c_strlen (src);
|
||||
len = c_strlen (src, 1);
|
||||
if (len == 0 || TREE_SIDE_EFFECTS (len))
|
||||
return 0;
|
||||
|
||||
@ -2802,7 +2837,7 @@ expand_builtin_stpcpy (tree arglist, rtx target, enum machine_mode mode)
|
||||
because the latter will potentially produce pessimized code
|
||||
when used to produce the return value. */
|
||||
src = TREE_VALUE (TREE_CHAIN (arglist));
|
||||
if (! c_getstr (src) || ! (len = c_strlen (src)))
|
||||
if (! c_getstr (src) || ! (len = c_strlen (src, 0)))
|
||||
return 0;
|
||||
|
||||
dst = TREE_VALUE (arglist);
|
||||
@ -2841,7 +2876,7 @@ expand_builtin_strncpy (tree arglist, rtx target, enum machine_mode mode)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
|
||||
tree slen = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)), 1);
|
||||
tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
||||
tree fn;
|
||||
|
||||
@ -3267,8 +3302,8 @@ expand_builtin_strcmp (tree exp, rtx target, enum machine_mode mode)
|
||||
enum machine_mode insn_mode
|
||||
= insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
|
||||
|
||||
len1 = c_strlen (arg1);
|
||||
len2 = c_strlen (arg2);
|
||||
len1 = c_strlen (arg1, 1);
|
||||
len2 = c_strlen (arg2, 1);
|
||||
|
||||
if (len1)
|
||||
len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
|
||||
@ -3414,8 +3449,8 @@ expand_builtin_strncmp (tree exp, rtx target, enum machine_mode mode)
|
||||
enum machine_mode insn_mode
|
||||
= insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode;
|
||||
|
||||
len1 = c_strlen (arg1);
|
||||
len2 = c_strlen (arg2);
|
||||
len1 = c_strlen (arg1, 1);
|
||||
len2 = c_strlen (arg2, 1);
|
||||
|
||||
if (len1)
|
||||
len1 = size_binop (PLUS_EXPR, ssize_int (1), len1);
|
||||
@ -4210,7 +4245,7 @@ expand_builtin_fputs (tree arglist, int ignore, int unlocked)
|
||||
|
||||
/* Get the length of the string passed to fputs. If the length
|
||||
can't be determined, punt. */
|
||||
if (!(len = c_strlen (TREE_VALUE (arglist)))
|
||||
if (!(len = c_strlen (TREE_VALUE (arglist), 1))
|
||||
|| TREE_CODE (len) != INTEGER_CST)
|
||||
return 0;
|
||||
|
||||
@ -4549,7 +4584,7 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
|
||||
|
||||
if (target != const0_rtx)
|
||||
{
|
||||
len = c_strlen (arg);
|
||||
len = c_strlen (arg, 1);
|
||||
if (! len || TREE_CODE (len) != INTEGER_CST)
|
||||
return 0;
|
||||
}
|
||||
@ -5441,7 +5476,7 @@ fold_builtin (tree exp)
|
||||
case BUILT_IN_STRLEN:
|
||||
if (validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
|
||||
{
|
||||
tree len = c_strlen (TREE_VALUE (arglist));
|
||||
tree len = c_strlen (TREE_VALUE (arglist), 0);
|
||||
if (len)
|
||||
{
|
||||
/* Convert from the internal "sizetype" type to "size_t". */
|
||||
|
@ -1,3 +1,10 @@
|
||||
2003-06-28 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.c-torture/execute/builtins/string-8.c: New test.
|
||||
* gcc.c-torture/execute/builtins/string-8-lib.c: New.
|
||||
* gcc.c-torture/execute/stdio-opt-1.c (main): Add new tests.
|
||||
* gcc.c-torture/execute/string-opt-7.c (main): Add new test.
|
||||
|
||||
2003-06-27 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/10468
|
||||
|
@ -0,0 +1 @@
|
||||
#include "lib/strlen.c"
|
41
gcc/testsuite/gcc.c-torture/execute/builtins/string-8.c
Normal file
41
gcc/testsuite/gcc.c-torture/execute/builtins/string-8.c
Normal file
@ -0,0 +1,41 @@
|
||||
/* Copyright (C) 2003 Free Software Foundation.
|
||||
|
||||
Test strlen optimizations on conditional expressions.
|
||||
|
||||
Written by Jakub Jelinek, June 23, 2003. */
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
extern char *strcpy (char *, const char *);
|
||||
extern int memcmp (const void *, const void *, size_t);
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
extern int inside_main;
|
||||
|
||||
size_t g, h, i, j, k, l;
|
||||
|
||||
size_t
|
||||
foo (void)
|
||||
{
|
||||
if (l)
|
||||
abort ();
|
||||
return ++l;
|
||||
}
|
||||
|
||||
void
|
||||
main_test (void)
|
||||
{
|
||||
if (strlen (i ? "foo" + 1 : j ? "bar" + 1 : "baz" + 1) != 2)
|
||||
abort ();
|
||||
if (strlen (g++ ? "foo" : "bar") != 3 || g != 1)
|
||||
abort ();
|
||||
if (strlen (h++ ? "xfoo" + 1 : "bar") != 3 || h != 1)
|
||||
abort ();
|
||||
if (strlen ((i++, "baz")) != 3 || i != 1)
|
||||
abort ();
|
||||
/* The following calls might not optimize strlen call away. */
|
||||
inside_main = 0;
|
||||
if (strlen (j ? "foo" + k++ : "bar" + k++) != 3 || k != 1)
|
||||
abort ();
|
||||
if (strlen (foo () ? "foo" : "bar") != 3 || l != 1)
|
||||
abort ();
|
||||
}
|
@ -12,6 +12,8 @@ extern void abort(void);
|
||||
If stdio.h provides one, that is okay. */
|
||||
extern int fputs();
|
||||
|
||||
int i;
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *s_array[] = {stdout, NULL}, **s_ptr = s_array;
|
||||
@ -51,6 +53,15 @@ int main()
|
||||
__builtin_fputc ('\n', *s_ptr);
|
||||
__builtin_fwrite ("hello\n", 1, 6, *s_ptr);
|
||||
|
||||
/* Check side-effects in conditional expression. */
|
||||
s_ptr = s_array;
|
||||
fputs (i++ ? "f" : "x", *s_ptr++);
|
||||
if (s_ptr != s_array+1 || *s_ptr != 0 || i != 1)
|
||||
abort();
|
||||
fputs (--i ? "\n" : "\n", *--s_ptr);
|
||||
if (s_ptr != s_array || i != 0)
|
||||
abort();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,8 @@ extern int strcmp (const char *, const char *);
|
||||
extern int strncmp (const char *, const char *, size_t);
|
||||
extern void *memset (void *, int, size_t);
|
||||
|
||||
int i;
|
||||
|
||||
int main ()
|
||||
{
|
||||
const char *const src = "hello world";
|
||||
@ -62,6 +64,12 @@ int main ()
|
||||
if (__builtin_strncpy (dst, src, 4) != dst || strncmp (dst, src, 4))
|
||||
abort();
|
||||
|
||||
memset (dst, 0, sizeof (dst));
|
||||
if (strncpy (dst, i++ ? "xfoo" + 1 : "bar", 4) != dst
|
||||
|| strcmp (dst, "bar")
|
||||
|| i != 1)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user