This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix assign_parm_setup_stack on big-endian (PR target/40668)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 8 Jul 2009 21:07:27 +0200
- Subject: [PATCH] Fix assign_parm_setup_stack on big-endian (PR target/40668)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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