+2004-09-23 Diego Novillo <dnovillo@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ * tree-flow.h (find_new_referenced_vars): Add prototype.
+ * tree-sra.c (find_new_referenced_vars_1, find_new_referenced_vars):
+ Move to...
+ * tree-dfa.c (find_new_referenced_vars_1, find_new_referenced_vars):
+ ... here.
+ (mark_new_vars_to_rename): Walk through all operands.
+ * tree-ssa-ccp.c (convert_to_gimple_builtin): New function.
+ (execute_fold_all_builtins): Use it.
+ (pass_fold_builtins): Add TODO_rename_vars to todo_flags_finish.
+
2004-09-23 P.J. Darcy <darcypj@us.ibm.com>
* gthr-tpf.h: New file.
+2004-09-23 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.c-torture/execute/builtins/strcpy-2.c: New test.
+ * gcc.c-torture/execute/builtins/strcpy-2-lib.c: New.
+
2004-09-23 Andrew Pinski <pinskia@physics.uc.edu>
PR c++/17618
--- /dev/null
+#include "lib/strcpy.c"
--- /dev/null
+/* Copyright (C) 2004 Free Software Foundation.
+
+ Ensure builtin strcpy is optimized into memcpy
+ even when there is more than one possible string literal
+ passed to it, but all string literals passed to it
+ have equal length.
+
+ Written by Jakub Jelinek, 9/15/2004. */
+
+extern void abort (void);
+extern char *strcpy (char *, const char *);
+typedef __SIZE_TYPE__ size_t;
+extern void *memcpy (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+char buf[32], *p;
+int i;
+
+char *
+__attribute__((noinline))
+test (void)
+{
+ int j;
+ const char *q = "abcdefg";
+ for (j = 0; j < 3; ++j)
+ {
+ if (j == i)
+ q = "bcdefgh";
+ else if (j == i + 1)
+ q = "cdefghi";
+ else if (j == i + 2)
+ q = "defghij";
+ }
+ p = strcpy (buf, q);
+ return strcpy (buf + 16, q);
+}
+
+void
+main_test (void)
+{
+#ifndef __OPTIMIZE_SIZE__
+ /* For -Os, strcpy above is not replaced with
+ memcpy (buf, q, 8);, as that is larger. */
+ if (test () != buf + 16 || p != buf)
+ abort ();
+#endif
+}
v_may_defs_after = NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt));
v_must_defs_after = NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt));
- FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter,
- SSA_OP_VMAYDEF | SSA_OP_VUSE | SSA_OP_VMUSTDEF)
-
+ FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_ALL_OPERANDS)
{
if (DECL_P (val))
{
BITMAP_XFREE (vars_in_vops_to_rename);
}
+
+/* Find all variables within the gimplified statement that were not previously
+ visible to the function and add them to the referenced variables list. */
+
+static tree
+find_new_referenced_vars_1 (tree *tp, int *walk_subtrees,
+ void *data ATTRIBUTE_UNUSED)
+{
+ tree t = *tp;
+
+ if (TREE_CODE (t) == VAR_DECL && !var_ann (t))
+ add_referenced_tmp_var (t);
+
+ if (IS_TYPE_OR_DECL_P (t))
+ *walk_subtrees = 0;
+
+ return NULL;
+}
+
+void
+find_new_referenced_vars (tree *stmt_p)
+{
+ walk_tree (stmt_p, find_new_referenced_vars_1, NULL, NULL);
+}
extern tree get_virtual_var (tree);
extern void add_referenced_tmp_var (tree var);
extern void mark_new_vars_to_rename (tree, bitmap);
+extern void find_new_referenced_vars (tree *);
+
extern void redirect_immediate_uses (tree, tree);
extern tree make_rename_temp (tree, const char *);
}
}
-/* Find all variables within the gimplified statement that were not previously
- visible to the function and add them to the referenced variables list. */
-
-static tree
-find_new_referenced_vars_1 (tree *tp, int *walk_subtrees,
- void *data ATTRIBUTE_UNUSED)
-{
- tree t = *tp;
-
- if (TREE_CODE (t) == VAR_DECL && !var_ann (t))
- add_referenced_tmp_var (t);
-
- if (IS_TYPE_OR_DECL_P (t))
- *walk_subtrees = 0;
-
- return NULL;
-}
-
-static inline void
-find_new_referenced_vars (tree *stmt_p)
-{
- walk_tree (stmt_p, find_new_referenced_vars_1, NULL, NULL);
-}
-
/* Generate an assignment VAR = INIT, where INIT may need gimplification.
Add the result to *LIST_P. */
}
\f
+/* Convert EXPR into a GIMPLE value suitable for substitution on the
+ RHS of an assignment. Insert the necessary statements before
+ iterator *SI_P. */
+
+static tree
+convert_to_gimple_builtin (block_stmt_iterator *si_p, tree expr)
+{
+ tree_stmt_iterator ti;
+ tree stmt = bsi_stmt (*si_p);
+ tree tmp, stmts = NULL;
+
+ push_gimplify_context ();
+ tmp = get_initialized_tmp_var (expr, &stmts, NULL);
+ pop_gimplify_context (NULL);
+
+ /* The replacement can expose previously unreferenced variables. */
+ for (ti = tsi_start (stmts); !tsi_end_p (ti); tsi_next (&ti))
+ {
+ find_new_referenced_vars (tsi_stmt_ptr (ti));
+ mark_new_vars_to_rename (tsi_stmt (ti), vars_to_rename);
+ }
+
+ if (EXPR_HAS_LOCATION (stmt))
+ annotate_all_with_locus (&stmts, EXPR_LOCATION (stmt));
+
+ bsi_insert_before (si_p, stmts, BSI_SAME_STMT);
+
+ return tmp;
+}
+
+
/* A simple pass that attempts to fold all builtin functions. This pass
is run after we've propagated as many constants as we can. */
print_generic_stmt (dump_file, *stmtp, dump_flags);
}
- if (set_rhs (stmtp, result))
- modify_stmt (*stmtp);
+ if (!set_rhs (stmtp, result))
+ {
+ result = convert_to_gimple_builtin (&i, result);
+ if (result && !set_rhs (stmtp, result))
+ abort ();
+ }
+ modify_stmt (*stmtp);
if (dump_file && (dump_flags & TDF_DETAILS))
{
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func | TODO_verify_ssa, /* todo_flags_finish */
+ TODO_dump_func
+ | TODO_verify_ssa
+ | TODO_rename_vars, /* todo_flags_finish */
0 /* letter */
};