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
This commit is contained in:
Richard Guenther 2012-06-05 09:24:43 +00:00 committed by Richard Biener
parent 44072af5b0
commit b6dd52618f
5 changed files with 149 additions and 7 deletions

View File

@ -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.

View File

@ -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.

View File

@ -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"
}

View File

@ -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" } } */

View File

@ -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);
}