From 36846b26721512effe580079a9ef6b982c651cb8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 19 Jan 2011 09:14:31 -0800 Subject: [PATCH] mn10300: Cleanup legitimate addresses Allow REG+REG and POST_MODIFY addressing for AM33. Fix AM33 base and index register classes. Remove a bunch of register class combinations that aren't really useful after this cleanup. From-SVN: r169006 --- gcc/ChangeLog | 28 +++++++ gcc/config/mn10300/mn10300-protos.h | 2 + gcc/config/mn10300/mn10300.c | 157 +++++++++++++++++++++++++----------- gcc/config/mn10300/mn10300.h | 85 +++++++++---------- 4 files changed, 175 insertions(+), 97 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 06b439e..7ef09cc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,33 @@ 2011-01-19 Richard Henderson + * config/mn10300/mn10300.c (mn10300_print_operand_address): Handle + POST_MODIFY. + (mn10300_secondary_reload): Tidy combination reload classes. + (mn10300_legitimate_address_p): Allow post-modify and reg+reg + addresses for AM33. Allow symbolic offsets for reg+imm. + (mn10300_regno_in_class_p): New. + (mn10300_legitimize_reload_address): New. + * config/mn10300/mn10300.h (enum reg_class): Remove + DATA_OR_ADDRESS_REGS, DATA_OR_EXTENDED_REGS, ADDRESS_OR_EXTENDED_REGS, + SP_OR_EXTENDED_REGS, SP_OR_ADDRESS_OR_EXTENDED_REGS. Add + SP_OR_GENERAL_REGS. + (REG_CLASS_NAMES): Update to match. + (REG_CLASS_CONTENTS): Likewise. + (INDEX_REG_CLASS): Use GENERAL_REGS for AM33. + (BASE_REG_CLASS): Use SP_OR_GENERAL_REGS for AM33. + (REGNO_IN_RANGE_P): Remove. + (REGNO_DATA_P): Use mn10300_regno_in_class_p. + (REGNO_ADDRESS_P, REGNO_EXTENDED_P): Likewise. + (REGNO_STRICT_OK_FOR_BASE_P): Likewise. + (REGNO_STRICT_OK_FOR_BIT_BASE_P): Likewise. + (REGNO_STRICT_OK_FOR_INDEX_P): Likewise. + (REGNO_SP_P, REGNO_AM33_P, REGNO_FP_P): Remove. + (REGNO_GENERAL_P): New. + (HAVE_POST_MODIFY_DISP): New. + (USE_LOAD_POST_INCREMENT, USE_STORE_POST_INCREMENT): New. + (LEGITIMIZE_RELOAD_ADDRESS): New. + * config/mn10300/mn10300-protos.h: Update. + * config/mn10300/mn10300.c (mn10300_preferred_reload_class): Allow DATA_REGS for AM33 stack-pointer destination. (mn10300_preferred_output_reload_class): Likewise. diff --git a/gcc/config/mn10300/mn10300-protos.h b/gcc/config/mn10300/mn10300-protos.h index 37968ff..d0ce1b3 100644 --- a/gcc/config/mn10300/mn10300-protos.h +++ b/gcc/config/mn10300/mn10300-protos.h @@ -26,6 +26,7 @@ #ifdef RTX_CODE extern rtx mn10300_legitimize_pic_address (rtx, rtx); extern int mn10300_legitimate_pic_operand_p (rtx); +extern rtx mn10300_legitimize_reload_address (rtx, Mmode, int, int, int); extern bool mn10300_function_value_regno_p (const unsigned int); extern int mn10300_get_live_callee_saved_regs (void); extern bool mn10300_hard_regno_mode_ok (unsigned int, Mmode); @@ -40,6 +41,7 @@ extern int mn10300_store_multiple_operation (rtx, Mmode); extern int mn10300_symbolic_operand (rtx, Mmode); #endif /* RTX_CODE */ +extern bool mn10300_regno_in_class_p (unsigned, int, bool); extern int mn10300_can_use_return_insn (void); extern void mn10300_expand_prologue (void); extern void mn10300_expand_epilogue (void); diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c index 29cf337..197ff85 100644 --- a/gcc/config/mn10300/mn10300.c +++ b/gcc/config/mn10300/mn10300.c @@ -495,26 +495,38 @@ mn10300_print_operand_address (FILE *file, rtx addr) switch (GET_CODE (addr)) { case POST_INC: - mn10300_print_operand_address (file, XEXP (addr, 0)); + mn10300_print_operand (file, XEXP (addr, 0), 0); fputc ('+', file); break; + + case POST_MODIFY: + mn10300_print_operand (file, XEXP (addr, 0), 0); + fputc ('+', file); + fputc (',', file); + mn10300_print_operand (file, XEXP (addr, 1), 0); + break; + case REG: mn10300_print_operand (file, addr, 0); break; case PLUS: { - rtx base, index; - if (REG_P (XEXP (addr, 0)) - && REG_OK_FOR_BASE_P (XEXP (addr, 0))) - base = XEXP (addr, 0), index = XEXP (addr, 1); - else if (REG_P (XEXP (addr, 1)) - && REG_OK_FOR_BASE_P (XEXP (addr, 1))) - base = XEXP (addr, 1), index = XEXP (addr, 0); - else - gcc_unreachable (); + rtx base = XEXP (addr, 0); + rtx index = XEXP (addr, 1); + + if (REG_P (index) && !REG_OK_FOR_INDEX_P (index)) + { + rtx x = base; + base = index; + index = x; + + gcc_assert (REG_P (index) && REG_OK_FOR_INDEX_P (index)); + } + gcc_assert (REG_OK_FOR_BASE_P (base)); + mn10300_print_operand (file, index, 0); fputc (',', file); - mn10300_print_operand (file, base, 0);; + mn10300_print_operand (file, base, 0); break; } case SYMBOL_REF: @@ -1395,8 +1407,7 @@ mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, if (in_p && rclass != SP_REGS && rclass != SP_OR_ADDRESS_REGS - && rclass != SP_OR_EXTENDED_REGS - && rclass != SP_OR_ADDRESS_OR_EXTENDED_REGS + && rclass != SP_OR_GENERAL_REGS && GET_CODE (x) == PLUS && (XEXP (x, 0) == stack_pointer_rtx || XEXP (x, 1) == stack_pointer_rtx)) @@ -1422,7 +1433,7 @@ mn10300_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, addr = XEXP (x, 0); if (addr && CONSTANT_ADDRESS_P (addr)) - return DATA_OR_EXTENDED_REGS; + return GENERAL_REGS; } /* Otherwise assume no secondary reloads are needed. */ @@ -1954,51 +1965,99 @@ mn10300_legitimate_pic_operand_p (rtx x) static bool mn10300_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) { - if (CONSTANT_ADDRESS_P (x) - && (! flag_pic || mn10300_legitimate_pic_operand_p (x))) - return TRUE; + rtx base, index; + + if (CONSTANT_ADDRESS_P (x)) + return !flag_pic || mn10300_legitimate_pic_operand_p (x); if (RTX_OK_FOR_BASE_P (x, strict)) - return TRUE; + return true; - if (TARGET_AM33 - && GET_CODE (x) == POST_INC - && RTX_OK_FOR_BASE_P (XEXP (x, 0), strict) - && (mode == SImode || mode == SFmode || mode == HImode)) - return TRUE; + if (TARGET_AM33 && (mode == SImode || mode == SFmode || mode == HImode)) + { + if (GET_CODE (x) == POST_INC) + return RTX_OK_FOR_BASE_P (XEXP (x, 0), strict); + if (GET_CODE (x) == POST_MODIFY) + return (RTX_OK_FOR_BASE_P (XEXP (x, 0), strict) + && CONSTANT_ADDRESS_P (XEXP (x, 1))); + } - if (GET_CODE (x) == PLUS) + if (GET_CODE (x) != PLUS) + return false; + + base = XEXP (x, 0); + index = XEXP (x, 1); + + if (!REG_P (base)) + return false; + if (REG_P (index)) { - rtx base = 0, index = 0; + /* ??? Without AM33 generalized (Ri,Rn) addressing, reg+reg + addressing is hard to satisfy. */ + if (!TARGET_AM33) + return false; - if (REG_P (XEXP (x, 0)) - && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 0)), strict)) - { - base = XEXP (x, 0); - index = XEXP (x, 1); - } + return (REGNO_GENERAL_P (REGNO (base), strict) + && REGNO_GENERAL_P (REGNO (index), strict)); + } - if (REG_P (XEXP (x, 1)) - && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 1)), strict)) - { - base = XEXP (x, 1); - index = XEXP (x, 0); - } + if (!REGNO_STRICT_OK_FOR_BASE_P (REGNO (base), strict)) + return false; - if (base != 0 && index != 0) - { - if (CONST_INT_P (index)) - return TRUE; - if (GET_CODE (index) == CONST - && GET_CODE (XEXP (index, 0)) != PLUS - && (! flag_pic - || (mn10300_legitimate_pic_operand_p (index) - && GET_MODE_SIZE (mode) == 4))) - return TRUE; - } + if (CONST_INT_P (index)) + return IN_RANGE (INTVAL (index), -1 - 0x7fffffff, 0x7fffffff); + + if (CONSTANT_ADDRESS_P (index)) + return !flag_pic || mn10300_legitimate_pic_operand_p (index); + + return false; +} + +bool +mn10300_regno_in_class_p (unsigned regno, int rclass, bool strict) +{ + if (regno >= FIRST_PSEUDO_REGISTER) + { + if (!strict) + return true; + if (!reg_renumber) + return false; + regno = reg_renumber[regno]; + } + return TEST_HARD_REG_BIT (reg_class_contents[rclass], regno); +} + +rtx +mn10300_legitimize_reload_address (rtx x, + enum machine_mode mode ATTRIBUTE_UNUSED, + int opnum, int type, + int ind_levels ATTRIBUTE_UNUSED) +{ + bool any_change = false; + + /* See above re disabling reg+reg addressing for MN103. */ + if (!TARGET_AM33) + return NULL_RTX; + + if (GET_CODE (x) != PLUS) + return NULL_RTX; + + if (XEXP (x, 0) == stack_pointer_rtx) + { + push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, + GENERAL_REGS, GET_MODE (x), VOIDmode, 0, 0, + opnum, (enum reload_type) type); + any_change = true; + } + if (XEXP (x, 1) == stack_pointer_rtx) + { + push_reload (XEXP (x, 1), NULL_RTX, &XEXP (x, 1), NULL, + GENERAL_REGS, GET_MODE (x), VOIDmode, 0, 0, + opnum, (enum reload_type) type); + any_change = true; } - return FALSE; + return any_change ? x : NULL_RTX; } /* Used by LEGITIMATE_CONSTANT_P(). Returns TRUE if X is a valid diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h index 1ed13b9..587ba17 100644 --- a/gcc/config/mn10300/mn10300.h +++ b/gcc/config/mn10300/mn10300.h @@ -261,12 +261,9 @@ extern enum processor_type mn10300_tune_cpu; enum reg_class { - NO_REGS, DATA_REGS, ADDRESS_REGS, SP_REGS, - DATA_OR_ADDRESS_REGS, SP_OR_ADDRESS_REGS, - EXTENDED_REGS, DATA_OR_EXTENDED_REGS, ADDRESS_OR_EXTENDED_REGS, - SP_OR_EXTENDED_REGS, SP_OR_ADDRESS_OR_EXTENDED_REGS, - FP_REGS, FP_ACC_REGS, CC_REGS, - GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES + NO_REGS, DATA_REGS, ADDRESS_REGS, SP_REGS, SP_OR_ADDRESS_REGS, + EXTENDED_REGS, FP_REGS, FP_ACC_REGS, CC_REGS, + GENERAL_REGS, SP_OR_GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES }; #define N_REG_CLASSES (int) LIM_REG_CLASSES @@ -274,13 +271,9 @@ enum reg_class /* Give names of register classes as strings for dump file. */ #define REG_CLASS_NAMES \ -{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS", \ - "SP_REGS", "DATA_OR_ADDRESS_REGS", "SP_OR_ADDRESS_REGS", \ - "EXTENDED_REGS", \ - "DATA_OR_EXTENDED_REGS", "ADDRESS_OR_EXTENDED_REGS", \ - "SP_OR_EXTENDED_REGS", "SP_OR_ADDRESS_OR_EXTENDED_REGS", \ - "FP_REGS", "FP_ACC_REGS", "CC_REGS", \ - "GENERAL_REGS", "ALL_REGS", "LIM_REGS" \ +{ "NO_REGS", "DATA_REGS", "ADDRESS_REGS", "SP_REGS", "SP_OR_ADDRESS_REGS", \ + "EXTENDED_REGS", "FP_REGS", "FP_ACC_REGS", "CC_REGS", \ + "GENERAL_REGS", "SP_OR_GENERAL_REGS", "ALL_REGS", "LIM_REGS" \ } /* Define which registers fit in which classes. @@ -292,17 +285,13 @@ enum reg_class { 0x0000000f, 0 }, /* DATA_REGS */ \ { 0x000001f0, 0 }, /* ADDRESS_REGS */ \ { 0x00000200, 0 }, /* SP_REGS */ \ - { 0x000001ff, 0 }, /* DATA_OR_ADDRESS_REGS */ \ { 0x000003f0, 0 }, /* SP_OR_ADDRESS_REGS */ \ { 0x0003fc00, 0 }, /* EXTENDED_REGS */ \ - { 0x0003fc0f, 0 }, /* DATA_OR_EXTENDED_REGS */ \ - { 0x0003fdf0, 0 }, /* ADDRESS_OR_EXTENDED_REGS */ \ - { 0x0003fe00, 0 }, /* SP_OR_EXTENDED_REGS */ \ - { 0x0003fff0, 0 }, /* SP_OR_ADDRESS_OR_EXTENDED_REGS */ \ { 0xfffc0000, 0x3ffff },/* FP_REGS */ \ { 0x03fc0000, 0 }, /* FP_ACC_REGS */ \ { 0x00000000, 0x80000 },/* CC_REGS */ \ { 0x0003fdff, 0 }, /* GENERAL_REGS */ \ + { 0x0003ffff, 0 }, /* SP_OR_GENERAL_REGS */ \ { 0xffffffff, 0xfffff } /* ALL_REGS */ \ } @@ -334,8 +323,10 @@ enum reg_class NO_REGS) /* The class value for index registers, and the one for base regs. */ -#define INDEX_REG_CLASS DATA_OR_EXTENDED_REGS -#define BASE_REG_CLASS SP_OR_ADDRESS_REGS +#define INDEX_REG_CLASS \ + (TARGET_AM33 ? GENERAL_REGS : DATA_REGS) +#define BASE_REG_CLASS \ + (TARGET_AM33 ? SP_OR_GENERAL_REGS : SP_OR_ADDRESS_REGS) /* Macros to check register numbers against specific register classes. */ @@ -364,50 +355,31 @@ enum reg_class # define REG_STRICT 1 #endif -# define REGNO_IN_RANGE_P(regno,min,max,strict) \ - (IN_RANGE ((regno), (min), (max)) \ - || ((strict) \ - ? (reg_renumber \ - && reg_renumber[(regno)] >= (min) \ - && reg_renumber[(regno)] <= (max)) \ - : (regno) >= FIRST_PSEUDO_REGISTER)) - #define REGNO_DATA_P(regno, strict) \ - (REGNO_IN_RANGE_P ((regno), FIRST_DATA_REGNUM, LAST_DATA_REGNUM, \ - (strict))) + mn10300_regno_in_class_p (regno, DATA_REGS, strict) #define REGNO_ADDRESS_P(regno, strict) \ - (REGNO_IN_RANGE_P ((regno), FIRST_ADDRESS_REGNUM, LAST_ADDRESS_REGNUM, \ - (strict))) -#define REGNO_SP_P(regno, strict) \ - (REGNO_IN_RANGE_P ((regno), STACK_POINTER_REGNUM, STACK_POINTER_REGNUM, \ - (strict))) + mn10300_regno_in_class_p (regno, ADDRESS_REGS, strict) #define REGNO_EXTENDED_P(regno, strict) \ - (REGNO_IN_RANGE_P ((regno), FIRST_EXTENDED_REGNUM, LAST_EXTENDED_REGNUM, \ - (strict))) -#define REGNO_AM33_P(regno, strict) \ - (REGNO_DATA_P ((regno), (strict)) || REGNO_ADDRESS_P ((regno), (strict)) \ - || REGNO_EXTENDED_P ((regno), (strict))) -#define REGNO_FP_P(regno, strict) \ - (REGNO_IN_RANGE_P ((regno), FIRST_FP_REGNUM, LAST_FP_REGNUM, (strict))) + mn10300_regno_in_class_p (regno, EXTENDED_REGS, strict) +#define REGNO_GENERAL_P(regno, strict) \ + mn10300_regno_in_class_p (regno, GENERAL_REGS, strict) #define REGNO_STRICT_OK_FOR_BASE_P(regno, strict) \ - (REGNO_SP_P ((regno), (strict)) \ - || REGNO_ADDRESS_P ((regno), (strict)) \ - || REGNO_EXTENDED_P ((regno), (strict))) + mn10300_regno_in_class_p (regno, BASE_REG_CLASS, strict) #define REGNO_OK_FOR_BASE_P(regno) \ (REGNO_STRICT_OK_FOR_BASE_P ((regno), REG_STRICT)) #define REG_OK_FOR_BASE_P(X) \ (REGNO_OK_FOR_BASE_P (REGNO (X))) #define REGNO_STRICT_OK_FOR_BIT_BASE_P(regno, strict) \ - (REGNO_SP_P ((regno), (strict)) || REGNO_ADDRESS_P ((regno), (strict))) + mn10300_regno_in_class_p (regno, ADDRESS_REGS, strict) #define REGNO_OK_FOR_BIT_BASE_P(regno) \ (REGNO_STRICT_OK_FOR_BIT_BASE_P ((regno), REG_STRICT)) #define REG_OK_FOR_BIT_BASE_P(X) \ (REGNO_OK_FOR_BIT_BASE_P (REGNO (X))) #define REGNO_STRICT_OK_FOR_INDEX_P(regno, strict) \ - (REGNO_DATA_P ((regno), (strict)) || REGNO_EXTENDED_P ((regno), (strict))) + mn10300_regno_in_class_p (regno, INDEX_REG_CLASS, strict) #define REGNO_OK_FOR_INDEX_P(regno) \ (REGNO_STRICT_OK_FOR_INDEX_P ((regno), REG_STRICT)) #define REG_OK_FOR_INDEX_P(X) \ @@ -557,7 +529,15 @@ struct cum_arg #define MAX_REGS_PER_ADDRESS 2 -#define HAVE_POST_INCREMENT (TARGET_AM33) +/* We have post-increments. */ +#define HAVE_POST_INCREMENT TARGET_AM33 +#define HAVE_POST_MODIFY_DISP TARGET_AM33 + +/* ... But we don't want to use them for block moves. Small offsets are + just as effective, at least for inline block move sizes, and appears + to produce cleaner code. */ +#define USE_LOAD_POST_INCREMENT(M) 0 +#define USE_STORE_POST_INCREMENT(M) 0 /* Accept either REG or SUBREG where a register is valid. */ @@ -568,6 +548,15 @@ struct cum_arg && REGNO_STRICT_OK_FOR_BASE_P (REGNO (SUBREG_REG (X)), \ (strict)))) +#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN) \ +do { \ + rtx new_x = mn10300_legitimize_reload_address (X, MODE, OPNUM, TYPE, IND_L); \ + if (new_x) \ + { \ + X = new_x; \ + goto WIN; \ + } \ +} while (0) /* Nonzero if the constant value X is a legitimate general operand. -- 2.7.4