public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Cleanup estimated/max-niter API
@ 2012-04-11 14:29 Richard Guenther
  0 siblings, 0 replies; only message in thread
From: Richard Guenther @ 2012-04-11 14:29 UTC (permalink / raw)
  To: gcc-patches


I stumbled over the following hunk in one of my pending patches

Index: gcc/tree-ssa-loop-prefetch.c
===================================================================
--- gcc/tree-ssa-loop-prefetch.c.orig   2011-10-12 13:14:10.000000000 
+0200
+++ gcc/tree-ssa-loop-prefetch.c        2012-02-23 15:05:45.000000000 
+0100
@@ -1801,6 +1801,8 @@ loop_prefetch_arrays (struct loop *loop)

   ahead = (PREFETCH_LATENCY + time - 1) / time;
   est_niter = max_stmt_executions_int (loop, false);
+  if (est_niter == -1)
+    est_niter = max_stmt_executions_int (loop, true);

   /* Prefetching is not likely to be profitable if the trip count to 
ahead
      ratio is too small.  */

which confused me.  Then I looked at the existing API which
confused me more ;)  So the following ditches the 'conservative'
parameter in all of the functions and explicitely calls them
estimated_* and max_*.  Still way too many, but - oh well.

The other question is whether estimated_* should return max_*
if we have a maximum recorded but no estimate (the above hunk
would make us use the recorded maximum if available and no
estimate is available).  Or if that should be done in the callers
depending on their behavior in the case no estimate is available.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2012-04-11  Richard Guenther  <rguenther@suse.de>

	* cfgloop.h (estimated_loop_iterations_int): Ditch
	'conservative' parameter.
	(max_stmt_executions_int): Likewise.
	(estimated_loop_iterations): Likewise.
	(max_stmt_executions): Likewise.
	(max_loop_iterations): Declare.
	(max_loop_iterations_int): Likewise.
	(estimated_stmt_executions): Likewise.
	(estimated_stmt_executions_int): Likewise.
	* tree-ssa-loop-niter.c (estimated_loop_iterations):
	Split parts to ...
	(max_loop_iterations): ... this.
	(estimated_loop_iterations_int): Split parts to ...
	(max_loop_iterations_int): ... this.
	(max_stmt_executions_int): Split parts to ...
	(estimated_stmt_executions_int): ... this.
	(max_stmt_executions): Split parts to ...
	(estimated_stmt_executions): ... this.
	* graphite-sese-to-poly.c (build_loop_iteration_domains): Adjust.
	* predict.c (predict_loops): Likewise.
	* tree-data-ref.c (max_stmt_executions_tree): Likewise.
	(analyze_siv_subscript_cst_affine): Likewise.
	(compute_overlap_steps_for_affine_1_2): Likewise.
	(analyze_subscript_affine_affine): Likewise.
	(init_omega_for_ddr_1): Likewise.
	* tree-parloops.c (parallelize_loops): Likewise.
	* tree-ssa-loop-ivopts.c (avg_loop_niter): Likewise.
	(may_eliminate_iv): Likewise.
	* tree-ssa-loop-prefetch.c (determine_loop_nest_reuse): Likewise.
	(loop_prefetch_arrays): Likewise.
	* tree-vrp.c (adjust_range_with_scev): Likewise.

Index: gcc/cfgloop.h
===================================================================
*** gcc/cfgloop.h.orig	2012-04-11 15:31:56.000000000 +0200
--- gcc/cfgloop.h	2012-04-11 15:41:05.688414649 +0200
*************** extern unsigned expected_loop_iterations
*** 279,288 ****
  extern rtx doloop_condition_get (rtx);
  
  void estimate_numbers_of_iterations_loop (struct loop *, bool);
! HOST_WIDE_INT estimated_loop_iterations_int (struct loop *, bool);
! HOST_WIDE_INT max_stmt_executions_int (struct loop *, bool);
! bool estimated_loop_iterations (struct loop *, bool, double_int *);
! bool max_stmt_executions (struct loop *, bool, double_int *);
  
  /* Loop manipulation.  */
  extern bool can_duplicate_loop_p (const struct loop *loop);
