+2012-09-26 Georg-Johann Lay <avr@gjlay.de>
+
+ PR middle-end/54635
+ * doc/tm.texi.in (TARGET_MODE_DEPENDENT_ADDRESS_P): Document new
+ parameter addrspace.
+ * doc/tm.texi: Regenerate.
+ * target.def (mode_dependent_address_p): Add addr_space_t parameter.
+ * targhooks.h (default_mode_dependent_address_p): Ditto.
+ * targhooks.c (default_mode_dependent_address_p): Ditto.
+ * expr.c (convert_move): Pass address space to mode_dependent_address_p.
+ * combine.c (combine_simplify_rtx): Ditto.
+ (make_extraction): Ditto.
+ (simplify_shift_const_1): Ditto.
+ (gen_lowpart_for_combine): Ditto.
+ * lower-subreg.c (simple_move_operand): Ditto.
+ * recog.c (simplify_while_replacing): Ditto.
+ (offsettable_address_addr_space_p): Ditto.
+ (mode_dependent_address_p): Ditto.
+ * simplify-rtx.c (simplify_unary_operation_1): Ditto.
+ (simplify_subreg): Ditto.
+ * config/m68k/m68k.md: Ditto.
+ * config/vax/vax.md: Ditto.
+ * config/vax/constraints.md (Q): Ditto.
+ * config/vax/predicates.md (indexed_memory_operand): Ditto.
+ * config/alpha/alpha.c (alpha_mode_dependent_address_p): Add
+ unused addr_space_t parameter.
+ * config/avr/avr.c (avr_mode_dependent_address_p): Ditto.
+ * config/h8300/h8300.c (h8300_mode_dependent_address_p): Ditto.
+ * config/m32r/m32r.c (m32r_mode_dependent_address_p): Ditto.
+ * config/rs6000/rs6000.c (rs6000_mode_dependent_address_p): Ditto.
+ * config/rx/rx.c (rx_mode_dependent_address_p): Ditto.
+ * config/sparc/sparc.c (sparc_mode_dependent_address_p): Ditto.
+ * config/stormy16/stormy16.c (xstormy16_mode_dependent_address_p):
+ Ditto.
+ * config/vax/vax.c (vax_mode_dependent_address_p): Ditto.
+ * config/xtensa/xtensa.c (xtensa_mode_dependent_address_p): Ditto.
+
2012-09-26 Christophe Lyon <christophe.lyon@linaro.org>
* tree-ssa-math-opts.c (bswap_stats): Add found_16bit field.
of the address. */
if (MEM_P (SUBREG_REG (x))
&& (MEM_VOLATILE_P (SUBREG_REG (x))
- || mode_dependent_address_p (XEXP (SUBREG_REG (x), 0))))
+ || mode_dependent_address_p (XEXP (SUBREG_REG (x), 0),
+ MEM_ADDR_SPACE (SUBREG_REG (x)))))
return gen_rtx_CLOBBER (mode, const0_rtx);
/* Note that we cannot do any narrowing for non-constants since
may not be aligned, for one thing). */
&& GET_MODE_PRECISION (inner_mode) >= GET_MODE_PRECISION (tmode)
&& (inner_mode == tmode
- || (! mode_dependent_address_p (XEXP (inner, 0))
+ || (! mode_dependent_address_p (XEXP (inner, 0),
+ MEM_ADDR_SPACE (inner))
&& ! MEM_VOLATILE_P (inner))))))
{
/* If INNER is a MEM, make a new MEM that encompasses just the desired
/* If we have to change the mode of memory and cannot, the desired mode
is EXTRACTION_MODE. */
if (inner_mode != wanted_inner_mode
- && (mode_dependent_address_p (XEXP (inner, 0))
+ && (mode_dependent_address_p (XEXP (inner, 0), MEM_ADDR_SPACE (inner))
|| MEM_VOLATILE_P (inner)
|| pos_rtx))
wanted_inner_mode = extraction_mode;
&& ! pos_rtx
&& GET_MODE_SIZE (wanted_inner_mode) < GET_MODE_SIZE (is_mode)
&& MEM_P (inner)
- && ! mode_dependent_address_p (XEXP (inner, 0))
+ && ! mode_dependent_address_p (XEXP (inner, 0), MEM_ADDR_SPACE (inner))
&& ! MEM_VOLATILE_P (inner))
{
int offset = 0;
minus the width of a smaller mode, we can do this with a
SIGN_EXTEND or ZERO_EXTEND from the narrower memory location. */
if ((code == ASHIFTRT || code == LSHIFTRT)
- && ! mode_dependent_address_p (XEXP (varop, 0))
+ && ! mode_dependent_address_p (XEXP (varop, 0),
+ MEM_ADDR_SPACE (varop))
&& ! MEM_VOLATILE_P (varop)
&& (tmode = mode_for_size (GET_MODE_BITSIZE (mode) - count,
MODE_INT, 1)) != BLKmode)
/* Refuse to work on a volatile memory ref or one with a mode-dependent
address. */
- if (MEM_VOLATILE_P (x) || mode_dependent_address_p (XEXP (x, 0)))
+ if (MEM_VOLATILE_P (x)
+ || mode_dependent_address_p (XEXP (x, 0), MEM_ADDR_SPACE (x)))
goto fail;
/* If we want to refer to something bigger than the original memref,
We can simplify the test since we know that the address must be valid. */
static bool
-alpha_mode_dependent_address_p (const_rtx addr)
+alpha_mode_dependent_address_p (const_rtx addr,
+ addr_space_t as ATTRIBUTE_UNUSED)
{
return GET_CODE (addr) == AND;
}
with mov<mode> expanders in avr.md. */
static bool
-avr_mode_dependent_address_p (const_rtx addr)
+avr_mode_dependent_address_p (const_rtx addr, addr_space_t as ATTRIBUTE_UNUSED)
{
return GET_MODE (addr) != Pmode;
}
;; "*addhq3" "*adduhq3"
;; "*addha3" "*adduha3"
(define_insn "*add<mode>3"
- [(set (match_operand:ALL2 0 "register_operand" "=r,d,!w ,d")
+ [(set (match_operand:ALL2 0 "register_operand" "=?r,d,!w ,d")
(plus:ALL2 (match_operand:ALL2 1 "register_operand" "%0,0,0 ,0")
(match_operand:ALL2 2 "nonmemory_or_const_operand" "r,s,IJ YIJ,n Ynn")))]
""
(the amount of decrement or increment being the length of the operand). */
static bool
-h8300_mode_dependent_address_p (const_rtx addr)
+h8300_mode_dependent_address_p (const_rtx addr,
+ addr_space_t as ATTRIBUTE_UNUSED)
{
if (GET_CODE (addr) == PLUS
&& h8300_get_index (XEXP (addr, 0), VOIDmode, 0) != XEXP (addr, 0))
static int m32r_is_insn (rtx);
static bool m32r_legitimate_address_p (enum machine_mode, rtx, bool);
static rtx m32r_legitimize_address (rtx, rtx, enum machine_mode);
-static bool m32r_mode_dependent_address_p (const_rtx);
+static bool m32r_mode_dependent_address_p (const_rtx, addr_space_t);
static tree m32r_handle_model_attribute (tree *, tree, tree, int, bool *);
static void m32r_print_operand (FILE *, rtx, int);
static void m32r_print_operand_address (FILE *, rtx);
/* Worker function for TARGET_MODE_DEPENDENT_ADDRESS_P. */
static bool
-m32r_mode_dependent_address_p (const_rtx addr)
+m32r_mode_dependent_address_p (const_rtx addr, addr_space_t as ATTRIBUTE_UNUSED)
{
if (GET_CODE (addr) == LO_SUM)
return true;
(match_operand:SI 2 "general_src_operand" "rmSi"))]
"TARGET_68020 && TARGET_BITFIELD
&& (INTVAL (operands[1]) % 8) == 0
- && ! mode_dependent_address_p (XEXP (operands[0], 0))"
+ && ! mode_dependent_address_p (XEXP (operands[0], 0),
+ MEM_ADDR_SPACE (operands[0]))"
{
operands[0]
= adjust_address (operands[0], SImode, INTVAL (operands[1]) / 8);
&& (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
&& INTVAL (operands[2]) % INTVAL (operands[1]) == 0
&& (GET_CODE (operands[0]) == REG
- || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
+ || ! mode_dependent_address_p (XEXP (operands[0], 0),
+ MEM_ADDR_SPACE (operands[0])))"
{
if (REG_P (operands[0]))
{
(match_operand:SI 2 "const_int_operand" "n")))]
"TARGET_68020 && TARGET_BITFIELD
&& (INTVAL (operands[2]) % 8) == 0
- && ! mode_dependent_address_p (XEXP (operands[1], 0))"
+ && ! mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1]))"
{
operands[1]
= adjust_address (operands[1], SImode, INTVAL (operands[2]) / 8);
&& (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& INTVAL (operands[3]) % INTVAL (operands[2]) == 0
&& (GET_CODE (operands[1]) == REG
- || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ || ! mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1])))"
{
cc_status.flags |= CC_NOT_NEGATIVE;
if (REG_P (operands[1]))
(match_operand:SI 2 "const_int_operand" "n")))]
"TARGET_68020 && TARGET_BITFIELD
&& (INTVAL (operands[2]) % 8) == 0
- && ! mode_dependent_address_p (XEXP (operands[1], 0))"
+ && ! mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1]))"
{
operands[1]
= adjust_address (operands[1], SImode, INTVAL (operands[2]) / 8);
&& (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& INTVAL (operands[3]) % INTVAL (operands[2]) == 0
&& (GET_CODE (operands[1]) == REG
- || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ || ! mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1])))"
{
if (REG_P (operands[1]))
{
/* Implement TARGET_MODE_DEPENDENT_ADDRESS_P. */
static bool
-rs6000_mode_dependent_address_p (const_rtx addr)
+rs6000_mode_dependent_address_p (const_rtx addr,
+ addr_space_t as ATTRIBUTE_UNUSED)
{
return rs6000_mode_dependent_address_ptr (addr);
}
/* Implement TARGET_MODE_DEPENDENT_ADDRESS_P. */
static bool
-rx_mode_dependent_address_p (const_rtx addr)
+rx_mode_dependent_address_p (const_rtx addr, addr_space_t as ATTRIBUTE_UNUSED)
{
if (GET_CODE (addr) == CONST)
addr = XEXP (addr, 0);
static rtx sparc_legitimize_pic_address (rtx, rtx);
static rtx sparc_legitimize_address (rtx, rtx, enum machine_mode);
static rtx sparc_delegitimize_address (rtx);
-static bool sparc_mode_dependent_address_p (const_rtx);
+static bool sparc_mode_dependent_address_p (const_rtx, addr_space_t);
static bool sparc_pass_by_reference (cumulative_args_t,
enum machine_mode, const_tree, bool);
static void sparc_function_arg_advance (cumulative_args_t,
static bool
-sparc_mode_dependent_address_p (const_rtx addr)
+sparc_mode_dependent_address_p (const_rtx addr,
+ addr_space_t as ATTRIBUTE_UNUSED)
{
if (flag_pic && GET_CODE (addr) == PLUS)
{
or pre-decrement address. */
static bool
-xstormy16_mode_dependent_address_p (const_rtx x)
+xstormy16_mode_dependent_address_p (const_rtx x,
+ addr_space_t as ATTRIBUTE_UNUSED)
{
if (LEGITIMATE_ADDRESS_CONST_INT_P (x, 0)
&& ! LEGITIMATE_ADDRESS_CONST_INT_P (x, 6))
(define_memory_constraint "Q"
"operand is a MEM that does not have a mode-dependent address."
(and (match_code "mem")
- (match_test "!mode_dependent_address_p (XEXP (op, 0))")))
+ (match_test "!mode_dependent_address_p (XEXP (op, 0),
+ MEM_ADDR_SPACE (op))")))
(define_memory_constraint "B"
""
(define_predicate "indexed_memory_operand"
(match_code "mem")
{
- op = XEXP (op, 0);
- return GET_CODE (op) != PRE_DEC && GET_CODE (op) != POST_INC
- && mode_dependent_address_p (op);
+ rtx addr = XEXP (op, 0);
+ return GET_CODE (addr) != PRE_DEC && GET_CODE (addr) != POST_INC
+ && mode_dependent_address_p (addr, MEM_ADDR_SPACE (op));
})
(define_predicate "illegal_blk_memory_operand"
static void vax_asm_trampoline_template (FILE *);
static void vax_trampoline_init (rtx, tree, rtx);
static int vax_return_pops_args (tree, tree, int);
-static bool vax_mode_dependent_address_p (const_rtx);
+static bool vax_mode_dependent_address_p (const_rtx, addr_space_t);
\f
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
thus (because the index scale factor is the length of the operand). */
static bool
-vax_mode_dependent_address_p (const_rtx x)
+vax_mode_dependent_address_p (const_rtx x, addr_space_t as ATTRIBUTE_UNUSED)
{
rtx xfoo0, xfoo1;
"(INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
&& INTVAL (operands[2]) % INTVAL (operands[1]) == 0
&& (REG_P (operands[0])
- || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
+ || ! mode_dependent_address_p (XEXP (operands[0], 0),
+ MEM_ADDR_SPACE (operands[0])))"
"*
{
if (REG_P (operands[0]))
"(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& INTVAL (operands[3]) % INTVAL (operands[2]) == 0
&& (REG_P (operands[1])
- || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ || ! mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1])))"
"*
{
if (REG_P (operands[1]))
"(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& INTVAL (operands[3]) % INTVAL (operands[2]) == 0
&& (REG_P (operands[1])
- || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
+ || ! mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1])))"
"*
{
if (REG_P (operands[1]))
|| INTVAL (operands[2]) + INTVAL (operands[3]) > 32
|| side_effects_p (operands[1])
|| (MEM_P (operands[1])
- && mode_dependent_address_p (XEXP (operands[1], 0))))
+ && mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1]))))
return \"extv %3,%2,%1,%0\";
if (INTVAL (operands[2]) == 8)
return \"rotl %R3,%1,%0\;cvtbl %0,%0\";
|| INTVAL (operands[2]) + INTVAL (operands[3]) > 32
|| side_effects_p (operands[1])
|| (MEM_P (operands[1])
- && mode_dependent_address_p (XEXP (operands[1], 0))))
+ && mode_dependent_address_p (XEXP (operands[1], 0),
+ MEM_ADDR_SPACE (operands[1]))))
return \"extzv %3,%2,%1,%0\";
if (INTVAL (operands[2]) == 8)
return \"rotl %R3,%1,%0\;movzbl %0,%0\";
static struct machine_function * xtensa_init_machine_status (void);
static rtx xtensa_legitimize_tls_address (rtx);
static rtx xtensa_legitimize_address (rtx, rtx, enum machine_mode);
-static bool xtensa_mode_dependent_address_p (const_rtx);
+static bool xtensa_mode_dependent_address_p (const_rtx, addr_space_t);
static bool xtensa_return_in_msb (const_tree);
static void printx (FILE *, signed int);
static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT);
by default. */
static bool
-xtensa_mode_dependent_address_p (const_rtx addr)
+xtensa_mode_dependent_address_p (const_rtx addr,
+ addr_space_t as ATTRIBUTE_UNUSED)
{
return constantpool_address_p (addr);
}
address; but often a machine-dependent strategy can generate better code.
@end defmac
-@deftypefn {Target Hook} bool TARGET_MODE_DEPENDENT_ADDRESS_P (const_rtx @var{addr})
-This hook returns @code{true} if memory address @var{addr} can have
+@deftypefn {Target Hook} bool TARGET_MODE_DEPENDENT_ADDRESS_P (const_rtx @var{addr}, addr_space_t @var{addrspace})
+This hook returns @code{true} if memory address @var{addr} in address
+space @var{addrspace} can have
different meanings depending on the machine mode of the memory
reference it is used for or if the address is valid for some modes
but not others.
@end defmac
@hook TARGET_MODE_DEPENDENT_ADDRESS_P
-This hook returns @code{true} if memory address @var{addr} can have
+This hook returns @code{true} if memory address @var{addr} in address
+space @var{addrspace} can have
different meanings depending on the machine mode of the memory
reference it is used for or if the address is valid for some modes
but not others.
if (!((MEM_P (from)
&& ! MEM_VOLATILE_P (from)
&& direct_load[(int) to_mode]
- && ! mode_dependent_address_p (XEXP (from, 0)))
+ && ! mode_dependent_address_p (XEXP (from, 0),
+ MEM_ADDR_SPACE (from)))
|| REG_P (from)
|| GET_CODE (from) == SUBREG))
from = force_reg (from_mode, from);
if (!((MEM_P (from)
&& ! MEM_VOLATILE_P (from)
&& direct_load[(int) to_mode]
- && ! mode_dependent_address_p (XEXP (from, 0)))
+ && ! mode_dependent_address_p (XEXP (from, 0),
+ MEM_ADDR_SPACE (from)))
|| REG_P (from)
|| GET_CODE (from) == SUBREG))
from = force_reg (from_mode, from);
if (MEM_P (x)
&& (MEM_VOLATILE_P (x)
- || mode_dependent_address_p (XEXP (x, 0))))
+ || mode_dependent_address_p (XEXP (x, 0), MEM_ADDR_SPACE (x))))
return false;
return true;
if (MEM_P (XEXP (x, 0))
&& CONST_INT_P (XEXP (x, 1))
&& CONST_INT_P (XEXP (x, 2))
- && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0))
+ && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0),
+ MEM_ADDR_SPACE (XEXP (x, 0)))
&& !MEM_VOLATILE_P (XEXP (x, 0)))
{
enum machine_mode wanted_mode = VOIDmode;
/* Adjusting an offsettable address involves changing to a narrower mode.
Make sure that's OK. */
- if (mode_dependent_address_p (y))
+ if (mode_dependent_address_p (y, as))
return 0;
/* ??? How much offset does an offsettable BLKmode reference need?
/* Return 1 if ADDR is an address-expression whose effect depends
on the mode of the memory reference it is used in.
+ ADDRSPACE is the address space associated with the address.
+
Autoincrement addressing is a typical example of mode-dependence
because the amount of the increment depends on the mode. */
bool
-mode_dependent_address_p (rtx addr)
+mode_dependent_address_p (rtx addr, addr_space_t addrspace)
{
/* Auto-increment addressing with anything other than post_modify
or pre_modify always introduces a mode dependency. Catch such
|| GET_CODE (addr) == POST_DEC)
return true;
- return targetm.mode_dependent_address_p (addr);
+ return targetm.mode_dependent_address_p (addr, addrspace);
}
\f
/* Like extract_insn, but save insn extracted and don't extract again, when
#define offsettable_address_p(strict,mode,addr) \
offsettable_address_addr_space_p ((strict), (mode), (addr), \
ADDR_SPACE_GENERIC)
-extern bool mode_dependent_address_p (rtx);
+extern bool mode_dependent_address_p (rtx, addr_space_t);
extern int recog (rtx, rtx, int *);
#ifndef GENERATOR_FILE
if we are not changing the meaning of the address. */
if (GET_CODE (op) == MEM
&& !MEM_VOLATILE_P (op)
- && !mode_dependent_address_p (XEXP (op, 0)))
+ && !mode_dependent_address_p (XEXP (op, 0), MEM_ADDR_SPACE (op)))
return rtl_hooks.gen_lowpart_no_emit (mode, op);
break;
or if we would be widening it. */
if (MEM_P (op)
- && ! mode_dependent_address_p (XEXP (op, 0))
+ && ! mode_dependent_address_p (XEXP (op, 0), MEM_ADDR_SPACE (op))
/* Allow splitting of volatile memory references in case we don't
have instruction to move the whole thing. */
&& (! MEM_VOLATILE_P (op)
&& (INTVAL (XEXP (op, 1)) % GET_MODE_BITSIZE (outermode)) == 0
&& INTVAL (XEXP (op, 1)) > 0
&& INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (innermode)
- && ! mode_dependent_address_p (XEXP (XEXP (op, 0), 0))
+ && ! mode_dependent_address_p (XEXP (XEXP (op, 0), 0),
+ MEM_ADDR_SPACE (XEXP (op, 0)))
&& ! MEM_VOLATILE_P (XEXP (op, 0))
&& byte == subreg_lowpart_offset (outermode, innermode)
&& (GET_MODE_SIZE (outermode) >= UNITS_PER_WORD
DEFHOOK
(mode_dependent_address_p,
"",
- bool, (const_rtx addr),
+ bool, (const_rtx addr, addr_space_t addrspace),
default_mode_dependent_address_p)
/* Given an invalid address X for a given machine mode, try machine-specific
/* The default implementation of TARGET_MODE_DEPENDENT_ADDRESS_P. */
bool
-default_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED)
+default_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED,
+ addr_space_t addrspace ATTRIBUTE_UNUSED)
{
return false;
}
extern tree default_emutls_var_fields (tree, tree *);
extern tree default_emutls_var_init (tree, tree, tree);
extern bool default_hard_regno_scratch_ok (unsigned int);
-extern bool default_mode_dependent_address_p (const_rtx addr);
+extern bool default_mode_dependent_address_p (const_rtx, addr_space_t);
extern bool default_target_option_valid_attribute_p (tree, tree, tree, int);
extern bool default_target_option_pragma_parse (tree, tree);
extern bool default_target_can_inline_p (tree, tree);