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]

PATCHes: Fix two Thumb failures.


This patch fixes two Thumb failures.

The first was a crash on gcc.c-torture/compile/20000804-1.c.  The
problem here was that we tried to put a 64-bit value in { r7, r8 },
but r8 is not a valid register in Thumb mode for multiple-register
loads.  The bug was that regrename.c failed to check HARD_REGNO_NREGS.

The second was a failure to compile gcc.c-torture/execute/930628-1.c.
The compiler tried to use an addressing mode like:

  str r1, [r3, sp]

in Thumb mode, which doesn't work because sp is not a valid register
for addressing in this mode.  The problem was that we originally had
an instruction like:

  (SET (MEM:SI (PLUS:SI (REG:SI 100) (REG:SI 101))) 
       (REG:SI 102)

and then, at some point, decided to eliminate one of the registers to
the stack pointer.  There's some code in the ARM back end to try to
prevent that (by not permitting the original address to be valid if
one of the registers is the frame pointer), but in this case the
registers were simply two pseudos.  Reload noticed that the address
was invalid, but was unable to fix it up, so we have to explictly tell
reload to reload the address in that case.

Tested on arm-none-elf, in both ARM and Thumb modes, and applied on
the csl-arm-branch.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2003-12-31  Mark Mitchell  <mark@codesourcery.com>

	* regrename.c (find_oldest_value_reg): Handle HARD_REGNO_NREGS > 1
	correctly.

	* config/arm/arm.h (THUMB_LEGTITIMIZE_RELOAD_ADDRESS): Reload REG
	+ REG addressing modes.

Index: gcc/regrename.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/regrename.c,v
retrieving revision 1.69.4.1
diff -c -5 -p -r1.69.4.1 regrename.c
*** gcc/regrename.c	23 Dec 2003 22:08:03 -0000	1.69.4.1
--- gcc/regrename.c	31 Dec 2003 17:15:33 -0000
*************** find_oldest_value_reg (enum reg_class cl
*** 1337,1355 ****
  
    for (i = vd->e[regno].oldest_regno; i != regno; i = vd->e[i].next_regno)
      {
        enum machine_mode oldmode = vd->e[i].mode;
        rtx new;
! 
!     if (TEST_HARD_REG_BIT (reg_class_contents[class], i)
! 	&& (new = maybe_mode_change (oldmode, vd->e[regno].mode, mode, i,
! 				     regno)))
!       {
! 	ORIGINAL_REGNO (new) = ORIGINAL_REGNO (reg);
!         REG_ATTRS (new) = REG_ATTRS (reg);
! 	return new;
!       }
      }
  
    return NULL_RTX;
  }
  
--- 1337,1360 ----
  
    for (i = vd->e[regno].oldest_regno; i != regno; i = vd->e[i].next_regno)
      {
        enum machine_mode oldmode = vd->e[i].mode;
        rtx new;
!       int j;
!       
!       for (j = 0; j < HARD_REGNO_NREGS (regno, mode); ++j)
! 	if (!TEST_HARD_REG_BIT (reg_class_contents[class], i + j))
! 	  return NULL_RTX;
!       
!       new = maybe_mode_change (oldmode, vd->e[regno].mode, mode, i,
! 			       regno);
!       if (new)
! 	{
! 	  ORIGINAL_REGNO (new) = ORIGINAL_REGNO (reg);
! 	  REG_ATTRS (new) = REG_ATTRS (reg);
! 	  return new;
! 	}
      }
  
    return NULL_RTX;
  }
  
