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


> > The code is wrong for post-SUBREG_BYTE patch as it checks that the
> > partial regs have exactly size of one word, but we do allow subregs on
> > registers of different sizes.  We need to verify that offset can
> > represent the register exactly.
> 
> Is it really wrong or is it incomplete now, in the post-SUBREG_BYTE era?
Hi,
this is the patch I am currently playing with.  The
subreg_offset_representable_p should return false when we can't
represent the subreg and should abort in the cases I believe current
implemetnation would get entirely confused.  I am not quite sure I got
it right, but you may want to take a look :)

Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.318
diff -c -3 -p -r1.318 emit-rtl.c
*** emit-rtl.c	4 Apr 2003 22:44:02 -0000	1.318
--- emit-rtl.c	11 Apr 2003 18:06:01 -0000
*************** subreg_hard_regno (x, check_mode)
*** 1080,1086 ****
      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)
--- 1080,1090 ----
      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.211
diff -c -3 -p -r1.211 reload.c
*** reload.c	26 Mar 2003 07:48:13 -0000	1.211
--- reload.c	11 Apr 2003 18:06:01 -0000
*************** find_reloads (insn, replace, ind_levels,
*** 2880,2885 ****
--- 2880,2891 ----
  	      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,
*** 2935,2960 ****
  			  )
  #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;
  	    }
--- 2941,2946 ----
*************** find_reloads_address_1 (mode, x, context
*** 5271,5276 ****
--- 5257,5275 ----
  						       GET_MODE (SUBREG_REG (orig_op1)),
  						       SUBREG_BYTE (orig_op1),
  						       GET_MODE (orig_op1))));
+ 	  }
+ 	/* Plus in the index register may be created only as a result of
+ 	   register remateralization for expresion like &localvar*4.  Reload it.
+ 	   It may be possible to combine the displacement on the outer level,
+ 	   but it is probably not worthwhile to do so.  */
+ 	if (context)
+ 	  {
+ 	    find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
+ 				  opnum, ADDR_TYPE (type), ind_levels, insn);
+ 	    push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
+ 			 (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
+ 			 GET_MODE (x), VOIDmode, 0, 0, opnum, type);
+ 	    return 1;
  	  }
  
  	if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE

+   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]