This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Gimplify result of ccp_fold_builtin if not already gimple


Hi!

fold_builtin folds strcpy (foo, "bar") into (char *) memcpy (foo, "bar", 4).
If this can be done before gimplification, it is optimized, but when this
only happens in later tree optimization phases, it is not, as
(char *) memcpy (...) is not gimple.
execute_fold_all_builtins fails to set_rhs () and throws it away.
The following patch fixes this by gimplifying it.

Bootstrapped/regtested on {i386,x86_64,s390,ppc}-redhat-linux.
Ok to commit?

2004-09-20  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-20 17:53:05.893692996 +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-20 17:55:15.863740870 +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-20 17:54:45.909028760 +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-20 18:04:32.250418533 +0200
@@ -2072,6 +2072,34 @@ 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 tmp = make_rename_temp (TREE_TYPE (expr), "FB");
+  tree stmt = build (MODIFY_EXPR, TREE_TYPE (expr), tmp, expr);
+
+  push_gimplify_context ();
+  gimplify_stmt (&stmt);
+  pop_gimplify_context (NULL);
+
+  /* The replacement can expose previously unreferenced variables.  */
+  for (ti = tsi_start (stmt); !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);
+    }
+
+  bsi_insert_before (si_p, stmt, 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 +2143,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 +2175,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-20 17:48:58.099448386 +0200
+++ gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2.c	2004-09-20 17:48:58.099448386 +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-20 17:48:58.100448209 +0200
+++ gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-2-lib.c	2004-09-20 17:48:58.101448033 +0200
@@ -0,0 +1 @@
+#include "lib/strcpy.c"

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]