This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR58553


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;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]