Loop movables patch

Michael Hayes mhayes@redhat.com
Sun Dec 31 03:07:00 GMT 2000


The purpose of this patch is to allow a number of independent loops
to be optimised at the same time.  It also gets rid of another global
variable :-)  Tested by bootstrapping gcc for i686-pc-gnu-linux.


2000-12-27  Michael Hayes  <mhayes@redhat.com>

	* loop.h (struct loop_movables): New.
	(LOOP_MOVABLES): New.
	(struct loop_info): Add movables field.

	* loop.c (struct movables): Delete.  Replace all uses
	with struct loop_movables.
	(the_movables): Delete.  Replace all uses with movables
	field in loop_info.
	(loop_movables_add, loop_movables_free): New functions.
	(scan_loop): Use xmalloc instead of alloca for movables.
	Call loop_movables_free.
	
	
Index: loop.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/loop.c,v
retrieving revision 1.299
diff -c -3 -p -r1.299 loop.c
*** loop.c	2000/11/30 06:31:17	1.299
--- loop.c	2000/12/27 03:40:54
*************** struct movable
*** 132,148 ****
    struct movable *next;
  };
  
- struct movables
- {
-   /* Head of movable chain.  */
-   struct movable *head;
-   /* Last movable in chain.  */
-   struct movable *last;
-   /* Number of movables in the loop.  */
-   int num;
- };
- 
- static struct movables the_movables;
  
  FILE *loop_dump_stream;
  
--- 132,137 ----
*************** static void replace_call_address PARAMS 
*** 170,184 ****
  #endif
  static rtx skip_consec_insns PARAMS ((rtx, int));
  static int libcall_benefit PARAMS ((rtx));
! static void ignore_some_movables PARAMS ((struct movables *));
! static void force_movables PARAMS ((struct movables *));
! static void combine_movables PARAMS ((struct movables *, struct loop_regs *));
! static int regs_match_p PARAMS ((rtx, rtx, struct movables *));
! static int rtx_equal_for_loop_p PARAMS ((rtx, rtx, struct movables *,
  					 struct loop_regs *));
  static void add_label_notes PARAMS ((rtx, rtx));
! static void move_movables PARAMS ((struct loop *loop, struct movables *,
  				   int, int));
  static int count_nonfixed_reads PARAMS ((const struct loop *, rtx));
  static void strength_reduce PARAMS ((struct loop *, int, int));
  static void find_single_use_in_loop PARAMS ((rtx, rtx, varray_type));
--- 159,177 ----
  #endif
  static rtx skip_consec_insns PARAMS ((rtx, int));
  static int libcall_benefit PARAMS ((rtx));
! static void ignore_some_movables PARAMS ((struct loop_movables *));
! static void force_movables PARAMS ((struct loop_movables *));
! static void combine_movables PARAMS ((struct loop_movables *,
! 				      struct loop_regs *));
! static int regs_match_p PARAMS ((rtx, rtx, struct loop_movables *));
! static int rtx_equal_for_loop_p PARAMS ((rtx, rtx, struct loop_movables *,
  					 struct loop_regs *));
  static void add_label_notes PARAMS ((rtx, rtx));
! static void move_movables PARAMS ((struct loop *loop, struct loop_movables *,
  				   int, int));
+ static void loop_movables_add PARAMS((struct loop_movables *,
+ 				      struct movable *));
+ static void loop_movables_free PARAMS((struct loop_movables *));
  static int count_nonfixed_reads PARAMS ((const struct loop *, rtx));
  static void strength_reduce PARAMS ((struct loop *, int, int));
  static void find_single_use_in_loop PARAMS ((rtx, rtx, varray_type));
*************** scan_loop (loop, flags)
*** 516,522 ****
    /* The SET from an insn, if it is the only SET in the insn.  */
    rtx set, set1;
    /* Chain describing insns movable in current loop.  */
!   struct movables *movables = &the_movables;
    /* Ratio of extra register life span we can justify
       for saving an instruction.  More if loop doesn't call subroutines
       since in that case saving an insn makes more difference
--- 509,515 ----
    /* The SET from an insn, if it is the only SET in the insn.  */
    rtx set, set1;
    /* Chain describing insns movable in current loop.  */
