From 78f6dd686219c887085d40b3dacfb7f1a96aad95 Mon Sep 17 00:00:00 2001 From: Martin Jambor Date: Tue, 6 Aug 2013 11:22:16 +0200 Subject: [PATCH] re PR middle-end/58041 (Unaligned access to arrays in packed structure) 2013-08-06 Martin Jambor PR middle-end/58041 * gimple-ssa-strength-reduction.c (replace_ref): Make sure built MEM_REF has proper alignment information. testsuite/ * gcc.dg/torture/pr58041.c: New test. * gcc.target/arm/pr58041.c: Likewise. From-SVN: r201523 --- gcc/ChangeLog | 6 +++++ gcc/gimple-ssa-strength-reduction.c | 22 ++++++++++++---- gcc/testsuite/ChangeLog | 6 +++++ gcc/testsuite/gcc.dg/torture/pr58041.c | 35 ++++++++++++++++++++++++++ gcc/testsuite/gcc.target/arm/pr58041.c | 30 ++++++++++++++++++++++ 5 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr58041.c create mode 100644 gcc/testsuite/gcc.target/arm/pr58041.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 394da1348b2..6274c8bd564 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2013-08-06 Martin Jambor + + PR middle-end/58041 + * gimple-ssa-strength-reduction.c (replace_ref): Make sure built + MEM_REF has proper alignment information. + 2013-08-05 Oleg Endo PR other/12081 diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c index c6f305c35ea..e85e6293db4 100644 --- a/gcc/gimple-ssa-strength-reduction.c +++ b/gcc/gimple-ssa-strength-reduction.c @@ -1728,11 +1728,23 @@ dump_incr_vec (void) static void replace_ref (tree *expr, slsr_cand_t c) { - tree add_expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (c->base_expr), - c->base_expr, c->stride); - tree mem_ref = fold_build2 (MEM_REF, TREE_TYPE (*expr), add_expr, - double_int_to_tree (c->cand_type, c->index)); - + tree add_expr, mem_ref, acc_type = TREE_TYPE (*expr); + unsigned HOST_WIDE_INT misalign; + unsigned align; + + /* Ensure the memory reference carries the minimum alignment + requirement for the data type. See PR58041. */ + get_object_alignment_1 (*expr, &align, &misalign); + if (misalign != 0) + align = (misalign & -misalign); + if (align < TYPE_ALIGN (acc_type)) + acc_type = build_aligned_type (acc_type, align); + + add_expr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (c->base_expr), + c->base_expr, c->stride); + mem_ref = fold_build2 (MEM_REF, acc_type, add_expr, + double_int_to_tree (c->cand_type, c->index)); + /* Gimplify the base addressing expression for the new MEM_REF tree. */ gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt); TREE_OPERAND (mem_ref, 0) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e8ac8604c76..790c5568cdc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2013-08-06 Martin Jambor + + PR middle-end/58041 + * gcc.dg/torture/pr58041.c: New test. + * gcc.target/arm/pr58041.c: Likewise. + 2013-08-06 Janus Weil PR fortran/57306 diff --git a/gcc/testsuite/gcc.dg/torture/pr58041.c b/gcc/testsuite/gcc.dg/torture/pr58041.c new file mode 100644 index 00000000000..e22ec3c86ab --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr58041.c @@ -0,0 +1,35 @@ +/* { dg-do run } */ + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V v; } P __attribute__((aligned (1))); + +struct s +{ + char u; + V v[2]; +} __attribute__((packed,aligned(1))); + +__attribute__((noinline, noclone)) +long long foo(struct s *x, int y, V z) +{ + V a = x->v[y]; + x->v[y] = z; + return a[1]; +} + +struct s a = {0,{0,0}}; +int main() +{ + V v1 = {0,1}; + V v2 = {0,2}; + + if (foo(&a,0,v1) != 0) + __builtin_abort(); + if (foo(&a,0,v2) != 1) + __builtin_abort(); + if (foo(&a,1,v1) != 0) + __builtin_abort(); + return 0; +} diff --git a/gcc/testsuite/gcc.target/arm/pr58041.c b/gcc/testsuite/gcc.target/arm/pr58041.c new file mode 100644 index 00000000000..481a72b81c7 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr58041.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -mno-unaligned-access" } */ +/* { dg-final { scan-assembler "ldrb" } } */ +/* { dg-final { scan-assembler "strb" } } */ + +struct s +{ + char u; + long long v[2]; +} __attribute__((packed,aligned(1))); + +__attribute__((noinline, noclone)) +long long foo(struct s *x, int y, long long z) +{ + long long a = x->v[y]; + x->v[y] = z; + return a; +} + +struct s a = {0,{0,0}}; +int main() +{ + if (foo(&a,0,1) != 0) + __builtin_abort(); + if (foo(&a,0,2) != 1) + __builtin_abort(); + if (foo(&a,1,1) != 0) + __builtin_abort(); + return 0; +}