This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

reloading paradoxical subregs with equivalences


Consider 

   (insn 16 14 17 (set (reg/v/f:SI 32)
           (plus:SI (reg/f:SI 13 r13)
               (const_int 116 [0x74]))) 10 {addsi3} (nil)
       (expr_list:REG_EQUIV (plus:SI (reg/f:SI 13 r13)
               (const_int 116 [0x74]))
           (nil)))
   ...
   (insn 144 142 145 (set (reg:HI 87)
           (mem/s:HI (reg/v/f:SI 32) 0)) 3 {*movhi_internal} (nil)
       (expr_list:REG_EQUIV (mem/s:HI (reg/v/f:SI 32) 0)
           (nil)))
   ...
   (insn 191 186 196 (set (reg:SI 114)
           (and:SI (subreg:SI (reg:HI 87) 0)
               (reg:SI 45))) 21 {andsi3} (nil)
       (expr_list:REG_DEAD (reg:HI 87)
           (expr_list:REG_DEAD (reg:SI 45)
               (nil))))

Altogether that means that r87 has an eqivalence at sp+0x74, which
is obviously 4 byte aligned.  However, in trying to simplify the
paradoxical subreg, we'll apply a big-endian correction and turn
this into sp+0x72, which is insufficiently aligned for SImode.

This was moderately irritating to track down because the target in
question does not fault on unaligned memory references, but merely
drops bits silently giving incorrect results.

This seems save enough because the only caller of 
find_reloads_subreg_address with paradoxical arguments contains
commentary concerning two other cases in which we can do nothing,
and notes that find_reloads will do the right thing.

Tested on the new target and alphaev6 for sanity.


r~


        * reload.c (find_reloads_subreg_address): Fail the substitution
        if the resulting address is insufficiently aligned.

Index: reload.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload.c,v
retrieving revision 1.141
diff -c -p -d -r1.141 reload.c
*** reload.c	2001/01/10 02:34:14	1.141
--- reload.c	2001/01/24 22:55:21
*************** find_reloads_subreg_address (x, force_re
*** 5648,5668 ****
  	      || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
  	    {
  	      int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
  
  	      if (BYTES_BIG_ENDIAN)
  		{
! 		  int size;
! 
! 		  size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
! 		  offset += MIN (size, UNITS_PER_WORD);
! 		  size = GET_MODE_SIZE (GET_MODE (x));
! 		  offset -= MIN (size, UNITS_PER_WORD);
  		}
  	      XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
  	      PUT_MODE (tem, GET_MODE (x));
  	      find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
  				    &XEXP (tem, 0), opnum, ADDR_TYPE (type),
  				    ind_levels, insn);
  	      /* If this is not a toplevel operand, find_reloads doesn't see
  		 this substitution.  We have to emit a USE of the pseudo so
  		 that delete_output_reload can see it.  */
--- 5648,5689 ----
  	      || ! rtx_equal_p (tem, reg_equiv_mem[regno]))
  	    {
  	      int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
+ 	      unsigned outer_size = GET_MODE_SIZE (GET_MODE (x));
+ 	      unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
  
  	      if (BYTES_BIG_ENDIAN)
  		{
! 		  offset += MIN (inner_size, UNITS_PER_WORD);
! 		  offset -= MIN (outer_size, UNITS_PER_WORD);
  		}
  	      XEXP (tem, 0) = plus_constant (XEXP (tem, 0), offset);
  	      PUT_MODE (tem, GET_MODE (x));
+ 
+ 	      /* If this was a paradoxical subreg that we replaced, the
+ 		 resulting memory must be sufficiently aligned to allow
+ 		 us to widen the mode of the memory.  */
+ 	      if (outer_size > inner_size && STRICT_ALIGNMENT)
+ 		{
+ 		  rtx base;
+ 
+ 		  base = XEXP (tem, 0);
+ 		  if (GET_CODE (base) == PLUS)
+ 		    {
+ 		      if (GET_CODE (XEXP (base, 1)) == CONST_INT
+ 			  && INTVAL (XEXP (base, 1)) % outer_size != 0)
+ 			return x;
+ 		      base = XEXP (base, 0);
+ 		    }
+ 		  if (GET_CODE (base) != REG
+ 		      || (REGNO_POINTER_ALIGN (REGNO (base))
+ 			  < outer_size * BITS_PER_UNIT))
+ 		    return x;
+ 		}
+ 
  	      find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
  				    &XEXP (tem, 0), opnum, ADDR_TYPE (type),
  				    ind_levels, insn);
+ 
  	      /* If this is not a toplevel operand, find_reloads doesn't see
  		 this substitution.  We have to emit a USE of the pseudo so
  		 that delete_output_reload can see it.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]