[1/2] cfgloop: Extend loop iteration macros to loop only over sub-loops

Message ID ri6r1p2z4kg.fsf@suse.cz
State New
Headers show
Series
  • [1/2] cfgloop: Extend loop iteration macros to loop only over sub-loops
Related show

Commit Message

Martin Jambor Nov. 9, 2020, 7:57 p.m.
Hi,

This patch adds loop iteration macros FOR_EACH_ENCLOSED_LOOP and
FOR_EACH_ENCLOSED_LOOP_FN which can loop only over inner loops of a
given loop.

The patch is required for a follow-up patch which enables loop
invariant motion to only work on a selected loop.  I have bootstrapped
and tested the two patches on x86_64-linux and aarch64-linux.  OK for
trunk once the follow-up patch is accepted too?

Thanks,

Martin


gcc/ChangeLog:

2020-10-29  Martin Jambor  <mjambor@suse.cz>

	* cfgloop.h (loop_iterator::loop_iterator): Add parameter to the
	constructor, make it iterate over sub-loops if non-NULL.
	(FOR_EACH_LOOP): Pass extra NULL to loop_iterator::loop_iterator.
	(FOR_EACH_LOOP_FN): Likewise.
	(FOR_EACH_ENCLOSED_LOOP): New macro.
	(FOR_EACH_ENCLOSED_LOOP_FN): Likewise.
---
 gcc/cfgloop.h | 44 ++++++++++++++++++++++++++++++++------------
 1 file changed, 32 insertions(+), 12 deletions(-)

-- 
2.29.2

Comments

Richard Biener Nov. 10, 2020, 7:27 a.m. | #1
On Mon, 9 Nov 2020, Martin Jambor wrote:

> Hi,

> 

> This patch adds loop iteration macros FOR_EACH_ENCLOSED_LOOP and

> FOR_EACH_ENCLOSED_LOOP_FN which can loop only over inner loops of a

> given loop.

> 

> The patch is required for a follow-up patch which enables loop

> invariant motion to only work on a selected loop.  I have bootstrapped

> and tested the two patches on x86_64-linux and aarch64-linux.  OK for

> trunk once the follow-up patch is accepted too?


OK for trunk.

Thanks,
Richard.

> Thanks,

> 

> Martin

> 

> 

> gcc/ChangeLog:

> 

> 2020-10-29  Martin Jambor  <mjambor@suse.cz>

> 

> 	* cfgloop.h (loop_iterator::loop_iterator): Add parameter to the

> 	constructor, make it iterate over sub-loops if non-NULL.

> 	(FOR_EACH_LOOP): Pass extra NULL to loop_iterator::loop_iterator.

> 	(FOR_EACH_LOOP_FN): Likewise.

> 	(FOR_EACH_ENCLOSED_LOOP): New macro.

> 	(FOR_EACH_ENCLOSED_LOOP_FN): Likewise.

> ---

>  gcc/cfgloop.h | 44 ++++++++++++++++++++++++++++++++------------

>  1 file changed, 32 insertions(+), 12 deletions(-)

> 

> diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h

> index d14689dc31f..e8ffa5b2964 100644

> --- a/gcc/cfgloop.h

> +++ b/gcc/cfgloop.h

> @@ -663,7 +663,7 @@ enum li_flags

>  class loop_iterator

>  {

>  public:

> -  loop_iterator (function *fn, loop_p *loop, unsigned flags);

> +  loop_iterator (function *fn, loop_p top, loop_p *loop, unsigned flags);

>  

>    inline loop_p next ();

>  

> @@ -693,8 +693,15 @@ loop_iterator::next ()

>    return NULL;

>  }

>  

> +/* Constructor to set up iteration over loops.  FN is the function in which the

> +   loop tree resides.  If TOP is NULL iterate over all loops in the function,

> +   otherwise iterate only over sub-loops of TOP (including TOP).  LOOP points

> +   to the iteration pointer in the iteration.  FLAGS modify the iteration as

> +   described in enum li_flags.  */

> +

>  inline

> -loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)

