Bug 35658 - [4.3 Regression] between -funroll-loops -fno-automatic -O2 and common block variable
Summary: [4.3 Regression] between -funroll-loops -fno-automatic -O2 and common block v...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.3.0
: P5 normal
Target Milestone: 4.4.0
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2008-03-21 17:57 UTC by Kevin McCarty
Modified: 2011-06-27 12:04 UTC (History)
3 users (show)

See Also:
Host: ia64-linux-gnu
Target: ia64-linux-gnu
Build: ia64-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2008-05-22 18:52:59


Attachments
cutdown test case (451 bytes, text/plain)
2008-05-22 18:52 UTC, Steve Ellcey
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Kevin McCarty 2008-03-21 17:57:33 UTC
Hi,

[This bug was initially submitted to the Debian BTS at http://bugs.debian.org/466911 -- at the request of Debian's gcc maintainer, I am also sending it here]

In porting CERNLIB to gfortran, I've found an apparent gfortran compiler bug that results in incorrect code on ia64 (Itanium) with the compiler flags -funroll-loops -fno-automatic -O2 (or higher), possibly due to a bad interaction between these flags and a common block variable used in a computed GO TO statement of the form "GO TO (1,2,3,4), L".

The bug ONLY occurs in gfortran-4.3 -- I have tested that it does NOT happen in gfortran-4.1 (4.1.2-19), gfortran-4.2 (4.2.3-1), or g77-3.4 (3.4.6-6).

The output of gfortran-4.3 -v is:

(sid)kmccarty@merulo:~$ gfortran-4.3 -v
Using built-in specs.
Target: ia64-linux-gnu
Configured with: ../src/configure linux gnu
Thread model: posix
gcc version 4.3.1 20080309 (prerelease) (Debian 4.3.0-1)

Please see the complete test case I've provided at http://people.debian.org/~kmccarty/ia64-gfortran-test-fail.tar.gz

[Note, I have updated this test case tarball to the gfortran version noted above since I originally submitted this bug to the Debian BTS.]

Notes on the test case:

1) The code that gets mis-compiled is in c201s.F (this can be verified by building c201s.F with -O0 and building all the rest with -funroll-loops -fno-automatic -O2, then linking and running the test program c201test)

2) If *any* of the compiler flags are changed (remove -funroll-loops, remove -fno-automatic, or lower the optimization to -O1) the code is built OK.

3) I have put the output of gfortran-4.3 on ia64 (files c201s.f, c201s.s, and c201s.o) for various compiler flag combinations in subdirectories in the test case tarball.  Also the output of the test program when run, in the file output.txt in each subdirectory. (Subdirectories are named first after whether the test succeeds, and second after the specific compiler flags used.)  You can quickly regenerate this output for all the various flag combinations in the test case with "make output".

4) I believe the problem is that the variable L in common block "FLABEL" is not seen as having the correct value (should be 1, is set to that value in c201m.F prior to any call of C201S) within c201s.F.

5) If I make any tweak to L in c201s.F, the bug disappears.  (Argh, heisenbug!)  For instance, any of the following tweaks individually causes the test program to succeed:

a) changing L to a local variable initialized to the value 1 at the top of c201s.F
b) setting L=1 at the top of c201s.F (keeping it in the common block)
c) printing the value of L to stdout at the top of c201s.F with a WRITE statement
d) printing the literal string 'L=n' to stdout (n being one of 1,2,3,4) immediately after each label that the first GO TO jumps to (i.e. the value of L is not even directly read from).

Hence I was not able to simplify the test case any, unfortunately.

best regards,
Kevin McCarty
Comment 1 Mark Mitchell 2008-04-28 04:28:37 UTC
Fortran is not a primary language.
Comment 2 Steve Ellcey 2008-05-20 20:50:09 UTC
I cannot reproduce this error.  I have compiled the test case with
various options and always get output that includes

 Test#  1 ( C201 ): *** failed ***

and 

 Test#  1 ( GENT ): *** failed ***

