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 assign_parm_setup_stack on big-endian (PR target/40668)


Hi!

assign_parm_setup_stack if promoted mode is different from nominal mode
changes stack_parm using adjust_address to the different mode (i.e. the same
location for the low bits on little endian, but different on big endian),
but doesn't adjust MEM_OFFSET if any.  For PARM_DECLs which have smaller
mode, promoted to larger one, where assign_parm_find_stack_rtl adjusts
MEM_OFFSET accordingly (in this case to x+-4) assign_parm_setup_stack
needs to adjust it again when changing data->stack_parm.

Without this the parameter remains MEM_OFFSET -4, but when get_memory_rtx
is called on &x during memcpy expansion, it sets MEM_OFFSET to 0 and thus
aliasing code thinks the store of the parameter can't alias the loads from
that location.

Mikael Pettersson said in bugzilla he has bootstrapped/regtested this patch
on sparc64-linux and tested with Linux kernel as well.

Ok for trunk/4.4?

2009-07-08  Jakub Jelinek  <jakub@redhat.com>

	PR target/40668
	* function.c (assign_parm_setup_stack): Adjust
	MEM_OFFSET (data->stack_parm) if promoted_mode is different
	from nominal_mode on big endian.

	* gcc.c-torture/execute/pr40668.c: New test.

--- gcc/function.c.jj	2009-04-24 21:41:31.000000000 +0200
+++ gcc/function.c	2009-07-07 20:55:09.000000000 +0200
@@ -2977,9 +2977,17 @@ assign_parm_setup_stack (struct assign_p
 					  TYPE_UNSIGNED (TREE_TYPE (parm)));
 
       if (data->stack_parm)
-	/* ??? This may need a big-endian conversion on sparc64.  */
-	data->stack_parm
-	  = adjust_address (data->stack_parm, data->nominal_mode, 0);
+	{
+	  int offset = subreg_lowpart_offset (data->nominal_mode,
+					      GET_MODE (data->stack_parm));
+	  /* ??? This may need a big-endian conversion on sparc64.  */
+	  data->stack_parm
+	    = adjust_address (data->stack_parm, data->nominal_mode, 0);
+	  if (offset && MEM_OFFSET (data->stack_parm))
+	    set_mem_offset (data->stack_parm,
+			    plus_constant (MEM_OFFSET (data->stack_parm),
+					   offset));
+	}
     }
 
   if (data->entry_parm != data->stack_parm)
--- gcc/testsuite/gcc.c-torture/execute/pr40668.c.jj	2009-07-07 20:59:20.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr40668.c	2009-07-07 20:58:17.000000000 +0200
@@ -0,0 +1,35 @@
+static void
+foo (unsigned int x, void *p)
+{
+  __builtin_memcpy (p, &x, sizeof x);
+}
+
+void
+bar (int type, void *number)
+{
+  switch (type)
+    {
+    case 1:
+      foo (0x12345678, number);
+      break;
+    case 7:
+      foo (0, number);
+      break;
+    case 8:
+      foo (0, number);
+      break;
+    case 9:
+      foo (0, number);
+      break;
+    }
+}
+
+int
+main (void)
+{
+  unsigned int x;
+  bar (1, &x);
+  if (x != 0x12345678)
+    __builtin_abort ();
+  return 0;
+}

	Jakub


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