===================================================================
@@ -4565,6 +4565,47 @@ mem_ref_refers_to_non_mem_p (tree ref)
&& !MEM_P (DECL_RTL (base)));
}
+/* Expand a MEM_REF referring an object in memory to a MEM RTX. Any spacial
+ treatment of misalignment must be handled on top of the returned result. */
+
+static rtx
+expand_mem_ref_to_mem_rtx (tree ref)
+{
+ enum machine_mode address_mode, mode = TYPE_MODE (TREE_TYPE (ref));
+ tree base = TREE_OPERAND (ref, 0);
+ addr_space_t as
+ = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (ref, 0))));
+ gimple def_stmt;
+ rtx mem, op0;
+
+ gcc_checking_assert (!mem_ref_refers_to_non_mem_p (ref));
+
+ address_mode = targetm.addr_space.address_mode (as);
+
+ if ((def_stmt = get_def_for_expr (base, BIT_AND_EXPR)))
+ {
+ tree mask = gimple_assign_rhs2 (def_stmt);
+ base = build2 (BIT_AND_EXPR, TREE_TYPE (base),
+ gimple_assign_rhs1 (def_stmt), mask);
+ TREE_OPERAND (ref, 0) = base;
+ }
+ op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
+ op0 = convert_memory_address_addr_space (address_mode, op0, as);
+ if (!integer_zerop (TREE_OPERAND (ref, 1)))
+ {
+ rtx off
+ = immed_double_int_const (mem_ref_offset (ref), address_mode);
+ op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
+ }
+ op0 = memory_address_addr_space (mode, op0, as);
+ mem = gen_rtx_MEM (mode, op0);
+ set_mem_attributes (mem, ref, 0);
+ set_mem_addr_space (mem, as);
+ if (TREE_THIS_VOLATILE (ref))
+ MEM_VOLATILE_P (mem) = 1;
+ return mem;
+}
+
/* Expand an assignment that stores the value of FROM into TO. If NONTEMPORAL
is true, try generating a nontemporal store. */
@@ -4600,46 +4641,31 @@ expand_assignment (tree to, tree from, b
!= CODE_FOR_nothing)
|| SLOW_UNALIGNED_ACCESS (mode, align)))
{
- addr_space_t as
- = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (to, 0))));
struct expand_operand ops[2];
- enum machine_mode address_mode;
- rtx reg, op0, mem;
+ rtx reg, mem;
reg = expand_expr (from, NULL_RTX, VOIDmode, EXPAND_NORMAL);
reg = force_not_mem (reg);
if (TREE_CODE (to) == MEM_REF)
- {
- tree base = TREE_OPERAND (to, 0);
- address_mode = targetm.addr_space.address_mode (as);
- op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_NORMAL);
- op0 = convert_memory_address_addr_space (address_mode, op0, as);
- if (!integer_zerop (TREE_OPERAND (to, 1)))
- {
- rtx off
- = immed_double_int_const (mem_ref_offset (to), address_mode);
- op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
- }
- op0 = memory_address_addr_space (mode, op0, as);
- mem = gen_rtx_MEM (mode, op0);
- set_mem_attributes (mem, to, 0);
- set_mem_addr_space (mem, as);
- }
+ mem = expand_mem_ref_to_mem_rtx (to);
else if (TREE_CODE (to) == TARGET_MEM_REF)
{
+ addr_space_t as
+ = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (to, 0))));
struct mem_address addr;
+ rtx op0;
get_address_description (to, &addr);
op0 = addr_for_mem_ref (&addr, as, true);
op0 = memory_address_addr_space (mode, op0, as);
mem = gen_rtx_MEM (mode, op0);
set_mem_attributes (mem, to, 0);
set_mem_addr_space (mem, as);
+ if (TREE_THIS_VOLATILE (to))
+ MEM_VOLATILE_P (mem) = 1;
}
else
gcc_unreachable ();
- if (TREE_THIS_VOLATILE (to))
- MEM_VOLATILE_P (mem) = 1;
if (icode != CODE_FOR_nothing)
{
@@ -4737,7 +4763,11 @@ expand_assignment (tree to, tree from, b
else
{
misalignp = false;
- to_rtx = expand_normal (tem);
+ if (TREE_CODE (tem) == MEM_REF
+ && !mem_ref_refers_to_non_mem_p (tem))
+ to_rtx = expand_mem_ref_to_mem_rtx (tem);
+ else
+ to_rtx = expand_normal (tem);
}
/* If the bitfield is volatile, we want to access it in the
@@ -9395,17 +9425,12 @@ expand_expr_real_1 (tree exp, rtx target
case MEM_REF:
{
- addr_space_t as
- = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))));
- enum machine_mode address_mode;
- tree base = TREE_OPERAND (exp, 0);
- gimple def_stmt;
enum insn_code icode;
- unsigned align;
/* Handle expansion of non-aliased memory with non-BLKmode. That
might end up in a register. */
if (mem_ref_refers_to_non_mem_p (exp))
{
+ tree base = TREE_OPERAND (exp, 0);
HOST_WIDE_INT offset = mem_ref_offset (exp).low;
tree bit_offset;
tree bftype;
@@ -9437,32 +9462,9 @@ expand_expr_real_1 (tree exp, rtx target
bit_offset),
target, tmode, modifier);
}
- address_mode = targetm.addr_space.address_mode (as);
- base = TREE_OPERAND (exp, 0);
- if ((def_stmt = get_def_for_expr (base, BIT_AND_EXPR)))
- {
- tree mask = gimple_assign_rhs2 (def_stmt);
- base = build2 (BIT_AND_EXPR, TREE_TYPE (base),
- gimple_assign_rhs1 (def_stmt), mask);
- TREE_OPERAND (exp, 0) = base;
- }
- align = get_object_or_type_alignment (exp);
- op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
- op0 = memory_address_addr_space (address_mode, op0, as);
- if (!integer_zerop (TREE_OPERAND (exp, 1)))
- {
- rtx off
- = immed_double_int_const (mem_ref_offset (exp), address_mode);
- op0 = simplify_gen_binary (PLUS, address_mode, op0, off);
- }
- op0 = memory_address_addr_space (mode, op0, as);
- temp = gen_rtx_MEM (mode, op0);
- set_mem_attributes (temp, exp, 0);
- set_mem_addr_space (temp, as);
- if (TREE_THIS_VOLATILE (exp))
- MEM_VOLATILE_P (temp) = 1;
+ temp = expand_mem_ref_to_mem_rtx (exp);
if (mode != BLKmode
- && align < GET_MODE_ALIGNMENT (mode)
+ && get_object_or_type_alignment (exp) < GET_MODE_ALIGNMENT (mode)
/* If the target does not have special handling for unaligned
loads of mode then it can use regular moves for them. */
&& ((icode = optab_handler (movmisalign_optab, mode))