I get this when I use -fno-automatic -O2 -funroll-loops and when I use no optimization at all.  This is with GCC 4.3 released bits and ToT bits on
a Debian 3.1 IA64 system.
Comment 3 Kevin McCarty 2008-05-21 03:59:00 UTC
(In reply to comment #2)

>  Test#  1 ( GENT ): *** failed ***
> 
> I get this when I use -fno-automatic -O2 -funroll-loops and when I use no
> optimization at all.  This is with GCC 4.3 released bits and ToT bits on
> a Debian 3.1 IA64 system.

I tried again with the version of gcc from the 4.3 release branch (Subversion branch gcc-4_3-branch downloaded today) and can still reproduce the bug (and also can still reproduce the successes with no optimization or with -fno-automatic -O2 but not -funroll-loops).

This is on an up-to-date Debian Sid system.  (N.B. are you aware that Debian 3.1 is no longer security-supported?)
Comment 4 Steve Ellcey 2008-05-21 15:30:18 UTC
Now I can reproduce it.  I don't know if you intended this or not but the clean target in the Makefile removed the good objects but left the bad one so that when I rebuilt I still had the old bad object around.
Comment 5 Steve Ellcey 2008-05-22 18:52:31 UTC
Created attachment 15672 [details]
cutdown test case

This smaller test case requires the same options as the original.
Comment 6 Steve Ellcey 2008-05-23 15:02:46 UTC
It looks like this is a bug in register renaming.  register renaming is turned on by -floop-unroll.  You can reproduce the bug using -frename-registers in place of -funroll-loops.
Comment 7 Steve Ellcey 2008-06-05 23:02:06 UTC
I now think this is a register scheduling bug.  If I use -fno-schedule-insns2 then the bug doesn't happen even with "-O2 fno-automatic -frename-registers".

The problem seems to be scheduling the assignment to TEMP2 and assigning TEMP2 to F(K).

In the good code, in C201S I see the following instructions, in this order:

         addl r17 = @gprel(temp2.717#), gp - r17 is addr of temp2
         stfd [r17] = f0                   - zero out temp2
         (p11) stfd [r17] = f10            - (maybe) put value (2.0) in temp2
         ldfd f9 = [r17]                   - load temp2
         add r16 = r34, r37                - r16 is addr of F(1)
         stfd [r16] = f9                   - store temp2 in F(1)

In the bad code (with instruction scheduling turned on) I see:


         addl r17 = @gprel(temp2.717#), gp - r17 is addr of temp2
         add r16 = r34, r37                - r16 is addr of F(1)
         ldfd f9 = [r17]                   - load temp2
         stfd [r17] = f0                   - zero out temp2
         stfd [r16] = f9                   - store (old) temp2 in F(1)
         (p11) stfd [r17] = f10            - (maybe) put value (2.0) in temp2

The store into F(1) is done before we have put the correct value int temp2.
I don't understand how instruction scheduling could be this broken.
Comment 8 Richard Biener 2008-06-06 14:59:15 UTC
4.3.1 is being released, adjusting target milestone.
Comment 9 Steve Ellcey 2008-08-18 21:51:38 UTC
Kevin, I can no longer reproduce this bug.  I think it was fixed by the same patch that fixed PR 35659.  Are you able to reproduce this or can we close it as fixed?
Comment 10 Kevin McCarty 2008-08-23 02:59:07 UTC
(In reply to comment #9)
> Kevin, I can no longer reproduce this bug.  I think it was fixed by the same
> patch that fixed PR 35659.  Are you able to reproduce this or can we close it
> as fixed?

First, sorry for the delayed reply.

With the latest gfortran from the gcc 4.3 branch in svn, I can unfortunately still reproduce this bug using both my test case and the cut-down test case provided by Steve Ellcey.  I do find that PR 35659 is now fixed for me.

(sid)kmccarty@merulo:~$ ~/gcc-4.3-branch/bin/gfortran -v
Using built-in specs.
Target: ia64-unknown-linux-gnu
Configured with: ./configure --enable-fortran --prefix=/home/kmccarty/gcc-4.3-branch/ --with-mpfr=/home/kmccarty/gcc-4.3-branch/ --with-gmp=/home/kmccarty/gcc-4.3-branch/
Thread model: posix
gcc version 4.3.2 20080822 (prerelease) (GCC)

Would you like me to also try with SVN trunk?  Anything else you need to know?
Comment 11 Kevin McCarty 2008-08-23 03:24:40 UTC
(In reply to comment #9)

By the way, Steve, I do find (as you mentioned) that -frename-registers in place of -funroll-loops also triggers the bug, and that adding -fno-schedule-insns2 makes it go away.
Comment 12 Joseph S. Myers 2008-08-27 22:03:39 UTC
4.3.2 is released, changing milestones to 4.3.3.
Comment 13 Richard Biener 2009-01-24 10:20:13 UTC
GCC 4.3.3 is being released, adjusting target milestone.
Comment 14 Richard Biener 2009-08-04 12:29:04 UTC
GCC 4.3.4 is being released, adjusting target milestone.
Comment 15 Richard Biener 2010-05-22 18:12:17 UTC
GCC 4.3.5 is being released, adjusting target milestone.
Comment 16 Steven Bosscher 2010-07-20 13:55:52 UTC
May be a dup of 43494, based on comment #7.
Comment 17 Richard Biener 2011-06-27 12:04:19 UTC
Fixed for 4.4.0.