aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/builtins.c41
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20030626-1.c13
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20030626-2.c14
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/string-opt-16.c10
6 files changed, 60 insertions, 34 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 90789f4..f06e8a6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
* config/ia64/ia64.h (REGISTER_NAMES): R0 is really AP.
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 3872fd56..44ecbde 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -4492,8 +4492,8 @@ expand_builtin_cabs (tree arglist, rtx target)
static rtx
expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
{
- tree dest, fmt, stripped;
- tree orig_arglist;
+ tree orig_arglist, dest, fmt;
+ const char *fmt_str;
orig_arglist = arglist;
@@ -4512,36 +4512,33 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
arglist = TREE_CHAIN (arglist);
/* Check whether the format is a literal string constant. */
- stripped = fmt;
- STRIP_NOPS (stripped);
- if (stripped && TREE_CODE (stripped) == ADDR_EXPR)
- stripped = TREE_OPERAND (stripped, 0);
- if (TREE_CODE (stripped) != STRING_CST)
+ fmt_str = c_getstr (fmt);
+ if (fmt_str == NULL)
return 0;
/* 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 exp;
- if (arglist || !fn)
+ if (arglist || ! fn)
return 0;
expand_expr (build_function_call_expr (fn, orig_arglist),
const0_rtx, VOIDmode, EXPAND_NORMAL);
if (target == 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));
return expand_expr (exp, target, mode, EXPAND_NORMAL);
}
- /* If the format is "%s", use strcpy and possibly strlen. */
- else if (strcmp (TREE_STRING_POINTER (stripped), "%s") == 0)
+ /* If the format is "%s", use strcpy if the result isn't used. */
+ else if (strcmp (fmt_str, "%s") == 0)
{
- tree strcpy_fn, strlen_fn, exp, arg;
- strcpy_fn = implicit_built_in_decls[BUILT_IN_STRCPY];
+ tree fn, arg, len;
+ fn = implicit_built_in_decls[BUILT_IN_STRCPY];
- if (! strcpy_fn)
+ if (! fn)
return 0;
if (! arglist || TREE_CHAIN (arglist))
@@ -4552,25 +4549,21 @@ expand_builtin_sprintf (tree arglist, rtx target, enum machine_mode mode)
if (target != const0_rtx)
{
- strlen_fn = implicit_built_in_decls[BUILT_IN_STRLEN];
- if (! strlen_fn)
+ len = c_strlen (arg);
+ if (! len || TREE_CODE (len) != INTEGER_CST)
return 0;
- arg = save_expr (arg);
}
else
- strlen_fn = 0;
+ len = NULL_TREE;
arglist = build_tree_list (NULL_TREE, arg);
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);
if (target == const0_rtx)
return const0_rtx;
-
- 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 expand_expr (len, target, mode, EXPAND_NORMAL);
}
return 0;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index df08e07..51bed04 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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>
* gcc.c-torture/execute/multi-ix.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20030626-1.c b/gcc/testsuite/gcc.c-torture/execute/20030626-1.c
new file mode 100644
index 0000000..8b985f0
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20030626-1.c
@@ -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;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/20030626-2.c b/gcc/testsuite/gcc.c-torture/execute/20030626-2.c
new file mode 100644
index 0000000..5483d0c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20030626-2.c
@@ -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;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/string-opt-16.c b/gcc/testsuite/gcc.c-torture/execute/string-opt-16.c
index 82f3c41..8556b8f 100644
--- a/gcc/testsuite/gcc.c-torture/execute/string-opt-16.c
+++ b/gcc/testsuite/gcc.c-torture/execute/string-opt-16.c
@@ -38,10 +38,6 @@ void test5(char *ptr)
sprintf(buffer,"%s",ptr);
}
-int test6(char *ptr)
-{
- return sprintf(buffer,"%s",ptr);
-}
int main()
{
@@ -72,12 +68,6 @@ int main()
if (memcmp(buffer, "barf", 5) || buffer[5] != 'A')
abort ();
- memset (buffer, 'A', 32);
- if (test6 ("barf") != 4)
- abort ();
- if (memcmp(buffer, "barf", 5) || buffer[5] != 'A')
- abort ();
-
return 0;
}