patch to reduce register pressure from strength reduction

Joern Rennecke amylaar@cygnus.co.uk
Fri Jan 29 16:32:00 GMT 1999


> Program received signal SIGSEGV, Segmentation fault.
> copy_loop_body (copy_start=0x82e40d4, copy_end=0x82e4144,
> map=0xbfff423c, exit_label=0x83304a8, last_iteration=0,
> unroll_type=UNROLL_MODULO, 
>     start_label=0x82e410c, loop_end=0x82e4e80, insert_before=0x82e4190,
> copy_notes_from=0x82e4190) at ../../egcs/gcc/unroll.c:1733
> 
> Here's the code:

I have made a patch that allows me to compile your testcase.
I haven't analyzed the generated code, so please check it out.

Fri Jan 29 23:13:20 1999  J"orn Rennecke <amylaar@cygnus.co.uk>

	* loop.h (express_from): Declare.
	(struct induction): Replace derived flag with derived_from pointer.
	* loop.c (strength_reduce, record_giv, recombine_givs): Likewise.
	(express_from): No longer static.
	* unroll.c (find_splittable_givs): Replace derived with derived_from.
	When processing an address giv with which another giv has been
	combined that has also been derived from a third giv, handle like
	having combined with the third giv.
	Set splittable_regs_updates to 1 for derived givs.

Index: loop.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/loop.h,v
retrieving revision 1.16
diff -p -r1.16 loop.h
*** loop.h	1999/01/28 15:36:04	1.16
--- loop.h	1999/01/29 23:09:37
*************** struct induction
*** 101,108 ****
  				   initialized in unrolled loop.  */
    unsigned shared : 1;
    unsigned no_const_addval : 1; /* 1 if add_val does not contain a const. */
-   unsigned derived : 1;         /* For a giv, 1 if we decided to derive this
- 				   giv from another one.  */
    int lifetime;			/* Length of life of this giv */
    rtx derive_adjustment;	/* If nonzero, is an adjustment to be
  				   subtracted from add_val when this giv
--- 101,106 ----
*************** struct induction
*** 115,120 ****
--- 113,120 ----
    struct induction *same;	/* If this giv has been combined with another
  				   giv, this points to the base giv.  The base
  				   giv will have COMBINED_WITH non-zero.  */
+   struct induction *derived_from;/* For a giv, if we decided to derive this
+ 				   giv from another one.  */
    HOST_WIDE_INT const_adjust;	/* Used by loop unrolling, when an address giv
  				   is split, and a constant is eliminated from
  				   the address, the -constant is stored here
*************** extern int first_increment_giv, last_inc
*** 226,231 ****
--- 226,232 ----
  int invariant_p PROTO((rtx));
  rtx get_condition_for_loop PROTO((rtx));
  void emit_iv_add_mult PROTO((rtx, rtx, rtx, rtx, rtx));
+ rtx express_from PROTO((struct induction *, struct induction *));
  
  /* Forward declarations for non-static functions declared in stmt.c.  */
  void find_loop_tree_blocks PROTO((void));
