This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH, arm] Fix gcc.c-torture/execute/930628-1.c -O3 for Thumb
- From: Adam Nemet <anemet at Lnxw dot COM>
- To: gcc-patches at gcc dot gnu dot org
- Cc: nickc at redhat dot com, rearnsha at arm dot com
- Date: 29 Oct 2002 21:08:07 -0800
- Subject: [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) \