This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFA: fix an aliasing problem in cygwin prologues
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 30 Jul 2004 08:06:27 +0100
- Subject: RFA: fix an aliasing problem in cygwin prologues
If a cygwin function needs a large frame, its prologue will use
__alloca() to allocate it page-by-page. Since __alloca() takes the size
of the frame in eax, a regparm prologue must save eax before the call
and restore it afterwards.
Function foo() in the testcase below is one example of this. Although not
explicitly a regparm function, it's local to the compilation unit, so we
can use local arg-passing conventions for it. We then end up with the rtl
equivalent of:
push eax ; Save eax
eax = 0x10000
__alloca()
eax = esp[0x10000] ; Restore eax
ebp[-4] = edi ; Save edi
where &esp[0x10000] == &ebp[-4]. This falls foul of the assumption that
stack accesses based on the stack pointer don't alias those based on the
frame pointer. We therefore assume there's no alias between the last two
instructions and they get swapped at -O2.
The testcase is reduced from a miscompilation of expect. Many thanks to
Corinna for isolating the miscompiled function.
Patch bootstrapped & regression tested on i686-pc-cygwin. It fixes
the testcase and introduces no new failures. OK to install?
Richard
* config/i386/i386.c (ix86_expand_prologue): If the function uses a
frame pointer, restore eax with an ebp-relative address.
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.702
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.702 i386.c
*** config/i386/i386.c 27 Jul 2004 21:41:19 -0000 1.702
--- config/i386/i386.c 30 Jul 2004 07:04:07 -0000
*************** ix86_expand_prologue (void)
*** 5399,5405 ****
if (eax_live)
{
! rtx t = plus_constant (stack_pointer_rtx, allocate);
emit_move_insn (eax, gen_rtx_MEM (SImode, t));
}
}
--- 5399,5412 ----
if (eax_live)
{
! rtx t;
! if (frame_pointer_needed)
! t = plus_constant (hard_frame_pointer_rtx,
! allocate
! - frame.to_allocate
! - frame.nregs * UNITS_PER_WORD);
! else
! t = plus_constant (stack_pointer_rtx, allocate);
emit_move_insn (eax, gen_rtx_MEM (SImode, t));
}
}
*** /dev/null Fri Apr 23 00:21:55 2004
--- testsuite/gcc.c-torture/execute/20040729-1.c Fri Jul 30 08:03:19 2004
***************
*** 0 ****
--- 1,26 ----
+ int a[2] = { 2, 3 };
+
+ static int __attribute__((noinline))
+ bar (int x, void *b)
+ {
+ a[0]++;
+ return x;
+ }
+
+ static int __attribute__((noinline))
+ foo (int x)
+ {
+ char buf[0x10000];
+ int y = a[0];
+ a[1] = y;
+ x = bar (x, buf);
+ y = bar (y, buf);
+ return x + y;
+ }
+
+ int main ()
+ {
+ if (foo (100) != 102)
+ abort ();
+ exit (0);
+ }