public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
* optimization/7069: Instruction scheduling for some CPUs is very wrong with -O2; gcc generates bad code
@ 2002-06-18  9:36 mark
  0 siblings, 0 replies; 2+ messages in thread
From: mark @ 2002-06-18  9:36 UTC (permalink / raw)
  To: gcc-gnats


>Number:         7069
>Category:       optimization
>Synopsis:       Instruction scheduling for some CPUs is very wrong with -O2; gcc generates bad code
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          wrong-code
>Submitter-Id:   net
>Arrival-Date:   Tue Jun 18 09:16:02 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Mark Mentovai
>Release:        3.1
>Organization:
>Environment:
System: SunOS s7 5.8 Generic_108528-15 sun4u sparc SUNW,UltraAX-i2
Architecture: sun4
Sun Netra T1 200, 500MHz UltraSPARC IIe, 1GB, 2x18GB
Sun Solaris 8 7/01 MU 7
host: sparc-sun-solaris2.8
build: sparc-sun-solaris2.8
target: sparc-sun-solaris2.8
configured with: ../gcc-3.1/configure --enable-shared --with-gnu-as --with-gnu-ld --enable-threads --with-cpu=ultrasparc --enable-libgcj --with-system-zlib

Also exhibited on:

System: Linux localhost 2.4.18 #5 SMP Wed May 8 11:52:37 EDT 2002 sparc64 unknown
Architecture: sparc64
Sun Enterprise 220R, 450MHz UltraSPARC II, 1GB, 2x18GB
Debian GNU/Linux 2.2, Linux 2.4.18 (sparc64)
host: sparc-sun-linux-gnu
build: sparc-sun-linux-gnu
target: sparc-sun-linux-gnu
configured with: ../gcc-3.1/configure --enable-shared --with-gnu-as --with-gnu-ld --enable-threads --enable-libgcj --with-system-zlib sparc-sun-linux-gnu
>Description:
Instruction scheduling for some CPUs is very wrong with -O2; gcc generates bad code.  The optimized code is incorrect, it functions differently from non-optimized code, and various levels of optimization may produce code that functions differently as well.

Given the C code gcc-bug-20020618.c:
--
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char **argv) {
  char c[4]={222,173,190,239};
  int *p;
  p=(int *)&c;
  printf("p = 0x%08x\n",*p);
  exit(0);
  return 0;
}
--

GCC schedules the load of *p for the call to printf before the stores of c[0..3]; *p thus has an incorrect value.

This occurs with -O2 and higher (but not -Os) when instruction scheduling for ultrasparc, cypress, or tsc701 is selected with -mcpu or -mtune.  Default scheduling for all SPARC architectures appears to be unaffected, as does implementation-specific scheduling for implementations other than ultrasparc, cypress, and tsc701.  I have not tested non-SPARC architectures.

Note that cypress is the default implementation selected at configure time in the absence of --with-cpu.

As one example, the assembly source output on Solaris from "gcc -mcpu=ultrasparc -O2 gcc-bug-20020618.c -S -o gcc-bug-20020618,ultrasparc-O2.s":

--
        .file   "gcc-bug-20020618.c"
        .section        .rodata.str1.8,"aMS",@progbits,1
        .align 8
.LLC0:
        .asciz  "*p = 0x%08x\n"
        .section        ".text"
        .align 4
        .align 32
        .global main
        .type   main,#function
        .proc   04
main:
        !#PROLOGUE# 0
        save    %sp, -120, %sp
        !#PROLOGUE# 1
        mov     -34, %o2
        mov     -83, %o3
        ld      [%fp-24], %o1
        sethi   %hi(.LLC0), %o0
        stb     %o2, [%fp-24]
        mov     -66, %o2
        or      %o0, %lo(.LLC0), %o0
        stb     %o3, [%fp-23]
        mov     -17, %o3
        stb     %o2, [%fp-22]
        call    printf, 0
        stb     %o3, [%fp-21]
        call    exit, 0
        mov     0, %o0
        nop
.LLfe1:
        .size   main,.LLfe1-main
        .ident  "GCC: (GNU) 3.1"
--

As you can see, "ld [%fp-24], %o1" is scheduled in advance of any stb instruction to [%fp-24]..[%fp-21].

This bug has been observed on SPARC running gcc 3.1 under both SunOS 5.8 and Linux 2.4.18.  gcc 3.0.4 does not exhibit this bug.

C source included rather than preprocessed code, as it is more relevant in this case, and this test case does not depend on anything esoteric.  The expected output is "*p = 0xdeadbeef" on big-endian platforms.
>How-To-Repeat:
Compile and run gcc-bug-20020618.c with -O2 or higher and ultrasparc or cypress as the selected CPU with -mcpu, or select instruction scheduling only with -mtune.  The expected output is "*p = 0xdeadbeef" as seen when building with -O1 or when using default instruction scheduling parameters (selecting -mcpu=v7 or -mcpu=v9).