> +loop_iterator::loop_iterator (function *fn, loop_p top, loop_p *loop,

> +			      unsigned flags)

>  {

>    class loop *aloop;

>    unsigned i;

> @@ -716,13 +723,16 @@ loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)

>        for (i = 0; vec_safe_iterate (loops_for_fn (fn)->larray, i, &aloop); i++)

>  	if (aloop != NULL

>  	    && aloop->inner == NULL

> -	    && aloop->num >= mn)

> +	    && aloop->num >= mn

> +	    && (!top || flow_loop_nested_p (top, aloop)))

>  	  this->to_visit.quick_push (aloop->num);

>      }

>    else if (flags & LI_FROM_INNERMOST)

>      {

> +      if (!top)

> +	top = loops_for_fn (fn)->tree_root;

>        /* Push the loops to LI->TO_VISIT in postorder.  */

> -      for (aloop = loops_for_fn (fn)->tree_root;

> +      for (aloop = top;

>  	   aloop->inner != NULL;

>  	   aloop = aloop->inner)

>  	continue;

> @@ -732,15 +742,15 @@ loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)

>  	  if (aloop->num >= mn)

>  	    this->to_visit.quick_push (aloop->num);

>  

> -	  if (aloop->next)

> +	  if (aloop == top)

> +	    break;

> +	  else if (aloop->next)

>  	    {

>  	      for (aloop = aloop->next;

>  		   aloop->inner != NULL;

>  		   aloop = aloop->inner)

>  		continue;

>  	    }

> -	  else if (!loop_outer (aloop))

> -	    break;

>  	  else

>  	    aloop = loop_outer (aloop);

>  	}

> @@ -748,7 +758,7 @@ loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)

>    else

>      {

>        /* Push the loops to LI->TO_VISIT in preorder.  */

> -      aloop = loops_for_fn (fn)->tree_root;

> +      aloop = top ? top : loops_for_fn (fn)->tree_root;

>        while (1)

>  	{

>  	  if (aloop->num >= mn)

> @@ -758,9 +768,9 @@ loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)

>  	    aloop = aloop->inner;

>  	  else

>  	    {

> -	      while (aloop != NULL && aloop->next == NULL)

> +	      while (aloop != top && aloop->next == NULL)

>  		aloop = loop_outer (aloop);

> -	      if (aloop == NULL)

> +	      if (aloop == top)

>  		break;

>  	      aloop = aloop->next;

>  	    }

> @@ -771,12 +781,22 @@ loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)

>  }

>  

>  #define FOR_EACH_LOOP(LOOP, FLAGS) \

