aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2012-02-29 18:45:55 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2012-02-29 18:45:55 +0100
commita3017cf147db82ad86e5a81b9677e8ca8e29ead2 (patch)
tree09361607593fdcf9bf322ea8635b1c004c6db317 /gcc
parent598e67d7a04954fe1d1652c4a7220977ab8b230f (diff)
downloadgcc-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/ChangeLog4
-rw-r--r--gcc/expr.c57
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr52419.c32
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.
diff --git a/gcc/expr.c b/gcc/expr.c
index 2e716cc..a3ace7a 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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;
+}