Fix PR target/9929

Jan Hubicka jh@suse.cz
Mon Dec 29 14:14:00 GMT 2003


Hi,
I've re-bootstrapped and re-tested this patch again for current mainline
and 3.3-branch on i686-pc-gnu-linux and x86_64-linux.

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.228
diff -c -3 -p -r1.228 reload.c
*** reload.c	15 Dec 2003 17:42:43 -0000	1.228
--- reload.c	29 Dec 2003 10:12:18 -0000
*************** find_reloads_toplev (rtx x, int opnum, e
*** 4481,4493 ****
        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)
  	{
--- 4481,4486 ----
*************** find_reloads_address_1 (enum machine_mod
*** 5674,5679 ****
--- 5667,5732 ----
      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 (enum machine_mod
*** 5692,5704 ****
  		}
  	    }
  	  /* 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);
--- 5745,5758 ----
  		}
  	    }
  	  /* 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);



More information about the Gcc-patches mailing list