+2011-10-29 Anatoly Sokolov <aesok@post.ru>
+
+ * 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.
+
2011-10-21 Andi Kleen <ak@linux.intel.com>
* ggc-page (PAGE_ALIGN): Add.
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);
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);
#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
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)
{
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);
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
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;
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,
/* 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;
/* 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, reload_in_progress || reload_completed))
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, reload_in_progress || reload_completed))
return 0;
/* Don't do this when -mno-split. */
/* 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], reload_in_progress || reload_completed)
+ && cris_base_p (ops[other_op],
+ reload_in_progress || reload_completed)
&& REGNO (ops[lreg]) == REGNO (ops[other_op]))
|| rtx_equal_p (ops[other_op], ops[lreg]))
return 0;
return 0;
if (code == PLUS
- && ! BASE_P (val_rtx))
+ && ! cris_base_p (val_rtx, reload_in_progress || reload_completed))
{
/* Do not allow rx = rx + n if a normal add or sub with same size
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),
+ reload_in_progress || reload_completed))
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),
+ reload_in_progress || reload_completed))
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,
+ reload_in_progress || reload_completed)))
{
/* Do not allow rx = rx + ry.S, since it doesn't give better code. */
if (rtx_equal_p (ops[lreg], reg_rtx)
return 0;
/* Only allow r + ... */
- if (! BASE_P (reg_rtx))
+ if (! cris_base_p (reg_rtx, reload_in_progress || reload_completed))
return 0;
/* If we got here, all seems ok.
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);
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))
{
/* 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) \
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. */
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 \
(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], true) || cris_base_p (operands[2], true))
&& !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)
(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], true) || cris_base_p (operands[2], true))
&& !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)