!   struct loop_movables *movables = LOOP_MOVABLES (loop);
    /* Ratio of extra register life span we can justify
       for saving an instruction.  More if loop doesn't call subroutines
       since in that case saving an insn makes more difference
*************** scan_loop (loop, flags)
*** 808,814 ****
  		  continue;
  		}
  
! 	      m = (struct movable *) alloca (sizeof (struct movable));
  	      m->next = 0;
  	      m->insn = p;
  	      m->set_src = src;
--- 801,807 ----
  		  continue;
  		}
  
! 	      m = (struct movable *) xmalloc (sizeof (struct movable));
  	      m->next = 0;
  	      m->insn = p;
  	      m->set_src = src;
*************** scan_loop (loop, flags)
*** 840,850 ****
  		m->savings += libcall_benefit (p);
  	      VARRAY_INT (regs->set_in_loop, regno) = move_insn ? -2 : -1;
  	      /* Add M to the end of the chain MOVABLES.  */
! 	      if (movables->head == 0)
! 		movables->head = m;
! 	      else
! 		movables->last->next = m;
! 	      movables->last = m;
  
  	      if (m->consec > 0)
  		{
--- 833,839 ----
  		m->savings += libcall_benefit (p);
  	      VARRAY_INT (regs->set_in_loop, regno) = move_insn ? -2 : -1;
  	      /* Add M to the end of the chain MOVABLES.  */
! 	      loop_movables_add (movables, m);
  
  	      if (m->consec > 0)
  		{
*************** scan_loop (loop, flags)
*** 949,959 ****
  		  m->savings = 1;
  		  VARRAY_INT (regs->set_in_loop, regno) = -1;
  		  /* Add M to the end of the chain MOVABLES.  */
! 		  if (movables->head == 0)
! 		    movables->head = m;
! 		  else
! 		    movables->last->next = m;
! 		  movables->last = m;
  		}
  	    }
  	}
--- 938,944 ----
  		  m->savings = 1;
  		  VARRAY_INT (regs->set_in_loop, regno) = -1;
  		  /* Add M to the end of the chain MOVABLES.  */
! 		  loop_movables_add (movables, m);
  		}
  	    }
  	}
*************** scan_loop (loop, flags)
*** 1056,1061 ****
--- 1041,1050 ----
  	delete_insn (update_end);
      }
  
+ 
+   /* The movable information is required for strength reduction.  */
+   loop_movables_free (movables);
+ 
    VARRAY_FREE (regs->single_usage);
    VARRAY_FREE (regs->set_in_loop);
    VARRAY_FREE (regs->n_times_set);
*************** skip_consec_insns (insn, count)
*** 1255,1261 ****
  
  static void
  ignore_some_movables (movables)
