mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
c37257a1f6
commit
908b951938
|
@ -1,3 +1,15 @@
|
|||
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.
|
||||
|
|
21
gcc/expr.c
21
gcc/expr.c
|
@ -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. */
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
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
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/* 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);
|
||||
|
|
Loading…
Reference in New Issue