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]

Re: [patch] Make niter analysis return COND_EXPRs


On Thu, May 27, 2010 at 10:48, Richard Guenther <rguenther@suse.de> wrote:
> + ?if (COMPARISON_CLASS_P (may_be_zero))
> + ? ?return fold_build3 (COND_EXPR, TREE_TYPE (res), may_be_zero,
> + ? ? ? ? ? ? ? ? ? ? ? build_int_cst (TREE_TYPE (res), 0), res);
>
> will still build a COND_EXPR then and _not_ cache it, so you'll
> end up returning a non-COND_EXPR in the case where loop->nb_iterations
> is set.
>
> Exactly my initial complaint.
>
> You cache a constant number of iterations while it isn't really
> constant but may be zero.
>

Right, I inlined the helper function to see this better.
What do you think about this revised patch?

Thanks for your review,
Sebastian
From 76bb62869940a6a4c4114e175e405db3240e1df0 Mon Sep 17 00:00:00 2001
From: Sebastian Pop <sebpop@gmail.com>
Date: Tue, 25 May 2010 18:07:07 -0500
Subject: [PATCH] When niter may be zero, return a COND_EXPR with the may_be_zero condition.

	* gcc.dg/vect/vect-outer-fir-lb.c: Un-XFAIL-ed.
	* tree-scalar-evolution.c (set_nb_iterations_in_loop): Inlined in the
	only place it was called from.
	(number_of_latch_executions_1): Split from number_of_latch_executions.
	(number_of_latch_executions): Do not return chrec_dont_know when the
	may_be_zero is a runtime condition: instead, return a COND_EXPR
	including the may_be_zero condition.
---
 gcc/testsuite/gcc.dg/vect/vect-outer-fir-lb.c |   14 ++---
 gcc/tree-scalar-evolution.c                   |   84 ++++++++++++++-----------
 2 files changed, 53 insertions(+), 45 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/vect/vect-outer-fir-lb.c b/gcc/testsuite/gcc.dg/vect/vect-outer-fir-lb.c
index bdc07f9..3c1a362 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-outer-fir-lb.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-outer-fir-lb.c
@@ -10,10 +10,7 @@ float coeff[M];
 float out[N];
 float fir_out[N];
 
-/* Should be vectorized. Fixed misaligment in the inner-loop.  */
-/* Currently not vectorized because the loop-count for the inner-loop
-   has a maybe_zero component. Will be fixed when we incorporate the
-   "cond_expr in rhs" patch.  */
+/* Vectorized.  Fixed misaligment in the inner-loop.  */
 __attribute__ ((noinline))
 void foo (){
  int i,j,k;
@@ -30,7 +27,7 @@ void foo (){
 
     do {
       diff += in[j+i]*coeff[j];
-      j+=4;	
+      j+=4;
     } while (j < M);
 
     out[i] += diff;
@@ -39,7 +36,7 @@ void foo (){
 
 }
 
-/* Vectorized. Changing misalignment in the inner-loop.  */
+/* Vectorized.  Changing misalignment in the inner-loop.  */
 __attribute__ ((noinline))
 void fir (){
   int i,j,k;
@@ -68,7 +65,7 @@ int main (void)
 
   foo ();
   fir ();
-  
+
   for (i = 0; i < N; i++) {
     if (out[i] != fir_out[i])
       abort ();
@@ -77,6 +74,5 @@ int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 2 "vect" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail vect_no_align } } } */
+/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 2 "vect" { xfail vect_no_align } } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index e2ed1f5..9b43ba6 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -900,23 +900,6 @@ add_to_evolution (unsigned loop_nb, tree chrec_before, enum tree_code code,
   return res;
 }
 
-/* Helper function.  */
-
-static inline tree
-set_nb_iterations_in_loop (struct loop *loop,
-			   tree res)
-{
-  if (dump_file && (dump_flags & TDF_DETAILS))
-    {
-      fprintf (dump_file, "  (set_nb_iterations_in_loop = ");
-      print_generic_expr (dump_file, res, 0);
-      fprintf (dump_file, "))\n");
-    }
-
-  loop->nb_iterations = res;
-  return res;
-}
-
 
 
 /* This section selects the loops that will be good candidates for the
@@ -2685,8 +2668,11 @@ resolve_mixers (struct loop *loop, tree chrec)
 /* Entry point for the analysis of the number of iterations pass.
    This function tries to safely approximate the number of iterations
    the loop will run.  When this property is not decidable at compile
-   time, the result is chrec_dont_know.  Otherwise the result is
-   a scalar or a symbolic parameter.
+   time, the result is chrec_dont_know.  Otherwise the result is a
+   scalar or a symbolic parameter.  When the number of iterations may
+   be equal to zero and the property cannot be determined at compile
+   time, the result is a COND_EXPR that represents in a symbolic form
+   the conditions under which the number of iterations is not zero.
 
    Example of analysis: suppose that the loop has an exit condition:
 
@@ -2705,37 +2691,63 @@ resolve_mixers (struct loop *loop, tree chrec)
 tree
 number_of_latch_executions (struct loop *loop)
 {
-  tree res, type;
   edge exit;
   struct tree_niter_desc niter_desc;
+  tree may_be_zero;
+  tree res;
 
-  /* Determine whether the number_of_iterations_in_loop has already
+  /* Determine whether the number of iterations in loop has already
      been computed.  */
   res = loop->nb_iterations;
   if (res)
     return res;
-  res = chrec_dont_know;
+
+  may_be_zero = NULL_TREE;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
-    fprintf (dump_file, "(number_of_iterations_in_loop\n");
+    fprintf (dump_file, "(number_of_iterations_in_loop = \n");
 
+  res = chrec_dont_know;
   exit = single_exit (loop);
-  if (!exit)
-    goto end;
 
-  if (!number_of_iterations_exit (loop, exit, &niter_desc, false))
-    goto end;
+  if (exit && number_of_iterations_exit (loop, exit, &niter_desc, false))
+    {
+      may_be_zero = niter_desc.may_be_zero;
+      res = niter_desc.niter;
+    }
 
-  type = TREE_TYPE (niter_desc.niter);
-  if (integer_nonzerop (niter_desc.may_be_zero))
-    res = build_int_cst (type, 0);
-  else if (integer_zerop (niter_desc.may_be_zero))
-    res = niter_desc.niter;
-  else
-    res = chrec_dont_know;
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "  (set_nb_iterations_in_loop = ");
+      print_generic_expr (dump_file, res, 0);
+      fprintf (dump_file, "))\n");
+    }
+
+  loop->nb_iterations = res;
+
+  if (res == chrec_dont_know
+      || !may_be_zero
+      || integer_zerop (may_be_zero))
+    return res;
 
-end:
-  return set_nb_iterations_in_loop (loop, res);
+  if (integer_nonzerop (may_be_zero))
+    {
+      res = build_int_cst (TREE_TYPE (res), 0);
+      loop->nb_iterations = res;
+      return res;
+    }
+
+  if (COMPARISON_CLASS_P (may_be_zero))
+    {
+      res = fold_build3 (COND_EXPR, TREE_TYPE (res), may_be_zero,
+			 build_int_cst (TREE_TYPE (res), 0), res);
+
+      loop->nb_iterations = res;
+      return res;
+    }
+
+  loop->nb_iterations = chrec_dont_know;
+  return chrec_dont_know;
 }
 
 /* Returns the number of executions of the exit condition of LOOP,
-- 
1.7.0.4


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