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 PR56034


The following implements what I thought was present (eh ...).  For
partitions that contain reductions (feed loop closed PHI nodes) we
rely on them being in the last partition of the loop - as we do not
bother to copy / care for loop closed PHI nodes.  The following now
implements that fully (I've had a patch for that around), by both
seeding initial partition generation from scalar reductions and
taking care of merging them again into the very last partition of
the loop.

Completely disabling partitioning for loops with reductions would
have broken some existing testcases that happen to work because
for them the partitions are already in proper order.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2013-01-28  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/56034
	* tree-loop-distribution.c (enum partition_kind): Add
	PKIND_REDUCTION.
	(partition_builtin_p): Adjust.
	(generate_code_for_partition): Handle PKIND_REDUCTION.  Assert
	it is the last partition.
	(rdg_flag_uses): Check SSA_NAME_IS_DEFAULT_DEF before looking
	up the vertex for the definition.
	(classify_partition): Classify whether a partition is a
	PKIND_REDUCTION, thus has uses outside of the loop.
	(ldist_gen): Inherit PKIND_REDUCTION when merging partitions.
	Merge all PKIND_REDUCTION partitions into the last partition.
	(tree_loop_distribution): Seed partitions from reductions as well.

	* gcc.dg/torture/pr56034.c: New testcase.

Index: gcc/tree-loop-distribution.c
===================================================================
*** gcc/tree-loop-distribution.c	(revision 195502)
--- gcc/tree-loop-distribution.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 51,57 ****
  #include "tree-scalar-evolution.h"
  #include "tree-pass.h"
  
! enum partition_kind { PKIND_NORMAL, PKIND_MEMSET, PKIND_MEMCPY };
  
  typedef struct partition_s
  {
--- 51,59 ----
  #include "tree-scalar-evolution.h"
  #include "tree-pass.h"
  
! enum partition_kind {
!     PKIND_NORMAL, PKIND_REDUCTION, PKIND_MEMSET, PKIND_MEMCPY
! };
  
  typedef struct partition_s
  {
*************** partition_free (partition_t partition)
*** 90,96 ****
  static bool
  partition_builtin_p (partition_t partition)
  {
!   return partition->kind != PKIND_NORMAL;
  }
  
  /* Returns true if the partition has an writes.  */
--- 92,98 ----
  static bool
  partition_builtin_p (partition_t partition)
  {
!   return partition->kind > PKIND_REDUCTION;
  }
  
  /* Returns true if the partition has an writes.  */
*************** generate_code_for_partition (struct loop
*** 481,486 ****
--- 483,491 ----
  	destroy_loop (loop);
        break;
  
+     case PKIND_REDUCTION:
+       /* Reductions all have to be in the last partition.  */
+       gcc_assert (!copy_p);
      case PKIND_NORMAL:
        generate_loops_for_partition (loop, partition, copy_p);
        break;
*************** rdg_flag_uses (struct graph *rdg, int u,
*** 628,634 ****
  	{
  	  tree use = USE_FROM_PTR (use_p);
  
! 	  if (TREE_CODE (use) == SSA_NAME)
  	    {
  	      gimple def_stmt = SSA_NAME_DEF_STMT (use);
  	      int v = rdg_vertex_for_stmt (rdg, def_stmt);
--- 633,640 ----
  	{
  	  tree use = USE_FROM_PTR (use_p);
  
! 	  if (TREE_CODE (use) == SSA_NAME
! 	      && !SSA_NAME_IS_DEFAULT_DEF (use))
  	    {
  	      gimple def_stmt = SSA_NAME_DEF_STMT (use);
  	      int v = rdg_vertex_for_stmt (rdg, def_stmt);
*************** classify_partition (loop_p loop, struct
*** 858,882 ****
    unsigned i;
    tree nb_iter;
    data_reference_p single_load, single_store;
  
    partition->kind = PKIND_NORMAL;
    partition->main_dr = NULL;
    partition->secondary_dr = NULL;
  
-   if (!flag_tree_loop_distribute_patterns)
-     return;
- 
-   /* Perform general partition disqualification for builtins.  */
-   nb_iter = number_of_exit_cond_executions (loop);
-   if (!nb_iter || nb_iter == chrec_dont_know)
-     return;
- 
    EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
      {
        gimple stmt = RDG_STMT (rdg, i);
  
        if (gimple_has_volatile_ops (stmt))
! 	return;
  
        /* If the stmt has uses outside of the loop fail.
  	 ???  If the stmt is generated in another partition that
--- 864,881 ----
    unsigned i;
    tree nb_iter;
    data_reference_p single_load, single_store;
+   bool volatiles_p = false;
  
    partition->kind = PKIND_NORMAL;
    partition->main_dr = NULL;
    partition->secondary_dr = NULL;
  
    EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, i, bi)
      {
        gimple stmt = RDG_STMT (rdg, i);
  
        if (gimple_has_volatile_ops (stmt))
! 	volatiles_p = true;
  
        /* If the stmt has uses outside of the loop fail.
  	 ???  If the stmt is generated in another partition that
*************** classify_partition (loop_p loop, struct
*** 886,895 ****
--- 885,904 ----
  	  if (dump_file && (dump_flags & TDF_DETAILS))
  	    fprintf (dump_file, "not generating builtin, partition has "
  		     "scalar uses outside of the loop\n");
+ 	  partition->kind = PKIND_REDUCTION;
  	  return;
  	}
      }
  
+   /* Perform general partition disqualification for builtins.  */
+   if (volatiles_p
+       || !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;
*************** ldist_gen (struct loop *loop, struct gra
*** 1294,1299 ****
--- 1303,1310 ----
  	    if (!partition_builtin_p (partition))
  	      {
  		bitmap_ior_into (into->stmts, partition->stmts);
+ 		if (partition->kind == PKIND_REDUCTION)
+ 		  into->kind = PKIND_REDUCTION;
  		partitions.ordered_remove (i);
  		i--;
  	      }
*************** ldist_gen (struct loop *loop, struct gra
*** 1328,1333 ****
--- 1339,1346 ----
  			       "memory accesses\n");
  		    }
  		  bitmap_ior_into (into->stmts, partition->stmts);
+ 		  if (partition->kind == PKIND_REDUCTION)
+ 		    into->kind = PKIND_REDUCTION;
  		  partitions.ordered_remove (j);
  		  j--;
  		}
*************** ldist_gen (struct loop *loop, struct gra
*** 1335,1340 ****
--- 1348,1376 ----
  	}
      }
  
+   /* Fuse all reduction partitions into the last.  */
+   if (partitions.length () > 1)
+     {
+       partition_t into = partitions.last ();
+       for (i = partitions.length () - 2; i >= 0; --i)
+ 	{
+ 	  partition_t what = partitions[i];
+ 	  if (what->kind == PKIND_REDUCTION)
+ 	    {
+ 	      if (dump_file && (dump_flags & TDF_DETAILS))
+ 		{
+ 		  fprintf (dump_file, "fusing partitions\n");
+ 		  dump_bitmap (dump_file, into->stmts);
+ 		  dump_bitmap (dump_file, what->stmts);
+ 		  fprintf (dump_file, "because the latter has reductions\n");
+ 		}
+ 	      bitmap_ior_into (into->stmts, what->stmts);
+ 	      into->kind = PKIND_REDUCTION;
+ 	      partitions.ordered_remove (i);
+ 	    }
+ 	}
+     }
+ 
    nbp = partitions.length ();
    if (nbp == 0
        || (nbp == 1 && !partition_builtin_p (partitions[0]))
*************** tree_loop_distribution (void)
*** 1478,1488 ****
  	  for (gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi); gsi_next (&gsi))
  	    {
  	      gimple stmt = gsi_stmt (gsi);
! 	      /* Only distribute stores for now.
! 	         ???  We should also try to distribute scalar reductions,
! 		 thus SSA defs that have scalar uses outside of the loop.  */
! 	      if (!gimple_assign_single_p (stmt)
! 		  || is_gimple_reg (gimple_assign_lhs (stmt)))
  		continue;
  
  	      work_list.safe_push (stmt);
--- 1514,1526 ----
  	  for (gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi); gsi_next (&gsi))
  	    {
  	      gimple stmt = gsi_stmt (gsi);
! 	      /* Distribute stmts which have defs that are used outside of
! 	         the loop.  */
! 	      if (stmt_has_scalar_dependences_outside_loop (loop, stmt))
! 		;
! 	      /* Otherwise only distribute stores for now.  */
! 	      else if (!gimple_assign_single_p (stmt)
! 		       || is_gimple_reg (gimple_assign_lhs (stmt)))
  		continue;
  
  	      work_list.safe_push (stmt);
Index: gcc/testsuite/gcc.dg/torture/pr56034.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr56034.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr56034.c	(working copy)
***************
*** 0 ****
--- 1,19 ----
+ /* { dg-do compile } */
+ /* { dg-options "-ftree-loop-distribution" } */
+ 
+ int a, b, *p;
+ 
+ void f(void)
+ {
+   int *q;
+ 
+   while(b++)
+     {
+       int i;
+       p = &i;
+       a = *q;
+     }
+ 
+   if(a)
+     for(;; b++);
+ }


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