Commit b0f4a35f by Richard Guenther Committed by Richard Biener

tree.h (get_object_or_type_alignment): Remove.

2012-07-18  Richard Guenther  <rguenther@suse.de>

	* tree.h (get_object_or_type_alignment): Remove.
	* builtins.c (get_object_alignment_2): New function copied from
	get_object_alignment_1.  Take extra argument to indicate whether
	we take the address of EXP.  Rework to use type alignment information
	if not, and return whether the result is an approximation or not.
	(get_object_alignment_1): Wrap around get_object_alignment_2.
	(get_pointer_alignment_1): Call get_object_alignment_2 indicating
	we take the address.
	(get_object_or_type_alignment): Remove.
	* expr.c (expand_assignment): Call get_object_alignment.
	(expand_expr_real_1): Likewise.

From-SVN: r189607
parent dad57b68
2012-07-18 Richard Guenther <rguenther@suse.de>
* tree.h (get_object_or_type_alignment): Remove.
* builtins.c (get_object_alignment_2): New function copied from
get_object_alignment_1. Take extra argument to indicate whether
we take the address of EXP. Rework to use type alignment information
if not, and return whether the result is an approximation or not.
(get_object_alignment_1): Wrap around get_object_alignment_2.
(get_pointer_alignment_1): Call get_object_alignment_2 indicating
we take the address.
(get_object_or_type_alignment): Remove.
* expr.c (expand_assignment): Call get_object_alignment.
(expand_expr_real_1): Likewise.
2012-07-18 Nick Clifton <nickc@redhat.com> 2012-07-18 Nick Clifton <nickc@redhat.com>
* doc/invoke.texi (ARM Options): Document -munaligned-access. * doc/invoke.texi (ARM Options): Document -munaligned-access.
......
...@@ -273,11 +273,14 @@ called_as_built_in (tree node) ...@@ -273,11 +273,14 @@ called_as_built_in (tree node)
on the address at which an object is actually located. These two on the address at which an object is actually located. These two
addresses are not always the same. For example, on ARM targets, addresses are not always the same. For example, on ARM targets,
the address &foo of a Thumb function foo() has the lowest bit set, the address &foo of a Thumb function foo() has the lowest bit set,
whereas foo() itself starts on an even address. */ whereas foo() itself starts on an even address.
bool If ADDR_P is true we are taking the address of the memory reference EXP
get_object_alignment_1 (tree exp, unsigned int *alignp, and thus cannot rely on the access taking place. */
unsigned HOST_WIDE_INT *bitposp)
static bool
get_object_alignment_2 (tree exp, unsigned int *alignp,
unsigned HOST_WIDE_INT *bitposp, bool addr_p)
{ {
HOST_WIDE_INT bitsize, bitpos; HOST_WIDE_INT bitsize, bitpos;
tree offset; tree offset;
...@@ -293,48 +296,40 @@ get_object_alignment_1 (tree exp, unsigned int *alignp, ...@@ -293,48 +296,40 @@ get_object_alignment_1 (tree exp, unsigned int *alignp,
/* Extract alignment information from the innermost object and /* Extract alignment information from the innermost object and
possibly adjust bitpos and offset. */ possibly adjust bitpos and offset. */
if (TREE_CODE (exp) == CONST_DECL) if (TREE_CODE (exp) == FUNCTION_DECL)
exp = DECL_INITIAL (exp); {
if (DECL_P (exp) /* Function addresses can encode extra information besides their
&& TREE_CODE (exp) != LABEL_DECL) alignment. However, if TARGET_PTRMEMFUNC_VBIT_LOCATION
{ allows the low bit to be used as a virtual bit, we know
if (TREE_CODE (exp) == FUNCTION_DECL) that the address itself must be at least 2-byte aligned. */
{ if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
/* Function addresses can encode extra information besides their align = 2 * BITS_PER_UNIT;
alignment. However, if TARGET_PTRMEMFUNC_VBIT_LOCATION
allows the low bit to be used as a virtual bit, we know
that the address itself must be 2-byte aligned. */
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn)
{
known_alignment = true;
align = 2 * BITS_PER_UNIT;
}
}
else
{
known_alignment = true;
align = DECL_ALIGN (exp);
}
} }
else if (CONSTANT_CLASS_P (exp)) else if (TREE_CODE (exp) == LABEL_DECL)
;
else if (TREE_CODE (exp) == CONST_DECL)
{ {
known_alignment = true; /* The alignment of a CONST_DECL is determined by its initializer. */
exp = DECL_INITIAL (exp);
align = TYPE_ALIGN (TREE_TYPE (exp)); align = TYPE_ALIGN (TREE_TYPE (exp));
#ifdef CONSTANT_ALIGNMENT #ifdef CONSTANT_ALIGNMENT
align = (unsigned)CONSTANT_ALIGNMENT (exp, align); if (CONSTANT_CLASS_P (exp))
align = (unsigned) CONSTANT_ALIGNMENT (exp, align);
#endif #endif
known_alignment = true;
} }
else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR) else if (DECL_P (exp))
{ {
align = DECL_ALIGN (exp);
known_alignment = true; known_alignment = true;
align = TYPE_ALIGN (TREE_TYPE (exp));
} }
else if (TREE_CODE (exp) == INDIRECT_REF) else if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
{ {
known_alignment = true;
align = TYPE_ALIGN (TREE_TYPE (exp)); align = TYPE_ALIGN (TREE_TYPE (exp));
} }
else if (TREE_CODE (exp) == MEM_REF) else if (TREE_CODE (exp) == INDIRECT_REF
|| TREE_CODE (exp) == MEM_REF
|| TREE_CODE (exp) == TARGET_MEM_REF)
{ {
tree addr = TREE_OPERAND (exp, 0); tree addr = TREE_OPERAND (exp, 0);
unsigned ptr_align; unsigned ptr_align;
...@@ -343,58 +338,51 @@ get_object_alignment_1 (tree exp, unsigned int *alignp, ...@@ -343,58 +338,51 @@ get_object_alignment_1 (tree exp, unsigned int *alignp,
if (TREE_CODE (addr) == BIT_AND_EXPR if (TREE_CODE (addr) == BIT_AND_EXPR
&& TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST) && TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST)
{ {
known_alignment = true;
align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)) align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
& -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))); & -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
align *= BITS_PER_UNIT; align *= BITS_PER_UNIT;
addr = TREE_OPERAND (addr, 0); addr = TREE_OPERAND (addr, 0);
} }
if (get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos)) known_alignment
= get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos);
bitpos += ptr_bitpos;
align = MAX (ptr_align, align);
if (TREE_CODE (exp) == MEM_REF
|| TREE_CODE (exp) == TARGET_MEM_REF)
bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT;
if (TREE_CODE (exp) == TARGET_MEM_REF)
{ {
known_alignment = true; if (TMR_INDEX (exp))
bitpos += ptr_bitpos & ~(align - 1); {
align = MAX (ptr_align, align); unsigned HOST_WIDE_INT step = 1;
if (TMR_STEP (exp))
step = TREE_INT_CST_LOW (TMR_STEP (exp));
align = MIN (align, (step & -step) * BITS_PER_UNIT);
}
if (TMR_INDEX2 (exp))
align = BITS_PER_UNIT;
known_alignment = false;
} }
bitpos += mem_ref_offset (exp).low * BITS_PER_UNIT; /* When EXP is an actual memory reference then we can use
TYPE_ALIGN of a pointer indirection to derive alignment.
Do so only if get_pointer_alignment_1 did not reveal absolute
alignment knowledge. */
if (!addr_p && !known_alignment)
align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
} }
else if (TREE_CODE (exp) == TARGET_MEM_REF) else if (TREE_CODE (exp) == STRING_CST)
{ {
unsigned ptr_align; /* STRING_CST are the only constant objects we allow to be not
unsigned HOST_WIDE_INT ptr_bitpos; wrapped inside a CONST_DECL. */
tree addr = TMR_BASE (exp); align = TYPE_ALIGN (TREE_TYPE (exp));
#ifdef CONSTANT_ALIGNMENT
if (TREE_CODE (addr) == BIT_AND_EXPR if (CONSTANT_CLASS_P (exp))
&& TREE_CODE (TREE_OPERAND (addr, 1)) == INTEGER_CST) align = (unsigned) CONSTANT_ALIGNMENT (exp, align);
{ #endif
known_alignment = true; known_alignment = true;
align = (TREE_INT_CST_LOW (TREE_OPERAND (addr, 1))
& -TREE_INT_CST_LOW (TREE_OPERAND (addr, 1)));
align *= BITS_PER_UNIT;
addr = TREE_OPERAND (addr, 0);
}
if (get_pointer_alignment_1 (addr, &ptr_align, &ptr_bitpos))
{
known_alignment = true;
bitpos += ptr_bitpos & ~(align - 1);
align = MAX (ptr_align, align);
}
if (TMR_OFFSET (exp))
bitpos += TREE_INT_CST_LOW (TMR_OFFSET (exp)) * BITS_PER_UNIT;
if (TMR_INDEX (exp) && TMR_STEP (exp))
{
unsigned HOST_WIDE_INT step = TREE_INT_CST_LOW (TMR_STEP (exp));
align = MIN (align, (step & -step) * BITS_PER_UNIT);
known_alignment = true;
}
else if (TMR_INDEX (exp))
known_alignment = false;
if (TMR_INDEX2 (exp))
known_alignment = false;
} }
/* If there is a non-constant offset part extract the maximum /* If there is a non-constant offset part extract the maximum
...@@ -435,29 +423,32 @@ get_object_alignment_1 (tree exp, unsigned int *alignp, ...@@ -435,29 +423,32 @@ get_object_alignment_1 (tree exp, unsigned int *alignp,
} }
else else
{ {
known_alignment = false; inner = MIN (inner, BITS_PER_UNIT);
break; break;
} }
offset = next_offset; offset = next_offset;
} }
/* Alignment is innermost object alignment adjusted by the constant
and non-constant offset parts. */
align = MIN (align, inner);
if (known_alignment) *alignp = align;
{ *bitposp = bitpos & (*alignp - 1);
/* Alignment is innermost object alignment adjusted by the constant
and non-constant offset parts. */
align = MIN (align, inner);
bitpos = bitpos & (align - 1);
*alignp = align;
}
else
{
bitpos = bitpos & (BITS_PER_UNIT - 1);
*alignp = BITS_PER_UNIT;
}
*bitposp = bitpos;
return known_alignment; return known_alignment;
} }
/* For a memory reference expression EXP compute values M and N such that M
divides (&EXP - N) and such that N < M. If these numbers can be determined,
store M in alignp and N in *BITPOSP and return true. Otherwise return false
and store BITS_PER_UNIT to *alignp and any bit-offset to *bitposp. */
bool
get_object_alignment_1 (tree exp, unsigned int *alignp,
unsigned HOST_WIDE_INT *bitposp)
{
return get_object_alignment_2 (exp, alignp, bitposp, false);
}
/* Return the alignment in bits of EXP, an object. */ /* Return the alignment in bits of EXP, an object. */
unsigned int unsigned int
...@@ -476,36 +467,10 @@ get_object_alignment (tree exp) ...@@ -476,36 +467,10 @@ get_object_alignment (tree exp)
return align; return align;
} }
/* Return the alignment of object EXP, also considering its type when we do
not know of explicit misalignment. Only handle MEM_REF and TARGET_MEM_REF.
??? Note that, in the general case, the type of an expression is not kept
consistent with misalignment information by the front-end, for example when
taking the address of a member of a packed structure. However, in most of
the cases, expressions have the alignment of their type so we optimistically
fall back to this alignment when we cannot compute a misalignment. */
unsigned int
get_object_or_type_alignment (tree exp)
{
unsigned HOST_WIDE_INT misalign;
unsigned int align;
bool known_alignment;
gcc_assert (TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF);
known_alignment = get_object_alignment_1 (exp, &align, &misalign);
if (misalign != 0)
align = (misalign & -misalign);
else if (!known_alignment)
align = TYPE_ALIGN (TREE_TYPE (exp));
return align;
}
/* For a pointer valued expression EXP compute values M and N such that M /* For a pointer valued expression EXP compute values M and N such that M
divides (EXP - N) and such that N < M. If these numbers can be determined, divides (EXP - N) and such that N < M. If these numbers can be determined,
store M in alignp and N in *BITPOSP and return true. Otherwise return false store M in alignp and N in *BITPOSP and return true. Return false if
and store BITS_PER_UNIT to *alignp and any bit-offset to *bitposp. the results are just a conservative approximation.
If EXP is not a pointer, false is returned too. */ If EXP is not a pointer, false is returned too. */
...@@ -516,7 +481,8 @@ get_pointer_alignment_1 (tree exp, unsigned int *alignp, ...@@ -516,7 +481,8 @@ get_pointer_alignment_1 (tree exp, unsigned int *alignp,
STRIP_NOPS (exp); STRIP_NOPS (exp);
if (TREE_CODE (exp) == ADDR_EXPR) if (TREE_CODE (exp) == ADDR_EXPR)
return get_object_alignment_1 (TREE_OPERAND (exp, 0), alignp, bitposp); return get_object_alignment_2 (TREE_OPERAND (exp, 0),
alignp, bitposp, true);
else if (TREE_CODE (exp) == SSA_NAME else if (TREE_CODE (exp) == SSA_NAME
&& POINTER_TYPE_P (TREE_TYPE (exp))) && POINTER_TYPE_P (TREE_TYPE (exp)))
{ {
...@@ -527,6 +493,7 @@ get_pointer_alignment_1 (tree exp, unsigned int *alignp, ...@@ -527,6 +493,7 @@ get_pointer_alignment_1 (tree exp, unsigned int *alignp,
{ {
*bitposp = ptr_misalign * BITS_PER_UNIT; *bitposp = ptr_misalign * BITS_PER_UNIT;
*alignp = ptr_align * BITS_PER_UNIT; *alignp = ptr_align * BITS_PER_UNIT;
/* We cannot really tell whether this result is an approximation. */
return true; return true;
} }
else else
......
...@@ -4590,7 +4590,7 @@ expand_assignment (tree to, tree from, bool nontemporal) ...@@ -4590,7 +4590,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
|| TREE_CODE (to) == TARGET_MEM_REF) || TREE_CODE (to) == TARGET_MEM_REF)
&& mode != BLKmode && mode != BLKmode
&& !mem_ref_refers_to_non_mem_p (to) && !mem_ref_refers_to_non_mem_p (to)
&& ((align = get_object_or_type_alignment (to)) && ((align = get_object_alignment (to))
< GET_MODE_ALIGNMENT (mode)) < GET_MODE_ALIGNMENT (mode))
&& (((icode = optab_handler (movmisalign_optab, mode)) && (((icode = optab_handler (movmisalign_optab, mode))
!= CODE_FOR_nothing) != CODE_FOR_nothing)
...@@ -4652,7 +4652,7 @@ expand_assignment (tree to, tree from, bool nontemporal) ...@@ -4652,7 +4652,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
mode = TYPE_MODE (TREE_TYPE (tem)); mode = TYPE_MODE (TREE_TYPE (tem));
if (TREE_CODE (tem) == MEM_REF if (TREE_CODE (tem) == MEM_REF
&& mode != BLKmode && mode != BLKmode
&& ((align = get_object_or_type_alignment (tem)) && ((align = get_object_alignment (tem))
< GET_MODE_ALIGNMENT (mode)) < GET_MODE_ALIGNMENT (mode))
&& ((icode = optab_handler (movmisalign_optab, mode)) && ((icode = optab_handler (movmisalign_optab, mode))
!= CODE_FOR_nothing)) != CODE_FOR_nothing))
...@@ -9496,7 +9496,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -9496,7 +9496,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
temp = gen_rtx_MEM (mode, op0); temp = gen_rtx_MEM (mode, op0);
set_mem_attributes (temp, exp, 0); set_mem_attributes (temp, exp, 0);
set_mem_addr_space (temp, as); set_mem_addr_space (temp, as);
align = get_object_or_type_alignment (exp); align = get_object_alignment (exp);
if (modifier != EXPAND_WRITE if (modifier != EXPAND_WRITE
&& mode != BLKmode && mode != BLKmode
&& align < GET_MODE_ALIGNMENT (mode) && align < GET_MODE_ALIGNMENT (mode)
...@@ -9570,7 +9570,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -9570,7 +9570,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
gimple_assign_rhs1 (def_stmt), mask); gimple_assign_rhs1 (def_stmt), mask);
TREE_OPERAND (exp, 0) = base; TREE_OPERAND (exp, 0) = base;
} }
align = get_object_or_type_alignment (exp); align = get_object_alignment (exp);
op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM); op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
op0 = memory_address_addr_space (address_mode, op0, as); op0 = memory_address_addr_space (address_mode, op0, as);
if (!integer_zerop (TREE_OPERAND (exp, 1))) if (!integer_zerop (TREE_OPERAND (exp, 1)))
......
...@@ -5485,7 +5485,6 @@ extern bool is_builtin_fn (tree); ...@@ -5485,7 +5485,6 @@ extern bool is_builtin_fn (tree);
extern bool get_object_alignment_1 (tree, unsigned int *, extern bool get_object_alignment_1 (tree, unsigned int *,
unsigned HOST_WIDE_INT *); unsigned HOST_WIDE_INT *);
extern unsigned int get_object_alignment (tree); extern unsigned int get_object_alignment (tree);
extern unsigned int get_object_or_type_alignment (tree);
extern bool get_pointer_alignment_1 (tree, unsigned int *, extern bool get_pointer_alignment_1 (tree, unsigned int *,
unsigned HOST_WIDE_INT *); unsigned HOST_WIDE_INT *);
extern unsigned int get_pointer_alignment (tree); extern unsigned int get_pointer_alignment (tree);
......
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