aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@cygnus.com>1998-09-23 16:44:39 +0000
committerNick Clifton <nickc@gcc.gnu.org>1998-09-23 16:44:39 +0000
commita5f421658c4dfe336f6b50153ffbe1fbc203107f (patch)
tree811ac8b66e4882c61dd2b5fea781e6c17069d42d
parentf916eeb6db92d698c87706411143f50ddfe9b126 (diff)
downloadgcc-a5f421658c4dfe336f6b50153ffbe1fbc203107f.zip
gcc-a5f421658c4dfe336f6b50153ffbe1fbc203107f.tar.gz
gcc-a5f421658c4dfe336f6b50153ffbe1fbc203107f.tar.bz2
Add Jim's patches to improve reload behaviour.
From-SVN: r22561
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/arm/thumb.h68
2 files changed, 67 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8351c37..2e46e4d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
Wed Sep 23 16:22:01 1998 Nick Clifton <nickc@cygnus.com>
+ * config/arm/thumb.h: The following patches were made by Jim Wilson:
+ (enum reg_class): Add NONARG_LO_REGS support.
+ (REG_CLASS_NAMES, REG_CLASS_CONTENTS, REGNO_REG_CLASS,
+ PREFERRED_RELOAD_CLASS, SECONDARY_RELOAD_CLASS): Likewise.
+ (GO_IF_LEGITIMATE_ADDRESS): Disable REG+REG addresses before reload
+ completes. Re-enable HImode REG+OFFSET addresses.
+ (LEGITIMIZE_RELOAD_ADDRESS): Define.
+
* expmed.c (extract_bit_field): Add comment from Jim Wilson.
Wed Sep 23 13:26:02 1998 Richard Henderson <rth@cygnus.com>
diff --git a/gcc/config/arm/thumb.h b/gcc/config/arm/thumb.h
index 4030e37..0f6c60c 100644
--- a/gcc/config/arm/thumb.h
+++ b/gcc/config/arm/thumb.h
@@ -472,9 +472,15 @@ extern char * structure_size_string;
#define MODES_TIEABLE_P(MODE1,MODE2) 1
+/* The NOARG_LO_REGS class is the set of LO_REGS that are not used for passing
+ arguments to functions. These are the registers that are available for
+ spilling during reload. The code in reload1.c:init_reload() will detect this
+ class and place it into 'reload_address_base_reg_class'. */
+
enum reg_class
{
NO_REGS,
+ NONARG_LO_REGS,
LO_REGS,
STACK_REG,
BASE_REGS,
@@ -490,6 +496,7 @@ enum reg_class
#define REG_CLASS_NAMES \
{ \
"NO_REGS", \
+ "NONARG_LO_REGS", \
"LO_REGS", \
"STACK_REG", \
"BASE_REGS", \
@@ -500,6 +507,7 @@ enum reg_class
#define REG_CLASS_CONTENTS \
{ \
0x00000, \
+ 0x000f0, \
0x000ff, \
0x02000, \
0x020ff, \
@@ -509,7 +517,8 @@ enum reg_class
#define REGNO_REG_CLASS(REGNO) \
((REGNO) == STACK_POINTER_REGNUM ? STACK_REG \
- : (REGNO) < 8 ? LO_REGS \
+ : (REGNO) < 8 ? ((REGNO) < 4 ? LO_REGS \
+ : NONARG_LO_REGS) \
: HI_REGS)
#define BASE_REG_CLASS BASE_REGS
@@ -555,8 +564,15 @@ enum reg_class
abort. Alternatively, this could be fixed by modifying BASE_REG_CLASS
to be LO_REGS instead of BASE_REGS. It is not clear what affect this
change would have. */
+/* ??? This looks even more suspiciously wrong. PREFERRED_RELOAD_CLASS
+ must always return a strict subset of the input class. Just blindly
+ returning LO_REGS is safe only if the input class is a superset of LO_REGS,
+ but there is no check for this. Added another exception for NONARG_LO_REGS
+ because it is not a superset of LO_REGS. */
+/* ??? We now use NONARG_LO_REGS for caller_save_spill_class, so the
+ comments about BASE_REGS are now obsolete. */
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
- ((CLASS) == BASE_REGS ? (CLASS) \
+ ((CLASS) == BASE_REGS || (CLASS) == NONARG_LO_REGS ? (CLASS) \
: LO_REGS)
/*
((CONSTANT_P ((X)) && GET_CODE ((X)) != CONST_INT \
@@ -565,9 +581,10 @@ enum reg_class
&& (unsigned HOST_WIDE_INT) INTVAL ((X)) > 255) ? NO_REGS \
: LO_REGS) */
-/* Must leave BASE_REGS reloads alone, see comment above. */
+/* Must leave BASE_REGS and NONARG_LO_REGS reloads alone, see comment
+ above. */
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,X) \
- ((CLASS) != LO_REGS && (CLASS) != BASE_REGS \
+ ((CLASS) != LO_REGS && (CLASS) != BASE_REGS && (CLASS) != NONARG_LO_REGS \
? ((true_regnum (X) == -1 ? LO_REGS \
: (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \
: NO_REGS)) \
@@ -885,6 +902,16 @@ int thumb_shiftable_const ();
else if (GET_CODE (X) == PLUS) \
{ \
/* REG+REG address can be any two index registers. */ \
+ /* ??? REG+REG addresses have been completely disabled before \
+ reload completes, because we do not have enough available \
+ reload registers. We only have 3 guaranteed reload registers \
+ (NONARG_LO_REGS - the frame pointer), but we need at least 4 \
+ to support REG+REG addresses. We have left them enabled after \
+ reload completes, in the hope that reload_cse_regs and related \
+ routines will be able to create them after the fact. It is \
+ probably possible to support REG+REG addresses with additional \
+ reload work, but I do not not have enough time to attempt such \
+ a change at this time. */ \
/* ??? Normally checking the mode here is wrong, since it isn't \
impossible to use REG+REG with DFmode. However, the movdf \
pattern requires offsettable addresses, and REG+REG is not \
@@ -898,14 +925,14 @@ int thumb_shiftable_const ();
will be replaced with STACK, and SP relative addressing only \
permits SP+OFFSET. */ \
if (GET_MODE_SIZE (MODE) <= 4 \
+ /* ??? See comment above. */ \
+ && reload_completed \
&& GET_CODE (XEXP (X, 0)) == REG \
&& GET_CODE (XEXP (X, 1)) == REG \
&& XEXP (X, 0) != frame_pointer_rtx \
&& XEXP (X, 1) != frame_pointer_rtx \
- /* CYGNUS LOCAL nickc */ \
&& XEXP (X, 0) != virtual_stack_vars_rtx \
&& XEXP (X, 1) != virtual_stack_vars_rtx \
- /* END CYGNUS LOCAL */ \
&& REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
&& REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
goto WIN; \
@@ -913,9 +940,6 @@ int thumb_shiftable_const ();
else if (GET_CODE (XEXP (X, 0)) == REG \
&& (REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
|| XEXP (X, 0) == arg_pointer_rtx) \
- /* CYGNUS LOCAL nickc */ \
- && GET_MODE_SIZE (MODE) != 2 \
- /* END CYGNUS LOCAL */ \
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
&& LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
goto WIN; \
@@ -933,6 +957,32 @@ int thumb_shiftable_const ();
} \
}
+/* ??? 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 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 \
+ && ! LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
+ { \
+ rtx orig_X = X; \
+ X = copy_rtx (X); \
+ push_reload (orig_X, NULL_RTX, &X, NULL_PTR, \
+ reload_address_base_reg_class, \
+ Pmode, VOIDmode, 0, 0, OPNUM, TYPE); \
+ goto WIN; \
+ } \
+}
+
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)