Bug 23453 - [4.0/4.1/4.2 regression] miscompilation of PARI/GP on x86 with gcse after reload
[4.0/4.1/4.2 regression] miscompilation of PARI/GP on x86 with gcse after reload
Status: RESOLVED DUPLICATE of bug 25196
Product: gcc
Classification: Unclassified
Component: rtl-optimization
4.0.2
: P2 critical
: 4.0.3
Assigned To: Not yet assigned to anyone
: wrong-code
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2005-08-18 07:25 UTC by Debian GCC Maintainers
Modified: 2005-12-20 16:11 UTC (History)
6 users (show)

See Also:
Host:
Target: i486-linux
Build:
Known to work: 3.4.4
Known to fail: 4.0.2 4.1.0
Last reconfirmed: 2005-10-13 20:55:16


Attachments
preprocessed source (53.20 KB, application/x-gzip)
2005-08-18 07:36 UTC, Debian GCC Maintainers
Details
testcase, part1 (948 bytes) (948 bytes, text/plain)
2005-08-18 21:08 UTC, Serge Belyshev
Details
testcase, part2 (3112 bytes) (3.04 KB, text/plain)
2005-08-18 21:14 UTC, Serge Belyshev
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Debian GCC Maintainers 2005-08-18 07:25:13 UTC
[forwarded from http://bugs.debian.org/309210]

rechecked with 4.0 CVS 20050816

wrong code for PARI/GP 2.2.10 on x86.
The pari source code can be found here:
<http://pari.math.u-bordeaux.fr/pub/pari/unstable/pari-2.2.10.alpha.tar.gz>

The problem is in the file src/basemath/alglin1.c, function ker0().

The compilation command used was:
gcc-4.0  -c -O3 -DGCC_INLINE -Wall -fno-strict-aliasing -fomit-frame-pointer
-DBOTH_GNUPLOT_AND_X11 -I. -I../src/headers  -o alglin1.o alglin1.i

using gcc-4.0 -O2 or gcc-3.4 -O3 generates correct code.

The problem can be reproduces running the gp interpreter:

1) download the tarball mentionned in the bug report and untar it
2) do 
CC=gcc-4.0 ./Configure
3) do 
make bench

One test-case fails (alglin).
Alternatively, you can do
make gp
./gp
matker([1,2;3,4])
  *** matker: bug in GP (Segmentation Fault), please report

More information about compiler options that fix this problem:
<http://pari.math.u-bordeaux.fr/archives/pari-dev-0505/msg00007.html>

> Can you make a stand-alone testcase?

Not at that time, unfortunately. The bug only occurs inside deeply inlined
code.
Comment 1 Debian GCC Maintainers 2005-08-18 07:36:10 UTC
Created attachment 9526 [details]
preprocessed source
Comment 2 Andrew Pinski 2005-08-18 12:05:32 UTC
We need at least a testcase which links.
Comment 3 Debian GCC Maintainers 2005-08-18 13:15:18 UTC
testcase at http://people.debian.org/~doko/tmp/tst.tar.bz2
Comment 4 Serge Belyshev 2005-08-18 21:08:19 UTC
Created attachment 9542 [details]
testcase, part1 (948 bytes)
Comment 5 Serge Belyshev 2005-08-18 21:14:47 UTC
Created attachment 9543 [details]
testcase, part2 (3112 bytes)

These two files are self-contained tescase for this bug, to compile use this
command:
gcc bug1.c bug2.c -O3 -fno-strict-aliasing -fomit-frame-pointer -march=i486

Seems that gcse2 miscompiles gauss_pivot_ker() from bug2.c, here is a diff
between code generated with -fno-gcse-after-reload and w/o that option:

	movl	$1, 100(%esp)
	movl	$0, 36(%esp)
-	.p2align 4,,15
-.L23:
	movl	100(%esp), %edi
+	movl	100(%esp), %ecx
	sall	$2, %edi
	pushl	$0
	pushl	$0
	pushl	$0
-	movl	100(%esp), %ecx
	movl	(%ecx,%edi), %ecx
	pushl	%ecx
	call	gauss_get_pivot_max