Index: gcc/config/arm/arm.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.210.2.9
diff -c -5 -p -r1.210.2.9 arm.h
*** gcc/config/arm/arm.h	31 Dec 2003 06:40:47 -0000	1.210.2.9
--- gcc/config/arm/arm.h	31 Dec 2003 17:15:34 -0000
*************** enum reg_class
*** 1568,1597 ****
  
  /* XXX If an HImode FP+large_offset address is converted to an HImode
     SP+large_offset address, then reload won't know how to fix it.  It sees
     only that SP isn't valid for HImode, and so reloads the SP into an index
     register, but the resulting address is still invalid because the offset
!    is too big.  We fix it here instead by reloading the entire address.  */
  /* We could probably achieve better results by defining PROMOTE_MODE to help
     cope with the variances between the Thumb's signed and unsigned byte and
     halfword load instructions.  */
  #define THUMB_LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)	\
! {									\
!   if (GET_CODE (X) == PLUS						\
!       && GET_MODE_SIZE (MODE) < 4					\
!       && GET_CODE (XEXP (X, 0)) == REG					\
!       && XEXP (X, 0) == stack_pointer_rtx				\
!       && GET_CODE (XEXP (X, 1)) == CONST_INT				\
!       && ! thumb_legitimate_offset_p (MODE, INTVAL (XEXP (X, 1))))	\
!     {									\
!       rtx orig_X = X;							\
!       X = copy_rtx (X);							\
!       push_reload (orig_X, NULL_RTX, &X, NULL,				\
! 		   MODE_BASE_REG_CLASS (MODE),				\
! 		   Pmode, VOIDmode, 0, 0, OPNUM, TYPE);			\
!       goto WIN;								\
!     }									\
  }
  
  #define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)   \
    if (TARGET_ARM)							   \
      ARM_LEGITIMIZE_RELOAD_ADDRESS (X, MODE, OPNUM, TYPE, IND_LEVELS, WIN); \
--- 1568,1607 ----
  
  /* XXX If an HImode FP+large_offset address is converted to an HImode
     SP+large_offset address, then reload won't know how to fix it.  It sees
     only that SP isn't valid for HImode, and so reloads the SP into an index
     register, but the resulting address is still invalid because the offset
!    is too big.  We fix it here instead by reloading the entire address.
! 
!    If we get an illegitimate address of the form (PLUS (REG) (REG))
!    here, we reload that as well.  That can happen if a pseudo-register
!    is replaced by a hard register that is not in LO_REGS.  */
  /* We could probably achieve better results by defining PROMOTE_MODE to help
     cope with the variances between the Thumb's signed and unsigned byte and
     halfword load instructions.  */
  #define THUMB_LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)	\
! {									      \
!   if (GET_CODE (X) == PLUS						      \
!       && ((GET_MODE_SIZE (MODE) < 4					      \
!            && GET_CODE (XEXP (X, 0)) == REG				      \
!            && XEXP (X, 0) == stack_pointer_rtx				      \
!            && GET_CODE (XEXP (X, 1)) == CONST_INT			      \
!            && ! thumb_legitimate_offset_p (MODE, INTVAL (XEXP (X, 1))))	      \
!           || (GET_CODE (XEXP (X, 0)) == REG				      \
! 	      && GET_CODE (XEXP (X, 1)) == REG))			      \
!               && ((REGNO (XEXP (X, 0)) < FIRST_PSEUDO_REGISTER		      \
! 		   && !THUMB_REG_MODE_OK_FOR_BASE_P (XEXP (X, 0), MODE))      \
!                   || (REGNO (XEXP (X, 1)) < FIRST_PSEUDO_REGISTER	      \
! 		      && !THUMB_REG_MODE_OK_FOR_BASE_P (XEXP (X, 1), MODE)))) \
!     {									      \
!       rtx orig_X = X;							      \
!       X = copy_rtx (X);							      \
!       push_reload (orig_X, NULL_RTX, &X, NULL,				      \
! 		   MODE_BASE_REG_CLASS (MODE),				      \
! 		   Pmode, VOIDmode, 0, 0, OPNUM, TYPE);			      \
!       goto WIN;								      \
!     }									      \
  }
  
  #define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)   \
    if (TARGET_ARM)							   \
      ARM_LEGITIMIZE_RELOAD_ADDRESS (X, MODE, OPNUM, TYPE, IND_LEVELS, WIN); \


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