diff options
author | Jakub Jelinek <jakub@redhat.com> | 2012-02-29 18:45:55 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-02-29 18:45:55 +0100 |
commit | a3017cf147db82ad86e5a81b9677e8ca8e29ead2 (patch) | |
tree | 09361607593fdcf9bf322ea8635b1c004c6db317 /gcc | |
parent | 598e67d7a04954fe1d1652c4a7220977ab8b230f (diff) | |
download | gcc-a3017cf147db82ad86e5a81b9677e8ca8e29ead2.zip gcc-a3017cf147db82ad86e5a81b9677e8ca8e29ead2.tar.gz gcc-a3017cf147db82ad86e5a81b9677e8ca8e29ead2.tar.bz2 |
re PR middle-end/52419 (Wrong expansion of misaligned vector store)
PR middle-end/52419
* expr.c (expand_assignment): If doing misaligned store that doesn't
cover all mode bits, perform a RMW cycle.
* gcc.dg/torture/pr52419.c: New test.
From-SVN: r184666
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/expr.c | 57 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr52419.c | 32 |
4 files changed, 76 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8b2e26b..8de6c89 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,9 @@ 2012-02-29 Jakub Jelinek <jakub@redhat.com> + PR middle-end/52419 + * expr.c (expand_assignment): If doing misaligned store that doesn't + cover all mode bits, perform a RMW cycle. + PR tree-optimization/52429 * tree-parloops.c (separate_decls_in_region_debug): Return early if var is LABEL_DECL. @@ -4666,6 +4666,7 @@ expand_assignment (tree to, tree from, bool nontemporal) int volatilep = 0; tree tem; bool misalignp; + rtx mem = NULL_RTX; push_temp_slots (); tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1, @@ -4686,8 +4687,44 @@ expand_assignment (tree to, tree from, bool nontemporal) && ((icode = optab_handler (movmisalign_optab, mode)) != CODE_FOR_nothing)) { + enum machine_mode address_mode; + rtx op0; + struct expand_operand ops[2]; + addr_space_t as = TYPE_ADDR_SPACE + (TREE_TYPE (TREE_TYPE (TREE_OPERAND (tem, 0)))); + tree base = TREE_OPERAND (tem, 0); + misalignp = true; to_rtx = gen_reg_rtx (mode); + + address_mode = targetm.addr_space.address_mode (as); + op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_NORMAL); + op0 = convert_memory_address_addr_space (address_mode, op0, as); + if (!integer_zerop (TREE_OPERAND (tem, 1))) + { + rtx off = immed_double_int_const (mem_ref_offset (tem), + address_mode); + op0 = simplify_gen_binary (PLUS, address_mode, op0, off); + } + op0 = memory_address_addr_space (mode, op0, as); + mem = gen_rtx_MEM (mode, op0); + set_mem_attributes (mem, tem, 0); + set_mem_addr_space (mem, as); + if (TREE_THIS_VOLATILE (tem)) + MEM_VOLATILE_P (mem) = 1; + + /* If the misaligned store doesn't overwrite all bits, perform + rmw cycle on MEM. */ + if (bitsize != GET_MODE_BITSIZE (mode)) + { + create_input_operand (&ops[0], to_rtx, mode); + create_fixed_operand (&ops[1], mem); + /* The movmisalign<mode> pattern cannot fail, else the assignment + would silently be omitted. */ + expand_insn (icode, 2, ops); + + mem = copy_rtx (mem); + } } else { @@ -4842,26 +4879,6 @@ expand_assignment (tree to, tree from, bool nontemporal) if (misalignp) { struct expand_operand ops[2]; - enum machine_mode address_mode; - rtx op0, mem; - addr_space_t as = TYPE_ADDR_SPACE - (TREE_TYPE (TREE_TYPE (TREE_OPERAND (tem, 0)))); - tree base = TREE_OPERAND (tem, 0); - address_mode = targetm.addr_space.address_mode (as); - op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_NORMAL); - op0 = convert_memory_address_addr_space (address_mode, op0, as); - if (!integer_zerop (TREE_OPERAND (tem, 1))) - { - rtx off = immed_double_int_const (mem_ref_offset (tem), - address_mode); - op0 = simplify_gen_binary (PLUS, address_mode, op0, off); - } - op0 = memory_address_addr_space (mode, op0, as); - mem = gen_rtx_MEM (mode, op0); - set_mem_attributes (mem, tem, 0); - set_mem_addr_space (mem, as); - if (TREE_THIS_VOLATILE (tem)) - MEM_VOLATILE_P (mem) = 1; create_fixed_operand (&ops[0], mem); create_input_operand (&ops[1], to_rtx, mode); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7b1ad21..5826e28 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2012-02-29 Jakub Jelinek <jakub@redhat.com> + PR middle-end/52419 + * gcc.dg/torture/pr52419.c: New test. + PR tree-optimization/52429 * gcc.dg/torture/pr52429.c: New test. * g++.dg/opt/pr52429.C: New test. diff --git a/gcc/testsuite/gcc.dg/torture/pr52419.c b/gcc/testsuite/gcc.dg/torture/pr52419.c new file mode 100644 index 0000000..d24225a --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr52419.c @@ -0,0 +1,32 @@ +/* PR middle-end/52419 */ +/* { dg-do run } */ + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V b; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +__attribute__((noinline, noclone)) void +foo (P *p) +{ + p->b[1] = 5; +} + +int +main () +{ + V a = { 3, 4 }; + struct T t; + + t.s.b = a; + foo (&t.s); + + if (t.s.b[0] != 3 || t.s.b[1] != 5) + abort (); + + return 0; +} |