This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Gimplify result of ccp_fold_builtin if not already gimple (take 2)
On Tue, Sep 21, 2004 at 05:01:11AM -0400, Jakub Jelinek wrote:
> > > + for (ti = tsi_start (stmt); !tsi_end_p (ti); tsi_next (&ti))
> >
> > ... here.
> >
> > But, given that you're recording all new temporaries by hand anyway,
> > it might be best to just use get_initialized_tmp_var instead of
> > make_rename_temp and building your own MODIFY_EXPR.
>
> I couldn't make this to work.
Sorry, posted too early.
Here is the updated patch.
2004-09-21 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.
* gcc.c-torture/execute/builtins/strcpy-2.c: New test.
* gcc.c-torture/execute/builtins/strcpy-2-lib.c: New.
--- gcc/tree-flow.h.jj 2004-09-17 12:58:21.000000000 +0200
+++ gcc/tree-flow.h 2004-09-21 10:10:07.008884678 +0200
@@ -541,6 +541,8 @@ extern void free_df_for_stmt (tree);
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 *);
--- gcc/tree-dfa.c.jj 2004-09-18 13:49:35.000000000 +0200
+++ gcc/tree-dfa.c 2004-09-21 10:10:07.010884324 +0200
@@ -978,9 +978,7 @@ mark_new_vars_to_rename (tree stmt, bitm
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))
{
@@ -1001,3 +999,27 @@ mark_new_vars_to_rename (tree stmt, bitm
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);
+}
--- gcc/tree-sra.c.jj 2004-09-18 13:49:35.000000000 +0200
+++ gcc/tree-sra.c 2004-09-21 10:10:07.012883971 +0200
@@ -1541,30 +1541,6 @@ generate_element_zero (struct sra_elt *e
}
}
-/* 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. */
--- gcc/tree-ssa-ccp.c.jj 2004-09-18 13:49:35.000000000 +0200
+++ gcc/tree-ssa-ccp.c 2004-09-21 11:16:27.043290624 +0200
@@ -2072,6 +2072,37 @@ fold_stmt (tree *stmt_p)
}
+/* 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. */
@@ -2115,8 +2146,13 @@ execute_fold_all_builtins (void)
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))
{
@@ -2142,6 +2178,8 @@ struct tree_opt_pass pass_fold_builtins
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 */
};
--- gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2.c.jj 2004-09-21 10:10:07.016883265 +0200
+++ gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2.c 2004-09-21 10:10:07.017883088 +0200
@@ -0,0 +1,47 @@
+/* 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
+}
--- gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2-lib.c.jj 2004-09-21 10:10:07.018882912 +0200
+++ gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2-lib.c 2004-09-21 10:10:07.018882912 +0200
@@ -0,0 +1 @@
+#include "lib/strcpy.c"
Jakub