aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2012-06-05 09:24:43 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2012-06-05 09:24:43 +0000
commitb6dd52618f43de2492a727317bd6af3acfa78a23 (patch)
tree80310ade27a32fd660f2a3eea597d5c759baeec8
parent44072af5b08af901bf25a728a6beecde0664e92c (diff)
downloadgcc-b6dd52618f43de2492a727317bd6af3acfa78a23.zip
gcc-b6dd52618f43de2492a727317bd6af3acfa78a23.tar.gz
gcc-b6dd52618f43de2492a727317bd6af3acfa78a23.tar.bz2
re PR tree-optimization/53081 (memcpy/memset loop recognition)
2012-06-05 Richard Guenther <rguenther@suse.de> PR tree-optimization/53081 * tree-loop-distribution.c (generate_memset_builtin): Handle all kinds of byte-sized stores. (classify_partition): Likewise. (tree_loop_distribution): Adjust seed statements used for !flag_tree_loop_distribution. * gcc.dg/tree-ssa/ldist-19.c: New testcase. * gcc.c-torture/execute/builtins/builtins.exp: Always pass -fno-tree-loop-distribute-patterns. From-SVN: r188232
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-19.c72
-rw-r--r--gcc/tree-loop-distribution.c66
5 files changed, 149 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index faae6b7..1ebee7b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2012-06-05 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/53081
+ * tree-loop-distribution.c (generate_memset_builtin): Handle all
+ kinds of byte-sized stores.
+ (classify_partition): Likewise.
+ (tree_loop_distribution): Adjust seed statements used for
+ !flag_tree_loop_distribution.
+
2012-06-05 Alan Modra <amodra@gmail.com>
* config/rs6000/rs6000.c (ptr_regno_for_savres): Comment.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c87ae14..3bfc678 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2012-06-05 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/53081
+ * gcc.dg/tree-ssa/ldist-19.c: New testcase.
+ * gcc.c-torture/execute/builtins/builtins.exp: Always pass
+ -fno-tree-loop-distribute-patterns.
+
2012-06-05 Alan Modra <amodra@gmail.com>
* gcc.target/powerpc/savres.c: Add -mdynamic-no-pic for darwin.
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp b/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
index a54f3c1..f7cc82b 100644
--- a/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/builtins.exp
@@ -37,7 +37,7 @@ load_lib c-torture.exp
torture-init
set-torture-options $C_TORTURE_OPTIONS {{}} $LTO_TORTURE_OPTIONS
-set additional_flags ""
+set additional_flags "-fno-tree-loop-distribute-patterns"
if [istarget "powerpc-*-darwin*"] {
lappend additional_flags "-Wl,-multiply_defined,suppress"
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-19.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-19.c
new file mode 100644
index 0000000..332fedf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-19.c
@@ -0,0 +1,72 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-ldist-details" } */
+
+struct Foo
+{
+ char a;
+};
+
+struct Foo x[256];
+
+static void __attribute__((noinline,noclone))
+foo()
+{
+ int i;
+ for (i = 0; i < 256; ++i)
+ x[i] = (struct Foo){};
+}
+
+static void __attribute__((noinline,noclone))
+bar()
+{
+ int i;
+ for (i = 0; i < 256; ++i)
+ x[i].a = 1;
+}
+
+static void __attribute__((noinline,noclone))
+foobar(unsigned char c)
+{
+ int i;
+ for (i = 0; i < 256; ++i)
+ x[i].a = c;
+}
+
+static void __attribute__((noinline,noclone))
+foobar2(char c)
+{
+ int i;
+ for (i = 0; i < 256; ++i)
+ x[i].a = c;
+}
+
+struct Baz
+{
+ short a;
+};
+
+struct Baz y[256];
+
+static void __attribute__((noinline,noclone))
+baz()
+{
+ int i;
+ for (i = 0; i < 256; ++i)
+ y[i].a = -1;
+}
+
+int main()
+{
+ volatile int x;
+ foo();
+ bar();
+ foobar(x);
+ foobar2(x);
+ baz();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "generated memset zero" 1 "ldist" } } */
+/* { dg-final { scan-tree-dump-times "generated memset minus one" 1 "ldist" } } */
+/* { dg-final { scan-tree-dump-times "generated memset" 5 "ldist" } } */
+/* { dg-final { cleanup-tree-dump "ldist" } } */
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index db4fefc..5903918 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -332,6 +332,7 @@ generate_memset_builtin (struct loop *loop, struct graph *rdg,
gimple_seq stmt_list = NULL, stmts;
struct data_reference *dr = XCNEW (struct data_reference);
location_t loc;
+ tree val;
stmt = partition->main_stmt;
loc = gimple_location (stmt);
@@ -364,13 +365,44 @@ generate_memset_builtin (struct loop *loop, struct graph *rdg,
mem = force_gimple_operand (addr_base, &stmts, true, NULL);
gimple_seq_add_seq (&stmt_list, stmts);
+ /* This exactly matches the pattern recognition in classify_partition. */
+ val = gimple_assign_rhs1 (stmt);
+ if (integer_zerop (val)
+ || real_zerop (val)
+ || TREE_CODE (val) == CONSTRUCTOR)
+ val = integer_zero_node;
+ else if (integer_all_onesp (val))
+ val = build_int_cst (integer_type_node, -1);
+ else
+ {
+ if (TREE_CODE (val) == INTEGER_CST)
+ val = fold_convert (integer_type_node, val);
+ else if (!useless_type_conversion_p (integer_type_node, TREE_TYPE (val)))
+ {
+ gimple cstmt;
+ tree tem = create_tmp_reg (integer_type_node, NULL);
+ tem = make_ssa_name (tem, NULL);
+ cstmt = gimple_build_assign_with_ops (NOP_EXPR, tem, val, NULL_TREE);
+ gimple_seq_add_stmt (&stmt_list, cstmt);
+ val = tem;
+ }
+ }
+
fn = build_fold_addr_expr (builtin_decl_implicit (BUILT_IN_MEMSET));
- fn_call = gimple_build_call (fn, 3, mem, integer_zero_node, nb_bytes);
+ fn_call = gimple_build_call (fn, 3, mem, val, nb_bytes);
gimple_seq_add_stmt (&stmt_list, fn_call);
gsi_insert_seq_after (&gsi, stmt_list, GSI_CONTINUE_LINKING);
if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "generated memset zero\n");
+ {
+ fprintf (dump_file, "generated memset");
+ if (integer_zerop (val))
+ fprintf (dump_file, " zero\n");
+ else if (integer_all_onesp (val))
+ fprintf (dump_file, " minus one\n");
+ else
+ fprintf (dump_file, "\n");
+ }
}
/* Remove and destroy the loop LOOP. */
@@ -865,7 +897,19 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
return;
partition->main_stmt = stmt;
rhs = gimple_assign_rhs1 (stmt);
- if (!(integer_zerop (rhs) || real_zerop (rhs)))
+ if (!(integer_zerop (rhs)
+ || integer_all_onesp (rhs)
+ || real_zerop (rhs)
+ || (TREE_CODE (rhs) == CONSTRUCTOR
+ && !TREE_CLOBBER_P (rhs))
+ || (INTEGRAL_TYPE_P (TREE_TYPE (rhs))
+ && (TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)))
+ == TYPE_MODE (unsigned_char_type_node)))))
+ return;
+ if (TREE_CODE (rhs) == SSA_NAME
+ && !SSA_NAME_IS_DEFAULT_DEF (rhs)
+ && flow_bb_inside_loop_p
+ (loop, gimple_bb (SSA_NAME_DEF_STMT (rhs))))
return;
if (VEC_length (data_reference_p, RDG_DATAREFS (rdg, i)) != 1)
return;
@@ -1346,9 +1390,19 @@ tree_loop_distribution (void)
/* If we are only performing pattern detection restrict
what we try to distribute to stores from constants. */
- if (!flag_tree_loop_distribution
- && !is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
- continue;
+ if (!flag_tree_loop_distribution)
+ {
+ tree rhs = gimple_assign_rhs1 (stmt);
+ if (!is_gimple_min_invariant (rhs)
+ && TREE_CODE (rhs) != CONSTRUCTOR
+ && TREE_CODE (rhs) != SSA_NAME)
+ continue;
+ if (TREE_CODE (rhs) == SSA_NAME
+ && !SSA_NAME_IS_DEFAULT_DEF (rhs)
+ && flow_bb_inside_loop_p
+ (loop, gimple_bb (SSA_NAME_DEF_STMT (rhs))))
+ continue;
+ }
VEC_safe_push (gimple, heap, work_list, stmt);
}