Patchwork [1/2] Add pass_loop_distribute_memset_zero.

login
register
mail settings
Submitter Sebastian Pop
Date July 30, 2010, 8:40 p.m.
Message ID <1280522440-27919-2-git-send-email-sebpop@gmail.com>
Download mbox | patch
Permalink /patch/60381/
State New
Headers show

Comments

Sebastian Pop - July 30, 2010, 8:40 p.m.
---
 gcc/common.opt               |    4 ++
 gcc/doc/invoke.texi          |   22 ++++++++++++++-
 gcc/passes.c                 |    1 +
 gcc/tree-data-ref.c          |   26 +++++++++++++++++
 gcc/tree-data-ref.h          |    1 +
 gcc/tree-loop-distribution.c |   63 ++++++++++++++++++++++++++++++++++++++++++
 gcc/tree-pass.h              |    1 +
 7 files changed, 117 insertions(+), 1 deletions(-)

Patch

diff --git a/gcc/common.opt b/gcc/common.opt
index 41a9838..77cf58e 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1337,6 +1337,10 @@  ftree-loop-distribution
 Common Report Var(flag_tree_loop_distribution) Optimization
 Enable loop distribution on trees
 
+ftree-loop-distribute-memset-zero
+Common Report Var(flag_tree_loop_distribute_memset_zero) Optimization
+Enable loop distribution of initialization loops using memset zero
+
 ftree-loop-im
 Common Report Var(flag_tree_loop_im) Init(1) Optimization
 Enable loop invariant motion on trees
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 73051de..2d61382 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -384,7 +384,7 @@  Objective-C and Objective-C++ Dialects}.
 -ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-copy-prop @gol
 -ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse @gol
 -ftree-forwprop -ftree-fre -ftree-loop-if-convert -ftree-loop-im @gol
--ftree-phiprop -ftree-loop-distribution @gol
+-ftree-phiprop -ftree-loop-distribution -ftree-loop-distribute-memset-zero @gol
 -ftree-loop-ivcanon -ftree-loop-linear -ftree-loop-optimize @gol
 -ftree-parallelize-loops=@var{n} -ftree-pre -ftree-pta -ftree-reassoc @gol
 -ftree-sink -ftree-sra -ftree-switch-conversion @gol
@@ -6925,6 +6925,26 @@  DO I = 1, N
 ENDDO
 @end smallexample
 
+@item -ftree-loop-distribute-memset-zero
+Perform loop distribution of initialization loops and code generate
+them with a call to memset zero.  For example, the loop
+@smallexample
+DO I = 1, N
+  A(I) = 0
+  B(I) = A(I) + I
+ENDDO
+@end smallexample
+is transformed to
+@smallexample
+DO I = 1, N
+   A(I) = 0
+ENDDO
+DO I = 1, N
+   B(I) = A(I) + I
+ENDDO
+@end smallexample
+and the initialization loop is transformed into a call to memset zero.
+
 @item -ftree-loop-im
 @opindex ftree-loop-im
 Perform loop invariant motion on trees.  This pass moves only invariants that
diff --git a/gcc/passes.c b/gcc/passes.c
index 72e9b5a..7aed7e2 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -897,6 +897,7 @@  init_optimization_passes (void)
 	  NEXT_PASS (pass_scev_cprop);
 	  NEXT_PASS (pass_record_bounds);
 	  NEXT_PASS (pass_check_data_deps);
+	  NEXT_PASS (pass_loop_distribute_memset_zero);
 	  NEXT_PASS (pass_loop_distribution);
 	  NEXT_PASS (pass_linear_transform);
 	  NEXT_PASS (pass_graphite_transforms);
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index e7aa277..2656350 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -5038,6 +5038,32 @@  stores_from_loop (struct loop *loop, VEC (gimple, heap) **stmts)
   free (bbs);
 }
 
