builtins.c (expand_builtin_sprintf): Use c_getstr and strlen to obtain the format string instead of using...

* builtins.c (expand_builtin_sprintf): Use c_getstr and strlen to
	obtain the format string instead of using TREE_STRING_POINTER and
	TREE_STRING_LENGTH.  Only optimize sprintf(dst,"%s",src) when the
	return value is unused or the length of src is a known constant.

	* gcc.c-torture/execute/string-opt-16.c: Remove test for disabled
	sprintf(dst,"%s",src) optimization.
	* gcc.c-torture/execute/20030626-1.c: New test case.
	* gcc.c-torture/execute/20030626-2.c: New test case.

Co-Authored-By: Jakub Jelinek <jakub@redhat.com>

From-SVN: r68555
This commit is contained in:
Roger Sayle 2003-06-27 02:50:19 +00:00 committed by Roger Sayle
parent 34cd7ff698
commit 6ba701c8e9
6 changed files with 60 additions and 34 deletions

View File

@ -1,3 +1,11 @@
2003-06-26 Roger Sayle <roger@eyesopen.com>
Jakub Jelinek <jakub@redhat.com>
* builtins.c (expand_builtin_sprintf): Use c_getstr and strlen to
obtain the format string instead of using TREE_STRING_POINTER and
TREE_STRING_LENGTH. Only optimize sprintf(dst,"%s",src) when the
return value is unused or the length of src is a known constant.
2003-06-26 Richard Henderson <rth@redhat.com> 2003-06-26 Richard Henderson <rth@redhat.com>
* config/ia64/ia64.h (REGISTER_NAMES): R0 is really AP. * config/ia64/ia64.h (REGISTER_NAMES): R0 is really AP.

View File