On Solaris:
> gcc -mcpu=ultrasparc -O1 gcc-bug-20020618.c -o gcc-bug-20020618,ultrasparc-O1 && ./gcc-bug-20020618,ultrasparc-O1
*p = 0xdeadbeef
> gcc -mcpu=ultrasparc -O2 gcc-bug-20020618.c -o gcc-bug-20020618,ultrasparc-O2 && ./gcc-bug-20020618,ultrasparc-O2
*p = 0x00000004
> gcc -mcpu=ultrasparc -O3 gcc-bug-20020618.c -o gcc-bug-20020618,ultrasparc-O3 && ./gcc-bug-20020618,ultrasparc-O3
*p = 0x00000004
> gcc -mcpu=v9 -O3 gcc-bug-20020618.c -o gcc-bug-20020618,v9-O3 && ./gcc-bug-20020618,v9-O3
*p = 0xdeadbeef
> gcc -mcpu=cypress -O1 gcc-bug-20020618.c -o gcc-bug-20020618,cypress-O1 && ./gcc-bug-20020618,cypress-O1
*p = 0xdeadbeef
> gcc -mcpu=cypress -O2 gcc-bug-20020618.c -o gcc-bug-20020618,cypress-O2 && ./gcc-bug-20020618,cypress-O2
*p = 0xdeadbe04
> gcc -mcpu=cypress -O3 gcc-bug-20020618.c -o gcc-bug-20020618,cypress-O3 && ./gcc-bug-20020618,cypress-O3
*p = 0x00ad00ef
> gcc -mcpu=v7 -O3 gcc-bug-20020618.c -o gcc-bug-20020618,v7-O3 && ./gcc-bug-20020618,v7-O3
*p = 0xdeadbeef

On Linux:
> gcc -mcpu=ultrasparc -O1 gcc-bug-20020618.c -o gcc-bug-20020618,ultrasparc-O1 && ./gcc-bug-20020618,ultrasparc-O1
*p = 0xdeadbeef
> gcc -mcpu=ultrasparc -O2 gcc-bug-20020618.c -o gcc-bug-20020618,ultrasparc-O2 && ./gcc-bug-20020618,ultrasparc-O2
*p = 0x00000000
> gcc -mcpu=ultrasparc -O3 gcc-bug-20020618.c -o gcc-bug-20020618,ultrasparc-O3 && ./gcc-bug-20020618,ultrasparc-O3
*p = 0x00000000
> gcc -mcpu=v9 -O3 gcc-bug-20020618.c -o gcc-bug-20020618,v9-O3 && ./gcc-bug-20020618,v9-O3
*p = 0xdeadbeef
> gcc -mcpu=cypress -O1 gcc-bug-20020618.c -o gcc-bug-20020618,cypress-O1 && ./gcc-bug-20020618,cypress-O1
*p = 0xdeadbeef
> gcc -mcpu=cypress -O2 gcc-bug-20020618.c -o gcc-bug-20020618,cypress-O2 && ./gcc-bug-20020618,cypress-O2
*p = 0xdeadbe00
> gcc -mcpu=cypress -O3 gcc-bug-20020618.c -o gcc-bug-20020618,cypress-O3 && ./gcc-bug-20020618,cypress-O3
*p = 0x000000ef
> gcc -mcpu=v7 -O3 gcc-bug-20020618.c -o gcc-bug-20020618,v7-O3 && ./gcc-bug-20020618,v7-O3
*p = 0xdeadbeef
>Fix:
No fix.

Workaround: Do not use implementation-specific instruction scheduling, use "-mcpu=v9" or "-mcpu=v7" instead of "-mcpu=ultrasparc" and "-mcpu=cypress".  Alternatively, allow implementation-specific scheduling but use -O1 instead of -O2 or higher.

As cypress is the default CPU unless gcc is configured otherwise, users may wish to explicitly select another CPU by setting CC to something like "gcc -mcpu=v7", or by configuring gcc to use another CPU by default.
>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: text/plain; name="gcc-bug-20020618.c"
Content-Disposition: inline; filename="gcc-bug-20020618.c"

#include <stdio.h>
#include <stdlib.h>
int main(int argc,char **argv) {
  char c[4]={222,173,190,239};
  int *p;
  p=(int *)&c;
  printf("*p = 0x%08x\n",*p);
  exit(0);
  return 0;
}


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: optimization/7069: Instruction scheduling for some CPUs is very wrong with -O2; gcc generates bad code
@ 2002-06-20 12:26 rth
  0 siblings, 0 replies; 2+ messages in thread
From: rth @ 2002-06-20 12:26 UTC (permalink / raw)
  To: gcc-bugs, gcc-prs, mark, nobody, rth

Synopsis: Instruction scheduling for some CPUs is very wrong with -O2; gcc generates bad code

Responsible-Changed-From-To: unassigned->rth
Responsible-Changed-By: rth
Responsible-Changed-When: Thu Jun 20 12:15:54 2002
Responsible-Changed-Why:
    .
State-Changed-From-To: open->closed
State-Changed-By: rth
State-Changed-When: Thu Jun 20 12:15:54 2002
State-Changed-Why:
    http://gcc.gnu.org/ml/gcc-patches/2002-06/msg01730.html

http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=7069


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2002-06-20 19:15 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-06-18  9:36 optimization/7069: Instruction scheduling for some CPUs is very wrong with -O2; gcc generates bad code mark
2002-06-20 12:26 rth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).