From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14089 invoked by alias); 18 Jun 2002 16:16:14 -0000 Mailing-List: contact gcc-prs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-prs-owner@gcc.gnu.org Received: (qmail 13978 invoked by uid 71); 18 Jun 2002 16:16:04 -0000 Resent-Date: 18 Jun 2002 16:16:04 -0000 Resent-Message-ID: <20020618161604.13977.qmail@sources.redhat.com> Resent-From: gcc-gnats@gcc.gnu.org (GNATS Filer) Resent-To: nobody@gcc.gnu.org Resent-Cc: gcc-prs@gcc.gnu.org, gcc-bugs@gcc.gnu.org Resent-Reply-To: gcc-gnats@gcc.gnu.org, mark@moxienet.com Received: (qmail 9611 invoked by uid 61); 18 Jun 2002 16:06:38 -0000 Message-Id: <20020618160638.9610.qmail@sources.redhat.com> Date: Tue, 18 Jun 2002 09:36:00 -0000 From: mark@moxienet.com Reply-To: mark@moxienet.com To: gcc-gnats@gcc.gnu.org X-Send-Pr-Version: gnatsweb-2.9.3 (1.1.1.1.2.31) Subject: optimization/7069: Instruction scheduling for some CPUs is very wrong with -O2; gcc generates bad code X-SW-Source: 2002-06/txt/msg00422.txt.bz2 List-Id: >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 #include 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 #include 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; }