Commit 908b9519 by Eric Botcazou Committed by Eric Botcazou

re PR tree-optimization/51315 (unaligned memory accesses generated with -ftree-sra)

	PR tree-optimization/51315
	* tree.h (get_object_or_type_alignment): Declare.
	* expr.c (get_object_or_type_alignment): Move to...
	* builtins.c (get_object_or_type_alignment): ...here.  Add assertion.
	* tree-sra.c (tree_non_mode_aligned_mem_p): Rename to...
	(tree_non_aligned_mem_p): ...this.  Add ALIGN parameter.  Look into
	MEM_REFs and use get_object_or_type_alignment for them.
	(build_accesses_from_assign): Adjust for above change.
	(access_precludes_ipa_sra_p): Likewise.

From-SVN: r182102
parent c37257a1
2011-12-08 Eric Botcazou <ebotcazou@adacore.com>
PR tree-optimization/51315
* tree.h (get_object_or_type_alignment): Declare.
* expr.c (get_object_or_type_alignment): Move to...
* builtins.c (get_object_or_type_alignment): ...here. Add assertion.
* tree-sra.c (tree_non_mode_aligned_mem_p): Rename to...
(tree_non_aligned_mem_p): ...this. Add ALIGN parameter. Look into
MEM_REFs and use get_object_or_type_alignment for them.
(build_accesses_from_assign): Adjust for above change.
(access_precludes_ipa_sra_p): Likewise.
2011-12-08 Richard Guenther <rguenther@suse.de>
PR lto/48437
......@@ -452,6 +452,31 @@ get_object_alignment (tree exp)
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 = get_object_alignment_1 (exp, &misalign);
gcc_assert (TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF);
if (misalign != 0)
align = (misalign & -misalign);
else
align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
return align;
}
/* Return the alignment in bits of EXP, a pointer valued expression.
The alignment returned is, by default, the alignment of the thing that
EXP points to. If it is not a POINTER_TYPE, 0 is returned.
......
......@@ -4544,27 +4544,6 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
}
}
/* Return the alignment of the object EXP, also considering its type
when we do not know of explicit misalignment.
??? 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 the alignment of the
type when we cannot compute a misalignment. */
static unsigned int
get_object_or_type_alignment (tree exp)
{
unsigned HOST_WIDE_INT misalign;
unsigned int align = get_object_alignment_1 (exp, &misalign);
if (misalign != 0)
align = (misalign & -misalign);
else
align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
return align;
}
/* Expand an assignment that stores the value of FROM into TO. If NONTEMPORAL
is true, try generating a nontemporal store. */
......
2011-12-08 Eric Botcazou <ebotcazou@adacore.com>
* gcc.c-torture/execute/20111208-1.c: New test.
2011-12-08 Richard Guenther <rguenther@suse.de>
PR lto/48437
......
/* PR tree-optimization/51315 */
/* Reported by Jurij Smakov <jurij@wooyd.org> */
typedef unsigned int size_t;
extern void *memcpy (void *__restrict __dest,
__const void *__restrict __src, size_t __n)
__attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2)));
extern size_t strlen (__const char *__s)
__attribute__ ((__nothrow__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
typedef short int int16_t;
typedef int int32_t;
extern void abort (void);
int a;
static void __attribute__ ((noinline,noclone))
do_something (int item)
{
a = item;
}
int
pack_unpack (char *s, char *p)
{
char *send, *pend;
char type;
int integer_size;
send = s + strlen (s);
pend = p + strlen (p);
while (p < pend)
{
type = *p++;
switch (type)
{
case 's':
integer_size = 2;
goto unpack_integer;
case 'l':
integer_size = 4;
goto unpack_integer;
unpack_integer:
switch (integer_size)
{
case 2:
{
union
{
int16_t i;
char a[sizeof (int16_t)];
}
v;
memcpy (v.a, s, sizeof (int16_t));
s += sizeof (int16_t);
do_something (v.i);
}
break;
case 4:
{
union
{
int32_t i;
char a[sizeof (int32_t)];
}
v;
memcpy (v.a, s, sizeof (int32_t));
s += sizeof (int32_t);
do_something (v.i);
}
break;
}
break;
}
}
return (int) *s;
}
int
main (void)
{
int n = pack_unpack ("\200\001\377\376\035\300", "sl");
if (n != 0)
abort ();
return 0;
}
......@@ -1067,26 +1067,29 @@ disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
return false;
}
/* Return true iff type of EXP is not sufficiently aligned. */
/* Return true if EXP is a memory reference less aligned than ALIGN. This is
invoked only on strict-alignment targets. */
static bool
tree_non_mode_aligned_mem_p (tree exp)
tree_non_aligned_mem_p (tree exp, unsigned int align)
{
enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
unsigned int align;
unsigned int exp_align;
if (TREE_CODE (exp) == VIEW_CONVERT_EXPR)
exp = TREE_OPERAND (exp, 0);
if (TREE_CODE (exp) == SSA_NAME
|| TREE_CODE (exp) == MEM_REF
|| mode == BLKmode
|| is_gimple_min_invariant (exp)
|| !STRICT_ALIGNMENT)
if (TREE_CODE (exp) == SSA_NAME || is_gimple_min_invariant (exp))
return false;
align = get_object_alignment (exp);
if (GET_MODE_ALIGNMENT (mode) > align)
/* get_object_alignment will fall back to BITS_PER_UNIT if it cannot
compute an explicit alignment. Pretend that dereferenced pointers
are always aligned on strict-alignment targets. */
if (TREE_CODE (exp) == MEM_REF || TREE_CODE (exp) == TARGET_MEM_REF)
exp_align = get_object_or_type_alignment (exp);
else
exp_align = get_object_alignment (exp);
if (exp_align < align)
return true;
return false;
......@@ -1120,7 +1123,9 @@ build_accesses_from_assign (gimple stmt)
if (lacc)
{
lacc->grp_assignment_write = 1;
lacc->grp_unscalarizable_region |= tree_non_mode_aligned_mem_p (rhs);
if (STRICT_ALIGNMENT
&& tree_non_aligned_mem_p (rhs, get_object_alignment (lhs)))
lacc->grp_unscalarizable_region = 1;
}
if (racc)
......@@ -1129,7 +1134,9 @@ build_accesses_from_assign (gimple stmt)
if (should_scalarize_away_bitmap && !gimple_has_volatile_ops (stmt)
&& !is_gimple_reg_type (racc->type))
bitmap_set_bit (should_scalarize_away_bitmap, DECL_UID (racc->base));
racc->grp_unscalarizable_region |= tree_non_mode_aligned_mem_p (lhs);
if (STRICT_ALIGNMENT
&& tree_non_aligned_mem_p (lhs, get_object_alignment (rhs)))
racc->grp_unscalarizable_region = 1;
}
if (lacc && racc
......@@ -3705,7 +3712,8 @@ access_precludes_ipa_sra_p (struct access *access)
|| gimple_code (access->stmt) == GIMPLE_ASM))
return true;
if (tree_non_mode_aligned_mem_p (access->expr))
if (STRICT_ALIGNMENT
&& tree_non_aligned_mem_p (access->expr, TYPE_ALIGN (access->type)))
return true;
return false;
......
......@@ -5457,6 +5457,7 @@ extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode);
extern bool is_builtin_fn (tree);
extern unsigned int get_object_alignment_1 (tree, unsigned HOST_WIDE_INT *);
extern unsigned int get_object_alignment (tree);
extern unsigned int get_object_or_type_alignment (tree);
extern unsigned int get_pointer_alignment (tree);
extern tree fold_call_stmt (gimple, bool);
extern tree gimple_fold_builtin_snprintf_chk (gimple, tree, enum built_in_function);
......
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