@ -4492,8 +4492,8 @@ expand_builtin_cabs (tree arglist, rtx target)
static rtx static rtx
expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode) expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
{ {
tree dest, fmt, stripped; tree orig_arglist, dest, fmt;
tree orig_arglist; const char *fmt_str;
orig_arglist = arglist; orig_arglist = arglist;
@ -4512,36 +4512,33 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
arglist = TREE_CHAIN (arglist); arglist = TREE_CHAIN (arglist);
/* Check whether the format is a literal string constant. */ /* Check whether the format is a literal string constant. */
stripped = fmt; fmt_str = c_getstr (fmt);
STRIP_NOPS (stripped); if (fmt_str == NULL)
if (stripped && TREE_CODE (stripped) == ADDR_EXPR)
stripped = TREE_OPERAND (stripped, 0);
if (TREE_CODE (stripped) != STRING_CST)
return 0; return 0;
/* If the format doesn't contain % args or %%, use strcpy. */ /* If the format doesn't contain % args or %%, use strcpy. */
if (strchr (TREE_STRING_POINTER (stripped), '%') == 0) if (strchr (fmt_str, '%') == 0)
{ {
tree fn = implicit_built_in_decls[BUILT_IN_STRCPY]; tree fn = implicit_built_in_decls[BUILT_IN_STRCPY];
tree exp; tree exp;
if (arglist || !fn) if (arglist || ! fn)
return 0; return 0;
expand_expr (build_function_call_expr (fn, orig_arglist), expand_expr (build_function_call_expr (fn, orig_arglist),
const0_rtx, VOIDmode, EXPAND_NORMAL); const0_rtx, VOIDmode, EXPAND_NORMAL);
if (target == const0_rtx) if (target == const0_rtx)
return const0_rtx; return const0_rtx;
exp = build_int_2 (TREE_STRING_LENGTH (stripped) - 1, 0); exp = build_int_2 (strlen (fmt_str), 0);
exp = fold (build1 (NOP_EXPR, integer_type_node, exp)); exp = fold (build1 (NOP_EXPR, integer_type_node, exp));
return expand_expr (exp, target, mode, EXPAND_NORMAL); return expand_expr (exp, target, mode, EXPAND_NORMAL);
} }
/* If the format is "%s", use strcpy and possibly strlen. */ /* If the format is "%s", use strcpy if the result isn't used. */
else if (strcmp (TREE_STRING_POINTER (stripped), "%s") == 0) else if (strcmp (fmt_str, "%s") == 0)
{ {
tree strcpy_fn, strlen_fn, exp, arg; tree fn, arg, len;
strcpy_fn = implicit_built_in_decls[BUILT_IN_STRCPY]; fn = implicit_built_in_decls[BUILT_IN_STRCPY];
if (! strcpy_fn) if (! fn)
return 0; return 0;
if (! arglist || TREE_CHAIN (arglist)) if (! arglist || TREE_CHAIN (arglist))
@ -4552,25 +4549,21 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
if (target != const0_rtx) if (target != const0_rtx)
{ {
strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN]; len = c_strlen (arg);
if (! strlen_fn) if (! len || TREE_CODE (len) != INTEGER_CST)
return 0; return 0;
arg = save_expr (arg);
} }
else else
strlen_fn = 0; len = NULL_TREE;
arglist = build_tree_list (NULL_TREE, arg); arglist = build_tree_list (NULL_TREE, arg);
arglist = tree_cons (NULL_TREE, dest, arglist); arglist = tree_cons (NULL_TREE, dest, arglist);
expand_expr (build_function_call_expr (strcpy_fn, arglist), expand_expr (build_function_call_expr (fn, arglist),
const0_rtx, VOIDmode, EXPAND_NORMAL); const0_rtx, VOIDmode, EXPAND_NORMAL);
if (target == const0_rtx) if (target == const0_rtx)
return const0_rtx; return const0_rtx;
return expand_expr (len, target, mode, EXPAND_NORMAL);
exp = build_function_call_expr (strlen_fn, TREE_CHAIN (arglist));
exp = fold (build1 (NOP_EXPR, integer_type_node, exp));
return expand_expr (exp, target, mode, EXPAND_NORMAL);
} }
return 0; return 0;

View File

@ -1,3 +1,11 @@
2003-06-26 Roger Sayle <roger@eyesopen.com>
Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/execute/string-opt-16.c: Remove test for disabled
sprintf(dst,"%s",src) optimization.
* gcc.c-torture/execute/20030626-1.c: New test case.
* gcc.c-torture/execute/20030626-2.c: New test case.
2003-06-26 J"orn Rennecke <joern.rennecke@superh.com> 2003-06-26 J"orn Rennecke <joern.rennecke@superh.com>
* gcc.c-torture/execute/multi-ix.c: New test. * gcc.c-torture/execute/multi-ix.c: New test.

View File

@ -0,0 +1,13 @@
char buf[10];
extern void abort (void);
extern int sprintf (char*, const char*, ...);
int main()
{
int l = sprintf (buf, "foo\0bar");
if (l != 3)
abort ();
return 0;
}

View File

@ -0,0 +1,14 @@
char buf[40];
extern int sprintf (char*, const char*, ...);
extern void abort (void);
int main()
{
int i = 0;
int l = sprintf (buf, "%s", i++ ? "string" : "other string");
if (l != sizeof ("other string") - 1 || i != 1)
abort ();
return 0;
}

View File

@ -38,10 +38,6 @@ void test5(char *ptr)
sprintf(buffer,"%s",ptr); sprintf(buffer,"%s",ptr);
} }
int test6(char *ptr)
{
return sprintf(buffer,"%s",ptr);
}
int main() int main()
{ {
@ -72,12 +68,6 @@ int main()
if (memcmp(buffer, "barf", 5) || buffer[5] != 'A') if (memcmp(buffer, "barf", 5) || buffer[5] != 'A')
abort (); abort ();
memset (buffer, 'A', 32);
if (test6 ("barf") != 4)
abort ();
if (memcmp(buffer, "barf", 5) || buffer[5] != 'A')
abort ();
return 0; return 0;
} }