re PR middle-end/37774 (Alignment information is lost for ARRAY_REFs)

PR middle-end/37774
	* tree.h (get_object_alignment): Declare.
	* emit-rtl.c (set_mem_attributes_minus_bitpos): Call
	get_object_alignment if needed.
	* builtins.c (get_pointer_alignment): Move ADDR_EXPR operand handling
	to ...
	(get_object_alignment): ... here.  New function.  Try harder to
	determine alignment from get_inner_reference returned offset.

From-SVN: r141003
This commit is contained in:
Jakub Jelinek 2008-10-09 10:17:08 +02:00 committed by Jakub Jelinek
parent cc2a64dd80
commit df96b05947
4 changed files with 98 additions and 53 deletions

View file

@ -7,6 +7,15 @@
* tree-cfg.c (make_cond_expr_edges, make_goto_expr_edges): Only set
goto_block on edges if goto_locus is known.
PR middle-end/37774
* tree.h (get_object_alignment): Declare.
* emit-rtl.c (set_mem_attributes_minus_bitpos): Call
get_object_alignment if needed.
* builtins.c (get_pointer_alignment): Move ADDR_EXPR operand handling
to ...
(get_object_alignment): ... here. New function. Try harder to
determine alignment from get_inner_reference returned offset.
2008-10-08 Jakub Jelinek <jakub@redhat.com>
* graphite.c (gloog): Don't call find_unreachable_blocks

View file

@ -253,6 +253,82 @@ static bool called_as_built_in (tree node)
return false;
}
/* Return the alignment in bits of EXP, an object.
Don't return more than MAX_ALIGN no matter what, ALIGN is the inital
guessed alignment e.g. from type alignment. */
int
get_object_alignment (tree exp, unsigned int align, unsigned int max_align)
{
unsigned int inner;
inner = max_align;
if (handled_component_p (exp))
{
HOST_WIDE_INT bitsize, bitpos;
tree offset;
enum machine_mode mode;
int unsignedp, volatilep;
exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
&mode, &unsignedp, &volatilep, true);
if (bitpos)
inner = MIN (inner, (unsigned) (bitpos & -bitpos));
while (offset)
{
tree next_offset;
if (TREE_CODE (offset) == PLUS_EXPR)
{
next_offset = TREE_OPERAND (offset, 0);
offset = TREE_OPERAND (offset, 1);
}
else
next_offset = NULL;
if (host_integerp (offset, 1))
{
/* Any overflow in calculating offset_bits won't change
the alignment. */
unsigned offset_bits
= ((unsigned) tree_low_cst (offset, 1) * BITS_PER_UNIT);
if (offset_bits)
inner = MIN (inner, (offset_bits & -offset_bits));
}
else if (TREE_CODE (offset) == MULT_EXPR
&& host_integerp (TREE_OPERAND (offset, 1), 1))
{
/* Any overflow in calculating offset_factor won't change
the alignment. */
unsigned offset_factor
= ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
* BITS_PER_UNIT);
if (offset_factor)
inner = MIN (inner, (offset_factor & -offset_factor));
}
else
{
inner = MIN (inner, BITS_PER_UNIT);
break;
}
offset = next_offset;
}
}
if (DECL_P (exp))
align = MIN (inner, DECL_ALIGN (exp));
#ifdef CONSTANT_ALIGNMENT
else if (CONSTANT_CLASS_P (exp))
align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
#endif
else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
|| TREE_CODE (exp) == INDIRECT_REF)
align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
else
align = MIN (align, inner);
return MIN (align, max_align);
}
/* Return the alignment in bits of EXP, a pointer valued expression.
But don't return more than MAX_ALIGN no matter what.
The alignment returned is, by default, the alignment of the thing that
@ -306,59 +382,7 @@ get_pointer_alignment (tree exp, unsigned int max_align)
case ADDR_EXPR:
/* See what we are pointing at and look at its alignment. */
exp = TREE_OPERAND (exp, 0);
inner = max_align;
if (handled_component_p (exp))
{
HOST_WIDE_INT bitsize, bitpos;
tree offset;
enum machine_mode mode;
int unsignedp, volatilep;
exp = get_inner_reference (exp, &bitsize, &bitpos, &offset,
&mode, &unsignedp, &volatilep, true);
if (bitpos)
inner = MIN (inner, (unsigned) (bitpos & -bitpos));
if (offset && TREE_CODE (offset) == PLUS_EXPR
&& host_integerp (TREE_OPERAND (offset, 1), 1))
{
/* Any overflow in calculating offset_bits won't change
the alignment. */
unsigned offset_bits
= ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
* BITS_PER_UNIT);
if (offset_bits)
inner = MIN (inner, (offset_bits & -offset_bits));
offset = TREE_OPERAND (offset, 0);
}
if (offset && TREE_CODE (offset) == MULT_EXPR
&& host_integerp (TREE_OPERAND (offset, 1), 1))
{
/* Any overflow in calculating offset_factor won't change
the alignment. */
unsigned offset_factor
= ((unsigned) tree_low_cst (TREE_OPERAND (offset, 1), 1)
* BITS_PER_UNIT);
if (offset_factor)
inner = MIN (inner, (offset_factor & -offset_factor));
}
else if (offset)
inner = MIN (inner, BITS_PER_UNIT);
}
if (DECL_P (exp))
align = MIN (inner, DECL_ALIGN (exp));
#ifdef CONSTANT_ALIGNMENT
else if (CONSTANT_CLASS_P (exp))
align = MIN (inner, (unsigned)CONSTANT_ALIGNMENT (exp, align));
#endif
else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR
|| TREE_CODE (exp) == INDIRECT_REF)
align = MIN (TYPE_ALIGN (TREE_TYPE (exp)), inner);
else
align = MIN (align, inner);
return MIN (align, max_align);
return get_object_alignment (TREE_OPERAND (exp, 0), align, max_align);
default:
return align;

View file

@ -1564,6 +1564,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
if (! TYPE_P (t))
{
tree base;
bool align_computed = false;
if (TREE_THIS_VOLATILE (t))
MEM_VOLATILE_P (ref) = 1;
@ -1620,6 +1621,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
&& host_integerp (DECL_SIZE_UNIT (t), 1)
? GEN_INT (tree_low_cst (DECL_SIZE_UNIT (t), 1)) : 0);
align = DECL_ALIGN (t);
align_computed = true;
}
/* If this is a constant, we know the alignment. */
@ -1629,6 +1631,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
#ifdef CONSTANT_ALIGNMENT
align = CONSTANT_ALIGNMENT (t, align);
#endif
align_computed = true;
}
/* If this is a field reference and not a bit-field, record it. */
@ -1688,6 +1691,7 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
align = DECL_ALIGN (t2);
if (aoff && (unsigned HOST_WIDE_INT) aoff < align)
align = aoff;
align_computed = true;
offset = GEN_INT (ioff);
apply_bitpos = bitpos;
}
@ -1721,6 +1725,13 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
expr = t;
offset = NULL;
}
if (!align_computed && !INDIRECT_REF_P (t))
{
unsigned int obj_align
= get_object_alignment (t, align, BIGGEST_ALIGNMENT);
align = MAX (align, obj_align);
}
}
/* If we modified OFFSET based on T, then subtract the outstanding

View file

@ -4864,6 +4864,7 @@ extern tree build_string_literal (int, const char *);
extern bool validate_arglist (const_tree, ...);
extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
extern int get_pointer_alignment (tree, unsigned int);
extern int get_object_alignment (tree, unsigned int, unsigned int);
extern tree fold_call_stmt (gimple, bool);
extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);