This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
c++/2806: g++ 2.96 inadequate optimization in static and global initializers
- To: gcc-gnats at gcc dot gnu dot org
- Subject: c++/2806: g++ 2.96 inadequate optimization in static and global initializers
- From: eric-gcc at omnifarious dot org
- Date: 11 May 2001 21:59:54 -0000
- Reply-To: eric-gcc at omnifarious dot org
>Number: 2806
>Category: c++
>Synopsis: g++ 2.96 inadequate optimization in static and global initializers
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: unassigned
>State: open
>Class: pessimizes-code
>Submitter-Id: net
>Arrival-Date: Fri May 11 15:06:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator: Eric Hopper
>Release: gcc 2.96 (Yeah, yeah, I know, RedHat's, but I bet gcc 2.95.3 does it too)
>Organization:
>Environment:
RH Linux 7.0
>Description:
This code:
---- (example.cpp)
class Fred {
public:
Fred(int x) : x_(x) { }
private:
int x_;
};
class Barney : public Fred {
public:
Barney(int x, int y) : Fred(x), y_(y) { }
private:
int y_;
};
extern const Barney abarney(5, 6);
extern const Fred afred(2);
----
when compiled liked this: g++ -pipe -march=athlon -O2 -S example.cpp
results in this assembly:
---- (pessimized example.s)
.file "example.cpp"
.version "01.01"
gcc2_compiled.:
.globl abarney
.bss
.align 4
.type abarney,@object
.size abarney,8
abarney:
.zero 8
.globl afred
.align 4
.type afred,@object
.size afred,4
afred:
.zero 4
.text
.align 16
.type __static_initialization_and_destruction_0,@function
__static_initialization_and_destruction_0:
.LFB1:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
movl 12(%ebp), %eax
movl 8(%ebp), %edx
cmpl $65535, %eax
jne .L3
cmpl $1, %edx
jne .L3
movl $5, abarney
movl $6, abarney+4
.L3:
cmpl $65535, %eax
jne .L11
decl %edx
jne .L11
movl $2, afred
.L11:
popl %ebp
ret
.LFE1:
.Lfe1:
.size
__static_initialization_and_destruction_0,.Lfe1-__static_initialization_and_destruction_0
.align 16
.type _GLOBAL_.I.abarney,@function
_GLOBAL_.I.abarney:
.LFB2:
pushl %ebp
.LCFI2:
movl %esp, %ebp
.LCFI3:
subl $16, %esp
.LCFI4:
pushl $65535
pushl $1
.LCFI5:
call __static_initialization_and_destruction_0
addl $16, %esp
leave
ret
.LFE2:
.Lfe2:
.size _GLOBAL_.I.abarney,.Lfe2-_GLOBAL_.I.abarney
.section .ctors,"aw"
.long _GLOBAL_.I.abarney
.ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-81)"
----
when it should've resulted in something like this:
---- .file "example2.cpp"
.version "01.01"
gcc2_compiled.:
.globl abarney
.section .rodata
.align 4
.type abarney,@object
.size abarney,8
abarney:
.long 5
.long 6
.globl afred
.align 4
.type afred,@object
.size afred,4
afred:
.long 2
.ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-81)"
----
The results of all these initializers can be statically determined at compile time. There is no reason I can think of they shouldn't be stuck in the .rodata section. If they were not const, they could be stuck in the .data section.
Even if the initializer is run, the initializer itself will make repeated
comparisons of %eax against $65535 instead of simply jumping to the end if
the first such comparison registers as being equal. This situation is also
easily determined by simple analysis, and jump optimization in ordinary
code would catch it.
Actually, the repeated compare jump sequence can be created with non-initializer code too. Here's an example program that I've been told produced sub-optimal assembly:
int abarney[2];
int afred[1];
void foo(int edx, int eax)
{
if (eax == 65535)
{
if (edx == 1)
{
abarney[0] = 5;
abarney[1] = 6;
}
}
if (eax == 65535)
{
if (--edx == 0)
afred[0] = 2;
}
}
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted: