tertiary reload sanity

Richard Henderson rth@cygnus.com
Fri Aug 11 02:02:00 GMT 2000


For reasons I was never really clear on, reload might decide to
overlap the scratch register used for reload_in/out patterns
with one of the inputs.  I ran across this again today on the
IA-64 port and asked Jim "Why?".

After much digging it turns out the answer is "No reason".
In other words, a quirk of initial implementation sometime before
gcc 2.0, and the first users of reload_in/out either didn't require
non-overlapping scratches (sparc) or, by virtue of the register
classes involved, couldn't have overlap (romp).

We decided that it just didn't ever make sense to not provide
a brand new scratch register.  If you didn't need a new scratch,
why would you be asking for one?

Tested on ia64 and alpha ev4 linux.


r~

        * reload.c (push_secondary_reload): When invoking a reload_{in,out}
        pattern, always allocate a tertiary scratch register.

        * config/alpha/alpha.md (reload_inqi): Use a DImode scratch.
        (reload_inhi): Likewise.

Index: reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.117
diff -c -p -d -r1.117 reload.c
*** reload.c	2000/08/04 20:28:05	1.117
--- reload.c	2000/08/11 08:35:48
*************** push_secondary_reload (in_p, x, opnum, o
*** 375,387 ****
  	 in operand 1.  Outputs should have an initial "=", which we must
  	 skip.  */
  
!       char insn_letter
! 	= insn_data[(int) icode].operand[!in_p].constraint[in_p];
!       enum reg_class insn_class
! 	= (insn_letter == 'r' ? GENERAL_REGS
! 	   : REG_CLASS_FROM_LETTER ((unsigned char) insn_letter));
  
!       if (insn_class == NO_REGS
  	  || (in_p
  	      && insn_data[(int) icode].operand[!in_p].constraint[0] != '=')
  	  /* The scratch register's constraint must start with "=&".  */
--- 375,387 ----
  	 in operand 1.  Outputs should have an initial "=", which we must
  	 skip.  */
  
!       char insn_letter, t_letter;
  
!       insn_letter = insn_data[(int) icode].operand[!in_p].constraint[in_p];
!       class = (insn_letter == 'r' ? GENERAL_REGS
! 	       : REG_CLASS_FROM_LETTER ((unsigned char) insn_letter));
! 
!       if (class == NO_REGS
  	  || (in_p
  	      && insn_data[(int) icode].operand[!in_p].constraint[0] != '=')
  	  /* The scratch register's constraint must start with "=&".  */
*************** push_secondary_reload (in_p, x, opnum, o
*** 389,406 ****
  	  || insn_data[(int) icode].operand[2].constraint[1] != '&')
  	abort ();
  
!       if (reg_class_subset_p (reload_class, insn_class))
! 	mode = insn_data[(int) icode].operand[2].mode;
!       else
! 	{
! 	  char t_letter = insn_data[(int) icode].operand[2].constraint[2];
! 	  class = insn_class;
! 	  t_mode = insn_data[(int) icode].operand[2].mode;
! 	  t_class = (t_letter == 'r' ? GENERAL_REGS
! 		     : REG_CLASS_FROM_LETTER ((unsigned char) t_letter));
! 	  t_icode = icode;
! 	  icode = CODE_FOR_nothing;
! 	}
      }
  
    /* This case isn't valid, so fail.  Reload is allowed to use the same
--- 389,400 ----
  	  || insn_data[(int) icode].operand[2].constraint[1] != '&')
  	abort ();
  
!       t_letter = insn_data[(int) icode].operand[2].constraint[2];
!       t_mode = insn_data[(int) icode].operand[2].mode;
!       t_class = (t_letter == 'r' ? GENERAL_REGS
! 		 : REG_CLASS_FROM_LETTER ((unsigned char) t_letter));
!       t_icode = icode;
!       icode = CODE_FOR_nothing;
      }
  
    /* This case isn't valid, so fail.  Reload is allowed to use the same
*************** push_secondary_reload (in_p, x, opnum, o
*** 410,424 ****
       silently generating incorrect code later.
  
       The convention is that secondary input reloads are valid only if the
!      secondary_class is different from class.  If you have such a case, you
!      can not use secondary reloads, you must work around the problem some
!      other way.
  
!      Allow this when MODE is not reload_mode and assume that the generated
!      code handles this case (it does on the Alpha, which is the only place
!      this currently happens).  */
  
!   if (in_p && class == reload_class && mode == reload_mode)
      abort ();
  
    /* If we need a tertiary reload, see if we have one we can reuse or else
--- 404,417 ----
       silently generating incorrect code later.
  
       The convention is that secondary input reloads are valid only if the
!      secondary class is different from the reload class.  If you have such
!      a case, you can not use secondary reloads, you must work around the
!      problem some other way.
  
!      Allow this when a tertiary reload is used; i.e. assume that the
!      generated code handles this case.  */
  
!   if (in_p && class == reload_class && t_class == NO_REGS)
      abort ();
  
    /* If we need a tertiary reload, see if we have one we can reuse or else
Index: config/alpha/alpha.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/alpha/alpha.md,v
retrieving revision 1.125
diff -c -p -d -r1.125 alpha.md
*** alpha.md	2000/08/08 22:40:48	1.125
--- alpha.md	2000/08/11 08:35:48
***************
*** 5343,5353 ****
  (define_expand "reload_inqi"
    [(parallel [(match_operand:QI 0 "register_operand" "=r")
  	      (match_operand:QI 1 "any_memory_operand" "m")
! 	      (match_operand:TI 2 "register_operand" "=&r")])]
    "! TARGET_BWX"
    "
  {
!   rtx scratch, seq;
  
    if (GET_CODE (operands[1]) != MEM)
      abort ();
--- 5343,5353 ----
  (define_expand "reload_inqi"
    [(parallel [(match_operand:QI 0 "register_operand" "=r")
  	      (match_operand:QI 1 "any_memory_operand" "m")
! 	      (match_operand:DI 2 "register_operand" "=&r")])]
    "! TARGET_BWX"
    "
  {
!   rtx seq;
  
    if (GET_CODE (operands[1]) != MEM)
      abort ();
***************
*** 5361,5376 ****
      {
        rtx addr;
  
-       /* It is possible that one of the registers we got for operands[2]
- 	 might coincide with that of operands[0] (which is why we made
- 	 it TImode).  Pick the other one to use as our scratch.  */
-       if (REGNO (operands[0]) == REGNO (operands[2]))
- 	scratch = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
-       else
- 	scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
- 
        addr = get_unaligned_address (operands[1], 0);
!       seq = gen_unaligned_loadqi (operands[0], addr, scratch,
  			  gen_rtx_REG (DImode, REGNO (operands[0])));
        alpha_set_memflags (seq, operands[1]);
      }
--- 5361,5368 ----
      {
        rtx addr;
  
        addr = get_unaligned_address (operands[1], 0);
!       seq = gen_unaligned_loadqi (operands[0], addr, operands[2],
  			  gen_rtx_REG (DImode, REGNO (operands[0])));
        alpha_set_memflags (seq, operands[1]);
      }
***************
*** 5381,5391 ****
  (define_expand "reload_inhi"
    [(parallel [(match_operand:HI 0 "register_operand" "=r")
  	      (match_operand:HI 1 "any_memory_operand" "m")
! 	      (match_operand:TI 2 "register_operand" "=&r")])]
    "! TARGET_BWX"
    "
  {
!   rtx scratch, seq;
  
    if (GET_CODE (operands[1]) != MEM)
      abort ();
--- 5373,5383 ----
  (define_expand "reload_inhi"
    [(parallel [(match_operand:HI 0 "register_operand" "=r")
  	      (match_operand:HI 1 "any_memory_operand" "m")
! 	      (match_operand:DI 2 "register_operand" "=&r")])]
    "! TARGET_BWX"
    "
  {
!   rtx seq;
  
    if (GET_CODE (operands[1]) != MEM)
      abort ();
***************
*** 5399,5414 ****
      {
        rtx addr;
  
-       /* It is possible that one of the registers we got for operands[2]
- 	 might coincide with that of operands[0] (which is why we made
- 	 it TImode).  Pick the other one to use as our scratch.  */
-       if (REGNO (operands[0]) == REGNO (operands[2]))
- 	scratch = gen_rtx_REG (DImode, REGNO (operands[2]) + 1);
-       else
- 	scratch = gen_rtx_REG (DImode, REGNO (operands[2]));
- 
        addr = get_unaligned_address (operands[1], 0);
!       seq = gen_unaligned_loadhi (operands[0], addr, scratch,
  			  gen_rtx_REG (DImode, REGNO (operands[0])));
        alpha_set_memflags (seq, operands[1]);
      }
--- 5391,5398 ----
      {
        rtx addr;
  
        addr = get_unaligned_address (operands[1], 0);
!       seq = gen_unaligned_loadhi (operands[0], addr, operands[2],
  			  gen_rtx_REG (DImode, REGNO (operands[0])));
        alpha_set_memflags (seq, operands[1]);
      }


More information about the Gcc-patches mailing list