+/* Initialize STMTS with all the statements of LOOP that contain a
+   store to memory of the form "A[i] = 0".  */
+
+void
+stores_zero_from_loop (struct loop *loop, VEC (gimple, heap) **stmts)
+{
+  unsigned int i;
+  basic_block bb;
+  gimple_stmt_iterator si;
+  gimple stmt;
+  tree op;
+  basic_block *bbs = get_loop_body_in_dom_order (loop);
+
+  for (i = 0; i < loop->num_nodes; i++)
+    for (bb = bbs[i], si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+      if ((stmt = gsi_stmt (si))
+	  && gimple_vdef (stmt)
+	  && is_gimple_assign (stmt)
+	  && gimple_assign_rhs_code (stmt) == INTEGER_CST
+	  && (op = gimple_assign_rhs1 (stmt))
+	  && (integer_zerop (op) || real_zerop (op)))
+	VEC_safe_push (gimple, heap, *stmts, gsi_stmt (si));
+
+  free (bbs);
+}
+
 /* For a data reference REF, return the declaration of its base
    address or NULL_TREE if the base is not determined.  */
 
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index eff5348..9e18e26 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -564,6 +564,7 @@  index_in_loop_nest (int var, VEC (loop_p, heap) *loop_nest)
 }
 
 void stores_from_loop (struct loop *, VEC (gimple, heap) **);
+void stores_zero_from_loop (struct loop *, VEC (gimple, heap) **);
 void remove_similar_memory_refs (VEC (gimple, heap) **);
 bool rdg_defs_used_in_other_loops_p (struct graph *, int);
 bool have_similar_memory_accesses (gimple, gimple);
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 099a7fe..abc2ac9 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -1238,3 +1238,66 @@  struct gimple_opt_pass pass_loop_distribution =
   TODO_dump_func                /* todo_flags_finish */
  }
 };
+
+/* Distribute all the loops containing initializations to zero.  */
+
+static unsigned int
+tree_loop_distribute_memset_zero (void)
+{
+  struct loop *loop;
+  loop_iterator li;
+
+  FOR_EACH_LOOP (li, loop, 0)
+    {
+      VEC (gimple, heap) *work_list = VEC_alloc (gimple, heap, 3);
+      int nb_generated_loops = 0;
+
+      /* With the following working list, we're asking distribute_loop
+	 to separate from the rest of the loop the stores of the form
+	 "A[i] = 0".  */
+      stores_zero_from_loop (loop, &work_list);
+
+      if (VEC_length (gimple, work_list) > 0)
+	nb_generated_loops = distribute_loop (loop, work_list);
+
+      if (dump_file && (dump_flags & TDF_DETAILS))
+	{
+	  if (nb_generated_loops > 1)
+	    fprintf (dump_file, "Loop %d distributed: split to %d loops.\n",
+		     loop->num, nb_generated_loops);
+	  else
+	    fprintf (dump_file, "Loop %d is the same.\n", loop->num);
+	}
+
+      verify_loop_structure ();
+
+      VEC_free (gimple, heap, work_list);
+    }
+
+  return 0;
+}
+
+static bool
+gate_ldist_memset_zero (void)
+{
+  return flag_tree_loop_distribute_memset_zero != 0;
+}
+
+struct gimple_opt_pass pass_loop_distribute_memset_zero =
+{
+ {
+  GIMPLE_PASS,
+  "ldist-memset-zero",		/* name */
+  gate_ldist_memset_zero,  	/* gate */
+  tree_loop_distribute_memset_zero,       /* execute */
+  NULL,				/* sub */
+  NULL,				/* next */
+  0,				/* static_pass_number */
+  TV_TREE_LOOP_DISTRIBUTION,    /* tv_id */
+  PROP_cfg | PROP_ssa,		/* properties_required */
+  0,				/* properties_provided */
+  0,				/* properties_destroyed */
+  0,				/* todo_flags_start */
+  TODO_dump_func                /* todo_flags_finish */
+ }
+};
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index c72d7cf..3384aad 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -375,6 +375,7 @@  extern struct gimple_opt_pass pass_empty_loop;
 extern struct gimple_opt_pass pass_record_bounds;
 extern struct gimple_opt_pass pass_graphite_transforms;
 extern struct gimple_opt_pass pass_if_conversion;
+extern struct gimple_opt_pass pass_loop_distribute_memset_zero;
 extern struct gimple_opt_pass pass_loop_distribution;
 extern struct gimple_opt_pass pass_vectorize;
 extern struct gimple_opt_pass pass_slp_vectorize;