> -  for (loop_iterator li(cfun, &(LOOP), FLAGS); \

> +  for (loop_iterator li(cfun, NULL, &(LOOP), FLAGS);	\

>         (LOOP); \

>         (LOOP) = li.next ())

>  

>  #define FOR_EACH_LOOP_FN(FN, LOOP, FLAGS) \

> -  for (loop_iterator li(FN, &(LOOP), FLAGS); \

> +  for (loop_iterator li(FN, NULL, &(LOOP), FLAGS);	\

> +       (LOOP); \

> +       (LOOP) = li.next ())

> +

> +#define FOR_EACH_ENCLOSED_LOOP(TOP, LOOP, FLAGS)		\

> +  for (loop_iterator li(cfun, TOP, &(LOOP), FLAGS);	\

> +       (LOOP); \

> +       (LOOP) = li.next ())

> +

> +#define FOR_EACH_ENCLOSED_LOOP_FN(FN, TOP, LOOP, FLAGS) \

> +  for (loop_iterator li(FN, TOP, &(LOOP), FLAGS);	\

>         (LOOP); \

>         (LOOP) = li.next ())

>  

> 


-- 
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imend

Patch

diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index d14689dc31f..e8ffa5b2964 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -663,7 +663,7 @@  enum li_flags
 class loop_iterator
 {
 public:
-  loop_iterator (function *fn, loop_p *loop, unsigned flags);
+  loop_iterator (function *fn, loop_p top, loop_p *loop, unsigned flags);
 
   inline loop_p next ();
 
@@ -693,8 +693,15 @@  loop_iterator::next ()
   return NULL;
 }
 
+/* Constructor to set up iteration over loops.  FN is the function in which the
+   loop tree resides.  If TOP is NULL iterate over all loops in the function,
+   otherwise iterate only over sub-loops of TOP (including TOP).  LOOP points
+   to the iteration pointer in the iteration.  FLAGS modify the iteration as
+   described in enum li_flags.  */
+
 inline
-loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)
+loop_iterator::loop_iterator (function *fn, loop_p top, loop_p *loop,
+			      unsigned flags)
 {
   class loop *aloop;
   unsigned i;
@@ -716,13 +723,16 @@  loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)
       for (i = 0; vec_safe_iterate (loops_for_fn (fn)->larray, i, &aloop); i++)
 	if (aloop != NULL
 	    && aloop->inner == NULL
-	    && aloop->num >= mn)
+	    && aloop->num >= mn
+	    && (!top || flow_loop_nested_p (top, aloop)))
 	  this->to_visit.quick_push (aloop->num);
     }
   else if (flags & LI_FROM_INNERMOST)
     {
+      if (!top)
+	top = loops_for_fn (fn)->tree_root;
       /* Push the loops to LI->TO_VISIT in postorder.  */
-      for (aloop = loops_for_fn (fn)->tree_root;
+      for (aloop = top;
 	   aloop->inner != NULL;
 	   aloop = aloop->inner)
 	continue;
@@ -732,15 +742,15 @@  loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)
 	  if (aloop->num >= mn)
 	    this->to_visit.quick_push (aloop->num);
 
-	  if (aloop->next)
+	  if (aloop == top)
+	    break;
+	  else if (aloop->next)
 	    {
 	      for (aloop = aloop->next;
 		   aloop->inner != NULL;
 		   aloop = aloop->inner)
 		continue;
 	    }
-	  else if (!loop_outer (aloop))
-	    break;
 	  else
 	    aloop = loop_outer (aloop);
 	}
@@ -748,7 +758,7 @@  loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)
   else
     {
       /* Push the loops to LI->TO_VISIT in preorder.  */
-      aloop = loops_for_fn (fn)->tree_root;
+      aloop = top ? top : loops_for_fn (fn)->tree_root;
       while (1)
 	{
 	  if (aloop->num >= mn)
@@ -758,9 +768,9 @@  loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)
 	    aloop = aloop->inner;
 	  else
 	    {
-	      while (aloop != NULL && aloop->next == NULL)
+	      while (aloop != top && aloop->next == NULL)
 		aloop = loop_outer (aloop);
-	      if (aloop == NULL)
+	      if (aloop == top)
 		break;
 	      aloop = aloop->next;
 	    }
@@ -771,12 +781,22 @@  loop_iterator::loop_iterator (function *fn, loop_p *loop, unsigned flags)
 }
 
 #define FOR_EACH_LOOP(LOOP, FLAGS) \
-  for (loop_iterator li(cfun, &(LOOP), FLAGS); \
+  for (loop_iterator li(cfun, NULL, &(LOOP), FLAGS);	\
        (LOOP); \
        (LOOP) = li.next ())
 
 #define FOR_EACH_LOOP_FN(FN, LOOP, FLAGS) \
-  for (loop_iterator li(FN, &(LOOP), FLAGS); \
+  for (loop_iterator li(FN, NULL, &(LOOP), FLAGS);	\
+       (LOOP); \
+       (LOOP) = li.next ())
+
+#define FOR_EACH_ENCLOSED_LOOP(TOP, LOOP, FLAGS)		\
+  for (loop_iterator li(cfun, TOP, &(LOOP), FLAGS);	\
+       (LOOP); \
+       (LOOP) = li.next ())
+
+#define FOR_EACH_ENCLOSED_LOOP_FN(FN, TOP, LOOP, FLAGS) \
+  for (loop_iterator li(FN, TOP, &(LOOP), FLAGS);	\
        (LOOP); \
        (LOOP) = li.next ())