This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix up misaligned store expansion (PR middle-end/52419)


Hi!

This fixes misaligned store expansion if we aren't overwriting all bits
of the misaligned memory chunk to perform a RMW cycle.  Preapproved
by richi, bootstrapped/regtested on x86_64-linux and i686-linux,
committed to trunk.
For C++11/C11 memory model we probably will need some further improvements,
as a RMW cycle is not desirable in all cases (on the other side, with the
misaligned store we are probably already outside of the standards anyway).

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.

	* gcc.dg/torture/pr52419.c: New test.

--- gcc/expr.c.jj	2012-02-15 07:35:11.000000000 +0100
+++ gcc/expr.c	2012-02-29 15:46:36.377949543 +0100
@@ -4666,6 +4666,7 @@ expand_assignment (tree to, tree from, b
       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, b
 	  && ((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, b
       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);
--- gcc/testsuite/gcc.dg/torture/pr52419.c.jj	2012-02-29 15:47:47.510561267 +0100
+++ gcc/testsuite/gcc.dg/torture/pr52419.c	2012-02-29 15:47:54.881524082 +0100
@@ -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;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]