This is the mail archive of the gcc@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]

Re: Reload bug


oops, I stripped the patch too much last time.
I am attaching full one.  It fixes the 3.2 testcases I have...
Does it appear to make sense to you?
Will have to test it on big endian machine too...

Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.249.2.10.2.2
diff -c -3 -p -r1.249.2.10.2.2 emit-rtl.c
*** emit-rtl.c	3 Feb 2003 18:01:37 -0000	1.249.2.10.2.2
--- emit-rtl.c	11 Apr 2003 18:25:46 -0000
*************** subreg_hard_regno (x, check_mode)
*** 799,805 ****
      abort ();
    if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
      abort ();
! 
    /* Catch non-congruent offsets too.  */
    byte_offset = SUBREG_BYTE (x);
    if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
--- 799,809 ----
      abort ();
    if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
      abort ();
! #ifdef ENABLE_CHECKING
!   if (!subreg_offset_representable_p (REGNO (reg), GET_MODE (reg),
! 			  	      SUBREG_BYTE (x), mode))
!     abort ();
! #endif
    /* Catch non-congruent offsets too.  */
    byte_offset = SUBREG_BYTE (x);
    if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.178.2.4.2.4
diff -c -3 -p -r1.178.2.4.2.4 reload.c
*** reload.c	24 Oct 2002 08:59:49 -0000	1.178.2.4.2.4
--- reload.c	11 Apr 2003 18:25:48 -0000
*************** reload_inner_reg_of_subreg (x, mode, out
*** 817,822 ****
--- 817,829 ----
        || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
      return 0;
  
+   if (!subreg_offset_representable_p
+ 	(REGNO (SUBREG_REG (x)),
+ 		GET_MODE (SUBREG_REG (x)),
+ 		SUBREG_BYTE (x),
+ 		GET_MODE (x)))
+     return 1;
+ 
    /* If INNER is not ok for MODE, then INNER will need reloading.  */
    if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
      return 1;
*************** find_reloads (insn, replace, ind_levels,
*** 2856,2861 ****
--- 2863,2874 ----
  	      if (GET_CODE (SUBREG_REG (operand)) == REG
  		  && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
  		{
+ 		  if (!subreg_offset_representable_p
+ 			(REGNO (SUBREG_REG (operand)),
+ 			 GET_MODE (SUBREG_REG (operand)),
+ 			 SUBREG_BYTE (operand),
+ 			 GET_MODE (operand)))
+ 		     force_reload = 1;
  		  offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
  						 GET_MODE (SUBREG_REG (operand)),
  						 SUBREG_BYTE (operand),
*************** find_reloads (insn, replace, ind_levels,
*** 2911,2936 ****
  			  )
  #endif
  		      )
- 		  /* This following hunk of code should no longer be
- 		     needed at all with SUBREG_BYTE.  If you need this
- 		     code back, please explain to me why so I can
- 		     fix the real problem.  -DaveM */
- #if 0
- 		  /* Subreg of a hard reg which can't handle the subreg's mode
- 		     or which would handle that mode in the wrong number of
- 		     registers for subregging to work.  */
- 		  || (GET_CODE (operand) == REG
- 		      && REGNO (operand) < FIRST_PSEUDO_REGISTER
- 		      && ((GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
- 			   && (GET_MODE_SIZE (GET_MODE (operand))
- 			       > UNITS_PER_WORD)
- 			   && ((GET_MODE_SIZE (GET_MODE (operand))
- 				/ UNITS_PER_WORD)
- 			       != HARD_REGNO_NREGS (REGNO (operand),
- 						    GET_MODE (operand))))
- 			  || ! HARD_REGNO_MODE_OK (REGNO (operand) + offset,
- 						   operand_mode[i])))
- #endif
  		  )
  		force_reload = 1;
  	    }
--- 2924,2929 ----
Index: rtlanal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtlanal.c,v
retrieving revision 1.126.2.2.4.1
diff -c -3 -p -r1.126.2.2.4.1 rtlanal.c
*** rtlanal.c	9 Jan 2003 13:18:41 -0000	1.126.2.2.4.1
--- rtlanal.c	11 Apr 2003 18:25:48 -0000
*************** subreg_regno_offset (xregno, xmode, offs
*** 3045,3050 ****
--- 3045,3121 ----
    return (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode;
  }
  
+ /* This function returns true when the offset is representable via
+    subreg_offset in the given regno.
+    xregno - A regno of an inner hard subreg_reg (or what will become one).
+    xmode  - The mode of xregno.
+    offset - The byte offset.
+    ymode  - The mode of a top level SUBREG (or what may become one).
+    RETURN - The regno offset which would be used.  */
+ bool
+ subreg_offset_representable_p (xregno, xmode, offset, ymode)
+      unsigned int xregno;
+      enum machine_mode xmode;
+      unsigned int offset;
+      enum machine_mode ymode;
+ {
+   int nregs_xmode, nregs_ymode;
+   int mode_multiple, nregs_multiple;
+   int y_offset;
+ 
+   if (xregno >= FIRST_PSEUDO_REGISTER)
+     abort ();
+ 
+   nregs_xmode = HARD_REGNO_NREGS (xregno, xmode);
+   nregs_ymode = HARD_REGNO_NREGS (xregno, ymode);
+ 
+   /* paradoxical subregs are always valid.  */
+   if (offset == 0
+       && nregs_ymode > nregs_xmode
+       && (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
+ 	  ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
+     return true;
+ 
+   /* Lowpart subregs are always valid.  */
+   if (offset == subreg_lowpart_offset (ymode, xmode))
+     return true;
+ 
+ #ifdef ENABLE_CHECKING
+   /* This should always pass, otherwise we don't know how to verify the
+      constraint. 
+ 
+      These conditions may be relaxed but subreg_offset would need to be
+      redesigned.  */
+   if (GET_MODE_SIZE (xmode) % GET_MODE_SIZE (ymode)
+       || GET_MODE_SIZE (ymode) % nregs_ymode
+       || mode_for_size (GET_MODE_SIZE (ymode) / nregs_ymode,
+ 	      		MODE_INT, 0) == VOIDmode
+       || nregs_xmode % nregs_ymode)
+     abort ();
+ #endif
+ 
+   /* The XMODE value can be seen as an vector of NREGS_XMODE
+      values.  The subreg must represent an lowpart of given field.
+      Compute what field it is.  */
+   offset -= subreg_lowpart_offset (mode_for_size (GET_MODE_SIZE (ymode)
+ 			  			  / nregs_ymode,
+ 						  MODE_INT, 0), xmode);
+ 
+   /* size of ymode must not be greater than the size of xmode.  */
+   mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
+   if (mode_multiple == 0)
+     abort ();
+ 
+   y_offset = offset / GET_MODE_SIZE (ymode);
+   nregs_multiple =  nregs_xmode / nregs_ymode;
+ #ifdef ENABLE_CHECKING
+   if (offset % GET_MODE_SIZE (ymode)
+       || mode_multiple % nregs_multiple)
+     abort ();
+ #endif
+   return (!(y_offset % (mode_multiple / nregs_multiple)));
+ }
+ 
  /* Return the final regno that a subreg expression refers to.  */
  unsigned int 
  subreg_regno (x)


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