Commit 22345357 by Richard Guenther Committed by Richard Biener

re PR tree-optimization/50444 (-ftree-sra ignores alignment)

2012-01-27  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/50444
	* expr.c (mem_ref_refers_to_non_mem_p): New function.
	(expand_assignment): Use it.  Properly handle misaligned
	bases when expanding stores to component references.
	(expand_expr_real_1): Use mem_ref_refers_to_non_mem_p and
	refactor that case.

From-SVN: r183629
parent e08120b1
2012-01-27 Richard Guenther <rguenther@suse.de>
PR tree-optimization/50444
* expr.c (mem_ref_refers_to_non_mem_p): New function.
(expand_assignment): Use it. Properly handle misaligned
bases when expanding stores to component references.
(expand_expr_real_1): Use mem_ref_refers_to_non_mem_p and
refactor that case.
2012-01-27 Andrey Belevantsev <abel@ispras.ru> 2012-01-27 Andrey Belevantsev <abel@ispras.ru>
PR middle-end/51389 PR middle-end/51389
......
...@@ -4548,6 +4548,23 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart, ...@@ -4548,6 +4548,23 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
} }
} }
/* Returns true if the MEM_REF REF refers to an object that does not
reside in memory and has non-BLKmode. */
static bool
mem_ref_refers_to_non_mem_p (tree ref)
{
tree base = TREE_OPERAND (ref, 0);
if (TREE_CODE (base) != ADDR_EXPR)
return false;
base = TREE_OPERAND (base, 0);
return (DECL_P (base)
&& !TREE_ADDRESSABLE (base)
&& DECL_MODE (base) != BLKmode
&& DECL_RTL_SET_P (base)
&& !MEM_P (DECL_RTL (base)));
}
/* Expand an assignment that stores the value of FROM into TO. If NONTEMPORAL /* Expand an assignment that stores the value of FROM into TO. If NONTEMPORAL
is true, try generating a nontemporal store. */ is true, try generating a nontemporal store. */
...@@ -4571,6 +4588,7 @@ expand_assignment (tree to, tree from, bool nontemporal) ...@@ -4571,6 +4588,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
if (operand_equal_p (to, from, 0)) if (operand_equal_p (to, from, 0))
return; return;
/* Handle misaligned stores. */
mode = TYPE_MODE (TREE_TYPE (to)); mode = TYPE_MODE (TREE_TYPE (to));
if ((TREE_CODE (to) == MEM_REF if ((TREE_CODE (to) == MEM_REF
|| TREE_CODE (to) == TARGET_MEM_REF) || TREE_CODE (to) == TARGET_MEM_REF)
...@@ -4580,6 +4598,8 @@ expand_assignment (tree to, tree from, bool nontemporal) ...@@ -4580,6 +4598,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
&& ((icode = optab_handler (movmisalign_optab, mode)) && ((icode = optab_handler (movmisalign_optab, mode))
!= CODE_FOR_nothing)) != CODE_FOR_nothing))
{ {
addr_space_t as
= TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (to, 0))));
struct expand_operand ops[2]; struct expand_operand ops[2];
enum machine_mode address_mode; enum machine_mode address_mode;
rtx reg, op0, mem; rtx reg, op0, mem;
...@@ -4589,8 +4609,6 @@ expand_assignment (tree to, tree from, bool nontemporal) ...@@ -4589,8 +4609,6 @@ expand_assignment (tree to, tree from, bool nontemporal)
if (TREE_CODE (to) == MEM_REF) if (TREE_CODE (to) == MEM_REF)
{ {
addr_space_t as
= TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (to, 0))));
tree base = TREE_OPERAND (to, 0); tree base = TREE_OPERAND (to, 0);
address_mode = targetm.addr_space.address_mode (as); address_mode = targetm.addr_space.address_mode (as);
op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_NORMAL); op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_NORMAL);
...@@ -4608,10 +4626,7 @@ expand_assignment (tree to, tree from, bool nontemporal) ...@@ -4608,10 +4626,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
} }
else if (TREE_CODE (to) == TARGET_MEM_REF) 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; struct mem_address addr;
get_address_description (to, &addr); get_address_description (to, &addr);
op0 = addr_for_mem_ref (&addr, as, true); op0 = addr_for_mem_ref (&addr, as, true);
op0 = memory_address_addr_space (mode, op0, as); op0 = memory_address_addr_space (mode, op0, as);
...@@ -4636,12 +4651,10 @@ expand_assignment (tree to, tree from, bool nontemporal) ...@@ -4636,12 +4651,10 @@ expand_assignment (tree to, tree from, bool nontemporal)
if the structure component's rtx is not simply a MEM. if the structure component's rtx is not simply a MEM.
Assignment of an array element at a constant index, and assignment of Assignment of an array element at a constant index, and assignment of
an array element in an unaligned packed structure field, has the same an array element in an unaligned packed structure field, has the same
problem. */ problem. Same for (partially) storing into a non-memory object. */
if (handled_component_p (to) if (handled_component_p (to)
/* ??? We only need to handle MEM_REF here if the access is not
a full access of the base object. */
|| (TREE_CODE (to) == MEM_REF || (TREE_CODE (to) == MEM_REF
&& TREE_CODE (TREE_OPERAND (to, 0)) == ADDR_EXPR) && mem_ref_refers_to_non_mem_p (to))
|| TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE) || TREE_CODE (TREE_TYPE (to)) == ARRAY_TYPE)
{ {
enum machine_mode mode1; enum machine_mode mode1;
...@@ -4652,6 +4665,7 @@ expand_assignment (tree to, tree from, bool nontemporal) ...@@ -4652,6 +4665,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
int unsignedp; int unsignedp;
int volatilep = 0; int volatilep = 0;
tree tem; tree tem;
bool misalignp;
push_temp_slots (); push_temp_slots ();
tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1, tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
...@@ -4664,8 +4678,22 @@ expand_assignment (tree to, tree from, bool nontemporal) ...@@ -4664,8 +4678,22 @@ expand_assignment (tree to, tree from, bool nontemporal)
/* If we are going to use store_bit_field and extract_bit_field, /* If we are going to use store_bit_field and extract_bit_field,
make sure to_rtx will be safe for multiple use. */ make sure to_rtx will be safe for multiple use. */
mode = TYPE_MODE (TREE_TYPE (tem));
if (TREE_CODE (tem) == MEM_REF
&& mode != BLKmode
&& ((align = get_object_or_type_alignment (tem))
< GET_MODE_ALIGNMENT (mode))
&& ((icode = optab_handler (movmisalign_optab, mode))
!= CODE_FOR_nothing))
{
misalignp = true;
to_rtx = gen_reg_rtx (mode);
}
else
{
misalignp = false;
to_rtx = expand_normal (tem); to_rtx = expand_normal (tem);
}
/* If the bitfield is volatile, we want to access it in the /* If the bitfield is volatile, we want to access it in the
field's mode, not the computed mode. field's mode, not the computed mode.
...@@ -4811,6 +4839,37 @@ expand_assignment (tree to, tree from, bool nontemporal) ...@@ -4811,6 +4839,37 @@ expand_assignment (tree to, tree from, bool nontemporal)
nontemporal); nontemporal);
} }
if (misalignp)
{
struct expand_operand ops[2];
enum machine_mode address_mode;
rtx op0, mem;
addr_space_t as = TYPE_ADDR_SPACE
(TREE_TYPE (TREE_TYPE (TREE_OPERAND (tem, 0))));
tree base = TREE_OPERAND (tem, 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 (tem, 1)))
{
rtx off = immed_double_int_const (mem_ref_offset (tem),
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, tem, 0);
set_mem_addr_space (mem, as);
if (TREE_THIS_VOLATILE (tem))
MEM_VOLATILE_P (mem) = 1;
create_fixed_operand (&ops[0], mem);
create_input_operand (&ops[1], to_rtx, mode);
/* The movmisalign<mode> pattern cannot fail, else the assignment
would silently be omitted. */
expand_insn (icode, 2, ops);
}
if (result) if (result)
preserve_temp_slots (result); preserve_temp_slots (result);
free_temp_slots (); free_temp_slots ();
...@@ -4866,10 +4925,7 @@ expand_assignment (tree to, tree from, bool nontemporal) ...@@ -4866,10 +4925,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
return; return;
} }
/* Ordinary treatment. Expand TO to get a REG or MEM rtx. /* Ordinary treatment. Expand TO to get a REG or MEM rtx. */
Don't re-expand if it was expanded already (in COMPONENT_REF case). */
if (to_rtx == 0)
to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE); to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE);
/* Don't move directly into a return register. */ /* Don't move directly into a return register. */
...@@ -9295,27 +9351,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -9295,27 +9351,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
unsigned align; unsigned align;
/* Handle expansion of non-aliased memory with non-BLKmode. That /* Handle expansion of non-aliased memory with non-BLKmode. That
might end up in a register. */ might end up in a register. */
if (TREE_CODE (base) == ADDR_EXPR) if (mem_ref_refers_to_non_mem_p (exp))
{ {
HOST_WIDE_INT offset = mem_ref_offset (exp).low; HOST_WIDE_INT offset = mem_ref_offset (exp).low;
tree bit_offset; tree bit_offset;
base = TREE_OPERAND (base, 0);
if (!DECL_P (base))
{
HOST_WIDE_INT off;
base = get_addr_base_and_unit_offset (base, &off);
gcc_assert (base);
offset += off;
}
/* If we are expanding a MEM_REF of a non-BLKmode non-addressable
decl we must use bitfield operations. */
if (DECL_P (base)
&& !TREE_ADDRESSABLE (base)
&& DECL_MODE (base) != BLKmode
&& DECL_RTL_SET_P (base)
&& !MEM_P (DECL_RTL (base)))
{
tree bftype; tree bftype;
base = TREE_OPERAND (base, 0);
if (offset == 0 if (offset == 0
&& host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1) && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
&& (GET_MODE_BITSIZE (DECL_MODE (base)) && (GET_MODE_BITSIZE (DECL_MODE (base))
...@@ -9343,7 +9384,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -9343,7 +9384,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
bit_offset), bit_offset),
target, tmode, modifier); target, tmode, modifier);
} }
}
address_mode = targetm.addr_space.address_mode (as); address_mode = targetm.addr_space.address_mode (as);
base = TREE_OPERAND (exp, 0); base = TREE_OPERAND (exp, 0);
if ((def_stmt = get_def_for_expr (base, BIT_AND_EXPR))) if ((def_stmt = get_def_for_expr (base, BIT_AND_EXPR)))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment