From b6dd52618f43de2492a727317bd6af3acfa78a23 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Tue, 5 Jun 2012 09:24:43 +0000 Subject: [PATCH] re PR tree-optimization/53081 (memcpy/memset loop recognition) 2012-06-05 Richard Guenther 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 --- gcc/ChangeLog | 9 +++ gcc/testsuite/ChangeLog | 7 ++ .../execute/builtins/builtins.exp | 2 +- gcc/testsuite/gcc.dg/tree-ssa/ldist-19.c | 72 +++++++++++++++++++ gcc/tree-loop-distribution.c | 66 +++++++++++++++-- 5 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ldist-19.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index faae6b78d87..1ebee7b5dd3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2012-06-05 Richard Guenther + + 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 * config/rs6000/rs6000.c (ptr_regno_for_savres): Comment. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c87ae14132b..3bfc678473c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2012-06-05 Richard Guenther + + 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 * 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 a54f3c1b53e..f7cc82b1062 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 00000000000..332fedf462a --- /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 db4fefc3420..5903918c2ed 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); }