!      struct movables *movables;
  {
    register struct movable *m, *m1;
  
--- 1244,1250 ----
  
  static void
  ignore_some_movables (movables)
!      struct loop_movables *movables;
  {
    register struct movable *m, *m1;
  
*************** ignore_some_movables (movables)
*** 1287,1293 ****
  
  static void
  force_movables (movables)
!      struct movables *movables;
  {
    register struct movable *m, *m1;
    for (m1 = movables->head; m1; m1 = m1->next)
--- 1276,1282 ----
  
  static void
  force_movables (movables)
!      struct loop_movables *movables;
  {
    register struct movable *m, *m1;
    for (m1 = movables->head; m1; m1 = m1->next)
*************** force_movables (movables)
*** 1326,1332 ****
  
  static void
  combine_movables (movables, regs)
!      struct movables *movables;
       struct loop_regs *regs;
  {
    register struct movable *m;
--- 1315,1321 ----
  
  static void
  combine_movables (movables, regs)
!      struct loop_movables *movables;
       struct loop_regs *regs;
  {
    register struct movable *m;
*************** combine_movables (movables, regs)
*** 1446,1452 ****
  static int
  regs_match_p (x, y, movables)
       rtx x, y;
!      struct movables *movables;
  {
    unsigned int xn = REGNO (x);
    unsigned int yn = REGNO (y);
--- 1435,1441 ----
  static int
  regs_match_p (x, y, movables)
       rtx x, y;
!      struct loop_movables *movables;
  {
    unsigned int xn = REGNO (x);
    unsigned int yn = REGNO (y);
*************** regs_match_p (x, y, movables)
*** 1475,1481 ****
  static int
  rtx_equal_for_loop_p (x, y, movables, regs)
       rtx x, y;
!      struct movables *movables;
       struct loop_regs *regs;
  {
    register int i;
--- 1464,1470 ----
  static int
  rtx_equal_for_loop_p (x, y, movables, regs)
       rtx x, y;
!      struct loop_movables *movables;
       struct loop_regs *regs;
  {
    register int i;
*************** add_label_notes (x, insns)
*** 1632,1638 ****
  static void
  move_movables (loop, movables, threshold, insn_count)
       struct loop *loop;
!      struct movables *movables;
       int threshold;
       int insn_count;
  {
--- 1621,1627 ----
  static void
  move_movables (loop, movables, threshold, insn_count)
       struct loop *loop;
!      struct loop_movables *movables;
       int threshold;
       int insn_count;
  {
*************** move_movables (loop, movables, threshold
*** 2135,2140 ****
--- 2124,2157 ----
    free (reg_map);
    free (already_moved);
  }
+ 
+ 
+ static void
+ loop_movables_add (movables, m)
+      struct loop_movables *movables;
+      struct movable *m;
+ {
+   if (movables->head == 0)
+     movables->head = m;
+   else
+     movables->last->next = m;
+   movables->last = m;
+ }
+ 
+ 
+ static void
+ loop_movables_free (movables)
+      struct loop_movables *movables;
+ {
+   struct movable *m;
+   struct movable *m_next;
+ 
+   for (m = movables->head; m; m = m_next)
+     {
+       m_next = m->next;
+       free (m);
+     }
+ }  
  
  #if 0
  /* Scan X and replace the address of any MEM in it with ADDR.
*************** simplify_giv_expr (loop, x, ext_val, ben
*** 6019,6026 ****
  	  if (loop_invariant_p (loop, x) == 1)
  	    {
  	      struct movable *m;
  
! 	      for (m = the_movables.head; m; m = m->next)
  		if (rtx_equal_p (x, m->set_dest))
  		  {
  		    /* Ok, we found a match.  Substitute and simplify.  */
--- 6036,6044 ----
  	  if (loop_invariant_p (loop, x) == 1)
  	    {
  	      struct movable *m;
+ 	      struct loop_movables *movables = LOOP_MOVABLES (loop);
  
! 	      for (m = movables->head; m; m = m->next)
  		if (rtx_equal_p (x, m->set_dest))
  		  {
  		    /* Ok, we found a match.  Substitute and simplify.  */
*************** check_dbra_loop (loop, insn_count)
*** 7316,7322 ****
  	   && ! loop_info->has_volatile
  	   && reversible_mem_store
  	   && (bl->giv_count + bl->biv_count + loop_info->num_mem_sets
! 	       + the_movables.num + compare_and_branch == insn_count)
  	   && (bl == ivs->loop_iv_list && bl->next == 0))
  	  || no_use_except_counting)
  	{
--- 7334,7340 ----
  	   && ! loop_info->has_volatile
  	   && reversible_mem_store
  	   && (bl->giv_count + bl->biv_count + loop_info->num_mem_sets
! 	       + LOOP_MOVABLES (loop)->num + compare_and_branch == insn_count)
  	   && (bl == ivs->loop_iv_list && bl->next == 0))
  	  || no_use_except_counting)
  	{
Index: loop.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/loop.h,v
retrieving revision 1.40
diff -c -3 -p -r1.40 loop.h
*** loop.h	2000/09/19 16:01:13	1.40
--- loop.h	2000/12/27 03:40:54
*************** Boston, MA 02111-1307, USA.  */
*** 28,33 ****
--- 28,36 ----
  /* Get the loop info pointer of a loop.  */
  #define LOOP_INFO(LOOP) ((struct loop_info *) (LOOP)->aux)
  
+ /* Get a pointer to the loop movables structure.  */
+ #define LOOP_MOVABLES(LOOP) (&LOOP_INFO (loop)->movables)
+ 
  /* Get a pointer to the loop registers structure.  */
  #define LOOP_REGS(LOOP) (&LOOP_INFO (loop)->regs)
  
*************** struct loop_regs
*** 236,247 ****
--- 239,266 ----
    int multiple_uses;
  };
  
+ 
+ struct loop_movables
+ {
+   /* Head of movable chain.  */
+   struct movable *head;
+   /* Last movable in chain.  */
+   struct movable *last;
+   /* Number of movables in the loop.  */
+   int num;
+ };
+ 
+ 
  /* Information pertaining to a loop.  */
  
  struct loop_info
  {
    /* Nonzero if there is a subroutine call in the current loop.  */
    int has_call;
+   /* Nonzero if there is a libcall in the current loop.  */
+   int has_libcall;
+   /* Nonzero if there is a non constant call in the current loop.  */
+   int has_nonconst_call;
    /* Nonzero if there is a volatile memory reference in the current
       loop.  */
    int has_volatile;
*************** struct loop_info
*** 304,309 ****
--- 323,330 ----
    int num_mem_sets;
    /* The insn where the first of these was found.  */
    rtx first_loop_store_insn;
+   /* The chain of movable insns in loop.  */
+   struct loop_movables movables;
    /* The registers used the in loop.  */
    struct loop_regs regs;
    /* The induction variable information in loop.  */


More information about the Gcc-patches mailing list