--- 279,292 ----
  extern rtx doloop_condition_get (rtx);
  
  void estimate_numbers_of_iterations_loop (struct loop *, bool);
! bool estimated_loop_iterations (struct loop *, double_int *);
! bool max_loop_iterations (struct loop *, double_int *);
! HOST_WIDE_INT estimated_loop_iterations_int (struct loop *);
! HOST_WIDE_INT max_loop_iterations_int (struct loop *);
! bool max_stmt_executions (struct loop *, double_int *);
! bool estimated_stmt_executions (struct loop *, double_int *);
! HOST_WIDE_INT max_stmt_executions_int (struct loop *);
! HOST_WIDE_INT estimated_stmt_executions_int (struct loop *);
  
  /* Loop manipulation.  */
  extern bool can_duplicate_loop_p (const struct loop *loop);
Index: gcc/tree-ssa-loop-niter.c
===================================================================
*** gcc/tree-ssa-loop-niter.c.orig	2012-04-11 15:31:56.000000000 +0200
--- gcc/tree-ssa-loop-niter.c	2012-04-11 15:44:38.888401936 +0200
*************** estimate_numbers_of_iterations_loop (str
*** 3052,3076 ****
     the function returns false, otherwise returns true.  */
  
  bool
! estimated_loop_iterations (struct loop *loop, bool conservative,
! 			   double_int *nit)
  {
    estimate_numbers_of_iterations_loop (loop, true);
!   if (conservative)
!     {
!       if (!loop->any_upper_bound)
! 	return false;
  
!       *nit = loop->nb_iterations_upper_bound;
!     }
!   else
!     {
!       if (!loop->any_estimate)
! 	return false;
  
!       *nit = loop->nb_iterations_estimate;
!     }
  
    return true;
  }
  
--- 3078,3105 ----
     the function returns false, otherwise returns true.  */
  
  bool
! estimated_loop_iterations (struct loop *loop, double_int *nit)
  {
    estimate_numbers_of_iterations_loop (loop, true);
!   if (!loop->any_estimate)
!     return false;
  
!   *nit = loop->nb_iterations_estimate;
!   return true;
! }
  
! /* Sets NIT to an upper bound for the maximum number of executions of the
!    latch of the LOOP.  If we have no reliable estimate, the function returns
!    false, otherwise returns true.  */
  
+ bool
+ max_loop_iterations (struct loop *loop, double_int *nit)
+ {
+   estimate_numbers_of_iterations_loop (loop, true);
+   if (!loop->any_upper_bound)
+     return false;
+ 
+   *nit = loop->nb_iterations_upper_bound;
    return true;
  }
  
*************** estimated_loop_iterations (struct loop *
*** 3079,3090 ****
     on the number of iterations of LOOP could not be derived, returns -1.  */
  
  HOST_WIDE_INT
! estimated_loop_iterations_int (struct loop *loop, bool conservative)
  {
    double_int nit;
    HOST_WIDE_INT hwi_nit;
  
!   if (!estimated_loop_iterations (loop, conservative, &nit))
      return -1;
  
    if (!double_int_fits_in_shwi_p (nit))
--- 3108,3139 ----
     on the number of iterations of LOOP could not be derived, returns -1.  */
  
  HOST_WIDE_INT
! estimated_loop_iterations_int (struct loop *loop)
  {
    double_int nit;
    HOST_WIDE_INT hwi_nit;
  
!   if (!estimated_loop_iterations (loop, &nit))
!     return -1;
! 
!   if (!double_int_fits_in_shwi_p (nit))
!     return -1;
!   hwi_nit = double_int_to_shwi (nit);
! 
!   return hwi_nit < 0 ? -1 : hwi_nit;
! }
! 
! /* Similar to max_loop_iterations, but returns the estimate only
!    if it fits to HOST_WIDE_INT.  If this is not the case, or the estimate
!    on the number of iterations of LOOP could not be derived, returns -1.  */
! 
! HOST_WIDE_INT
! max_loop_iterations_int (struct loop *loop)
! {
!   double_int nit;
!   HOST_WIDE_INT hwi_nit;
! 
!   if (!max_loop_iterations (loop, &nit))
      return -1;
  
    if (!double_int_fits_in_shwi_p (nit))
*************** estimated_loop_iterations_int (struct lo
*** 3099,3107 ****
     the number of execution of the latch by one.  */
  
  HOST_WIDE_INT
! max_stmt_executions_int (struct loop *loop, bool conservative)
  {
!   HOST_WIDE_INT nit = estimated_loop_iterations_int (loop, conservative);
    HOST_WIDE_INT snit;
  
    if (nit == -1)
--- 3148,3175 ----
     the number of execution of the latch by one.  */
  
  HOST_WIDE_INT
! max_stmt_executions_int (struct loop *loop)
! {
!   HOST_WIDE_INT nit = max_loop_iterations_int (loop);
!   HOST_WIDE_INT snit;
! 
!   if (nit == -1)
!     return -1;
! 
!   snit = (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) nit + 1);
! 
!   /* If the computation overflows, return -1.  */
!   return snit < 0 ? -1 : snit;
! }
! 
! /* Returns an estimate for the number of executions of statements
!    in the LOOP.  For statements before the loop exit, this exceeds
!    the number of execution of the latch by one.  */
! 
! HOST_WIDE_INT
! estimated_stmt_executions_int (struct loop *loop)
  {
!   HOST_WIDE_INT nit = estimated_loop_iterations_int (loop);
    HOST_WIDE_INT snit;
  
    if (nit == -1)
*************** max_stmt_executions_int (struct loop *lo
*** 3113,3129 ****
    return snit < 0 ? -1 : snit;
  }
  
  /* Sets NIT to the estimated number of executions of the latch of the
!    LOOP, plus one.  If CONSERVATIVE is true, we must be sure that NIT is at
!    least as large as the number of iterations.  If we have no reliable
!    estimate, the function returns false, otherwise returns true.  */
  
  bool
! max_stmt_executions (struct loop *loop, bool conservative, double_int *nit)
  {
    double_int nit_minus_one;
  
!   if (!estimated_loop_iterations (loop, conservative, nit))
      return false;
  
    nit_minus_one = *nit;
--- 3181,3215 ----
    return snit < 0 ? -1 : snit;
  }
  
+ /* Sets NIT to the estimated maximum number of executions of the latch of the
+    LOOP, plus one.  If we have no reliable estimate, the function returns
+    false, otherwise returns true.  */
+ 
+ bool
+ max_stmt_executions (struct loop *loop, double_int *nit)
+ {
+   double_int nit_minus_one;
+ 
+   if (!max_loop_iterations (loop, nit))
+     return false;
+ 
+   nit_minus_one = *nit;
+ 
+   *nit = double_int_add (*nit, double_int_one);
+ 
+   return double_int_ucmp (*nit, nit_minus_one) > 0;
+ }
+ 
  /* Sets NIT to the estimated number of executions of the latch of the
!    LOOP, plus one.  If we have no reliable estimate, the function returns
!    false, otherwise returns true.  */
  
  bool
! estimated_stmt_executions (struct loop *loop, double_int *nit)
  {
    double_int nit_minus_one;
  
!   if (!estimated_loop_iterations (loop, nit))
      return false;
  
    nit_minus_one = *nit;
Index: gcc/graphite-sese-to-poly.c
===================================================================
*** gcc/graphite-sese-to-poly.c.orig	2011-08-23 13:14:25.000000000 +0200
--- gcc/graphite-sese-to-poly.c	2012-04-11 15:45:24.157399226 +0200
*************** build_loop_iteration_domains (scop_p sco
*** 1092,1098 ****
        scan_tree_for_params (SCOP_REGION (scop), nb_iters, ub_expr, one);
        mpz_clear (one);
  
!       if (max_stmt_executions (loop, true, &nit))
  	add_upper_bounds_from_estimated_nit (scop, nit, dim, ub_expr);
  
        /* loop_i <= expr_nb_iters */
--- 1092,1098 ----
        scan_tree_for_params (SCOP_REGION (scop), nb_iters, ub_expr, one);
        mpz_clear (one);
  
!       if (max_stmt_executions (loop, &nit))
  	add_upper_bounds_from_estimated_nit (scop, nit, dim, ub_expr);
  
        /* loop_i <= expr_nb_iters */
Index: gcc/predict.c
===================================================================
*** gcc/predict.c.orig	2012-04-05 11:39:55.000000000 +0200
--- gcc/predict.c	2012-04-11 15:45:59.117397137 +0200
*************** predict_loops (void)
*** 994,1000 ****
  	     the loop, use it to predict this exit.  */
  	  else if (n_exits == 1)
  	    {
! 	      nitercst = max_stmt_executions_int (loop, false);
  	      if (nitercst < 0)
  		continue;
  	      if (nitercst > max)
--- 994,1000 ----
  	     the loop, use it to predict this exit.  */
  	  else if (n_exits == 1)
  	    {
! 	      nitercst = estimated_stmt_executions_int (loop);
  	      if (nitercst < 0)
  		continue;
  	      if (nitercst > max)
Index: gcc/tree-data-ref.c
===================================================================
*** gcc/tree-data-ref.c.orig	2012-04-03 12:11:03.000000000 +0200
--- gcc/tree-data-ref.c	2012-04-11 15:48:04.872389634 +0200
*************** max_stmt_executions_tree (struct loop *l
*** 1709,1715 ****
  {
    double_int nit;
  
!   if (!max_stmt_executions (loop, true, &nit))
      return chrec_dont_know;
  
    if (!double_int_fits_to_tree_p (unsigned_type_node, nit))
--- 1709,1715 ----
  {
    double_int nit;
  
!   if (!max_stmt_executions (loop, &nit))
      return chrec_dont_know;
  
    if (!double_int_fits_to_tree_p (unsigned_type_node, nit))
*************** analyze_siv_subscript_cst_affine (tree c
*** 1791,1797 ****
  
  		      /* Perform weak-zero siv test to see if overlap is
  			 outside the loop bounds.  */
! 		      numiter = max_stmt_executions_int (loop, true);
  
  		      if (numiter >= 0
  			  && compare_tree_int (tmp, numiter) > 0)
--- 1791,1797 ----
  
  		      /* Perform weak-zero siv test to see if overlap is
  			 outside the loop bounds.  */
! 		      numiter = max_stmt_executions_int (loop);
  
  		      if (numiter >= 0
  			  && compare_tree_int (tmp, numiter) > 0)
*************** analyze_siv_subscript_cst_affine (tree c
*** 1869,1875 ****
  
  		      /* Perform weak-zero siv test to see if overlap is
  			 outside the loop bounds.  */
! 		      numiter = max_stmt_executions_int (loop, true);
  
  		      if (numiter >= 0
  			  && compare_tree_int (tmp, numiter) > 0)
--- 1869,1875 ----
  
  		      /* Perform weak-zero siv test to see if overlap is
  			 outside the loop bounds.  */
! 		      numiter = max_stmt_executions_int (loop);
  
  		      if (numiter >= 0
  			  && compare_tree_int (tmp, numiter) > 0)
*************** compute_overlap_steps_for_affine_1_2 (tr
*** 2049,2058 ****
    step_y = int_cst_value (CHREC_RIGHT (chrec_a));
    step_z = int_cst_value (CHREC_RIGHT (chrec_b));
  
!   niter_x =
!     max_stmt_executions_int (get_chrec_loop (CHREC_LEFT (chrec_a)), true);
!   niter_y = max_stmt_executions_int (get_chrec_loop (chrec_a), true);
!   niter_z = max_stmt_executions_int (get_chrec_loop (chrec_b), true);
  
    if (niter_x < 0 || niter_y < 0 || niter_z < 0)
      {
--- 2049,2057 ----
    step_y = int_cst_value (CHREC_RIGHT (chrec_a));
    step_z = int_cst_value (CHREC_RIGHT (chrec_b));
  
!   niter_x = max_stmt_executions_int (get_chrec_loop (CHREC_LEFT (chrec_a)));
!   niter_y = max_stmt_executions_int (get_chrec_loop (chrec_a));
!   niter_z = max_stmt_executions_int (get_chrec_loop (chrec_b));
  
    if (niter_x < 0 || niter_y < 0 || niter_z < 0)
      {
*************** analyze_subscript_affine_affine (tree ch
*** 2377,2384 ****
  	  HOST_WIDE_INT niter, niter_a, niter_b;
  	  affine_fn ova, ovb;
  
! 	  niter_a = max_stmt_executions_int (get_chrec_loop (chrec_a), true);
! 	  niter_b = max_stmt_executions_int (get_chrec_loop (chrec_b), true);
  	  niter = MIN (niter_a, niter_b);
  	  step_a = int_cst_value (CHREC_RIGHT (chrec_a));
  	  step_b = int_cst_value (CHREC_RIGHT (chrec_b));
--- 2376,2383 ----
  	  HOST_WIDE_INT niter, niter_a, niter_b;
  	  affine_fn ova, ovb;
  
! 	  niter_a = max_stmt_executions_int (get_chrec_loop (chrec_a));
! 	  niter_b = max_stmt_executions_int (get_chrec_loop (chrec_b));
  	  niter = MIN (niter_a, niter_b);
  	  step_a = int_cst_value (CHREC_RIGHT (chrec_a));
  	  step_b = int_cst_value (CHREC_RIGHT (chrec_b));
*************** analyze_subscript_affine_affine (tree ch
*** 2485,2494 ****
  
  	  if (i1 > 0 && j1 > 0)
  	    {
! 	      HOST_WIDE_INT niter_a = max_stmt_executions_int
! 		(get_chrec_loop (chrec_a), true);
! 	      HOST_WIDE_INT niter_b = max_stmt_executions_int
! 		(get_chrec_loop (chrec_b), true);
  	      HOST_WIDE_INT niter = MIN (niter_a, niter_b);
  
  	      /* (X0, Y0) is a solution of the Diophantine equation:
--- 2484,2493 ----
  
  	  if (i1 > 0 && j1 > 0)
  	    {
! 	      HOST_WIDE_INT niter_a
! 		= max_stmt_executions_int (get_chrec_loop (chrec_a));
! 	      HOST_WIDE_INT niter_b
! 		= max_stmt_executions_int (get_chrec_loop (chrec_b));
  	      HOST_WIDE_INT niter = MIN (niter_a, niter_b);
  
  	      /* (X0, Y0) is a solution of the Diophantine equation:
*************** init_omega_for_ddr_1 (struct data_refere
*** 3782,3788 ****
    for (i = 0; i <= DDR_INNER_LOOP (ddr)
  	 && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++)
      {
!       HOST_WIDE_INT nbi = max_stmt_executions_int (loopi, true);
  
        /* 0 <= loop_x */
        ineq = omega_add_zero_geq (pb, omega_black);
--- 3781,3787 ----
    for (i = 0; i <= DDR_INNER_LOOP (ddr)
  	 && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++)
      {
!       HOST_WIDE_INT nbi = max_stmt_executions_int (loopi);
  
        /* 0 <= loop_x */
        ineq = omega_add_zero_geq (pb, omega_black);
Index: gcc/tree-parloops.c
===================================================================
*** gcc/tree-parloops.c.orig	2012-04-11 10:44:37.000000000 +0200
--- gcc/tree-parloops.c	2012-04-11 15:48:30.864388085 +0200
*************** parallelize_loops (void)
*** 2192,2198 ****
  	     header-copied loops correctly - see PR46886.  */
  	  || !do_while_loop_p (loop))
  	continue;
!       estimated = max_stmt_executions_int (loop, false);
        /* FIXME: Bypass this check as graphite doesn't update the
        count and frequency correctly now.  */
        if (!flag_loop_parallelize_all
--- 2192,2198 ----
  	     header-copied loops correctly - see PR46886.  */
  	  || !do_while_loop_p (loop))
  	continue;
!       estimated = estimated_stmt_executions_int (loop);
        /* FIXME: Bypass this check as graphite doesn't update the
        count and frequency correctly now.  */
        if (!flag_loop_parallelize_all
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
*** gcc/tree-ssa-loop-ivopts.c.orig	2012-03-07 14:14:16.000000000 +0100
--- gcc/tree-ssa-loop-ivopts.c	2012-04-11 15:49:25.198384835 +0200
*************** along with GCC; see the file COPYING3.
*** 115,121 ****
  static inline HOST_WIDE_INT
  avg_loop_niter (struct loop *loop)
  {
!   HOST_WIDE_INT niter = max_stmt_executions_int (loop, false);
    if (niter == -1)
      return AVG_LOOP_NITER (loop);
  
--- 115,121 ----
  static inline HOST_WIDE_INT
  avg_loop_niter (struct loop *loop)
  {
!   HOST_WIDE_INT niter = estimated_stmt_executions_int (loop);
    if (niter == -1)
      return AVG_LOOP_NITER (loop);
  
*************** may_eliminate_iv (struct ivopts_data *da
*** 4709,4715 ****
            /* See if we can take advantage of infered loop bound information.  */
            if (data->loop_single_exit_p)
              {
!               if (!estimated_loop_iterations (loop, true, &max_niter))
                  return false;
                /* The loop bound is already adjusted by adding 1.  */
                if (double_int_ucmp (max_niter, period_value) > 0)
--- 4709,4715 ----
            /* See if we can take advantage of infered loop bound information.  */
            if (data->loop_single_exit_p)
              {
!               if (!max_loop_iterations (loop, &max_niter))
                  return false;
                /* The loop bound is already adjusted by adding 1.  */
                if (double_int_ucmp (max_niter, period_value) > 0)
Index: gcc/tree-ssa-loop-prefetch.c
===================================================================
*** gcc/tree-ssa-loop-prefetch.c.orig	2012-03-16 15:13:30.000000000 +0100
--- gcc/tree-ssa-loop-prefetch.c	2012-04-11 15:50:58.022379297 +0200
*************** determine_loop_nest_reuse (struct loop *
*** 1548,1554 ****
  	continue;
  
        aloop = VEC_index (loop_p, vloops, i);
!       vol = max_stmt_executions_int (aloop, false);
        if (vol < 0)
  	vol = expected_loop_iterations (aloop);
        volume *= vol;
--- 1548,1554 ----
  	continue;
  
        aloop = VEC_index (loop_p, vloops, i);
!       vol = estimated_stmt_executions_int (aloop);
        if (vol < 0)
  	vol = expected_loop_iterations (aloop);
        volume *= vol;
*************** loop_prefetch_arrays (struct loop *loop)
*** 1800,1806 ****
      return false;
  
    ahead = (PREFETCH_LATENCY + time - 1) / time;
!   est_niter = max_stmt_executions_int (loop, false);
  
    /* Prefetching is not likely to be profitable if the trip count to ahead
       ratio is too small.  */
--- 1800,1806 ----
      return false;
  
    ahead = (PREFETCH_LATENCY + time - 1) / time;
!   est_niter = estimated_stmt_executions_int (loop);
  
    /* Prefetching is not likely to be profitable if the trip count to ahead
       ratio is too small.  */
Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c.orig	2012-04-05 11:39:55.000000000 +0200
--- gcc/tree-vrp.c	2012-04-11 15:38:16.084424791 +0200
*************** adjust_range_with_scev (value_range_t *v
*** 3420,3426 ****
      {
        double_int nit;
  
!       if (estimated_loop_iterations (loop, true, &nit))
  	{
  	  value_range_t maxvr = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
  	  double_int dtmp;
--- 3420,3426 ----
      {
        double_int nit;
  
!       if (max_loop_iterations (loop, &nit))
  	{
  	  value_range_t maxvr = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
  	  double_int dtmp;

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2012-04-11 14:29 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-11 14:29 [PATCH] Cleanup estimated/max-niter API Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).