reload bugfix

Jim Wilson wilson@cygnus.com
Thu Feb 11 17:53:00 GMT 1999


This looks basically OK, but I found it a little hard to understand what
find_reloads_subreg_address was doing.  So I tried rewriting it a little
to make it clearer.  Does this look right?  I removed some of the nesting,
and added two more comments.

If you agree that this is right, then go ahead and install it.

Just as a sanity check, I did irix6 and x86 linux gcc only bootstraps to
check it.

Wed Feb  3 04:02:38 1999  J"orn Rennecke <amylaar@cygnus.co.uk>

	* reload.c (find_reloads_subreg_address): New function, broken out of
	find_reloads_toplev.
	(find_reloads_toplev, find_reloads_address_1): Use it.

Index: reload.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/reload.c,v
retrieving revision 1.145
diff -p -r1.145 reload.c
*** reload.c	1998/12/09 09:52:37	1.145
--- reload.c	1999/02/12 00:05:23
*************** static int find_reloads_address_1 PROTO(
*** 336,341 ****
--- 336,343 ----
  static void find_reloads_address_part PROTO((rtx, rtx *, enum reg_class,
  					     enum machine_mode, int,
  					     enum reload_type, int));
+ static rtx find_reloads_subreg_address PROTO((rtx, int, int, enum reload_type,
+ 					      int, rtx));
  static int find_inc_amount	PROTO((rtx, rtx));
  static int loc_mentioned_in_p	PROTO((rtx *, rtx));
  
*************** find_reloads_toplev (x, opnum, type, ind
*** 4454,4487 ****
  						      XEXP (reg_equiv_mem[regno], 0))
  			   || ! offsettable_memref_p (reg_equiv_mem[regno])
  			   || num_not_at_initial_offset))))
! 	{
! 	  int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
! 	  /* We must rerun eliminate_regs, in case the elimination
! 	     offsets have changed.  */
! 	  rtx addr = XEXP (eliminate_regs (reg_equiv_memory_loc[regno], 0,
! 					   NULL_RTX),
! 			   0);
! 	  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);
! 	    }
! 	  addr = plus_constant (addr, offset);
! 	  x = gen_rtx_MEM (GET_MODE (x), addr);
! 	  RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
! 	  find_reloads_address (GET_MODE (x), &x,
! 				XEXP (x, 0),
! 				&XEXP (x, 0), opnum, 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.  */
! 	  if (replace_reloads && recog_operand[opnum] != x)
! 	    emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), insn);
! 	}
! 
      }
  
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
--- 4456,4463 ----
  						      XEXP (reg_equiv_mem[regno], 0))
  			   || ! offsettable_memref_p (reg_equiv_mem[regno])
  			   || num_not_at_initial_offset))))
! 	x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
! 					 insn);
      }
  
    for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
*************** find_reloads_address_1 (mode, x, context
*** 5461,5466 ****
--- 5437,5444 ----
  	      if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
  		  > reg_class_size[class])
  		{
+ 		  x = find_reloads_subreg_address (x, 0, opnum, type,
+ 						   ind_levels, insn);
  		  push_reload (x, NULL_RTX, loc, NULL_PTR, class,
  			       GET_MODE (x), VOIDmode, 0, 0, opnum, type);
  		  return 1;
*************** find_reloads_address_part (x, loc, class
*** 5555,5560 ****
--- 5533,5621 ----
  
    push_reload (x, NULL_RTX, loc, NULL_PTR, class,
  	       mode, VOIDmode, 0, 0, opnum, type);
+ }
+ 
+ /* X, a subreg of a pseudo, is a part of an address that needs to be
+    reloaded.
+ 
+    If the pseudo is equivalent to a memory location that cannot be directly
+    addressed, make the necessary address reloads.
+ 
+    If address reloads have been necessary, or if the address is changed
+    by register elimination, return the rtx of the memory location;
+    otherwise, return X.
+ 
+    If FORCE_REPLACE is nonzero, unconditionally replace the subreg with the
+    memory location.
+ 
+    OPNUM and TYPE identify the purpose of the reload.
+ 
+    IND_LEVELS says how many levels of indirect addressing are
+    supported at this point in the address.
+ 
+    INSN, if nonzero, is the insn in which we do the reload.  It is used
+    to determine where to put USEs for pseudos that we have to replace with
+    stack slots.  */
+ 
+ static rtx
+ find_reloads_subreg_address (x, force_replace, opnum, type,
+ 			     ind_levels, insn)
+      rtx x;
+      int force_replace;
+      int opnum;
+      enum reload_type type;
+      int ind_levels;
+      rtx insn;
+ {
+   int regno = REGNO (SUBREG_REG (x));
+   rtx tem;
+ 
+   if (! reg_equiv_memory_loc[regno])
+     return x;
+ 
+   /* If the address is not directly addressable, or if the address is not
+      offsettable, then it must be replaced.  */
+   if (! force_replace
+       && (reg_equiv_address[regno]
+ 	  || ! offsettable_memref_p (reg_equiv_mem[regno])))
+     force_replace = 1;
+ 
+   tem = make_memloc (SUBREG_REG (x), regno);
+ 
+   /* If the address changes because of register elimination, then it must
+      be replaced.  */
+   if (! force_replace && num_not_at_initial_offset
+       && ! rtx_equal_p (tem, reg_equiv_mem[regno]))
+     force_replace = 1;
+ 
+   if (force_replace)
+     {
+       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));
+       x = tem;
+       find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 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.  */
+       if (replace_reloads && recog_operand[opnum] != x)
+ 	emit_insn_before (gen_rtx_USE (VOIDmode, SUBREG_REG (x)), insn);
+     }
+ 
+   return x;
  }
  
  /* Substitute into the current INSN the registers into which we have reloaded




More information about the Gcc-patches mailing list