which is clearly wrong.
Comment 6 Serge Belyshev 2005-08-19 01:03:47 UTC
Single-file testcase, compile with "-march=i486 -O2 -fomit-frame-pointer
-fno-strict-aliasing -fgcse-after-reload":

bar ()
{
  exit (0);
}

baz (x)
{
  return x;
}

foo ()
{
  abort ();
}

ker0 (int *x0, int a) 
{
  int *x, *c, *d, p, av, i, j, k, r, t, n, m, *dd;
  n = x0;
  m = x0 [0];
  x = baz (x0);
  if (a) 
    {
      if (m)
	foo ();
      for (k = 1; k <= n; k ++)
	((int **) x) [k] = foo (x [k]);
    }
  for (k = 1; k < m; k ++) 
    c [k] = 0;
  av = k;
  for (k = 0;; k ++) 
    {
      j = bar (x [k], 0, 0, 0);
      if (j > m) 
	{
	  r ++;
	  for (j = 1; j < k; j ++)
	    if (d [j])
	      ((int **) x) [k] [d [j]] = 0;
	}
      else
	{
	  foo (0, x [j]);
	  for (i = k + 1; i; i ++)
	    ((int *) x) [j] = 0;
	  for (t = 1; m; )
	    if (j) 
	      {
		p = x [t];
		for (i = k + 1; i; i ++)
		  x [t] = foo (x [i], foo (p, x [j]));
		if (av)
		  foo (k);
	      }
	}
    }
  *dd = r;
}

int main (void)
{
  int x = 0;
  ker0 (&x, 0);
  abort ();
}
Comment 7 Serge Belyshev 2005-08-19 19:51:17 UTC
gcse after reload may move loads from stack around stack pointer changes. here
is simple workaround, it is supposed to prevent gcse after reload from touching
expressions containing stack pointer at all.

Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.359
diff -u -r1.359 cse.c
--- cse.c	29 Jul 2005 05:57:37 -0000	1.359
+++ cse.c	19 Aug 2005 19:33:49 -0000
@@ -2221,6 +2221,14 @@
 		return 0;
 	      }
 	  }
+	else
+	  {
+	    if (x == stack_pointer_rtx)
+	      {
+		*do_not_record_p = 1;
+		return 0;
+	      }
+	  }
 
 	hash += ((unsigned int) REG << 7);
         hash += (have_reg_qty ? (unsigned) REG_QTY (regno) : regno);
Comment 8 Paolo Bonzini 2005-10-14 11:38:31 UTC
> gcse after reload may move loads from stack around stack pointer changes. here
> is simple workaround, it is supposed to prevent gcse after reload from touching
> expressions containing stack pointer at all.

Off the top of my head, if GCSE-after-reload is designed to remove redundant spills, will it do *anything* with your patch?
Comment 9 Mark Mitchell 2005-10-31 05:09:08 UTC
Leaving as P2.
Comment 10 Steven Bosscher 2005-11-05 10:48:11 UTC
This doesn't fail for me with the test case from comment #6...  :-(
Comment 11 Steven Bosscher 2005-12-15 06:50:38 UTC
If nobody is going to fix gcse2, the right thing to do is to not set flag_gcse_after_reload for optimize >= 3 in opts.c:

Index: opts.c
===================================================================
--- opts.c      (revision 108560)
+++ opts.c      (working copy)
@@ -588,7 +588,6 @@ decode_options (unsigned int argc, const
     {
       flag_inline_functions = 1;
       flag_unswitch_loops = 1;
-      flag_gcse_after_reload = 1;
     }

   if (optimize < 2 || optimize_size)


Obviously it would be better to just fix the bug, but so far I, for one, can't get a handle on it.
Comment 12 Steven Bosscher 2005-12-20 10:48:56 UTC
Almost certainly a dup of PR25196
Comment 13 Serge Belyshev 2005-12-20 10:59:12 UTC
Marking as dup of bug 25196 because that bug contains simpler test case.

*** This bug has been marked as a duplicate of 25196 ***
Comment 14 Steven Bosscher 2005-12-20 16:11:31 UTC
The patch proposed in bug 25196 comment #8 indeed makes the test case from comment #6 in this PR work (at least, it stops it from segfaulting).