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:
parent
44072af5b0
commit
b6dd52618f
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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" } } */
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue