[patch] Remove requirement on loop numbering

Zdenek Dvorak rakdver@atrey.karlin.mff.cuni.cz
Wed Jan 31 14:02:00 GMT 2007


Hello,

> But anyway, thanks for the remark; I noticed two mistakes in the patch
> (the loop iterators do not handle correctly the case loop gets removed,
> and actually, there is some code in tree-chrec that compares loop
> numbers instead of using flow_loop_nested_p); I will send a new version
> fixing these problems soon,

here is the updated version (bootstrapped & regtested on i686).  Since
nobody protested against the idea in the meantime, I have commited it.

Zdenek

Index: ChangeLog
===================================================================
*** ChangeLog	(revision 121419)
--- ChangeLog	(working copy)
***************
*** 1,3 ****
--- 1,26 ----
+ 2007-01-31  Zdenek Dvorak <dvorakz@suse.cz>
+ 
+ 	* cfgloop.h: Include vec-prim.h.
+ 	(enum li_flags): Remove LI_ONLY_OLD.
+ 	(loop_iterator): Changed.
+ 	(fel_next, fel_init): Iterate over loop tree.
+ 	(FOR_EACH_LOOP_BREAK): New macro.
+ 	* loop-unswitch.c (unswitch_loops): Do not pass LI_ONLY_OLD to
+ 	FOR_EACH_LOOP.
+ 	* tree-ssa-loop-unswitch.c (tree_ssa_unswitch_loops): Ditto.
+ 	* modulo-sched.c (sms_schedule): Ditto.
+ 	* tree-vectorizer.c (vectorize_loops): Ditto.
+ 	* doc/loop.texi: Update information on loop numbering and behavior of
+ 	FOR_EACH_LOOP wrto new loops.
+ 	* tree-scalar-evolution.c (compute_overall_effect_of_inner_loop,
+ 	add_to_evolution_1): Test nestedness of loops instead of comparing
+ 	their numbers.
+ 	* tree-chrec.c (chrec_fold_plus_poly_poly,
+ 	chrec_fold_multiply_poly_poly, chrec_evaluate,
+ 	hide_evolution_in_other_loops_than_loop, chrec_component_in_loop_num,
+ 	reset_evolution_in_loop): Ditto.
+ 	* Makefile.in (CFGLOOP_H): Add vecprim.h dependency.
+ 
  2007-01-31  Uros Bizjak  <ubizjak@gmail.com>
  
  	* optabs.h (enum optab_index): Add new OTI_isinf.
Index: loop-unswitch.c
===================================================================
*** loop-unswitch.c	(revision 121419)
--- loop-unswitch.c	(working copy)
*************** unswitch_loops (void)
*** 143,149 ****
  
    /* Go through inner loops (only original ones).  */
  
!   FOR_EACH_LOOP (li, loop, LI_ONLY_OLD | LI_ONLY_INNERMOST)
      {
        unswitch_single_loop (loop, NULL_RTX, 0);
  #ifdef ENABLE_CHECKING
--- 143,149 ----
  
    /* Go through inner loops (only original ones).  */
  
!   FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
      {
        unswitch_single_loop (loop, NULL_RTX, 0);
  #ifdef ENABLE_CHECKING
Index: doc/loop.texi
===================================================================
*** doc/loop.texi	(revision 121419)
--- doc/loop.texi	(working copy)
*************** function.  Each of the loops is represen
*** 64,80 ****
  structure.  Each loop is assigned an index (@code{num} field of the
  @code{struct loop} structure), and the pointer to the loop is stored in
  the corresponding field of the @code{larray} vector in the loops
! structure.  Index of a sub-loop is always greater than the index of its
! super-loop.  The indices do not have to be continuous, there may be
  empty (@code{NULL}) entries in the @code{larray} created by deleting
! loops.  The index of a loop never changes.
  
  The entries of the @code{larray} field should not be accessed directly.
  The function @code{get_loop} returns the loop description for a loop with
  the given index.  @code{number_of_loops} function returns number of
  loops in the function.  To traverse all loops, use @code{FOR_EACH_LOOP}
  macro.  The @code{flags} argument of the macro is used to determine
! the direction of traversal and the set of loops visited.
  
  Each basic block contains the reference to the innermost loop it belongs
  to (@code{loop_father}).  For this reason, it is only possible to have
--- 64,87 ----
  structure.  Each loop is assigned an index (@code{num} field of the
  @code{struct loop} structure), and the pointer to the loop is stored in
  the corresponding field of the @code{larray} vector in the loops
! structure.  The indices do not have to be continuous, there may be
  empty (@code{NULL}) entries in the @code{larray} created by deleting
! loops.  Also, there is no guarantee on the relative order of a loop
! and its subloops in the numbering.  The index of a loop never changes.
  
  The entries of the @code{larray} field should not be accessed directly.
  The function @code{get_loop} returns the loop description for a loop with
  the given index.  @code{number_of_loops} function returns number of
  loops in the function.  To traverse all loops, use @code{FOR_EACH_LOOP}
  macro.  The @code{flags} argument of the macro is used to determine
! the direction of traversal and the set of loops visited.  Each loop is
! guaranteed to be visited exactly once, regardless of the changes to the
! loop tree, and the loops may be removed during the traversal.  The newly
! created loops are never traversed, if they need to be visited, this
! must be done separately after their creation.  The @code{FOR_EACH_LOOP}
! macro allocates temporary variables.  If the @code{FOR_EACH_LOOP} loop
! were ended using break or goto, they would not be released;
! @code{FOR_EACH_LOOP_BREAK} macro must be used instead.
  
  Each basic block contains the reference to the innermost loop it belongs
  to (@code{loop_father}).  For this reason, it is only possible to have
Index: tree-ssa-loop-unswitch.c
===================================================================
*** tree-ssa-loop-unswitch.c	(revision 121419)
--- tree-ssa-loop-unswitch.c	(working copy)
*************** tree_ssa_unswitch_loops (void)
*** 88,94 ****
    bool changed = false;
  
    /* Go through inner loops (only original ones).  */
!   FOR_EACH_LOOP (li, loop, LI_ONLY_OLD | LI_ONLY_INNERMOST)
      {
        changed |= tree_unswitch_single_loop (loop, 0);
      }
--- 88,94 ----
    bool changed = false;
  
    /* Go through inner loops (only original ones).  */
!   FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST)
      {
        changed |= tree_unswitch_single_loop (loop, 0);
      }
Index: tree-scalar-evolution.c
===================================================================
*** tree-scalar-evolution.c	(revision 121419)
--- tree-scalar-evolution.c	(working copy)
*************** compute_overall_effect_of_inner_loop (st
*** 465,473 ****
  
    else if (TREE_CODE (evolution_fn) == POLYNOMIAL_CHREC)
      {
!       if (CHREC_VARIABLE (evolution_fn) >= (unsigned) loop->num)
  	{
- 	  struct loop *inner_loop = get_chrec_loop (evolution_fn);
  	  tree nb_iter = number_of_latch_executions (inner_loop);
  
  	  if (nb_iter == chrec_dont_know)
--- 465,475 ----
  
    else if (TREE_CODE (evolution_fn) == POLYNOMIAL_CHREC)
      {
!       struct loop *inner_loop = get_chrec_loop (evolution_fn);
! 
!       if (inner_loop == loop
! 	  || flow_loop_nested_p (loop, inner_loop))
  	{
  	  tree nb_iter = number_of_latch_executions (inner_loop);
  
  	  if (nb_iter == chrec_dont_know)
*************** add_to_evolution_1 (unsigned loop_nb, tr
*** 646,663 ****
  		    tree at_stmt)
  {
    tree type, left, right;
  
    switch (TREE_CODE (chrec_before))
      {
      case POLYNOMIAL_CHREC:
!       if (CHREC_VARIABLE (chrec_before) <= loop_nb)
  	{
  	  unsigned var;
  
  	  type = chrec_type (chrec_before);
  	  
  	  /* When there is no evolution part in this loop, build it.  */
! 	  if (CHREC_VARIABLE (chrec_before) < loop_nb)
  	    {
  	      var = loop_nb;
  	      left = chrec_before;
--- 648,668 ----
  		    tree at_stmt)
  {
    tree type, left, right;
+   struct loop *loop = get_loop (loop_nb), *chloop;
  
    switch (TREE_CODE (chrec_before))
      {
      case POLYNOMIAL_CHREC:
!       chloop = get_chrec_loop (chrec_before);
!       if (chloop == loop
! 	  || flow_loop_nested_p (chloop, loop))
  	{
  	  unsigned var;
  
  	  type = chrec_type (chrec_before);
  	  
  	  /* When there is no evolution part in this loop, build it.  */
! 	  if (chloop != loop)
  	    {
  	      var = loop_nb;
  	      left = chrec_before;
*************** add_to_evolution_1 (unsigned loop_nb, tr
*** 679,684 ****
--- 684,691 ----
  	}
        else
  	{
+ 	  gcc_assert (flow_loop_nested_p (loop, chloop));
+ 
  	  /* Search the evolution in LOOP_NB.  */
  	  left = add_to_evolution_1 (loop_nb, CHREC_LEFT (chrec_before),
  				     to_add, at_stmt);
Index: tree-chrec.c
===================================================================
*** tree-chrec.c	(revision 121419)
--- tree-chrec.c	(working copy)
*************** chrec_fold_plus_poly_poly (enum tree_cod
*** 99,104 ****
--- 99,106 ----
  			   tree poly1)
  {
    tree left, right;
+   struct loop *loop0 = get_chrec_loop (poly0);
+   struct loop *loop1 = get_chrec_loop (poly1);
  
    gcc_assert (poly0);
    gcc_assert (poly1);
*************** chrec_fold_plus_poly_poly (enum tree_cod
*** 111,117 ****
      {a, +, b}_1 + {c, +, d}_2  ->  {{a, +, b}_1 + c, +, d}_2,
      {a, +, b}_2 + {c, +, d}_1  ->  {{c, +, d}_1 + a, +, b}_2,
      {a, +, b}_x + {c, +, d}_x  ->  {a+c, +, b+d}_x.  */
!   if (CHREC_VARIABLE (poly0) < CHREC_VARIABLE (poly1))
      {
        if (code == PLUS_EXPR)
  	return build_polynomial_chrec 
--- 113,119 ----
      {a, +, b}_1 + {c, +, d}_2  ->  {{a, +, b}_1 + c, +, d}_2,
      {a, +, b}_2 + {c, +, d}_1  ->  {{c, +, d}_1 + a, +, b}_2,
      {a, +, b}_x + {c, +, d}_x  ->  {a+c, +, b+d}_x.  */
!   if (flow_loop_nested_p (loop0, loop1))
      {
        if (code == PLUS_EXPR)
  	return build_polynomial_chrec 
*************** chrec_fold_plus_poly_poly (enum tree_cod
*** 128,134 ****
  				: build_int_cst_type (type, -1)));
      }
    
!   if (CHREC_VARIABLE (poly0) > CHREC_VARIABLE (poly1))
      {
        if (code == PLUS_EXPR)
  	return build_polynomial_chrec 
--- 130,136 ----
  				: build_int_cst_type (type, -1)));
      }
    
!   if (flow_loop_nested_p (loop1, loop0))
      {
        if (code == PLUS_EXPR)
  	return build_polynomial_chrec 
*************** chrec_fold_plus_poly_poly (enum tree_cod
*** 141,147 ****
  	   chrec_fold_minus (type, CHREC_LEFT (poly0), poly1),
  	   CHREC_RIGHT (poly0));
      }
!   
    if (code == PLUS_EXPR)
      {
        left = chrec_fold_plus 
--- 143,153 ----
  	   chrec_fold_minus (type, CHREC_LEFT (poly0), poly1),
  	   CHREC_RIGHT (poly0));
      }
!  
!   /* This function should never be called for chrecs of loops that
!      do not belong to the same loop nest.  */
!   gcc_assert (loop0 == loop1);
! 
    if (code == PLUS_EXPR)
      {
        left = chrec_fold_plus 
*************** chrec_fold_multiply_poly_poly (tree type
*** 175,180 ****
--- 181,188 ----
  {
    tree t0, t1, t2;
    int var;
+   struct loop *loop0 = get_chrec_loop (poly0);
+   struct loop *loop1 = get_chrec_loop (poly1);
  
    gcc_assert (poly0);
    gcc_assert (poly1);
*************** chrec_fold_multiply_poly_poly (tree type
*** 186,205 ****
    /* {a, +, b}_1 * {c, +, d}_2  ->  {c*{a, +, b}_1, +, d}_2,
       {a, +, b}_2 * {c, +, d}_1  ->  {a*{c, +, d}_1, +, b}_2,
       {a, +, b}_x * {c, +, d}_x  ->  {a*c, +, a*d + b*c + b*d, +, 2*b*d}_x.  */
!   if (CHREC_VARIABLE (poly0) < CHREC_VARIABLE (poly1))
      /* poly0 is a constant wrt. poly1.  */
      return build_polynomial_chrec 
        (CHREC_VARIABLE (poly1), 
         chrec_fold_multiply (type, CHREC_LEFT (poly1), poly0),
         CHREC_RIGHT (poly1));
    
!   if (CHREC_VARIABLE (poly1) < CHREC_VARIABLE (poly0))
      /* poly1 is a constant wrt. poly0.  */
      return build_polynomial_chrec 
        (CHREC_VARIABLE (poly0), 
         chrec_fold_multiply (type, CHREC_LEFT (poly0), poly1),
         CHREC_RIGHT (poly0));
!   
    /* poly0 and poly1 are two polynomials in the same variable,
       {a, +, b}_x * {c, +, d}_x  ->  {a*c, +, a*d + b*c + b*d, +, 2*b*d}_x.  */
        
--- 194,215 ----
    /* {a, +, b}_1 * {c, +, d}_2  ->  {c*{a, +, b}_1, +, d}_2,
       {a, +, b}_2 * {c, +, d}_1  ->  {a*{c, +, d}_1, +, b}_2,
       {a, +, b}_x * {c, +, d}_x  ->  {a*c, +, a*d + b*c + b*d, +, 2*b*d}_x.  */
!   if (flow_loop_nested_p (loop0, loop1))
      /* poly0 is a constant wrt. poly1.  */
      return build_polynomial_chrec 
        (CHREC_VARIABLE (poly1), 
         chrec_fold_multiply (type, CHREC_LEFT (poly1), poly0),
         CHREC_RIGHT (poly1));
    
!   if (flow_loop_nested_p (loop1, loop0))
      /* poly1 is a constant wrt. poly0.  */
      return build_polynomial_chrec 
        (CHREC_VARIABLE (poly0), 
         chrec_fold_multiply (type, CHREC_LEFT (poly0), poly1),
         CHREC_RIGHT (poly0));
!  
!   gcc_assert (loop0 == loop1);
! 
    /* poly0 and poly1 are two polynomials in the same variable,
       {a, +, b}_x * {c, +, d}_x  ->  {a*c, +, a*d + b*c + b*d, +, 2*b*d}_x.  */
        
*************** chrec_evaluate (unsigned var, tree chrec
*** 492,500 ****
  {
    tree arg0, arg1, binomial_n_k;
    tree type = TREE_TYPE (chrec);
  
    while (TREE_CODE (chrec) == POLYNOMIAL_CHREC
! 	 && CHREC_VARIABLE (chrec) > var)
      chrec = CHREC_LEFT (chrec);
  
    if (TREE_CODE (chrec) == POLYNOMIAL_CHREC
--- 502,511 ----
  {
    tree arg0, arg1, binomial_n_k;
    tree type = TREE_TYPE (chrec);
+   struct loop *var_loop = get_loop (var);
  
    while (TREE_CODE (chrec) == POLYNOMIAL_CHREC
! 	 && flow_loop_nested_p (var_loop, get_chrec_loop (chrec)))
      chrec = CHREC_LEFT (chrec);
  
    if (TREE_CODE (chrec) == POLYNOMIAL_CHREC
*************** tree 
*** 631,656 ****
  hide_evolution_in_other_loops_than_loop (tree chrec, 
  					 unsigned loop_num)
  {
    if (automatically_generated_chrec_p (chrec))
      return chrec;
    
    switch (TREE_CODE (chrec))
      {
      case POLYNOMIAL_CHREC:
!       if (CHREC_VARIABLE (chrec) == loop_num)
  	return build_polynomial_chrec 
  	  (loop_num, 
  	   hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), 
  						    loop_num), 
  	   CHREC_RIGHT (chrec));
        
!       else if (CHREC_VARIABLE (chrec) < loop_num)
  	/* There is no evolution in this loop.  */
  	return initial_condition (chrec);
        
        else
! 	return hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), 
! 							loop_num);
        
      default:
        return chrec;
--- 642,673 ----
  hide_evolution_in_other_loops_than_loop (tree chrec, 
  					 unsigned loop_num)
  {
+   struct loop *loop = get_loop (loop_num), *chloop;
    if (automatically_generated_chrec_p (chrec))
      return chrec;
    
    switch (TREE_CODE (chrec))
      {
      case POLYNOMIAL_CHREC:
!       chloop = get_chrec_loop (chrec);
! 
!       if (chloop == loop)
  	return build_polynomial_chrec 
  	  (loop_num, 
  	   hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), 
  						    loop_num), 
  	   CHREC_RIGHT (chrec));
        
!       else if (flow_loop_nested_p (chloop, loop))
  	/* There is no evolution in this loop.  */
  	return initial_condition (chrec);
        
        else
! 	{
! 	  gcc_assert (flow_loop_nested_p (loop, chloop));
! 	  return hide_evolution_in_other_loops_than_loop (CHREC_LEFT (chrec), 
! 							  loop_num);
! 	}
        
      default:
        return chrec;
*************** chrec_component_in_loop_num (tree chrec,
*** 666,671 ****
--- 683,689 ----
  			     bool right)
  {
    tree component;
+   struct loop *loop = get_loop (loop_num), *chloop;
  
    if (automatically_generated_chrec_p (chrec))
      return chrec;
*************** chrec_component_in_loop_num (tree chrec,
*** 673,679 ****
    switch (TREE_CODE (chrec))
      {
      case POLYNOMIAL_CHREC:
!       if (CHREC_VARIABLE (chrec) == loop_num)
  	{
  	  if (right)
  	    component = CHREC_RIGHT (chrec);
--- 691,699 ----
    switch (TREE_CODE (chrec))
      {
      case POLYNOMIAL_CHREC:
!       chloop = get_chrec_loop (chrec);
! 
!       if (chloop == loop)
  	{
  	  if (right)
  	    component = CHREC_RIGHT (chrec);
*************** chrec_component_in_loop_num (tree chrec,
*** 693,706 ****
  	       component);
  	}
        
!       else if (CHREC_VARIABLE (chrec) < loop_num)
  	/* There is no evolution part in this loop.  */
  	return NULL_TREE;
        
        else
! 	return chrec_component_in_loop_num (CHREC_LEFT (chrec), 
! 					    loop_num, 
! 					    right);
        
       default:
        if (right)
--- 713,729 ----
  	       component);
  	}
        
!       else if (flow_loop_nested_p (chloop, loop))
  	/* There is no evolution part in this loop.  */
  	return NULL_TREE;
        
        else
! 	{
! 	  gcc_assert (flow_loop_nested_p (loop, chloop));
! 	  return chrec_component_in_loop_num (CHREC_LEFT (chrec), 
! 					      loop_num, 
! 					      right);
! 	}
        
       default:
        if (right)
*************** reset_evolution_in_loop (unsigned loop_n
*** 742,751 ****
  			 tree chrec, 
  			 tree new_evol)
  {
    gcc_assert (chrec_type (chrec) == chrec_type (new_evol));
  
    if (TREE_CODE (chrec) == POLYNOMIAL_CHREC
!       && CHREC_VARIABLE (chrec) > loop_num)
      {
        tree left = reset_evolution_in_loop (loop_num, CHREC_LEFT (chrec),
  					   new_evol);
--- 765,776 ----
  			 tree chrec, 
  			 tree new_evol)
  {
+   struct loop *loop = get_loop (loop_num);
+ 
    gcc_assert (chrec_type (chrec) == chrec_type (new_evol));
  
    if (TREE_CODE (chrec) == POLYNOMIAL_CHREC
!       && flow_loop_nested_p (loop, get_chrec_loop (chrec)))
      {
        tree left = reset_evolution_in_loop (loop_num, CHREC_LEFT (chrec),
  					   new_evol);
Index: modulo-sched.c
===================================================================
*** modulo-sched.c	(revision 121419)
--- modulo-sched.c	(working copy)
*************** sms_schedule (void)
*** 1028,1034 ****
    df = NULL;
  
    /* We don't want to perform SMS on new loops - created by versioning.  */
!   FOR_EACH_LOOP (li, loop, LI_ONLY_OLD)
      {
        rtx head, tail;
        rtx count_reg, count_init;
--- 1028,1034 ----
    df = NULL;
  
    /* We don't want to perform SMS on new loops - created by versioning.  */
!   FOR_EACH_LOOP (li, loop, 0)
      {
        rtx head, tail;
        rtx count_reg, count_init;
Index: tree-vectorizer.c
===================================================================
*** tree-vectorizer.c	(revision 121419)
--- tree-vectorizer.c	(working copy)
*************** vectorize_loops (void)
*** 2175,2181 ****
       than all previously defined loops. This fact allows us to run 
       only over initial loops skipping newly generated ones.  */
    vect_loops_num = number_of_loops ();
!   FOR_EACH_LOOP (li, loop, LI_ONLY_OLD)
      {
        loop_vec_info loop_vinfo;
  
--- 2175,2181 ----
       than all previously defined loops. This fact allows us to run 
       only over initial loops skipping newly generated ones.  */
    vect_loops_num = number_of_loops ();
!   FOR_EACH_LOOP (li, loop, 0)
      {
        loop_vec_info loop_vinfo;
  
Index: cfgloop.h
===================================================================
*** cfgloop.h	(revision 121419)
--- cfgloop.h	(working copy)
*************** Software Foundation, 51 Franklin Street,
*** 25,30 ****
--- 25,31 ----
  #include "basic-block.h"
  /* For rtx_code.  */
  #include "rtl.h"
+ #include "vecprim.h"
  
  /* Structure to hold decision about unrolling/peeling.  */
  enum lpt_dec
*************** number_of_loops (void)
*** 425,508 ****
  
  enum li_flags
  {
!   LI_INCLUDE_ROOT = 1,	/* Include the fake root of the loop tree.  */
!   LI_FROM_INNERMOST = 2,/* Iterate over the loops in the reverse order,
! 			   starting from innermost ones.  */
!   LI_ONLY_INNERMOST = 4,/* Iterate only over innermost loops.  */
!   LI_ONLY_OLD = 8	/* Do not traverse the loops created during the
! 			   traversal (this is the default behavior with
! 			   LI_FROM_INNERMOST).  */
  };
  
  /* The iterator for loops.  */
  
  typedef struct
  {
!   int idx;		/* Index of the actual loop.  */
!   int end;		/* Only loops before end should be traversed.  */
  } loop_iterator;
  
  static inline void
! fel_next (loop_iterator *li, loop_p *loop, unsigned flags)
  {
!   if (flags & LI_FROM_INNERMOST)
!     {
!       li->idx--;
!       for (; li->idx > li->end; li->idx--)
! 	{
! 	  *loop = VEC_index (loop_p, current_loops->larray, li->idx);
! 	  if (*loop
! 	      && (!(flags & LI_ONLY_INNERMOST)
! 		  || (*loop)->inner == NULL))
! 	    return;
! 	}
!     }
!   else
      {
-       if (!(flags & LI_ONLY_OLD))
- 	li->end = number_of_loops ();
        li->idx++;
!       for (; li->idx < li->end; li->idx++)
! 	{
! 	  *loop = VEC_index (loop_p, current_loops->larray, li->idx);
! 	  if (*loop
! 	      && (!(flags & LI_ONLY_INNERMOST)
! 		  || (*loop)->inner == NULL))
! 	    return;
! 	}
      }
  
    *loop = NULL;
  }
  
  static inline void
  fel_init (loop_iterator *li, loop_p *loop, unsigned flags)
  {
    if (!current_loops)
      {
!       li->idx = 0;
!       li->end = 0;
        *loop = NULL;
        return;
      }
  
!   if (flags & LI_FROM_INNERMOST)
      {
!       li->idx = number_of_loops ();
!       li->end = (flags & LI_INCLUDE_ROOT) ? -1 : 0;
      }
    else
      {
!       li->idx = (flags & LI_INCLUDE_ROOT) ? -1 : 0;
!       li->end = number_of_loops ();
      }
!   fel_next (li, loop, flags);
  }
  
  #define FOR_EACH_LOOP(LI, LOOP, FLAGS) \
    for (fel_init (&(LI), &(LOOP), FLAGS); \
         (LOOP); \
!        fel_next (&(LI), &(LOOP), FLAGS))
  
  /* The properties of the target.  */
  
--- 426,552 ----
  
  enum li_flags
  {
!   LI_INCLUDE_ROOT = 1,		/* Include the fake root of the loop tree.  */
!   LI_FROM_INNERMOST = 2,	/* Iterate over the loops in the reverse order,
! 				   starting from innermost ones.  */
!   LI_ONLY_INNERMOST = 4		/* Iterate only over innermost loops.  */
  };
  
  /* The iterator for loops.  */
  
  typedef struct
  {
!   /* The list of loops to visit.  */
!   VEC(int,heap) *to_visit;
! 
!   /* The index of the actual loop.  */
!   unsigned idx;
  } loop_iterator;
  
  static inline void
! fel_next (loop_iterator *li, loop_p *loop)
  {
!   int anum;
! 
!   while (VEC_iterate (int, li->to_visit, li->idx, anum))
      {
        li->idx++;
!       *loop = get_loop (anum);
!       if (*loop)
! 	return;
      }
  
+   VEC_free (int, heap, li->to_visit);
    *loop = NULL;
  }
  
  static inline void
  fel_init (loop_iterator *li, loop_p *loop, unsigned flags)
  {
+   struct loop *aloop;
+   unsigned i;
+   int mn;
+ 
+   li->idx = 0;
    if (!current_loops)
      {
!       li->to_visit = NULL;
        *loop = NULL;
        return;
      }
  
!   li->to_visit = VEC_alloc (int, heap, number_of_loops ());
!   mn = (flags & LI_INCLUDE_ROOT) ? 0 : 1;
! 
!   if (flags & LI_ONLY_INNERMOST)
      {
!       for (i = 0; VEC_iterate (loop_p, current_loops->larray, i, aloop); i++)
! 	if (aloop != NULL
! 	    && aloop->inner == NULL
! 	    && aloop->num >= mn)
! 	  VEC_quick_push (int, li->to_visit, aloop->num);
!     }
!   else if (flags & LI_FROM_INNERMOST)
!     {
!       /* Push the loops to LI->TO_VISIT in postorder.  */
!       for (aloop = current_loops->tree_root;
! 	   aloop->inner != NULL;
! 	   aloop = aloop->inner)
! 	continue;
! 
!       while (1)
! 	{
! 	  if (aloop->num >= mn)
! 	    VEC_quick_push (int, li->to_visit, aloop->num);
! 
! 	  if (aloop->next)
! 	    {
! 	      for (aloop = aloop->next;
! 		   aloop->inner != NULL;
! 		   aloop = aloop->inner)
! 		continue;
! 	    }
! 	  else if (!aloop->outer)
! 	    break;
! 	  else
! 	    aloop = aloop->outer;
! 	}
      }
    else
      {
!       /* Push the loops to LI->TO_VISIT in preorder.  */
!       aloop = current_loops->tree_root;
!       while (1)
! 	{
! 	  if (aloop->num >= mn)
! 	    VEC_quick_push (int, li->to_visit, aloop->num);
! 
! 	  if (aloop->inner != NULL)
! 	    aloop = aloop->inner;
! 	  else
! 	    {
! 	      while (aloop != NULL && aloop->next == NULL)
! 		aloop = aloop->outer;
! 	      if (aloop == NULL)
! 		break;
! 	      aloop = aloop->next;
! 	    }
! 	}
      }
! 
!   fel_next (li, loop);
  }
  
  #define FOR_EACH_LOOP(LI, LOOP, FLAGS) \
    for (fel_init (&(LI), &(LOOP), FLAGS); \
         (LOOP); \
!        fel_next (&(LI), &(LOOP)))
! 
! #define FOR_EACH_LOOP_BREAK(LI) \
!   { \
!     VEC_free (int, heap, (LI)->to_visit); \
!     break; \
!   }
  
  /* The properties of the target.  */
  
Index: Makefile.in
===================================================================
*** Makefile.in	(revision 121419)
--- Makefile.in	(working copy)
*************** RESOURCE_H = resource.h hard-reg-set.h
*** 749,755 ****
  SCHED_INT_H = sched-int.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H)
  INTEGRATE_H = integrate.h $(VARRAY_H)
  CFGLAYOUT_H = cfglayout.h $(BASIC_BLOCK_H)
! CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $(RTL_H)
  IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H) 
  IPA_REFERENCE_H = ipa-reference.h bitmap.h $(TREE_H)  
  IPA_TYPE_ESCAPE_H = ipa-type-escape.h $(TREE_H)  
--- 749,755 ----
  SCHED_INT_H = sched-int.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H)
  INTEGRATE_H = integrate.h $(VARRAY_H)
  CFGLAYOUT_H = cfglayout.h $(BASIC_BLOCK_H)
! CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) $(RTL_H) vecprim.h
  IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H) 
  IPA_REFERENCE_H = ipa-reference.h bitmap.h $(TREE_H)  
  IPA_TYPE_ESCAPE_H = ipa-type-escape.h $(TREE_H)  



More information about the Gcc-patches mailing list