This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug optimization/14937] New: GCSE bug with global register variables
- From: "gcc-bugzilla at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 13 Apr 2004 10:10:07 -0000
- Subject: [Bug optimization/14937] New: GCSE bug with global register variables
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
In a function using a global register variable, that conditionally calls
a nonreturning function, the GCSE omits the last update (a decrement)
of the global register variable.
Environment:
System: Linux linuix 2.4.21-99-default #1 Wed Sep 24 13:30:51 UTC 2003 i686 athlon i386 GNU/Linux
Architecture: i686
<machine, os, target, libraries (multiple lines)>
host: i586-suse-linux-gnu
build: i586-suse-linux-gnu
target: i586-suse-linux-gnu
configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib --enable-languages=c,c++,f77,objc,java,ada --disable-checking --enable-libgcj --with-gxx-include-dir=/usr/include/g++ --with-slibdir=/lib --with-system-zlib --enable-shared --enable-__cxa_atexit i586-suse-linux
How-To-Repeat:
================================= bug.c ====================================
typedef void * object;
register object* STACK __asm__("%ebx");
typedef struct {
object GCself;
unsigned int tfl;
unsigned int data[0];
} * Sstring;
typedef struct {
object GCself;
unsigned int tfl;
object enc_eol;
object enc_towcs_error;
object enc_tombs_error;
object enc_charset;
object enc_mblen;
object enc_mbstowcs;
object enc_wcslen;
object enc_wcstombs;
object enc_range;
object enc_table;
unsigned int min_bytes_per_char;
unsigned int max_bytes_per_char;
} * Encoding;
extern void __attribute__((__noreturn__)) fehler_notreached (const char * file, unsigned int line);
extern object allocate_s32string (unsigned int len);
object n_char_to_string (const char * srcptr, unsigned int blen, object encoding)
{
const unsigned char * bptr = (const unsigned char *)srcptr;
const unsigned char * bendptr = bptr + blen;
unsigned int clen = ((unsigned int (*) (object, const unsigned char *, const unsigned char *)) ((const void *)((void*)((unsigned long)(((Encoding)((unsigned long)(encoding)-1))->enc_mblen)))))(encoding,bptr,bendptr);
(STACK[0] = encoding, STACK += 1);
{
object obj = allocate_s32string(clen);
encoding = (STACK -= 1, STACK[0]);
{
unsigned int * cptr = &((Sstring)((unsigned long)(obj)-1))->data[0];
unsigned int * cendptr = cptr + clen;
((void (*) (object, object, const unsigned char **, const unsigned char *, unsigned int**, unsigned int*)) ((const void *)((void*)((unsigned long)(((Encoding)((unsigned long)(encoding)-1))->enc_mbstowcs)))))(encoding,(object)0,&bptr,bendptr,&cptr,cendptr);
if (!(cptr == cendptr))
fehler_notreached("encoding.d",1910);
}
return obj;
}
}
============================================================================
$ gcc -O2 -Wall -S bug.c
In the resulting bug.s, you see that %ebx is incremented by 4 (this
corresponds to the STACK += 1 expression) but is never decremented back
by 4 (as expected from the STACK -= 1 expression two lines below).
================================= bug.s ====================================
.file "bug.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "encoding.d"
.text
.p2align 4,,15
.globl n_char_to_string
.type n_char_to_string, @function
n_char_to_string:
pushl %ebp
movl %esp, %ebp
pushl %edi
pushl %esi
subl $36, %esp
movl 8(%ebp), %eax
movl 12(%ebp), %edx
movl 16(%ebp), %edi
addl %eax, %edx
movl %edx, -20(%ebp)
movl %eax, -16(%ebp)
pushl %edx
pushl %eax
pushl %edi
call *23(%edi)
movl %eax, %esi
movl %edi, (%ebx)
movl %eax, (%esp)
addl $4, %ebx
call allocate_s32string
movl %eax, -24(%ebp)
movl -4(%ebx), %edi
addl $7, %eax
movl %eax, -12(%ebp)
leal (%eax,%esi,4), %esi
movl %esi, -28(%ebp)
popl %ecx
popl %eax
leal -12(%ebp), %eax
pushl %esi
pushl %eax
leal -16(%ebp), %eax
movl -20(%ebp), %edx
pushl %edx
pushl %eax
pushl $0
pushl %edi
call *27(%edi)
movl -28(%ebp), %eax
addl $32, %esp
cmpl %eax, -12(%ebp)
jne .L4
movl -24(%ebp), %eax
leal -8(%ebp), %esp
popl %esi
popl %edi
popl %ebp
ret
.L4:
pushl %eax
pushl %eax
pushl $1910
pushl $.LC0
call fehler_notreached
.size n_char_to_string, .-n_char_to_string
.ident "GCC: (GNU) 3.3.1 (SuSE Linux)"
============================================================================
------- Additional Comments From bruno at clisp dot org 2004-04-13 10:09 -------
Fix:
The bug goes away if -fno-gcse is passed to gcc.
--
Summary: GCSE bug with global register variables
Product: gcc
Version: 3.3.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: optimization
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: bruno at clisp dot org
CC: gcc-bugs at gcc dot gnu dot org
GCC build triplet: i586-suse-linux-gnu
GCC host triplet: i586-suse-linux-gnu
GCC target triplet: i586-suse-linux-gnu
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=14937