Hello. This patch removes obsolete GO_IF_LEGITIMATE_ADDRESS macro from CRIS back end in the GCC and introduces equivalent ARGET_LEGITIMATE_ADDRESS_P target hook.
Regression tested on cris-axis-elf. OK to install? * config/cris/cris.c (reg_ok_for_base_p, reg_ok_for_index_p, cris_constant_index_p, cris_base_p, cris_index_p, cris_base_or_autoincr_p, cris_bdap_index_p, cris_biap_index_p, cris_legitimate_address_p): New functions. (TARGET_LEGITIMATE_ADDRESS_P): Define. (cris_pic_symbol_type, cris_valid_pic_const): Change arguments type from rtx to const_rtx. (cris_print_operand_address, cris_address_cost, cris_side_effect_mode_ok): Use cris_constant_index_p, cris_base_p, cris_base_or_autoincr_p, cris_biap_index_p and cris_bdap_index_p. * config/cris/cris.h (CONSTANT_INDEX_P, BASE_P, BASE_OR_AUTOINCR_P, BDAP_INDEX_P, BIAP_INDEX_P, GO_IF_LEGITIMATE_ADDRESS, REG_OK_FOR_BASE_P, REG_OK_FOR_INDEX_P): Remove. (EXTRA_CONSTRAINT_Q, EXTRA_CONSTRAINT_R, EXTRA_CONSTRAINT_T): Use cris_constant_index_p, cris_base_p, cris_base_or_autoincr_p, cris_biap_index_p and cris_bdap_index_p. * config/cris/cris.md (moversideqi movemsideqi peephole2): Use cris_base_p. * config/cris/cris-protos.h (cris_constant_index_p, cris_base_p, cris_base_or_autoincr_p, cris_bdap_index_p, cris_biap_index_p): New prototype. (cris_pic_symbol_type, cris_valid_pic_const): Update prototype. Index: gcc/config/cris/cris.c =================================================================== --- gcc/config/cris/cris.c (revision 180345) +++ gcc/config/cris/cris.c (working copy) @@ -125,6 +125,8 @@ static reg_class_t cris_preferred_reload_class (rtx, reg_class_t); +static bool cris_legitimate_address_p (enum machine_mode, rtx, bool); + static int cris_register_move_cost (enum machine_mode, reg_class_t, reg_class_t); static int cris_memory_move_cost (enum machine_mode, reg_class_t, bool); static bool cris_rtx_costs (rtx, int, int, int, int *, bool); @@ -200,6 +202,9 @@ #undef TARGET_INIT_LIBFUNCS #define TARGET_INIT_LIBFUNCS cris_init_libfuncs +#undef TARGET_LEGITIMATE_ADDRESS_P +#define TARGET_LEGITIMATE_ADDRESS_P cris_legitimate_address_p + #undef TARGET_PREFERRED_RELOAD_CLASS #define TARGET_PREFERRED_RELOAD_CLASS cris_preferred_reload_class @@ -1122,7 +1127,7 @@ if (CONSTANT_ADDRESS_P (x)) cris_output_addr_const (file, x); - else if (BASE_OR_AUTOINCR_P (x)) + else if (cris_base_or_autoincr_p (x, true)) cris_print_base (x, file); else if (GET_CODE (x) == PLUS) { @@ -1130,12 +1135,12 @@ x1 = XEXP (x, 0); x2 = XEXP (x, 1); - if (BASE_P (x1)) + if (cris_base_p (x1, true)) { cris_print_base (x1, file); cris_print_index (x2, file); } - else if (BASE_P (x2)) + else if (cris_base_p (x2, true)) { cris_print_base (x2, file); cris_print_index (x1, file); @@ -1272,6 +1277,136 @@ gcc_unreachable (); } +/* Nonzero if X is a hard reg that can be used as an index. */ +static inline bool +reg_ok_for_base_p (const_rtx x, bool strict) +{ + return ((! strict && ! HARD_REGISTER_P (x)) + || REGNO_OK_FOR_BASE_P (REGNO (x))); +} + +/* Nonzero if X is a hard reg that can be used as an index. */ +static inline bool +reg_ok_for_index_p (const_rtx x, bool strict) +{ + return reg_ok_for_base_p (x, strict); +} + +/* No symbol can be used as an index (or more correct, as a base) together + with a register with PIC; the PIC register must be there. */ + +bool +cris_constant_index_p (const_rtx x) +{ + return (CONSTANT_P (x) && (!flag_pic || cris_valid_pic_const (x, true))); +} + +/* True if X is a valid base register. */ + +bool +cris_base_p (const_rtx x, bool strict) +{ + return (REG_P (x) && reg_ok_for_base_p (x, strict)); +} + +/* True if X is a valid index register. */ + +static inline bool +cris_index_p (const_rtx x, bool strict) +{ + return (REG_P (x) && reg_ok_for_index_p (x, strict)); +} + +/* True if X is a valid base register with or without autoincrement. */ + +bool +cris_base_or_autoincr_p (const_rtx x, bool strict) +{ + return (cris_base_p (x, strict) + || (GET_CODE (x) == POST_INC + && cris_base_p (XEXP (x, 0), strict) + && REGNO (XEXP (x, 0)) != CRIS_ACR_REGNUM)); +} + +/* True if X is a valid (register) index for BDAP, i.e. [Rs].S or [Rs+].S. */ + +bool +cris_bdap_index_p (const_rtx x, bool strict) +{ + return ((MEM_P (x) + && GET_MODE (x) == SImode + && cris_base_or_autoincr_p (XEXP (x, 0), strict)) + || (GET_CODE (x) == SIGN_EXTEND + && MEM_P (XEXP (x, 0)) + && (GET_MODE (XEXP (x, 0)) == HImode + || GET_MODE (XEXP (x, 0)) == QImode) + && cris_base_or_autoincr_p (XEXP (XEXP (x, 0), 0), strict))); +} + +/* True if X is a valid (register) index for BIAP, i.e. Rd.m. */ + +bool +cris_biap_index_p (const_rtx x, bool strict) +{ + return (cris_index_p (x, strict) + || (GET_CODE (x) == MULT + && cris_index_p (XEXP (x, 0), strict) + && cris_scale_int_operand (XEXP (x, 1), VOIDmode))); +} + +/* Worker function for TARGET_LEGITIMATE_ADDRESS_P. + + A PIC operand looks like a normal symbol here. At output we dress it + in "[rPIC+symbol:GOT]" (global symbol) or "rPIC+symbol:GOTOFF" (local + symbol) so we exclude all addressing modes where we can't replace a + plain "symbol" with that. A global PIC symbol does not fit anywhere + here (but is thankfully a general_operand in itself). A local PIC + symbol is valid for the plain "symbol + offset" case. */ + +static bool +cris_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) +{ + const_rtx x1, x2; + + if (cris_base_or_autoincr_p (x, strict)) + return true; + else if (TARGET_V32) + /* Nothing else is valid then. */ + return false; + else if (cris_constant_index_p (x)) + return true; + /* Indexed? */ + else if (GET_CODE (x) == PLUS) + { + x1 = XEXP (x, 0); + x2 = XEXP (x, 1); + /* BDAP o, Rd. */ + if ((cris_base_p (x1, strict) && cris_constant_index_p (x2)) + || (cris_base_p (x2, strict) && cris_constant_index_p (x1)) + /* BDAP Rs[+], Rd. */ + || (GET_MODE_SIZE (mode) <= UNITS_PER_WORD + && ((cris_base_p (x1, strict) + && cris_bdap_index_p (x2, strict)) + || (cris_base_p (x2, strict) + && cris_bdap_index_p (x1, strict)) + /* BIAP.m Rs, Rd */ + || (cris_base_p (x1, strict) + && cris_biap_index_p (x2, strict)) + || (cris_base_p (x2, strict) + && cris_biap_index_p (x1, strict))))) + return true; + } + else if (MEM_P (x)) + { + /* DIP (Rs). Reject [[reg+]] and [[reg]] for DImode (long long). */ + if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD + && cris_base_or_autoincr_p (XEXP (x, 0), strict)) + return true; + } + + return false; +} + /* Worker function for LEGITIMIZE_RELOAD_ADDRESS. */ bool @@ -1860,7 +1995,7 @@ FIXME: this case is a stop-gap for 4.3 and 4.4, this whole function should be rewritten. */ - if (outer_code == PLUS && BIAP_INDEX_P (x)) + if (outer_code == PLUS && cris_biap_index_p (x, false)) { *total = 0; return true; @@ -1942,7 +2077,7 @@ loop there, without apparent reason. */ /* The cheapest addressing modes get 0, since nothing extra is needed. */ - if (BASE_OR_AUTOINCR_P (x)) + if (cris_base_or_autoincr_p (x, false)) return 0; /* An indirect mem must be a DIP. This means two bytes extra for code, @@ -1972,7 +2107,7 @@ /* A BIAP is 2 extra bytes for the prefix insn, nothing more. We recognize the typical MULT which is always in tem1 because of insn canonicalization. */ - if ((GET_CODE (tem1) == MULT && BIAP_INDEX_P (tem1)) + if ((GET_CODE (tem1) == MULT && cris_biap_index_p (tem1, false)) || REG_P (tem2)) return 2 / 2; @@ -2030,12 +2165,12 @@ /* The operands may be swapped. Canonicalize them in reg_rtx and val_rtx, where reg_rtx always is a reg (for this constraint to match). */ - if (! BASE_P (reg_rtx)) + if (! cris_base_p (reg_rtx, false)) reg_rtx = val_rtx, val_rtx = ops[rreg]; /* Don't forget to check that reg_rtx really is a reg. If it isn't, we have no business. */ - if (! BASE_P (reg_rtx)) + if (! cris_base_p (reg_rtx, false)) return 0; /* Don't do this when -mno-split. */ @@ -2060,8 +2195,8 @@ /* Check if the lvalue register is the same as the "other operand". If so, the result is undefined and we shouldn't do this. FIXME: Check again. */ - if ((BASE_P (ops[lreg]) - && BASE_P (ops[other_op]) + if ((cris_base_p (ops[lreg], false) + && cris_base_p (ops[other_op], false) && REGNO (ops[lreg]) == REGNO (ops[other_op])) || rtx_equal_p (ops[other_op], ops[lreg])) return 0; @@ -2074,7 +2209,7 @@ return 0; if (code == PLUS - && ! BASE_P (val_rtx)) + && ! cris_base_p (val_rtx, false)) { /* Do not allow rx = rx + n if a normal add or sub with same size @@ -2088,19 +2223,20 @@ if (CONSTANT_P (val_rtx)) return 1; - if (MEM_P (val_rtx) && BASE_OR_AUTOINCR_P (XEXP (val_rtx, 0))) + if (MEM_P (val_rtx) + && cris_base_or_autoincr_p (XEXP (val_rtx, 0), false)) return 1; if (GET_CODE (val_rtx) == SIGN_EXTEND && MEM_P (XEXP (val_rtx, 0)) - && BASE_OR_AUTOINCR_P (XEXP (XEXP (val_rtx, 0), 0))) + && cris_base_or_autoincr_p (XEXP (XEXP (val_rtx, 0), 0), false)) return 1; /* If we got here, it's not a valid addressing mode. */ return 0; } else if (code == MULT - || (code == PLUS && BASE_P (val_rtx))) + || (code == PLUS && cris_base_p (val_rtx, false))) { /* Do not allow rx = rx + ry.S, since it doesn't give better code. */ if (rtx_equal_p (ops[lreg], reg_rtx) @@ -2112,7 +2248,7 @@ return 0; /* Only allow r + ... */ - if (! BASE_P (reg_rtx)) + if (! cris_base_p (reg_rtx, false)) return 0; /* If we got here, all seems ok. @@ -2202,7 +2338,7 @@ elsewhere. */ bool -cris_valid_pic_const (rtx x, bool any_operand) +cris_valid_pic_const (const_rtx x, bool any_operand) { gcc_assert (flag_pic); @@ -2252,7 +2388,7 @@ given the original (non-PIC) representation. */ enum cris_pic_symbol_type -cris_pic_symbol_type_of (rtx x) +cris_pic_symbol_type_of (const_rtx x) { switch (GET_CODE (x)) { Index: gcc/config/cris/cris.h =================================================================== --- gcc/config/cris/cris.h (revision 180345) +++ gcc/config/cris/cris.h (working copy) @@ -676,17 +676,18 @@ /* Just an indirect register (happens to also be \ "all" slottable memory addressing modes not \ covered by other constraints, i.e. '>'). */ \ - MEM_P (X) && BASE_P (XEXP (X, 0)) \ + MEM_P (X) \ + && cris_base_p (XEXP (X, 0), reload_in_progress | reload_completed) \ ) #define EXTRA_CONSTRAINT_R(X) \ ( \ /* An operand to BDAP or BIAP: \ A BIAP; r.S? */ \ - BIAP_INDEX_P (X) \ + cris_biap_index_p (X, reload_in_progress | reload_completed) \ /* A [reg] or (int) [reg], maybe with post-increment. */ \ - || BDAP_INDEX_P (X) \ - || CONSTANT_INDEX_P (X) \ + || cris_bdap_index_p (X, reload_in_progress | reload_completed) \ + || cris_constant_index_p (X) \ ) #define EXTRA_CONSTRAINT_T(X) \ @@ -695,25 +696,33 @@ MEM_P (X) \ && ((MEM_P (XEXP (X, 0)) \ /* Double indirect: [[reg]] or [[reg+]]? */ \ - && (BASE_OR_AUTOINCR_P (XEXP (XEXP (X, 0), 0)))) \ + && (cris_base_or_autoincr_p (XEXP (XEXP (X, 0), 0), \ + reload_in_progress | reload_completed))) \ /* Just an explicit indirect reference: [const]? */ \ || CONSTANT_P (XEXP (X, 0)) \ /* Something that is indexed; [...+...]? */ \ || (GET_CODE (XEXP (X, 0)) == PLUS \ /* A BDAP constant: [reg+(8|16|32)bit offset]? */ \ - && ((BASE_P (XEXP (XEXP (X, 0), 0)) \ - && CONSTANT_INDEX_P (XEXP (XEXP (X, 0), 1))) \ + && ((cris_base_p (XEXP (XEXP (X, 0), 0), \ + reload_in_progress | reload_completed) \ + && cris_constant_index_p (XEXP (XEXP (X, 0), 1))) \ /* A BDAP register: [reg+[reg(+)].S]? */ \ - || (BASE_P (XEXP (XEXP (X, 0), 0)) \ - && BDAP_INDEX_P(XEXP(XEXP(X, 0), 1))) \ + || (cris_base_p (XEXP (XEXP (X, 0), 0), \ + reload_in_progress | reload_completed) \ + && cris_bdap_index_p (XEXP(XEXP(X, 0), 1), \ + reload_in_progress | reload_completed)) \ /* Same, but with swapped arguments (no canonical \ ordering between e.g. REG and MEM as of LAST_UPDATED \ "Thu May 12 03:59:11 UTC 2005"). */ \ - || (BASE_P (XEXP (XEXP (X, 0), 1)) \ - && BDAP_INDEX_P (XEXP (XEXP (X, 0), 0))) \ + || (cris_base_p (XEXP (XEXP (X, 0), 1), \ + reload_in_progress | reload_completed) \ + && cris_bdap_index_p (XEXP (XEXP (X, 0), 0), \ + reload_in_progress | reload_completed)) \ /* A BIAP: [reg+reg.S] (MULT comes first). */ \ - || (BASE_P (XEXP (XEXP (X, 0), 1)) \ - && BIAP_INDEX_P (XEXP (XEXP (X, 0), 0)))))) \ + || (cris_base_p (XEXP (XEXP (X, 0), 1), \ + reload_in_progress | reload_completed) \ + && cris_biap_index_p (XEXP (XEXP (X, 0), 0), \ + reload_in_progress | reload_completed))))) \ ) /* PIC-constructs for symbols. */ @@ -888,118 +897,6 @@ among all CRIS variants. */ #define MAX_REGS_PER_ADDRESS 2 -/* There are helper macros defined here which are used only in - GO_IF_LEGITIMATE_ADDRESS. - - Note that you *have to* reject invalid addressing modes for mode - MODE, even if it is legal for normal addressing modes. You cannot - rely on the constraints to do this work. They can only be used to - doublecheck your intentions. One example is that you HAVE TO reject - (mem:DI (plus:SI (reg:SI x) (reg:SI y))) because for some reason - this cannot be reloaded. (Which of course you can argue that gcc - should have done.) FIXME: Strange. Check. */ - -/* No symbol can be used as an index (or more correct, as a base) together - with a register with PIC; the PIC register must be there. */ -#define CONSTANT_INDEX_P(X) \ - (CONSTANT_P (X) && (!flag_pic || cris_valid_pic_const (X, true))) - -/* True if X is a valid base register. */ -#define BASE_P(X) \ - (REG_P (X) && REG_OK_FOR_BASE_P (X)) - -/* True if X is a valid base register with or without autoincrement. */ -#define BASE_OR_AUTOINCR_P(X) \ - (BASE_P (X) \ - || (GET_CODE (X) == POST_INC \ - && BASE_P (XEXP (X, 0)) \ - && REGNO (XEXP (X, 0)) != CRIS_ACR_REGNUM)) - -/* True if X is a valid (register) index for BDAP, i.e. [Rs].S or [Rs+].S. */ -#define BDAP_INDEX_P(X) \ - ((MEM_P (X) && GET_MODE (X) == SImode \ - && BASE_OR_AUTOINCR_P (XEXP (X, 0))) \ - || (GET_CODE (X) == SIGN_EXTEND \ - && MEM_P (XEXP (X, 0)) \ - && (GET_MODE (XEXP (X, 0)) == HImode \ - || GET_MODE (XEXP (X, 0)) == QImode) \ - && BASE_OR_AUTOINCR_P (XEXP (XEXP (X, 0), 0)))) - -/* True if X is a valid (register) index for BIAP, i.e. Rd.m. */ -#define BIAP_INDEX_P(X) \ - ((BASE_P (X) && REG_OK_FOR_INDEX_P (X)) \ - || (GET_CODE (X) == MULT \ - && BASE_P (XEXP (X, 0)) \ - && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \ - && CONST_INT_P (XEXP (X, 1)) \ - && (INTVAL (XEXP (X, 1)) == 2 \ - || INTVAL (XEXP (X, 1)) == 4))) - -/* A PIC operand looks like a normal symbol here. At output we dress it - in "[rPIC+symbol:GOT]" (global symbol) or "rPIC+symbol:GOTOFF" (local - symbol) so we exclude all addressing modes where we can't replace a - plain "symbol" with that. A global PIC symbol does not fit anywhere - here (but is thankfully a general_operand in itself). A local PIC - symbol is valid for the plain "symbol + offset" case. */ -#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ - { \ - rtx x1, x2; \ - if (BASE_OR_AUTOINCR_P (X)) \ - goto ADDR; \ - else if (TARGET_V32) \ - /* Nothing else is valid then. */ \ - ; \ - else if (CONSTANT_INDEX_P (X)) \ - goto ADDR; \ - /* Indexed? */ \ - else if (GET_CODE (X) == PLUS) \ - { \ - x1 = XEXP (X, 0); \ - x2 = XEXP (X, 1); \ - /* BDAP o, Rd. */ \ - if ((BASE_P (x1) && CONSTANT_INDEX_P (x2)) \ - || (BASE_P (x2) && CONSTANT_INDEX_P (x1)) \ - /* BDAP Rs[+], Rd. */ \ - || (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \ - && ((BASE_P (x1) && BDAP_INDEX_P (x2)) \ - || (BASE_P (x2) && BDAP_INDEX_P (x1)) \ - /* BIAP.m Rs, Rd */ \ - || (BASE_P (x1) && BIAP_INDEX_P (x2)) \ - || (BASE_P (x2) && BIAP_INDEX_P (x1))))) \ - goto ADDR; \ - } \ - else if (MEM_P (X)) \ - { \ - /* DIP (Rs). Reject [[reg+]] and [[reg]] for \ - DImode (long long). */ \ - if (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \ - && (BASE_P (XEXP (X, 0)) \ - || BASE_OR_AUTOINCR_P (XEXP (X, 0)))) \ - goto ADDR; \ - } \ - } - -#ifndef REG_OK_STRICT - /* Nonzero if X is a hard reg that can be used as a base reg - or if it is a pseudo reg. */ -# define REG_OK_FOR_BASE_P(X) \ - (REGNO (X) <= CRIS_LAST_GENERAL_REGISTER \ - || REGNO (X) == ARG_POINTER_REGNUM \ - || REGNO (X) >= FIRST_PSEUDO_REGISTER) -#else - /* Nonzero if X is a hard reg that can be used as a base reg. */ -# define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) -#endif - -#ifndef REG_OK_STRICT - /* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -# define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X) -#else - /* Nonzero if X is a hard reg that can be used as an index. */ -# define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) -#endif - /* Fix reloads known to cause suboptimal spilling. */ #define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, INDL, WIN) \ do \ Index: gcc/config/cris/cris.md =================================================================== --- gcc/config/cris/cris.md (revision 180345) +++ gcc/config/cris/cris.md (working copy) @@ -4680,7 +4680,7 @@ (match_operator 4 "cris_mem_op" [(match_dup 0)]))] "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD && REGNO (operands[3]) != REGNO (operands[0]) - && (BASE_P (operands[1]) || BASE_P (operands[2])) + && (cris_base_p (operands[1], false) || cris_base_p (operands[2], false)) && !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J') && !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N') && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128) @@ -4716,7 +4716,7 @@ (match_operand 4 "register_operand" ""))] "GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD && REGNO (operands[4]) != REGNO (operands[0]) - && (BASE_P (operands[1]) || BASE_P (operands[2])) + && (cris_base_p (operands[1], false) || cris_base_p (operands[2], false)) && !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J') && !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N') && (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128) Index: gcc/config/cris/cris-protos.h =================================================================== --- gcc/config/cris/cris-protos.h (revision 180345) +++ gcc/config/cris/cris-protos.h (working copy) @@ -33,8 +33,13 @@ extern rtx cris_return_addr_rtx (int, rtx); extern rtx cris_split_movdx (rtx *); extern int cris_legitimate_pic_operand (rtx); -extern enum cris_pic_symbol_type cris_pic_symbol_type_of (rtx); -extern bool cris_valid_pic_const (rtx, bool); +extern enum cris_pic_symbol_type cris_pic_symbol_type_of (const_rtx); +extern bool cris_valid_pic_const (const_rtx, bool); +extern bool cris_constant_index_p (const_rtx); +extern bool cris_base_p (const_rtx, bool); +extern bool cris_base_or_autoincr_p (const_rtx, bool); +extern bool cris_bdap_index_p (const_rtx, bool); +extern bool cris_biap_index_p (const_rtx, bool); extern bool cris_store_multiple_op_p (rtx); extern bool cris_movem_load_rest_p (rtx, int); extern void cris_asm_output_symbol_ref (FILE *, rtx); Anatoly.