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]

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);
+ }


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