This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR58553
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 1 Oct 2013 09:37:10 +0200 (CEST)
- Subject: [PATCH] Fix PR58553
- Authentication-results: sourceware.org; auth=none
This fixes niter analysis for memset/memcpy pattern recognition in
loop distribution. We now have to look in a more proper way whether
the store is dominating or dominated by the loop exit condition.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.
Richard.
2013-10-01 Richard Biener <rguenther@suse.de>
PR tree-optimization/58553
* tree-loop-distribution.c (struct partition_s): Add niter member.
(classify_partition): Populate niter member for the partition
and properly identify whether the relevant store happens before
or after the loop exit.
(generate_memset_builtin): Use niter member from the partition.
(generate_memcpy_builtin): Likewise.
* gcc.dg/torture/pr58553.c: New testcase.
Index: gcc/tree-loop-distribution.c
===================================================================
*** gcc/tree-loop-distribution.c (revision 203032)
--- gcc/tree-loop-distribution.c (working copy)
*************** typedef struct partition_s
*** 569,574 ****
--- 569,575 ----
/* data-references a kind != PKIND_NORMAL partition is about. */
data_reference_p main_dr;
data_reference_p secondary_dr;
+ tree niter;
} *partition_t;
*************** generate_memset_builtin (struct loop *lo
*** 848,868 ****
{
gimple_stmt_iterator gsi;
gimple stmt, fn_call;
! tree nb_iter, mem, fn, nb_bytes;
location_t loc;
tree val;
stmt = DR_STMT (partition->main_dr);
loc = gimple_location (stmt);
- if (gimple_bb (stmt) == loop->latch)
- nb_iter = number_of_latch_executions (loop);
- else
- nb_iter = number_of_exit_cond_executions (loop);
/* The new statements will be placed before LOOP. */
gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
! nb_bytes = build_size_arg_loc (loc, partition->main_dr, nb_iter);
nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
mem = build_addr_arg_loc (loc, partition->main_dr, nb_bytes);
--- 849,865 ----
{
gimple_stmt_iterator gsi;
gimple stmt, fn_call;
! tree mem, fn, nb_bytes;
location_t loc;
tree val;
stmt = DR_STMT (partition->main_dr);
loc = gimple_location (stmt);
/* The new statements will be placed before LOOP. */
gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
! nb_bytes = build_size_arg_loc (loc, partition->main_dr, partition->niter);
nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
mem = build_addr_arg_loc (loc, partition->main_dr, nb_bytes);
*************** generate_memcpy_builtin (struct loop *lo
*** 908,928 ****
{
gimple_stmt_iterator gsi;
gimple stmt, fn_call;
! tree nb_iter, dest, src, fn, nb_bytes;
location_t loc;
enum built_in_function kind;
stmt = DR_STMT (partition->main_dr);
loc = gimple_location (stmt);
- if (gimple_bb (stmt) == loop->latch)
- nb_iter = number_of_latch_executions (loop);
- else
- nb_iter = number_of_exit_cond_executions (loop);
/* The new statements will be placed before LOOP. */
gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
! nb_bytes = build_size_arg_loc (loc, partition->main_dr, nb_iter);
nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
dest = build_addr_arg_loc (loc, partition->main_dr, nb_bytes);
--- 905,921 ----
{
gimple_stmt_iterator gsi;
gimple stmt, fn_call;
! tree dest, src, fn, nb_bytes;
location_t loc;
enum built_in_function kind;
stmt = DR_STMT (partition->main_dr);
loc = gimple_location (stmt);
/* The new statements will be placed before LOOP. */
gsi = gsi_last_bb (loop_preheader_edge (loop)->src);
! nb_bytes = build_size_arg_loc (loc, partition->main_dr, partition->niter);
nb_bytes = force_gimple_operand_gsi (&gsi, nb_bytes, true, NULL_TREE,
false, GSI_CONTINUE_LINKING);
dest = build_addr_arg_loc (loc, partition->main_dr, nb_bytes);
*************** classify_partition (loop_p loop, struct
*** 1125,1130 ****
--- 1118,1124 ----
partition->kind = PKIND_NORMAL;
partition->main_dr = NULL;
partition->secondary_dr = NULL;
+ partition->niter = NULL_TREE;
EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
{
*************** classify_partition (loop_p loop, struct
*** 1151,1160 ****
|| !flag_tree_loop_distribute_patterns)
return;
- nb_iter = number_of_exit_cond_executions (loop);
- if (!nb_iter || nb_iter == chrec_dont_know)
- return;
-
/* Detect memset and memcpy. */
single_load = NULL;
single_store = NULL;
--- 1145,1150 ----
*************** classify_partition (loop_p loop, struct
*** 1193,1198 ****
--- 1183,1199 ----
}
}
+ if (!single_store)
+ return;
+
+ if (!dominated_by_p (CDI_DOMINATORS, single_exit (loop)->src,
+ gimple_bb (DR_STMT (single_store))))
+ nb_iter = number_of_latch_executions (loop);
+ else
+ nb_iter = number_of_exit_cond_executions (loop);
+ if (!nb_iter || nb_iter == chrec_dont_know)
+ return;
+
if (single_store && !single_load)
{
gimple stmt = DR_STMT (single_store);
*************** classify_partition (loop_p loop, struct
*** 1212,1217 ****
--- 1213,1219 ----
return;
partition->kind = PKIND_MEMSET;
partition->main_dr = single_store;
+ partition->niter = nb_iter;
}
else if (single_store && single_load)
{
*************** classify_partition (loop_p loop, struct
*** 1268,1273 ****
--- 1270,1276 ----
partition->kind = PKIND_MEMCPY;
partition->main_dr = single_store;
partition->secondary_dr = single_load;
+ partition->niter = nb_iter;
}
}
Index: gcc/testsuite/gcc.dg/torture/pr58553.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr58553.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr58553.c (working copy)
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do run } */
+
+ #define MAX_LENGTH 96
+ #define SEQUENCE_LENGTH 31
+
+ static struct {
+ char buf[MAX_LENGTH + 1];
+ } u1, u2;
+
+ extern void abort (void);
+
+ int main ()
+ {
+ int i;
+ char c;
+
+ for (i = 0, c = 'A'; i < MAX_LENGTH; i++, c++)
+ {
+ u1.buf[i] = 'a';
+ if (c >= 'A' + SEQUENCE_LENGTH)
+ c = 'A';
+ u2.buf[i] = c;
+ }
+ if (u1.buf[MAX_LENGTH] != '\0')
+ abort ();
+
+ return 0;
+ }