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]

[PATCH, arm] Fix gcc.c-torture/execute/930628-1.c -O3 for Thumb


Hi,

The testcase gcc.c-torture/execute/930628-1.c -O3 -funroll-loops fails
to compile on Thumb.  The problem is that GCC generates instunctions
like `str r6,[r2,sp]' which are not valid address combination on
Thumb.

SP is a valid base register but only with an immediate index.  Since
THUMB_REGNO_MODE_OK_FOR_BASE_P yields true for SP,
find_reloads_address_1 does not reload this register.  The only
solution I found was to manually reload either SP or the entire address
in LEGITIMIZE_RELOAD_ADDRESS.

I reg-tested the patch with arm-sim/-mthumb.  The two failures with
930628-1.c have gone away.

Please apply if OK.

Adam

2002-10-29  Adam Nemet  <anemet@lnxw.com>

	* config/arm/arm.h (THUMB_LEGITIMIZE_RELOAD_ADDRESS): Reload
	addresses of form SP + REG.

Index: arm.h
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.164
diff -c -r1.164 arm.h
*** arm.h	30 Sep 2002 11:18:38 -0000	1.164
--- arm.h	29 Oct 2002 19:48:58 -0000
***************
*** 1265,1295 ****
      }									   \
    while (0)
  
! /* ??? 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 (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)							   \
--- 1265,1326 ----
      }									   \
    while (0)
  
! #define THUMB_LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN) \
!   do									\
      {									\
!       /* ??? 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.  */						\
!       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 (MODE, INTVAL (XEXP (X, 1))))	\
! 	;								\
! 									\
!       /* An SP + REG address is not allowed for Thumb.  The REG part	\
! 	 gets reloaded later if REG is not a low register but SP is a	\
! 	 valid base register so it remains unchanged.  Let's only	\
! 	 reload SP if REG is a low register, otherwise reload the	\
! 	 entire address.  In this way we may save one reload.  */	\
!       else if  (GET_CODE (X) == PLUS					\
! 		&& GET_CODE (XEXP (X, 0)) == REG			\
! 		&& GET_CODE (XEXP (X, 1)) == REG)			\
! 	{								\
! 	  int sp = (XEXP (X, 0) == stack_pointer_rtx ? 0 :		\
! 		    XEXP (X, 1) == stack_pointer_rtx ? 1 : -1);		\
! 									\
! 	  /* If none of them is SP, let reload ensure that both are	\
! 	     low registers. */						\
! 	  if (sp == -1)							\
! 	    break;							\
! 									\
! 	  if (REGNO (XEXP (X, 1 - sp)) <= LAST_LO_REGNUM)		\
! 	    X = XEXP (X, sp);						\
! 									\
! 	  /* Fall through to the push_reload below.  */			\
! 	}								\
!       else								\
! 	break;								\
! 									\
!       {									\
! 	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;							\
!       }									\
      }									\
!   while (0)
  
  #define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)   \
    if (TARGET_ARM)							   \


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