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]
Other format: [Raw text]

PR target/9929


Hi,
In the SuSE GCC we are using for some time the attached patch that
apparently got suck in the review queue, so I am resending it.

Hi,
this patch finally fixes the testcase by making reload to do the right thing
on dealing with subregs.  I've copied the code from the plain operand handling
to simplify subregged regs equivalent to constant and memories and fixed
reloading of the whole subregs.

I also noticed one redundant hunk of code now when simplify_gen_subreg is as
strong as gen_lowpart.

Bootstrapped/regtested i386. OK for mainline/branch?

     typedef struct X {
         char * ptr;
         int    offset;
     } X_t;

     X_t foo(X_t *d1, char * A0);
int a,b;
     void bar() {
       X_t l1={a,b}, l2={a,b}, l3={a,b};
       l3 = foo(&l1, l2.ptr);
       (*(X_t *)(l2.ptr + l3.offset)) = l1;
     }

     typedef struct X {
         char * ptr;
         int    offset;
     } X_t;

     X_t foo(X_t *d1, char * A0);

     void bar() {
       X_t l1, l2, l3;
       l3 = foo(&l1, l2.ptr);
       (*(X_t *)(l2.ptr + l3.offset)) = l1;
     }
Sun Apr  6 17:43:49 CEST 2003  Jan Hubicka  <jh@suse.cz>
	PR target/9929
	* reload.c (find_reloads_toplev):  Remove now redundant alternative
	(find_reloads_address_1): Synchronize handling of subregs with
	find_reloads_toplev;  Always reload whole subreg when the inner
	value requires more registers.
Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.211
diff -c -3 -p -r1.211 reload.c
*** gcc/reload.c	26 Mar 2003 07:48:13 -0000	1.211
--- gcc/reload.c	6 Apr 2003 16:10:04 -0000
*************** find_reloads_toplev (x, opnum, type, ind
*** 4492,4504 ****
        int regno = REGNO (SUBREG_REG (x));
        rtx tem;
  
-       if (subreg_lowpart_p (x)
- 	  && regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
- 	  && reg_equiv_constant[regno] != 0
- 	  && (tem = gen_lowpart_common (GET_MODE (x),
- 					reg_equiv_constant[regno])) != 0)
- 	return tem;
- 
        if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
  	  && reg_equiv_constant[regno] != 0)
  	{
--- 4492,4497 ----
*************** find_reloads_address_1 (mode, x, context
*** 5679,5684 ****
--- 5673,5738 ----
      case SUBREG:
        if (GET_CODE (SUBREG_REG (x)) == REG)
  	{
+ 	  /* Check for SUBREG containing a REG that's equivalent to a constant.
+ 	     If the constant has a known value, truncate it right now.
+ 	     Similarly if we are extracting a single-word of a multi-word
+ 	     constant.  If the constant is symbolic, allow it to be substituted
+ 	     normally.  push_reload will strip the subreg later.  If the
+ 	     constant is VOIDmode, abort because we will lose the mode of
+ 	     the register (this should never happen because one of the cases
+ 	     above should handle it).  */
+ 
+ 	  int regno = REGNO (SUBREG_REG (x));
+ 	  rtx tem;
+ 	  if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
+ 	      && reg_equiv_constant[regno] != 0)
+ 	    {
+ 	      tem =
+ 		simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
+ 				     GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
+ 	      if (!tem)
+ 		abort ();
+ 	      find_reloads_address_part (tem, loc,
+ 					 (context ? INDEX_REG_CLASS :
+ 					  MODE_BASE_REG_CLASS (mode)),
+ 					 GET_MODE (x), opnum, type, ind_levels);
+ 	      return 1;
+ 	    }
+ 
+ 	  /* If the subreg contains a reg that will be converted to a mem,
+ 	     convert the subreg to a narrower memref now.
+ 	     Otherwise, we would get (subreg (mem ...) ...),
+ 	     which would force reload of the mem.
+ 
+ 	     We also need to do this if there is an equivalent MEM that is
+ 	     not offsettable.  In that case, alter_subreg would produce an
+ 	     invalid address on big-endian machines.
+ 
+ 	     For machines that extend byte loads, we must not reload using
+ 	     a wider mode if we have a paradoxical SUBREG.  find_reloads will
+ 	     force a reload in that case.  So we should not do anything here.  */
+ 
+ 	  else if (regno >= FIRST_PSEUDO_REGISTER
+ #ifdef LOAD_EXTEND_OP
+ 		   && (GET_MODE_SIZE (GET_MODE (x))
+ 		       <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ #endif
+ 		   && (reg_equiv_address[regno] != 0
+ 		       || (reg_equiv_mem[regno] != 0
+ 			   && (! strict_memory_address_p (GET_MODE (x),
+ 							  XEXP (reg_equiv_mem[regno], 0))
+ 			       || ! offsettable_memref_p (reg_equiv_mem[regno])
+ 			       || num_not_at_initial_offset))))
+ 	  {
+ 	    enum reg_class class = (context ? INDEX_REG_CLASS
+ 				    : MODE_BASE_REG_CLASS (mode));
+ 	    x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
+ 					     insn);
+ 	    push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
+ 			 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+ 	    return 1;
+ 	  }
+ 
  	  /* If this is a SUBREG of a hard register and the resulting register
  	     is of the wrong class, reload the whole SUBREG.  This avoids
  	     needless copies if SUBREG_REG is multi-word.  */
*************** find_reloads_address_1 (mode, x, context
*** 5697,5709 ****
  		}
  	    }
  	  /* If this is a SUBREG of a pseudo-register, and the pseudo-register
! 	     is larger than the class size, then reload the whole SUBREG.  */
  	  else
  	    {
  	      enum reg_class class = (context ? INDEX_REG_CLASS
  				      : MODE_BASE_REG_CLASS (mode));
  	      if ((unsigned) 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);
--- 5751,5764 ----
  		}
  	    }
  	  /* If this is a SUBREG of a pseudo-register, and the pseudo-register
! 	     requires more register than the subregged value,
! 	     then reload the whole SUBREG.  */
  	  else
  	    {
  	      enum reg_class class = (context ? INDEX_REG_CLASS
  				      : MODE_BASE_REG_CLASS (mode));
  	      if ((unsigned) CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
! 		  > (unsigned) CLASS_MAX_NREGS (class, GET_MODE (x)))
  		{
  		  x = find_reloads_subreg_address (x, 0, opnum, type,
  						   ind_levels, insn);


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