Bug 23775 - [4.1 Regression] wrong code in argument passing
Summary: [4.1 Regression] wrong code in argument passing
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.1.0
: P1 critical
Target Milestone: 4.1.0
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2005-09-08 02:31 UTC by snyder
Modified: 2005-11-16 21:32 UTC (History)
4 users (show)

See Also:
Host:
Target: i686-pc-linux-gnu
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-09-08 16:43:23


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description snyder 2005-09-08 02:31:29 UTC

On a i686 platform, the example below is miscompiled with -O1.
I expect this program to print -0.96.  Here's what it actually does:

$ g++ -O1 -o y y.cc
$ ./y
-1.288766
$ g++  -o y y.cc
$ ./y
-0.960000
$

The value that the optimized version prints is actually different
on each run of the program.

Here's the generated code for main(), 

.globl main
	.type	main, @function
main:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	movl	%ebx, -8(%ebp)
	movl	%esi, -4(%ebp)
	andl	$-16, %esp
	subl	$16, %esp
	movl	$0, 12(%esp)
	movl	8(%esp), %ebx    ; this seems to load ebx with garbage???
	movl	12(%esp), %esi
	fldz
	fstl	8(%esp)
	fstpl	(%esp)
	call	_Z8x_from_zdd
	fstpl	4(%esp)
	movl	%ebx, 8(%esp)    ; this clobbers half of the arg with
                                 ; the garbage
	movl	%esi, 12(%esp)
	movl	$0, (%esp)
	call	_Z17local_to_trflocalidi
	movl	$0, %eax
	movl	-8(%ebp), %ebx
	movl	-4(%ebp), %esi
	movl	%ebp, %esp
	popl	%ebp
	ret

It looks to me like the error occurs during RTL generation.
Here's the tree dump from the t87.final_cleanup file (slightly trimmed):

void local_to_trflocal(int, double, int) (D.1741, x_loc, D.1743)
{
<bb 0>:
  printf (&"%f\n"[0], x_loc);
  return;
}

double x_from_z(double, double) (pitch, stereo)
{
<bb 0>:
  return -9.59999999999999964472863211994990706443786621094e-1 / cos (stereo);
}

int main() ()
{
<bb 0>:
  local_to_trflocal (0, x_from_z (0.0, 0.0), 0);
  return 0;
}


But in the 00.expand file, here's the sequence leading
to the local_to_trflocal() call:

(insn 27 26 28 1 (set (mem/i:DF (plus:SI (reg/f:SI 56 virtual-outgoing-args)
                (const_int 4 [0x4])) [0 S8 A32])
        (reg:DF 71)) -1 (nil)
    (nil))

(insn 28 27 29 1 (set (mem:DI (plus:SI (reg/f:SI 56 virtual-outgoing-args)
                (const_int 8 [0x8])) [0 S8 A8])
        (reg:DI 68)) -1 (nil)
    (nil))

(insn 29 28 30 1 (set (mem:SI (reg/f:SI 56 virtual-outgoing-args) [0 S4 A32])
        (const_int 0 [0x0])) -1 (nil)
    (nil))

(call_insn 30 29 31 1 (call (mem:QI (symbol_ref:SI ("_Z17local_to_trflocalidi") [flags 0x3] <function_decl 0xb7f0df80 local_to_trflocal>) [0 S1 A8])
        (const_int 16 [0x10])) -1 (nil)
    (nil)
    (nil))


Reg 71 here is the return value from x_from_z.
I don't know where the DI store to v-o-a+8 is coming from...

Environment:
System: Linux karma 2.6.12.1sss #2 Thu Jul 7 00:28:21 EDT 2005 i686 i686 i386 GNU/Linux
Architecture: i686

	<machine, os, target, libraries (multiple lines)>
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: /home/sss/gcc/gcc/configure --prefix=/usr/local/gcc --enable-threads=posix --enable-long-long --enable-languages=c,c++,f95

How-To-Repeat:

Compile with -O1

-----------------------------------------------------
//g++ -O1 -g -o y y.cc 

extern "C" double cos(double);
extern "C" int printf (...);


double x_from_z(double pitch=0, double stereo=0)
{
  return -0.96/cos(stereo);
}

void local_to_trflocal(int, double x_loc, int=0)
{
  printf ("%f\n", x_loc);
}


int main()
{
  local_to_trflocal(0, x_from_z());
  return 0;
}

-----------------------------------------------------
Comment 1 snyder 2005-09-08 02:31:29 UTC
Fix:
	<how to correct or work around the problem, if known (multiple lines)>
Comment 2 Andrew Pinski 2005-09-08 05:52:53 UTC
Confirmed.
Comment 3 Richard Biener 2005-09-08 09:08:03 UTC
Reduced testcase:

extern "C" double cos(double);
extern "C" void abort(void);

double x_from_z(double pitch=0, double stereo=0); // __attribute__((const));
double x_from_z(double pitch, double stereo)
{
  return 1.0/cos(stereo);
}

void local_to_trflocal(int, double x_loc, int=0)
{
  if (x_loc != 1.0)
    abort ();
}

int main()
{
  local_to_trflocal(0, x_from_z());
  return 0;
}

Code is ok if you declare x_from_z const.
Comment 4 Andrew Pinski 2005-09-08 12:46:10 UTC
And here is a C testcase:
double cos(double);
void abort(void);

double x_from_z(double pitch, double stereo); // __attribute__((const));
double x_from_z(double pitch, double stereo)
{
  return 1.0/cos(stereo);
}

void local_to_trflocal(int b, double x_loc, int a)
{
  if (x_loc != 1.0)
    abort ();
}

int main()
{
  local_to_trflocal(0, x_from_z(0,0),0);
  return 0;
}
Comment 5 Jakub Jelinek 2005-09-09 17:43:36 UTC
The difference between 4.0 and HEAD is the expr.c hunk of
http://gcc.gnu.org/ml/gcc-patches/2005-07/msg02021.html
If Paolo's reversion of that:
http://gcc.gnu.org/ml/gcc-patches/2005-09/msg00589.html
makes it in, the testcase will pass again.

The real problem is I think that when calls.c decides to save stack area
under an argument for the inner expand_call, but that argument partially overlaps
with the result of the call, we save/restore the argument with the inner
expand_call's argument mode and don't just limit to the actual bytes that
have already been initialized.  So we read some uninitialized bits from the
stack and overwrite with them the computed argument.
Comment 6 Andrew Pinski 2005-10-16 21:51:48 UTC
Any news on getting this fixed?
Comment 7 Pawel Sikora 2005-10-17 19:01:58 UTC
both testcases works for me 4.1.0-20051005.
i have applied patches for: PR7776, PR20297, PR22533, PR23948, PR19505, PR20606/PR24069.
Comment 8 Mark Mitchell 2005-10-31 05:41:57 UTC
Yup, this is a showstoppper.
Comment 9 Steven Bosscher 2005-11-03 21:00:09 UTC
Jakub, ping!
What's up with this one?
Comment 10 Steven Bosscher 2005-11-04 22:56:19 UTC
For the record, Jakub has apparently dropped this bug from his list to put this bug back into unassigned state.
Comment 11 Andrew Pinski 2005-11-16 21:32:17 UTC
And for the realy record this was fixed by the patch which fixed PR 24003 also.