Index: loop.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/loop.c,v
retrieving revision 1.121
diff -p -r1.121 loop.c
*** loop.c	1999/01/29 14:36:59	1.121
--- loop.c	1999/01/29 23:09:40
*************** static int general_induction_var PROTO((
*** 320,326 ****
  static int consec_sets_giv PROTO((int, rtx, rtx, rtx, rtx *, rtx *, rtx *));
  static int check_dbra_loop PROTO((rtx, int, rtx, struct loop_info *));
  static rtx express_from_1 PROTO((rtx, rtx, rtx));
- static rtx express_from PROTO((struct induction *, struct induction *));
  static rtx combine_givs_p PROTO((struct induction *, struct induction *));
  static void combine_givs PROTO((struct iv_class *));
  struct recombine_givs_stats;
--- 320,325 ----
*************** strength_reduce (scan_start, end, loop_t
*** 4177,4183 ****
  	      v->auto_inc_opt = 0;
  	      v->unrolled = 0;
  	      v->shared = 0;
! 	      v->derived = 0;
  	      v->always_computable = 1;
  	      v->always_executed = 1;
  	      v->replaceable = 1;
--- 4176,4182 ----
  	      v->auto_inc_opt = 0;
  	      v->unrolled = 0;
  	      v->shared = 0;
! 	      v->derived_from = 0;
  	      v->always_computable = 1;
  	      v->always_executed = 1;
  	      v->replaceable = 1;
*************** strength_reduce (scan_start, end, loop_t
*** 4613,4619 ****
  
  	      v->new_reg = gen_reg_rtx (v->mode);
  
! 	      if (v->derived)
  		{
  		  PATTERN (v->insn)
  		    = replace_rtx (PATTERN (v->insn), v->dest_reg, v->new_reg);
--- 4612,4618 ----
  
  	      v->new_reg = gen_reg_rtx (v->mode);
  
! 	      if (v->derived_from)
  		{
  		  PATTERN (v->insn)
  		    = replace_rtx (PATTERN (v->insn), v->dest_reg, v->new_reg);
*************** record_giv (v, insn, src_reg, dest_reg, 
*** 5264,5270 ****
    v->auto_inc_opt = 0;
    v->unrolled = 0;
    v->shared = 0;
!   v->derived = 0;
    v->last_use = 0;
  
    /* The v->always_computable field is used in update_giv_derive, to
--- 5263,5269 ----
    v->auto_inc_opt = 0;
    v->unrolled = 0;
    v->shared = 0;
!   v->derived_from = 0;
    v->last_use = 0;
  
    /* The v->always_computable field is used in update_giv_derive, to
*************** express_from_1 (a, b, mult)
*** 6623,6629 ****
    return NULL_RTX;
  }
  
! static rtx
  express_from (g1, g2)
       struct induction *g1, *g2;
  {
--- 6622,6628 ----
    return NULL_RTX;
  }
  
! rtx
  express_from (g1, g2)
       struct induction *g1, *g2;
  {
*************** recombine_givs (bl, loop_start, loop_end
*** 7272,7278 ****
  	  rtx sum;
  
  	  v = giv_array[stats[i].giv_number];
! 	  if (v->giv_type != DEST_REG || v->derived || v->same)
  	    continue;
  	  if (! last_giv)
  	    {
--- 7271,7277 ----
  	  rtx sum;
  
  	  v = giv_array[stats[i].giv_number];
! 	  if (v->giv_type != DEST_REG || v->derived_from || v->same)
  	    continue;
  	  if (! last_giv)
  	    {
*************** recombine_givs (bl, loop_start, loop_end
*** 7313,7319 ****
  				  gen_rtx_SET (GET_MODE (v->dest_reg),
  					       v->dest_reg, sum), 0))
  	    {
! 	      v->derived = 1;
  	      v->new_reg = v->dest_reg;
  	      life_end = stats[i].end_luid;
  	    }
--- 7312,7318 ----
  				  gen_rtx_SET (GET_MODE (v->dest_reg),
  					       v->dest_reg, sum), 0))
  	    {
! 	      v->derived_from = last_giv;
  	      v->new_reg = v->dest_reg;
  	      life_end = stats[i].end_luid;
  	    }
Index: unroll.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/unroll.c,v
retrieving revision 1.44
diff -p -r1.44 unroll.c
*** unroll.c	1999/01/27 15:45:50	1.44
--- unroll.c	1999/01/29 23:09:41
*************** copy_loop_body (copy_start, copy_end, ma
*** 1801,1806 ****
--- 1801,1810 ----
  	      giv_dest_reg = SET_DEST (set);
  	      if (derived_regs[regno])
  		{
+ 		  /* ??? This relies on SET_SRC (SET) to be of
+ 		     the form (plus (reg) (const_int)), and thus
+ 		     forces recombine_givs to restrict the kind
+ 		     of giv derivations it does before unrolling.  */
  		  giv_src_reg = XEXP (SET_SRC (set), 0);
  		  giv_inc = XEXP (SET_SRC (set), 1);
  		}
*************** find_splittable_givs (bl, unroll_type, l
*** 2836,2842 ****
  		}
  		
  	      splittable_regs[REGNO (v->new_reg)] = value;
! 	      derived_regs[REGNO (v->new_reg)] = v->derived;
  	    }
  	  else
  	    {
--- 2840,2846 ----
  		}
  		
  	      splittable_regs[REGNO (v->new_reg)] = value;
! 	      derived_regs[REGNO (v->new_reg)] = v->derived_from != 0;
  	    }
  	  else
  	    {
*************** find_splittable_givs (bl, unroll_type, l
*** 2892,2899 ****
--- 2896,2914 ----
  		     Emit insn to initialize its value before loop start.  */
  
  		  rtx tem = gen_reg_rtx (v->mode);
+ 		  struct induction *same = v->same;
+ 		  rtx new_reg = v->new_reg;
  		  record_base_value (REGNO (tem), v->add_val, 0);
  
+ 		  if (same && same->derived_from)
+ 		    {
+ 		      /* Handle V as if the giv from which V->SAME has
+ 			 been derived has been combined with V.  */
+ 
+ 		      same = same->derived_from;
+ 		      new_reg = express_from (same, v);
+ 		    }
+ 
  		  /* If the address giv has a constant in its new_reg value,
  		     then this constant can be pulled out and put in value,
  		     instead of being part of the initialization code.  */
*************** find_splittable_givs (bl, unroll_type, l
*** 2944,2949 ****
--- 2959,2967 ----
  				 INSN_UID (v->insn));
  		      continue;
  		    }
+ 
+ 		  v->new_reg = new_reg;
+ 		  v->same = same;
  		  
  		  /* We set this after the address check, to guarantee that
  		     the register will be initialized.  */
*************** find_splittable_givs (bl, unroll_type, l
*** 3020,3026 ****
  		     Make sure that it's giv is marked as splittable here.  */
  		  
  		  splittable_regs[REGNO (v->new_reg)] = value;
! 		  derived_regs[REGNO (v->new_reg)] = v->derived;
  		  
  		  /* Make it appear to depend upon itself, so that the
  		     giv will be properly split in the main loop above.  */
--- 3038,3044 ----
  		     Make sure that it's giv is marked as splittable here.  */
  		  
  		  splittable_regs[REGNO (v->new_reg)] = value;
! 		  derived_regs[REGNO (v->new_reg)] = v->derived_from != 0;
  		  
  		  /* Make it appear to depend upon itself, so that the
  		     giv will be properly split in the main loop above.  */
*************** find_splittable_givs (bl, unroll_type, l
*** 3061,3067 ****
        if (GET_CODE (v->new_reg) == REG)
  	{
  	  int count = 1;
! 	  if (! v->ignore)
  	    count = reg_biv_class[REGNO (v->src_reg)]->biv_count;
  
  	  splittable_regs_updates[REGNO (v->new_reg)] = count;
--- 3079,3085 ----
        if (GET_CODE (v->new_reg) == REG)
  	{
  	  int count = 1;
! 	  if (! v->ignore && ! v->derived_from)
  	    count = reg_biv_class[REGNO (v->src_reg)]->biv_count;
  
  	  splittable_regs_updates[REGNO (v->new_reg)] = count;



More information about the Gcc-patches mailing list